From patchwork Tue Oct 16 18:20:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10644079 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 257F115E2 for ; Tue, 16 Oct 2018 18:21:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 18E9A2A550 for ; Tue, 16 Oct 2018 18:21:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0D3F62A5E3; Tue, 16 Oct 2018 18:21:19 +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 77DBE2A58C for ; Tue, 16 Oct 2018 18:21:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727275AbeJQCM6 (ORCPT ); Tue, 16 Oct 2018 22:12:58 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:36368 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727315AbeJQCMW (ORCPT ); Tue, 16 Oct 2018 22:12:22 -0400 Received: by mail-lf1-f67.google.com with SMTP id d4-v6so17761594lfa.3 for ; Tue, 16 Oct 2018 11:20:40 -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=UY3go5N1XkoYGbYQ+I2v/woXzZQofslDCysYUjuM+2c=; b=dJH8U1PJ/BNay3RDFioWP26l0qJrNM9u6DCNd1A5aZhrVn5sRESYG4A9S8nG4bHRmR dTGIx9Pt0AEHZ1awjb/erEJo9BxfvPZN/oOY1iAgiFZSYLLkEe2S6Ey+YUFWlNpcsZpC zL8a95KcAvI9rathAbiZ9TYbzYnA5ZCn0CMPI= 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=UY3go5N1XkoYGbYQ+I2v/woXzZQofslDCysYUjuM+2c=; b=QxUXuBoRmfhXTJ8agHlUoZTZG5HX7OM7swvBeNMF375H5UKZiDZBbQU4dBP5W34f8h /5NC+QfSvNdkRYkGZ6U85c6BaKAEfp2e92pGfC27KTF/I8i3t5Y+f+wWgXlXpavnfvm4 OYec2/mltl10xXSr4S2390OcRZ0onbZ/jOzdussVzVN/o8kfxRmXiu+rCKhzq2lBvPtv YCafenFV1TCug0Co8xJCbq9oKO9hdY0r+UrKp/4zNqMcbFKxwVo7wamHsXQ8jMC04opf wvFFm8ZAAoHyptA9pgejn+PnNMU7OLBYz19z0xu/LQoepS95KX0I/qn7U/UQn0gnJEYt IJ1g== X-Gm-Message-State: ABuFfojdGJFFJXUFQQfKK4OAwr25lnfT18EhHBC32ZELz5NiXgNm/3Qo gAMeu9mHAHqOGjq4UpFr2Gq34g== X-Google-Smtp-Source: ACcGV60CZa5GeLtVgVoQw02nFMELO2YxKvKGmva2gzIymsL5pKs3TPXKw9s1rJvCd1abhcWzuxmAwA== X-Received: by 2002:a19:db84:: with SMTP id t4-v6mr7532859lfi.74.1539714039774; Tue, 16 Oct 2018 11:20:39 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id i27-v6sm3207844lfc.22.2018.10.16.11.20.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Oct 2018 11:20:38 -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, Ivan Khoronzhuk Subject: [RFC PATCH net-next 1/4] net: core: dev_addr_lists: add auxiliary func to handle reference address updates Date: Tue, 16 Oct 2018 21:20:32 +0300 Message-Id: <20181016182035.18234-2-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org> References: <20181016182035.18234-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..1385d75fe5ea 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, keep_sync; + + /* 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 */ + keep_sync = ha->refcount - ha->sync_cnt; + if (unsync && unsync(dev, ha->addr, keep_sync)) + continue; + + ha->refcount = (keep_sync << 1) + 1; + ha->sync_cnt = keep_sync; + __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; + + keep_sync = ha->refcount - ha->sync_cnt; + err = sync(dev, ha->addr, keep_sync); + if (err) + return err; + + ha->refcount = keep_sync << 1; + ha->sync_cnt = keep_sync; + } + + 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 Tue Oct 16 18:20:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10644073 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 6E47013B0 for ; Tue, 16 Oct 2018 18:21:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 630952A550 for ; Tue, 16 Oct 2018 18:21:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 56CA62A5E3; Tue, 16 Oct 2018 18:21:03 +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 D81A62A550 for ; Tue, 16 Oct 2018 18:21:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727601AbeJQCMZ (ORCPT ); Tue, 16 Oct 2018 22:12:25 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:33269 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727433AbeJQCMY (ORCPT ); Tue, 16 Oct 2018 22:12:24 -0400 Received: by mail-lf1-f68.google.com with SMTP id o21-v6so17756409lfe.0 for ; Tue, 16 Oct 2018 11:20:42 -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=qMvp12l9HpDMt+3I+o7Ztx63A+0YQDl6lBkSGcvnOGY=; b=Si90Rq1sZ31V16S2ywoKtMnwHKjTBjCvpfPLoTDD5pjncIPiQhJaQ5/skVfJEiUwQk /vL4E225IMom3GkKtza2Q2O/P0cfzc60X8dognBpB7GKSv/7RgDmK6CJOAmxmQdDz/Uf BqqNBHmdSq/oMECjFfzpYMndPPbHMYGrM9nfw= 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=qMvp12l9HpDMt+3I+o7Ztx63A+0YQDl6lBkSGcvnOGY=; b=pVpqm/8HqroiP3OsT/2VATCFK5QDrdnakHBGO5ul01+sliGndXxuPX7zcYQxs7tlng m/4Mfj1fsTZELd7IDkPcFfTbqYQZ3QyTk6aQCs4FrWY4KSDyICDwj54ZTPBAWJDvK7YI PXr3GvyqVBzKpIGY5GAeX4h530Ym8BCnaJ7BGCFfunCYzC7pYF2tDrMMeQuNnovcAOsC R32XCtOuW+/aTjyH4hnfdb3AY0Lj9whMRVRvqXJbPJUX8VqtPCq70Zuyypqz9TQPIfg6 OTcdkSMGYHSTHJRN3vS4rybJYRTcUGgVhDwggII3PvT8JYbeCsIapge3EpWJSnqWztHT x1cg== X-Gm-Message-State: ABuFfog3szmSyDDDzqw3fp/2O81cbXRjAkcdfmf3lISBTeQiLCeO+cXn kg+efI3UfVsmwhlI2fkiCNSK0g== X-Google-Smtp-Source: ACcGV636YVIqaEbfmz9GrOpTlGYH3VaxLwnCgFnnjda6yOYI2/JVPYRndNAZ+j/SnLlgWe4keGW8lg== X-Received: by 2002:a19:480c:: with SMTP id v12-v6mr13279098lfa.46.1539714041252; Tue, 16 Oct 2018 11:20:41 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id i27-v6sm3207844lfc.22.2018.10.16.11.20.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Oct 2018 11:20:40 -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, Ivan Khoronzhuk Subject: [RFC PATCH net-next 2/4] net: 8021q: vlan_core: allow use list of vlans for real device Date: Tue, 16 Oct 2018 21:20:33 +0300 Message-Id: <20181016182035.18234-3-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org> References: <20181016182035.18234-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: Signed-off-by: Ivan Khoronzhuk --- include/linux/if_vlan.h | 10 ++++++++++ net/8021q/vlan_core.c | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 83ea4df6ab81..4ae3993f7166 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,13 @@ __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) +{ +} + 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 Tue Oct 16 18:20:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10644069 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 5E0EE15E2 for ; Tue, 16 Oct 2018 18:20:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 506BB2A550 for ; Tue, 16 Oct 2018 18:20:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 433F62A5E3; Tue, 16 Oct 2018 18:20:49 +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 A1D482A550 for ; Tue, 16 Oct 2018 18:20:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727528AbeJQCM0 (ORCPT ); Tue, 16 Oct 2018 22:12:26 -0400 Received: from mail-lf1-f68.google.com ([209.85.167.68]:39283 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727531AbeJQCM0 (ORCPT ); Tue, 16 Oct 2018 22:12:26 -0400 Received: by mail-lf1-f68.google.com with SMTP id n14-v6so5884465lfe.6 for ; Tue, 16 Oct 2018 11:20:43 -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=jLFuOs1cSVmlpobA1RYDVi6svvbcni9hZ6eXt8GSdXw=; b=FIaiTraVPXrqdoxh0HtJYKo8IhE+QVgs/NViyyoegt8hW2EPcAxXZMPTuP2KuIXD88 NLSCnk4RKWh4pG8tXs4ksgTJrb0A1ldbAv9u6IzOzhhQEg/VgitiZ7OnIS1viy3ODBzh wid/HPjpypVB2SjsbdCh0RON1srP7cKDGD9yg= 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=jLFuOs1cSVmlpobA1RYDVi6svvbcni9hZ6eXt8GSdXw=; b=WoOA1gfrvn7Do7sYF+Fa38UMDfMscoqeafUKLHXy80yuc4YuvikkB5gMoG/NDPjngd s2viQ6AwfUDm0u5utvY1I0awgfv4Jxomr59hGgfk6xesD+EdPQnZDhUL2GXxWksLXwr6 8m5+Z5ecRKZT2mIavFiV6rKrPs0FAeXlXXeIbYiYPObM16GvttHstNXBOzNmWdAok6ES lW/H1JuXlySlGJsVn7mpQUOQjDhatRL7jf+hitp1+Fmn34RwBHIGxUiJsra5HqKrTR5h ppKr1Nmd0yE/e7hG4u76AWIv3mlGnGB0BaNCNfhTyPki9OarFi4CgQOkOUzV0Wdnk28f vElg== X-Gm-Message-State: ABuFfohKJP7ubp1vqEAOV/dxDALq4sRWNZ0+6Q5c7LMJrvFRErJK7f38 H5ZF/NvUiVZBJfn5ECzY70IeEg== X-Google-Smtp-Source: ACcGV63NzpZi1n2cOSAgCTOqHPxWcPrm75bVEIwRa0h+IPaSALnevFe15RFyQvo4CPlbLkMEe21mxw== X-Received: by 2002:a19:d713:: with SMTP id o19-v6mr13078188lfg.114.1539714042680; Tue, 16 Oct 2018 11:20:42 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id i27-v6sm3207844lfc.22.2018.10.16.11.20.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Oct 2018 11:20:41 -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, Ivan Khoronzhuk Subject: [RFC PATCH net-next 3/4] net: ethernet: ti: cpsw: fix vlan mcast Date: Tue, 16 Oct 2018 21:20:34 +0300 Message-Id: <20181016182035.18234-4-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org> References: <20181016182035.18234-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 only 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. Also, move device to allmulti state if no space for new mcast entries. Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 172 +++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 226be2a56c1f..5967484619d4 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); @@ -660,29 +645,153 @@ 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 sync or unsync */ + int keep_num; /* number of address instances to be kept */ + 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 ret; + + /* vlan address is relevant if it's 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->keep_num--; + + if (sync_ctx->flush) { + if (!found) + cpsw_set_mc(sync_ctx->ndev, sync_ctx->addr, vid, 0); + return ret; + } + + 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 cpsw_common *cpsw = ndev_to_cpsw(ndev); + struct addr_sync_ctx sync_ctx; + int ret; + + sync_ctx.keep_num = num; + 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.keep_num && !ret) + ret = cpsw_set_mc(ndev, addr, -1, 1); + + /* table is overflowed, set ALLMULTI */ + if (ret == -ENOMEM) + cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI); + + 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.keep_num = num; + 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.keep_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 it's 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->keep_num--; + 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.keep_num = num; + + vlan_for_each(ndev, cpsw_purge_vlan_mc, &sync_ctx); + if (sync_ctx.keep_num) + cpsw_set_mc(ndev, addr, -1, 0); + return 0; } @@ -703,7 +812,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) @@ -1963,7 +2074,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); @@ -2414,6 +2525,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 Tue Oct 16 18:20:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 10644071 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 B9B0B13B0 for ; Tue, 16 Oct 2018 18:20:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AC9D62A550 for ; Tue, 16 Oct 2018 18:20:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A12D52A5E3; Tue, 16 Oct 2018 18:20:56 +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 4B7372A550 for ; Tue, 16 Oct 2018 18:20:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727526AbeJQCM1 (ORCPT ); Tue, 16 Oct 2018 22:12:27 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:33279 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727598AbeJQCM1 (ORCPT ); Tue, 16 Oct 2018 22:12:27 -0400 Received: by mail-lf1-f67.google.com with SMTP id o21-v6so17756594lfe.0 for ; Tue, 16 Oct 2018 11:20:44 -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=ssuygcYMLn1Q3WIghGGutlJDCYEv/K27yRAinbSWkn0=; b=SVgLBgPNL/Sitz1phBzvx86rsDjysgDcl4zkZoW8vR7l04xha37TWN57++dA+Z7tbG 8a62jDyS2L1Cmn1YBDyC8OBpIl6Sy83zj1YANM8LCJN9L7KJE56gjxwSuXKVXYISoQq7 HoWglV34ppwNd8C53EhQe0LRiHB1zASMCaoqc= 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=ssuygcYMLn1Q3WIghGGutlJDCYEv/K27yRAinbSWkn0=; b=RcM6zDl7r05Bee8Z+wfbsnAwimlVhk3JAgIzMWpECHrkkUWoQgNorAzA/NZkJMSSyN eSv2GNNh88cxCZWWoT+h5iz1LLxRR0FMSsrEiBYNnJLiC+z7mfhcfiYgoQM8KgGmOIii SV6jehF8LslwHXsp6ArTtdUNDsQofYORK9ZupT6gDF+Nmrqt1kjQUZToNTgMB22XtIK2 aTdSks21PH6/AzVmCbrh5EkbnryWLjsvmlxHyJwJlXK9Cr45SM5KGCXSUYL1vBNdRyxH 87qlhQIvQ31I5FlzkzM41cn00nzDn19DWDoESq/ZEuQe2BxUQ4wIE39by+yc4KIICxbg 2FDw== X-Gm-Message-State: ABuFfoiQwgGbGHAKRb6AgWwZUfajEUQ1yZqT5kMIKIHb9fSbz11uJaZC +RQBlCob+IscvuzZfcaPQGGbiw== X-Google-Smtp-Source: ACcGV63xvagoTNoSMklmn+Vbqu7O/3oz7HBsg8rMijkZXCRqDemPgsGVYfIMKZf9bwZda16jnK+bAQ== X-Received: by 2002:a19:d3c4:: with SMTP id k187-v6mr13953987lfg.101.1539714044045; Tue, 16 Oct 2018 11:20:44 -0700 (PDT) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id i27-v6sm3207844lfc.22.2018.10.16.11.20.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Oct 2018 11:20:43 -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, Ivan Khoronzhuk Subject: [RFC PATCH net-next 4/4] net: ethernet: ti: cpsw: fix vlan configuration while down/up Date: Tue, 16 Oct 2018 21:20:35 +0300 Message-Id: <20181016182035.18234-5-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181016182035.18234-1-ivan.khoronzhuk@linaro.org> References: <20181016182035.18234-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 This is TI sdk tool, dumping all ALE entries, see they are present ~# switch-config -d ~# ifconfig eth1 up See entry for vid 100 is absent ~# switch-config -d 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. 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 5967484619d4..0b28a90b62bb 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; @@ -1955,9 +1958,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);