From patchwork Wed Oct 24 22:10: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: 10655035 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 8927F14BB for ; Wed, 24 Oct 2018 22:11:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 79B322B42E for ; Wed, 24 Oct 2018 22:11:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 77DB12B3EE; Wed, 24 Oct 2018 22:11:20 +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 4B69E2B44E for ; Wed, 24 Oct 2018 22:11:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727041AbeJYGlH (ORCPT ); Thu, 25 Oct 2018 02:41:07 -0400 Received: from mail-lf1-f65.google.com ([209.85.167.65]:35988 "EHLO mail-lf1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726236AbeJYGlG (ORCPT ); Thu, 25 Oct 2018 02:41:06 -0400 Received: by mail-lf1-f65.google.com with SMTP id h192so262039lfg.3 for ; Wed, 24 Oct 2018 15:11:14 -0700 (PDT) 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=22nZ9/bSF5a5KbPfuw41q2GQOTsW0tyvBp+WWCauFas=; b=QEJk3NJcbDjR841N9DXE0vt2Gx8cPjd1QaH1gRkrDWiGfX4XP+xrDMTStChBmqJlVC en8284wnfANYkweMtdB15juEK7tT2Cd5tMApgtF8BVFAgzhBPPJVY2fu+EXrF7BOaNYv nXuYdfr26zxvlTAu+DbdmoEPEaGaWjXifmAho= 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=22nZ9/bSF5a5KbPfuw41q2GQOTsW0tyvBp+WWCauFas=; b=D+8d7c6hLqBXFYQ47sEyCYDNMNJ1Nf/3Ni5F34W3FAWPNOYoxyRIshDlbIA5FYcuZw x/VKwCcEGXlOfCGO11UPQzFR8aOoir4B1WKgfy9CnbsBTz0+PPjk/oAGB5705aXroh9l WbtP3DeyyfzNtLYmE7egHYS5fFRC3NzTah3MtHj4bH0ETAiM9z4UufdSviUymSF2DSvz AdK8lCdTyEUmrURciuAznvpQ0SDBN+skWrxbGrXD231acKIjAD96OQI0uzyBUshhpJn3 YLXMdCa8uwVJoqPDINdAdCzQF4c17PJooECFF8oCuX/YqeC9VTFuhZvPlUXXsxAXfrzs ZaoQ== X-Gm-Message-State: AGRZ1gJvTrhbS972z1W3oMTDNE+Arg/SCFbIROmz80bw9AVwrAvOE7Ef FiBmU20cZNfdDYaShXme7WeyVg== X-Google-Smtp-Source: AJdET5f3s2Jv2dv+2tM5MRb/p9obyxQls9mbdPx4BIN1SJ0ht88Js3piwLxaY4Y53Ji8EFYlNEZt3w== X-Received: by 2002:a19:d612:: with SMTP id n18-v6mr86329lfg.4.1540419073218; Wed, 24 Oct 2018 15:11:13 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id f19-v6sm835350ljc.31.2018.10.24.15.11.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 15:11:12 -0700 (PDT) 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 net-next 1/4] net: core: dev_addr_lists: add auxiliary func to handle reference address updates Date: Thu, 25 Oct 2018 01:10:56 +0300 Message-Id: <20181024221059.21834-2-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024221059.21834-1-ivan.khoronzhuk@linaro.org> References: <20181024221059.21834-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 dc1d9ed33b31..de95f96a6352 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4048,6 +4048,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 Wed Oct 24 22:10: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: 10655041 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 E538014BB for ; Wed, 24 Oct 2018 22:11:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D61EA2B457 for ; Wed, 24 Oct 2018 22:11:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CBE332B3E0; Wed, 24 Oct 2018 22:11:46 +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 3F9452B40E for ; Wed, 24 Oct 2018 22:11:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727030AbeJYGlf (ORCPT ); Thu, 25 Oct 2018 02:41:35 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:33438 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727140AbeJYGlH (ORCPT ); Thu, 25 Oct 2018 02:41:07 -0400 Received: by mail-lf1-f67.google.com with SMTP id w16-v6so3091602lfc.0 for ; Wed, 24 Oct 2018 15:11:15 -0700 (PDT) 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=kt0ifiviCYm9e+arNneTDb/upc83BNkTvPy8eJnbc1A=; b=ggodCmSyrpsvTrMb5CjscBt0YsKysH+YCtsFI/jgJVBzUDXK2BPABys6p8rLaw0i2p aVqW20qx6zqgqdUjnGTxhIaHhaRXcP9YIP74tW8Tt/c4akq5mmCUZGsfZTjfADXyQyxQ 6G3hGh+dTm83w3pV9VJL+U8KALfm8X2QtQIAk= 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=kt0ifiviCYm9e+arNneTDb/upc83BNkTvPy8eJnbc1A=; b=oXd2Fki+98zWhoSbXv/oP7cz6t4Kf8slZjBEvwWU79Yewp9XrC3IzapkgbxpdjvOzt lIeLQhmr0SWWqHaxJ6rET1TyHvQkzK5D+XjYq3hlJea1zJ17wDNtHwALgV1o1sL99btr 8NOlYb3Dpb25+KRslJR7CS4zD0Q7wtagJGqwXty8TBm4+7JasJTWQT0jz7XC0ossuGOp DzB9jKKCAbaP+DmBY+g2wpHNkCARBl/m2D98ADDq6vZbSbEISeoHUtrL5kLHxgnNN7qg OuYexeFH1fKhAVobFMS2Pf4hZp7BPFf9knXBTfb+Y2m7dbbZ3xnkk8RgckoS3jR3Ol7L DKYg== X-Gm-Message-State: AGRZ1gIuF6j0hnU5NzhLN/L4Zjwkm6o17CeV2/zMp0xgbiCI2GXClsjs ujaobN0mKUZOc8SmDSVAGB7ymg== X-Google-Smtp-Source: AJdET5d0ozkN75m3uQwtPQvWSEg05ubG+jS6KC3Dg33JU0cO9IWaG+68UehrTV9t7yQsG7N592njGg== X-Received: by 2002:a19:d824:: with SMTP id p36-v6mr73317lfg.23.1540419074714; Wed, 24 Oct 2018 15:11:14 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id f19-v6sm835350ljc.31.2018.10.24.15.11.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 15:11:13 -0700 (PDT) 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 net-next 2/4] net: 8021q: vlan_core: allow use list of vlans for real device Date: Thu, 25 Oct 2018 01:10:57 +0300 Message-Id: <20181024221059.21834-3-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024221059.21834-1-ivan.khoronzhuk@linaro.org> References: <20181024221059.21834-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 83ea4df6ab81..410a14cd856c 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 Wed Oct 24 22:10:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10655037 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 B3B0314E2 for ; Wed, 24 Oct 2018 22:11:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A538E2B397 for ; Wed, 24 Oct 2018 22:11:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A37B22B3E0; Wed, 24 Oct 2018 22:11:30 +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 B85222B438 for ; Wed, 24 Oct 2018 22:11:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725829AbeJYGlL (ORCPT ); Thu, 25 Oct 2018 02:41:11 -0400 Received: from mail-lj1-f194.google.com ([209.85.208.194]:46416 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727204AbeJYGlJ (ORCPT ); Thu, 25 Oct 2018 02:41:09 -0400 Received: by mail-lj1-f194.google.com with SMTP id x3-v6so6254937lji.13 for ; Wed, 24 Oct 2018 15:11:17 -0700 (PDT) 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=PUiuww+CWdHe5/9bJQng7EShpQKWC1i8aYNDyUPA2z0=; b=hcMAbRxvifU4qmZ1MlmdQ1YmXW7gGEXYLDI+TNG0ZAbIR1lezYSvPFNmv9B8rleeO9 xR59yhPENieK27UAILqcjjZ/6UXdD8s4exbcSO9stfARzHLhUO96nIxDAsSiAbkGPPQu gq4v66g3Lf2SLzN2KgM8I08Q61tBZmP+f2CwQ= 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=PUiuww+CWdHe5/9bJQng7EShpQKWC1i8aYNDyUPA2z0=; b=iUwXvfVnptnr4WDXks9rErm6tQpCtuBFBbg3N9sdX8IpKk+NIn55lMKYbRk7z5Kfa/ T/k6fUNDTUnLv4i/CU2s4misYgVxWywu+cfi2KIVzwUn2Pvw9fmwOrr4lERRO2+2EuU+ kuQFCwkTrBBf2/lmgD7h5wBcjbKC+IzzP/oh0vHeicqVGblsiwpUAvrZGhTAkWUVlguy k+zXuMCc53BDy89rLJ2OpYYi+OdYMbbEuSLsU0KMxlFBE4RZI5WMuEi7fXojRVWOsLP9 kFBXpLV6iN/yhnINz3zAxAywjqbDWBYejm1ClNFYBnLeeai6izalOJOQ0daN5bHSSYq+ u/Rw== X-Gm-Message-State: AGRZ1gLz/y6LhNIx3EEvu49U21VbtIMQYM/5wMg3uEdE/kJkU8UQgElI /jInZRdiz2OQj7oD+exORea3pw== X-Google-Smtp-Source: AJdET5c8E5zFgzsMaQFPLpVJg3ol7wkqrjtz8ar5F02Lgr5diJZTYl6mehilYUIdvml1gyDPvChFTg== X-Received: by 2002:a2e:9355:: with SMTP id m21-v6mr2894707ljh.135.1540419076166; Wed, 24 Oct 2018 15:11:16 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id f19-v6sm835350ljc.31.2018.10.24.15.11.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 15:11:15 -0700 (PDT) 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 net-next 3/4] net: ethernet: ti: cpsw: fix vlan mcast Date: Thu, 25 Oct 2018 01:10:58 +0300 Message-Id: <20181024221059.21834-4-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024221059.21834-1-ivan.khoronzhuk@linaro.org> References: <20181024221059.21834-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. In legacy switch mode ALE table can have untracked vlan addresses, it can conflict with method used to delete vlan mcast addresses, so for switch mode, do syncing as it is, leaving ability for a user to modify table in usual for him sequence. Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 195 +++++++++++++++++++++++++++------ 1 file changed, 164 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 500f7ed8c58c..27e0a5d5ccf9 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,174 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable) } } -static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr) +static int cpsw_switch_mode(struct net_device *ndev) { - struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = ndev_to_cpsw(ndev); - cpsw_add_mcast(priv, addr); - return 0; + return !(cpsw->data.dual_emac || cpsw->data.slaves == 1); } -static int cpsw_del_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 vid, flags; + int mask, flags, ret; - if (cpsw->data.dual_emac) { - vid = cpsw->slaves[priv->emac_port].port_vlan; - flags = ALE_VLAN; - } else { - vid = 0; - flags = 0; + 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; + + /* leave for legacy switch mode untracked ALE entries */ + if (cpsw_switch_mode(ndev)) { + ret = cpsw_set_mc(ndev, addr, -1, 1); + return 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; + + /* leave for legacy switch mode untracked ALE entries */ + if (cpsw_switch_mode(ndev)) { + if (!num) + cpsw_set_mc(ndev, addr, -1, 0); + return 0; + } + + 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); + + return 0; +} + +static int cpsw_purge_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; + + 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; + + /* leave for legacy switch mode untracked ALE entries */ + if (cpsw_switch_mode(ndev)) { + cpsw_set_mc(ndev, addr, -1, 0); + return 0; + } + + 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 +834,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 +2096,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 +2547,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 Wed Oct 24 22:10:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10655039 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 00A4317F3 for ; Wed, 24 Oct 2018 22:11:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E72E22B42E for ; Wed, 24 Oct 2018 22:11:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E59FD2B451; Wed, 24 Oct 2018 22:11:30 +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 863D72B430 for ; Wed, 24 Oct 2018 22:11:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727228AbeJYGlK (ORCPT ); Thu, 25 Oct 2018 02:41:10 -0400 Received: from mail-lj1-f194.google.com ([209.85.208.194]:41800 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725829AbeJYGlK (ORCPT ); Thu, 25 Oct 2018 02:41:10 -0400 Received: by mail-lj1-f194.google.com with SMTP id u21-v6so6260526lja.8 for ; Wed, 24 Oct 2018 15:11:18 -0700 (PDT) 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=TR0EsogAgO34iqbw5VJcRTSY0YEnIrhIhjr9xb1cTvc=; b=QH4l17QXxF0XBWk+z3/tnLL5j/cXJXpS/QtaI/1w62fb7r9KYN5Y65dC1lvQACWXHM ueVvCdK+DIwDu4w4OSSTQJd2uG8mHCeyihdzEZCFpc+ejNXzhsidz66vKNXDEmB166Ae VkGtsjN/WTeRBX7gLewyC6OEaA5jgepQ+gQhs= 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=TR0EsogAgO34iqbw5VJcRTSY0YEnIrhIhjr9xb1cTvc=; b=uKeGfO5cuyF4ZHxjqK10yQN8yk5rYxTsS74DNb8vu47UzeBfq+7neqz5spWb8eCMXA vCjQrs7xrMYQHQdkaGfFS0Buu14cCUxguyj00lb31W7rQ3jUkv81+/SoojWujLynyreG wYLjyN7QL+58Oww+WG9yZlWlunUfIkdUICpU9uk/IGBEYh3jboSJHpIgkYkSwfGzJ3f+ HBQjPvI81LAThB0ST+CkbVlrMVCDl/x6ZN3o9i8EISYNNwE1Z/xEPfYqIK76zqKdwK9U iIYILvFxZ12MWQ9huz8QKFiuQ6OYIUddWYCF0BcYk9KS59SVsWOGztlZqOzHHvWRUkGe d1Zw== X-Gm-Message-State: AGRZ1gL27P/cxTLJ/Xug4ykLIEI5xPmhJ+UaoYG6X/T4OTOguN+1MojB gqcafOFBFNUPxNOuyHe+LsOTqtPxLOQ= X-Google-Smtp-Source: AJdET5fzsjx9iC+dbzwJM7VcnPoh5bc5w9V1Txr9UORGlY/GVkTTHqWFQKHmYtAxHIDws5ipPDejkA== X-Received: by 2002:a2e:1311:: with SMTP id 17-v6mr2885804ljt.70.1540419077508; Wed, 24 Oct 2018 15:11:17 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id f19-v6sm835350ljc.31.2018.10.24.15.11.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 24 Oct 2018 15:11:16 -0700 (PDT) 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 net-next 4/4] net: ethernet: ti: cpsw: fix vlan configuration while down/up Date: Thu, 25 Oct 2018 01:10:59 +0300 Message-Id: <20181024221059.21834-5-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181024221059.21834-1-ivan.khoronzhuk@linaro.org> References: <20181024221059.21834-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 27e0a5d5ccf9..a061a12e3022 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; @@ -1977,9 +1980,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);