From patchwork Thu Nov 8 20:27:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10674969 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2724415A6 for ; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19D972E2AB for ; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0E3462E2D8; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 776D62E2AB for ; Thu, 8 Nov 2018 20:31:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727324AbeKIGIJ (ORCPT ); Fri, 9 Nov 2018 01:08:09 -0500 Received: from mail-lj1-f195.google.com ([209.85.208.195]:41239 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727074AbeKIGIH (ORCPT ); Fri, 9 Nov 2018 01:08:07 -0500 Received: by mail-lj1-f195.google.com with SMTP id z80-v6so19194768ljb.8 for ; Thu, 08 Nov 2018 12:30:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=j6h7cGyTcDwoxdKOJu25q1JmarscrLLy/bea2IWaKVw=; b=fdwgnrskFVFXQdC2Zsbdp+Y2cJu2gQPi4Y00LnERc5nmYMzNIkNHhdc5nVvDTkvJvP dDd9NE7D0UkJ9TQz6oEiK2HxxA7NOa8iAZtfSh34zlFGyAZGWQOQRtSTze/BM9Jx49dp ajZDzZsnhZPySHp2CZG8UdMVDLZTJM8UXb0HI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=j6h7cGyTcDwoxdKOJu25q1JmarscrLLy/bea2IWaKVw=; b=LBSckoKgNgRlHWMHVhl3j/X9qU7u79JwuDO2TsIVaqdJuD7k08hOsVg5UERs3oTNu5 UqnMZUrLN0c0Y+Jlt6y+DOy0HVZb2g2sLkSm5ziswIRz1z6o9qxprMSoREcNCe1qZAiY NvDVBXIkIVPbz3QNIDePB57IMkbpmXVolpehxqe5SKJvADAAw3ZqKkzMmJVbi3Lgbgrp J9/mA52i184FnQCPy9Rz4Jl9QJxmJPMOL/BzxUWAs6pO/hYVaLiSEDUJN6f1Gc/ydhXM Vb3YYD2GcpWIPQQusWu8oyKrcdX9iqOfKQIrZ3g0TTEOMErMYUm7Bn63DvRFqdXmLSQF FU1Q== X-Gm-Message-State: AGRZ1gIJwYZP2SSNtSNS+qTQWDrxL7uh5XamFmk2OWB6eoz0WugzSZ2D r2ZkdV0U3/MHFcVmSG5fPrmSWw== X-Google-Smtp-Source: AJdET5fKkUv3s9riUrhgueQXrA9lEESoHi3WpBDmLQ/aW4Gcq9Xx+nrSMBuwEE82wBuvrBRA3Ki23g== X-Received: by 2002:a2e:9c59:: with SMTP id t25-v6mr4152333ljj.107.1541709058001; Thu, 08 Nov 2018 12:30:58 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id w9sm809250lfc.66.2018.11.08.12.30.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Nov 2018 12:30:57 -0800 (PST) From: Ivan Khoronzhuk To: grygorii.strashko@ti.com, davem@davemloft.net Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alexander.h.duyck@intel.com, bjorn@mork.no, Ivan Khoronzhuk Subject: [PATCH v2 net-next 1/4] net: core: dev_addr_lists: add auxiliary func to handle reference address updates Date: Thu, 8 Nov 2018 22:27:54 +0200 Message-Id: <20181108202757.30110-2-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> References: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In order to avoid all table update, and only remove or add new address, the auxiliary function exists, named __hw_addr_sync_dev(). It allows end driver do nothing when nothing changed and add/rm when concrete address is firstly added or lastly removed. But it doesn't include cases when an address of real device or vlan was reused by other vlans or vlan/macval devices. For handaling events when address was reused/unreused the patch adds new auxiliary routine - __hw_addr_ref_sync_dev(). It allows to do nothing when nothing was changed and do updates only for an address being added/reused/deleted/unreused. Thus, clone address changes for vlans can be mirrored in the table. The function is exclusive with __hw_addr_sync_dev(). It's responsibility of the end driver to identify address vlan device, if it needs so. Signed-off-by: Ivan Khoronzhuk --- include/linux/netdevice.h | 10 ++++ net/core/dev_addr_lists.c | 97 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 857f8abf7b91..487fa5e0e165 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4068,6 +4068,16 @@ int __hw_addr_sync_dev(struct netdev_hw_addr_list *list, int (*sync)(struct net_device *, const unsigned char *), int (*unsync)(struct net_device *, const unsigned char *)); +int __hw_addr_ref_sync_dev(struct netdev_hw_addr_list *list, + struct net_device *dev, + int (*sync)(struct net_device *, + const unsigned char *, int), + int (*unsync)(struct net_device *, + const unsigned char *, int)); +void __hw_addr_ref_unsync_dev(struct netdev_hw_addr_list *list, + struct net_device *dev, + int (*unsync)(struct net_device *, + const unsigned char *, int)); void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list, struct net_device *dev, int (*unsync)(struct net_device *, diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index d884d8f5f0e5..81a8cd4ea3bd 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -277,6 +277,103 @@ int __hw_addr_sync_dev(struct netdev_hw_addr_list *list, } EXPORT_SYMBOL(__hw_addr_sync_dev); +/** + * __hw_addr_ref_sync_dev - Synchronize device's multicast address list taking + * into account references + * @list: address list to synchronize + * @dev: device to sync + * @sync: function to call if address or reference on it should be added + * @unsync: function to call if address or some reference on it should removed + * + * This function is intended to be called from the ndo_set_rx_mode + * function of devices that require explicit address or references on it + * add/remove notifications. The unsync function may be NULL in which case + * the addresses or references on it requiring removal will simply be + * removed without any notification to the device. That is responsibility of + * the driver to identify and distribute address or references on it between + * internal address tables. + **/ +int __hw_addr_ref_sync_dev(struct netdev_hw_addr_list *list, + struct net_device *dev, + int (*sync)(struct net_device *, + const unsigned char *, int), + int (*unsync)(struct net_device *, + const unsigned char *, int)) +{ + struct netdev_hw_addr *ha, *tmp; + int err, ref_cnt; + + /* first go through and flush out any unsynced/stale entries */ + list_for_each_entry_safe(ha, tmp, &list->list, list) { + /* sync if address is not used */ + if ((ha->sync_cnt << 1) <= ha->refcount) + continue; + + /* if fails defer unsyncing address */ + ref_cnt = ha->refcount - ha->sync_cnt; + if (unsync && unsync(dev, ha->addr, ref_cnt)) + continue; + + ha->refcount = (ref_cnt << 1) + 1; + ha->sync_cnt = ref_cnt; + __hw_addr_del_entry(list, ha, false, false); + } + + /* go through and sync updated/new entries to the list */ + list_for_each_entry_safe(ha, tmp, &list->list, list) { + /* sync if address added or reused */ + if ((ha->sync_cnt << 1) >= ha->refcount) + continue; + + ref_cnt = ha->refcount - ha->sync_cnt; + err = sync(dev, ha->addr, ref_cnt); + if (err) + return err; + + ha->refcount = ref_cnt << 1; + ha->sync_cnt = ref_cnt; + } + + return 0; +} +EXPORT_SYMBOL(__hw_addr_ref_sync_dev); + +/** + * __hw_addr_ref_unsync_dev - Remove synchronized addresses and references on + * it from device + * @list: address list to remove synchronized addresses (references on it) from + * @dev: device to sync + * @unsync: function to call if address and references on it should be removed + * + * Remove all addresses that were added to the device by + * __hw_addr_ref_sync_dev(). This function is intended to be called from the + * ndo_stop or ndo_open functions on devices that require explicit address (or + * references on it) add/remove notifications. If the unsync function pointer + * is NULL then this function can be used to just reset the sync_cnt for the + * addresses in the list. + **/ +void __hw_addr_ref_unsync_dev(struct netdev_hw_addr_list *list, + struct net_device *dev, + int (*unsync)(struct net_device *, + const unsigned char *, int)) +{ + struct netdev_hw_addr *ha, *tmp; + + list_for_each_entry_safe(ha, tmp, &list->list, list) { + if (!ha->sync_cnt) + continue; + + /* if fails defer unsyncing address */ + if (unsync && unsync(dev, ha->addr, ha->sync_cnt)) + continue; + + ha->refcount -= ha->sync_cnt - 1; + ha->sync_cnt = 0; + __hw_addr_del_entry(list, ha, false, false); + } +} +EXPORT_SYMBOL(__hw_addr_ref_unsync_dev); + /** * __hw_addr_unsync_dev - Remove synchronized addresses from device * @list: address list to remove synchronized addresses from From patchwork Thu Nov 8 20:27:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10674975 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CE70215A6 for ; Thu, 8 Nov 2018 20:31:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF1752E2D8 for ; Thu, 8 Nov 2018 20:31:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE1E52E30D; Thu, 8 Nov 2018 20:31:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2BBDB2E2D8 for ; Thu, 8 Nov 2018 20:31:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727509AbeKIGIh (ORCPT ); Fri, 9 Nov 2018 01:08:37 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:40803 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726182AbeKIGII (ORCPT ); Fri, 9 Nov 2018 01:08:08 -0500 Received: by mail-lj1-f196.google.com with SMTP id t22-v6so19207764lji.7 for ; Thu, 08 Nov 2018 12:31:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8QdsjuBuNR4syD4kYHeYJE3yp+I/xfPRdcYr33cc40E=; b=XufzLPeCqLvabFv/vXBBK9r+yrpq47Q+NRR/7PiXHDl3QB+5W+c2pF3Aiu7RewOUeK aCnxJzZwU1wqQ1kkvzysaOOCIyii+vi3OEaV/wq6kSyKH6WLmOD3SNv8KEBVlRUYQVpd YHTJXAvj/NxuP6RcxA6EPGYLbjuU1KOKfnEyU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8QdsjuBuNR4syD4kYHeYJE3yp+I/xfPRdcYr33cc40E=; b=eE0xlR5GkN9Jf8T5tMYPO/Z0T3sq7ivrPdoi1kh23AeBOz61NwnqXbD7EuFVg3FolX QF17CGrnpG8EKGZAkmBHxGsiwSLNksdwHqw7j++LzpjvFzG/al4108rxIVKB2qg56CX2 r+ntD6B50JEIrB3F3ZxFFRK+WJ2iiEkMcz57gdFSswekpBn+AEOqpcgBPSNJP7ydX/LM e2ltXk93D8rL6NnJiwN1zqNavN20AdNI3AtYOog8blXM9oMS/7skrIsFQPGUkFes6ukE GeLihIvREDM9QHXB/dpPeqKw2x9p9DXU6s3Ha398E8O33AnjbR0MKrkrcnl7ZXsE0vgP /IiQ== X-Gm-Message-State: AGRZ1gKjlc8nsfJvOWo4EWmAIOxZATnsWlPrlDRcEQM0Eg19xktJYHub OjnPzCMAyN9hxD2KvoLjQ4/kHw== X-Google-Smtp-Source: AJdET5crCkfP8Lb8xh9AJITif4hBPto7bJkJln6PavkKWDFY2p5UMnon/6XQ+xq3CeYWnjm6S6F9jg== X-Received: by 2002:a2e:8546:: with SMTP id u6-v6mr3725823ljj.95.1541709059378; Thu, 08 Nov 2018 12:30:59 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id w9sm809250lfc.66.2018.11.08.12.30.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Nov 2018 12:30:58 -0800 (PST) From: Ivan Khoronzhuk To: grygorii.strashko@ti.com, davem@davemloft.net Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alexander.h.duyck@intel.com, bjorn@mork.no, Ivan Khoronzhuk Subject: [PATCH v2 net-next 2/4] net: 8021q: vlan_core: allow use list of vlans for real device Date: Thu, 8 Nov 2018 22:27:55 +0200 Message-Id: <20181108202757.30110-3-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> References: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP It's redundancy for the drivers to hold the list of vlans when absolutely the same list exists in vlan core. In most cases it's needed only to traverse the vlan devices, their vids and sync some settings with h/w, so add API to simplify this. At least some of these drivers also can benefit: grep "for_each.*vid" -r drivers/net/ethernet/ drivers/net/ethernet/hisilicon/hns3/hns3_enet.c: drivers/net/ethernet/synopsys/dwc-xlgmac-hw.c: drivers/net/ethernet/qlogic/qlge/qlge_main.c: drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c: drivers/net/ethernet/via/via-rhine.c: drivers/net/ethernet/via/via-velocity.c: drivers/net/ethernet/intel/igb/igb_main.c: drivers/net/ethernet/intel/ice/ice_main.c: drivers/net/ethernet/intel/e1000/e1000_main.c: drivers/net/ethernet/intel/i40e/i40e_main.c: drivers/net/ethernet/intel/e1000e/netdev.c: drivers/net/ethernet/intel/igbvf/netdev.c: drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c: drivers/net/ethernet/intel/ixgb/ixgb_main.c: drivers/net/ethernet/intel/ixgbe/ixgbe_main.c: drivers/net/ethernet/amd/xgbe/xgbe-dev.c: drivers/net/ethernet/emulex/benet/be_main.c: drivers/net/ethernet/neterion/vxge/vxge-main.c: drivers/net/ethernet/adaptec/starfire.c: drivers/net/ethernet/brocade/bna/bnad.c: Reviewed-by: Grygorii Strashko Signed-off-by: Ivan Khoronzhuk --- include/linux/if_vlan.h | 11 +++++++++++ net/8021q/vlan_core.c | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 03b08ffded07..1be5230921b5 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -133,6 +133,9 @@ struct vlan_pcpu_stats { extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev, __be16 vlan_proto, u16 vlan_id); +extern int vlan_for_each(struct net_device *dev, + int (*action)(struct net_device *dev, int vid, + void *arg), void *arg); extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern __be16 vlan_dev_vlan_proto(const struct net_device *dev); @@ -236,6 +239,14 @@ __vlan_find_dev_deep_rcu(struct net_device *real_dev, return NULL; } +static inline int +vlan_for_each(struct net_device *dev, + int (*action)(struct net_device *dev, int vid, void *arg), + void *arg) +{ + return 0; +} + static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) { BUG(); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 4f60e86f4b8d..6308b5427a66 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -223,6 +223,33 @@ static int vlan_kill_rx_filter_info(struct net_device *dev, __be16 proto, u16 vi return -ENODEV; } +int vlan_for_each(struct net_device *dev, + int (*action)(struct net_device *dev, int vid, void *arg), + void *arg) +{ + struct vlan_vid_info *vid_info; + struct vlan_info *vlan_info; + struct net_device *vdev; + int ret; + + ASSERT_RTNL(); + + vlan_info = rtnl_dereference(dev->vlan_info); + if (!vlan_info) + return 0; + + list_for_each_entry(vid_info, &vlan_info->vid_list, list) { + vdev = vlan_group_get_device(&vlan_info->grp, vid_info->proto, + vid_info->vid); + ret = action(vdev, vid_info->vid, arg); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(vlan_for_each); + int vlan_filter_push_vids(struct vlan_info *vlan_info, __be16 proto) { struct net_device *real_dev = vlan_info->real_dev; From patchwork Thu Nov 8 20:27:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10674971 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB6C215E9 for ; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CE4B72E2AB for ; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C2A862E2D8; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2AC252E2CD for ; Thu, 8 Nov 2018 20:31:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727342AbeKIGIK (ORCPT ); Fri, 9 Nov 2018 01:08:10 -0500 Received: from mail-lj1-f195.google.com ([209.85.208.195]:40806 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726962AbeKIGIK (ORCPT ); Fri, 9 Nov 2018 01:08:10 -0500 Received: by mail-lj1-f195.google.com with SMTP id t22-v6so19207816lji.7 for ; Thu, 08 Nov 2018 12:31:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=H9TSrLDrzQqMmVYXXGLyWYnz91EkApCFQZh2j/4pA3E=; b=AJoilIjAYZb+Alj9APgoqx4N+3j0b7+Ts+qB7hvlCGVQ6effL/t6c3B92RX53bdccA mhdCtV5n4/S7+BpJVKLdK2WW+9tED7O6RW+bVJqg1Hh9v9HIUxht8TL+szqGxDp4NG2R HcznVWe3Q21pHBfSZqojPXFJbcpAGXg4RNPqM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=H9TSrLDrzQqMmVYXXGLyWYnz91EkApCFQZh2j/4pA3E=; b=QVtdXxwQnJHKNOOJODm8c2M3LbZ380YnoMc3AzSE+stAT+RxY8RrDCawOFyHanfcTe xEmcEVvlK4iVwA+j/dixpNJJn/0Pi1cGxrVyV6WtMb2eQUFYnLYlpmq2FqSh/IdDt47A F+KcSzHJ04mgdFYn9Hxzb7D8jQ76ZBFmUFTRfVoiKY3gDIqBK3L1acqRQd2j4Popcp8p m2dIPaZfq/NEXaNnCYfuhqNjLsyi9So9B157QNbtw5rTwrCinFcSllG34y6594DzNLOK l/K5ykQK9usBxaOMhJmKPnjWrUQUBZuPkXb1XpK7q/3sW/+JvbadjcOG7lG91+ajS4Mh fDxw== X-Gm-Message-State: AGRZ1gLJ+eRHhYKO87V/rzdvjndpsnp2pxajFsLP4W0ynx//w0CtG8x3 VQ1/oEcCPnw7tdIrANG2u1QWyA== X-Google-Smtp-Source: AJdET5e3IBqbddhhBiz9yiuyVkcHYoGtNZLS1Y2uA/934teMp7VGFPO5xqKuEvC4/dM/HZeYwBt5Kg== X-Received: by 2002:a2e:85d3:: with SMTP id h19-v6mr3668638ljj.82.1541709060731; Thu, 08 Nov 2018 12:31:00 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id w9sm809250lfc.66.2018.11.08.12.30.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Nov 2018 12:31:00 -0800 (PST) From: Ivan Khoronzhuk To: grygorii.strashko@ti.com, davem@davemloft.net Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alexander.h.duyck@intel.com, bjorn@mork.no, Ivan Khoronzhuk Subject: [PATCH v2 net-next 3/4] net: ethernet: ti: cpsw: fix vlan mcast Date: Thu, 8 Nov 2018 22:27:56 +0200 Message-Id: <20181108202757.30110-4-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> References: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP At this moment, mcast addresses are added for real device only (reserved vlans for dual-emac mode), even if a mcast address was added for some vlan only, thus ALE doesn't have corresponding vlan mcast entries after vlan socket joined multicast group. So ALE drops vlan frames with mcast addresses intended for vlans and potentially can receive mcast frames for base ndev. That's not correct. So, fix it by creating only vlan/mcast entries as requested. Patch doesn't use any additional lists and is based on device mc address list and cpsw ALE table entries. Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 169 +++++++++++++++++++++++++++------ 1 file changed, 138 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 500f7ed8c58c..0b18634d336c 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -570,21 +570,6 @@ static inline int cpsw_get_slave_port(u32 slave_num) return slave_num + 1; } -static void cpsw_add_mcast(struct cpsw_priv *priv, const u8 *addr) -{ - struct cpsw_common *cpsw = priv->cpsw; - - if (cpsw->data.dual_emac) { - struct cpsw_slave *slave = cpsw->slaves + priv->emac_port; - - cpsw_ale_add_mcast(cpsw->ale, addr, ALE_PORT_HOST, - ALE_VLAN, slave->port_vlan, 0); - return; - } - - cpsw_ale_add_mcast(cpsw->ale, addr, ALE_ALL_PORTS, 0, 0, 0); -} - static void cpsw_set_promiscious(struct net_device *ndev, bool enable) { struct cpsw_common *cpsw = ndev_to_cpsw(ndev); @@ -640,7 +625,7 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) /* Clear all mcast from ALE */ cpsw_ale_flush_multicast(ale, ALE_ALL_PORTS, -1); - __dev_mc_unsync(ndev, NULL); + __hw_addr_ref_unsync_dev(&ndev->mc, ndev, NULL); /* Flood All Unicast Packets to Host port */ cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1); @@ -661,29 +646,148 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) } } -static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr) +struct addr_sync_ctx { + struct net_device *ndev; + const u8 *addr; /* address to be synched */ + int consumed; /* number of address instances */ + int flush; /* flush flag */ +}; + +/** + * cpsw_set_mc - adds multicast entry to the table if it's not added or deletes + * if it's not deleted + * @ndev: device to sync + * @addr: address to be added or deleted + * @vid: vlan id, if vid < 0 set/unset address for real device + * @add: add address if the flag is set or remove otherwise + */ +static int cpsw_set_mc(struct net_device *ndev, const u8 *addr, + int vid, int add) { struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + int mask, flags, ret; + + if (vid < 0) { + if (cpsw->data.dual_emac) + vid = cpsw->slaves[priv->emac_port].port_vlan; + else + vid = 0; + } + + mask = cpsw->data.dual_emac ? ALE_PORT_HOST : ALE_ALL_PORTS; + flags = vid ? ALE_VLAN : 0; + + if (add) + ret = cpsw_ale_add_mcast(cpsw->ale, addr, mask, flags, vid, 0); + else + ret = cpsw_ale_del_mcast(cpsw->ale, addr, 0, flags, vid); + + return ret; +} + +static int cpsw_update_vlan_mc(struct net_device *vdev, int vid, void *ctx) +{ + struct addr_sync_ctx *sync_ctx = ctx; + struct netdev_hw_addr *ha; + int found = 0, ret = 0; + + if (!vdev || !(vdev->flags & IFF_UP)) + return 0; + + /* vlan address is relevant if its sync_cnt != 0 */ + netdev_for_each_mc_addr(ha, vdev) { + if (ether_addr_equal(ha->addr, sync_ctx->addr)) { + found = ha->sync_cnt; + break; + } + } + + if (found) + sync_ctx->consumed++; + + if (sync_ctx->flush) { + if (!found) + cpsw_set_mc(sync_ctx->ndev, sync_ctx->addr, vid, 0); + return 0; + } + + if (found) + ret = cpsw_set_mc(sync_ctx->ndev, sync_ctx->addr, vid, 1); + + return ret; +} + +static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr, int num) +{ + struct addr_sync_ctx sync_ctx; + int ret; + + sync_ctx.consumed = 0; + sync_ctx.addr = addr; + sync_ctx.ndev = ndev; + sync_ctx.flush = 0; + + ret = vlan_for_each(ndev, cpsw_update_vlan_mc, &sync_ctx); + if (sync_ctx.consumed < num && !ret) + ret = cpsw_set_mc(ndev, addr, -1, 1); + + return ret; +} + +static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr, int num) +{ + struct addr_sync_ctx sync_ctx; + + sync_ctx.consumed = 0; + sync_ctx.addr = addr; + sync_ctx.ndev = ndev; + sync_ctx.flush = 1; + + vlan_for_each(ndev, cpsw_update_vlan_mc, &sync_ctx); + if (sync_ctx.consumed == num) + cpsw_set_mc(ndev, addr, -1, 0); - cpsw_add_mcast(priv, addr); return 0; } -static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr) +static int cpsw_purge_vlan_mc(struct net_device *vdev, int vid, void *ctx) { - struct cpsw_priv *priv = netdev_priv(ndev); - struct cpsw_common *cpsw = priv->cpsw; - int vid, flags; + struct addr_sync_ctx *sync_ctx = ctx; + struct netdev_hw_addr *ha; + int found = 0; - if (cpsw->data.dual_emac) { - vid = cpsw->slaves[priv->emac_port].port_vlan; - flags = ALE_VLAN; - } else { - vid = 0; - flags = 0; + if (!vdev || !(vdev->flags & IFF_UP)) + return 0; + + /* vlan address is relevant if its sync_cnt != 0 */ + netdev_for_each_mc_addr(ha, vdev) { + if (ether_addr_equal(ha->addr, sync_ctx->addr)) { + found = ha->sync_cnt; + break; + } } - cpsw_ale_del_mcast(cpsw->ale, addr, 0, flags, vid); + if (!found) + return 0; + + sync_ctx->consumed++; + cpsw_set_mc(sync_ctx->ndev, sync_ctx->addr, vid, 0); + return 0; +} + +static int cpsw_purge_all_mc(struct net_device *ndev, const u8 *addr, int num) +{ + struct addr_sync_ctx sync_ctx; + + sync_ctx.addr = addr; + sync_ctx.ndev = ndev; + sync_ctx.consumed = 0; + + vlan_for_each(ndev, cpsw_purge_vlan_mc, &sync_ctx); + if (sync_ctx.consumed < num) + cpsw_set_mc(ndev, addr, -1, 0); + return 0; } @@ -704,7 +808,9 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) /* Restore allmulti on vlans if necessary */ cpsw_ale_set_allmulti(cpsw->ale, ndev->flags & IFF_ALLMULTI); - __dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr); + /* add/remove mcast address either for real netdev or for vlan */ + __hw_addr_ref_sync_dev(&ndev->mc, ndev, cpsw_add_mc_addr, + cpsw_del_mc_addr); } static void cpsw_intr_enable(struct cpsw_common *cpsw) @@ -1964,7 +2070,7 @@ static int cpsw_ndo_stop(struct net_device *ndev) struct cpsw_common *cpsw = priv->cpsw; cpsw_info(priv, ifdown, "shutting down cpsw device\n"); - __dev_mc_unsync(priv->ndev, cpsw_del_mc_addr); + __hw_addr_ref_unsync_dev(&ndev->mc, ndev, cpsw_purge_all_mc); netif_tx_stop_all_queues(priv->ndev); netif_carrier_off(priv->ndev); @@ -2415,6 +2521,7 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, HOST_PORT_NUM, ALE_VLAN, vid); ret |= cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid); + ret |= cpsw_ale_flush_multicast(cpsw->ale, 0, vid); err: pm_runtime_put(cpsw->dev); return ret; From patchwork Thu Nov 8 20:27:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10674973 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C8AEC15E9 for ; Thu, 8 Nov 2018 20:31:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BAB242E2D8 for ; Thu, 8 Nov 2018 20:31:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF58E2E30D; Thu, 8 Nov 2018 20:31:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4B4E92E2D8 for ; Thu, 8 Nov 2018 20:31:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727316AbeKIGIU (ORCPT ); Fri, 9 Nov 2018 01:08:20 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:42826 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727341AbeKIGIL (ORCPT ); Fri, 9 Nov 2018 01:08:11 -0500 Received: by mail-lj1-f196.google.com with SMTP id f3-v6so19210584ljk.9 for ; Thu, 08 Nov 2018 12:31:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=dJ21MFheqMtGC0GP2Ri/IKr1RXrXmw8gJIrPZPUwV48=; b=Dw3rPxBiETf1OwrXIWVr1CKTjQCoEq+y9ZtYnMuSqIaqrFOfSCxGvVTrGv7Z1sCD4/ m55iGr9ygEsGTpYgcl1nTL/BdnJMy8xMuVcPe/Bl1dTFIyDctu44hqNd8yILxr14cE6n gShHhNL3x+OhAI9iObgwRZObiDPLaPiwqQUI4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=dJ21MFheqMtGC0GP2Ri/IKr1RXrXmw8gJIrPZPUwV48=; b=L3FhkKj18l4H6SnVWz2ORKyL8F/LBcFJUGF14yAW5TKZbC+Z8zYDrmMljq6DAWkZkK OkZVO5KGRcv0uhenK5uf239VZjirN+HUQawfiqyb3H2YBO/Mw6r+W5eyugvmNcZK3rAb HOmaY0+rutCHZKtnJclPugWaZ3gAf/BD1iE5+bPMVHhgBHwhl/6SxS9FqbyNeXFIUfQf J8PoWqD2e7ZjngBJuE/JK3Y/kSoFLbt4dLsUDrQC0jpuzE92ABj++y1VZfsyArAbnfSY GqIUj4qswmsJpd9hGCZtTwl1+MhwMo6BgcAhs6oXU8DD0iGYPlKZp3HFGhXqt0B/6HOl 2Veg== X-Gm-Message-State: AGRZ1gJpTSL1Biaiy1B3cfln2kMjaD6gjc7tLdfZHP8yWJ6ELZkjAdxZ k/z2cCHAbgu4gui5YS751s61iw== X-Google-Smtp-Source: AJdET5cF+fJTMI+J55l+6qvX/0ENwvb3E9xzGzbQb+jycmJNUCL7K4CcSY8UIWQuewDBWMsEipRw2A== X-Received: by 2002:a2e:8989:: with SMTP id c9-v6mr343251lji.124.1541709062298; Thu, 08 Nov 2018 12:31:02 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id w9sm809250lfc.66.2018.11.08.12.31.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Nov 2018 12:31:01 -0800 (PST) From: Ivan Khoronzhuk To: grygorii.strashko@ti.com, davem@davemloft.net Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alexander.h.duyck@intel.com, bjorn@mork.no, Ivan Khoronzhuk Subject: [PATCH v2 net-next 4/4] net: ethernet: ti: cpsw: fix vlan configuration while down/up Date: Thu, 8 Nov 2018 22:27:57 +0200 Message-Id: <20181108202757.30110-5-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> References: <20181108202757.30110-1-ivan.khoronzhuk@linaro.org> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The vlan configuration is not restored after interface donw/up sequence (if dual-emac - both interfaces). Tested on am572x EVM. Steps to check: ~# ip link add link eth1 name eth1.100 type vlan id 100 ~# ifconfig eth0 down ~# ifconfig eth1 down Try to remove vid and observe warning: ~# ip link del eth1.100 [ 739.526757] net eth1: removing vlanid 100 from vlan filter [ 739.533322] failed to kill vid 0081/100 for device eth1 This patch fixes it, restoring only vlan ALE entries and all other unicast/multicast entries are restored by system calling rx_mode ndo. Reviewed-by: Grygorii Strashko Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 0b18634d336c..9434fd5a5477 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -565,6 +565,9 @@ static const struct cpsw_stats cpsw_gstrings_ch_stats[] = { (func)(slave++, ##arg); \ } while (0) +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev, + __be16 proto, u16 vid); + static inline int cpsw_get_slave_port(u32 slave_num) { return slave_num + 1; @@ -1951,9 +1954,23 @@ static void cpsw_mqprio_resume(struct cpsw_slave *slave, struct cpsw_priv *priv) slave_write(slave, tx_prio_map, tx_prio_rg); } +static int cpsw_restore_vlans(struct net_device *vdev, int vid, void *arg) +{ + struct cpsw_priv *priv = arg; + + if (!vdev) + return 0; + + cpsw_ndo_vlan_rx_add_vid(priv->ndev, 0, vid); + return 0; +} + /* restore resources after port reset */ static void cpsw_restore(struct cpsw_priv *priv) { + /* restore vlan configurations */ + vlan_for_each(priv->ndev, cpsw_restore_vlans, priv); + /* restore MQPRIO offload */ for_each_slave(priv, cpsw_mqprio_resume, priv);