From patchwork Tue Feb 26 18:45:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048511 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="fGy464fU"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44878n27Fxz9s71 for ; Wed, 27 Feb 2019 05:47:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729341AbfBZSrU (ORCPT ); Tue, 26 Feb 2019 13:47:20 -0500 Received: from mail-lf1-f66.google.com ([209.85.167.66]:34467 "EHLO mail-lf1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729066AbfBZSqc (ORCPT ); Tue, 26 Feb 2019 13:46:32 -0500 Received: by mail-lf1-f66.google.com with SMTP id u21so10465875lfu.1 for ; Tue, 26 Feb 2019 10:46:30 -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=DcDw7IrxqjOxRf2I8tQwrAbV9hm03kKacBat2OiHhV8=; b=fGy464fUWN2DY6G0KVw5uTrWDyl77JIUOm4Z9OOb3mluFGnXqneATfRFC2hVcqz9s5 B8vaorp5AihQbJsjaWf1QjmOeY8m9oYAARRuKhl5uJWsxitjDCw0JVt2rlc0DKp6GYQ1 gI72LtJlpTOXsk2aVhQPkRDTRVBnCV7B5KxyJJ4Qt1Iz7esmXtsKTHmjz8sA0JldvZcT FZjdvxegiVOMmf6WJJ4iia1+0E1m2TxB6nNsWxzBrhxohlMCiix/f/oF5UwdBL7fLp+2 A+bLACUJJcs+ql6tXaVfUMZ3UeMtORsXS1EuiVfrTkbhcsV+alcuxyPB45zgv5Rp9Ay2 jQkw== 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=DcDw7IrxqjOxRf2I8tQwrAbV9hm03kKacBat2OiHhV8=; b=KVOFRtZnO8847uLTGCJAuzTP+NhIClWsL+sR8j9yK/yH+VXfEHcORZgs+tqgbWD2g1 NANmhjgvcz4l9O/lZzoCdY1ROEtpppsDzuMTAjHG4DtKHeWc9809gto1CSbmP+bMXy1+ PcWvL3eXR6dVFZbvpztYJYH6IWtb3RnsJChwmQ8Z+3y2f0hkzgZRKNlA9+N5XnqxT7hT dJZ9BBNLlckCiiRL28UyD2SxDWtmxpA2wUAm4mYsadlqwcTCiVZH4+WrTODfzPqD6gef VZX+HJ4xDP3zitl+9UFTNHdqMm2vvQV0CL9Ere0YDxDpsN6UKL5WPPZiA3YW1oXA2m9o vszQ== X-Gm-Message-State: AHQUAuaRYHybZExLP3xYgBPmnRh5FBR3f8gqeQM4J74RCBZRYxVAVt5u zEkWwPDebncxN3OyFsnlrFMdOQ== X-Google-Smtp-Source: AHgI3IZRH6u20hog848kD7MkLxisz8NPypmeBXl/OAq4QHrMF09jtK7rzIw2Okf3ayAO4NqcvnjaTQ== X-Received: by 2002:a19:d411:: with SMTP id l17mr1323106lfg.112.1551206789404; Tue, 26 Feb 2019 10:46:29 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:28 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 1/6] net: core: dev_addr_lists: add VID to device address Date: Tue, 26 Feb 2019 20:45:51 +0200 Message-Id: <20190226184556.16082-2-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Despite this is supposed to be used for Ethernet VLANs, not Ethernet addresses with space for VID also can reuse this, so VID is considered as virtual ID extension, not belonging strictly to Ethernet VLAN VIDs, and overall change can be named individual virtual device filtering (IVDF). This patch adds VID tag at the end of each address. The actual reserved address size is 32 bytes. For Ethernet addresses with 6 bytes long that's possible to add tag w/o increasing address size. Thus, each address for the case has 32 - 6 = 26 bytes to hold additional info, say VID for virtual device addresses. Therefore, when addresses are synced to the address list of parent device the address list of latter can contain separate addresses for virtual devices. It allows to track separate address tables for virtual devices if they present and the device can be placed on any place of device tree as the address is propagated to to the end real device thru *_sync()/ndo_set_rx_mode() APIs. Also it simplifies handling VID addresses at real device when it supports IVDF. If parent device doesn't want to have virtual addresses in its address space the vid_len has to be 0, thus its address space is "shrunk" to the state as before this patch. For now it's 0 for every device. It allows two devices with and w/o IVDF to be part of same bond device for instance. The end real device supporting IVDF can retrieve VID tag from an address and set it for a given virtual device only. By default, vid 0 is used for real devices to distinguish it from virtual addresses. See next patches to see how it's used. Signed-off-by: Ivan Khoronzhuk --- include/linux/netdevice.h | 4 ++ net/core/dev_addr_lists.c | 124 +++++++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 23 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 58e83bd7a861..74fef35b6bec 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1660,6 +1660,7 @@ enum netdev_priv_flags { * @perm_addr: Permanent hw address * @addr_assign_type: Hw address assignment type * @addr_len: Hardware address length + * @vid_len: Virtual ID length, set in case of IVDF * @neigh_priv_len: Used in neigh_alloc() * @dev_id: Used to differentiate devices that share * the same link layer address @@ -1889,6 +1890,7 @@ struct net_device { unsigned char perm_addr[MAX_ADDR_LEN]; unsigned char addr_assign_type; unsigned char addr_len; + unsigned char vid_len; unsigned short neigh_priv_len; unsigned short dev_id; unsigned short dev_port; @@ -4141,8 +4143,10 @@ int dev_addr_init(struct net_device *dev); /* Functions used for unicast addresses handling */ int dev_uc_add(struct net_device *dev, const unsigned char *addr); +int dev_vid_uc_add(struct net_device *dev, const unsigned char *addr); int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr); int dev_uc_del(struct net_device *dev, const unsigned char *addr); +int dev_vid_uc_del(struct net_device *dev, const unsigned char *addr); int dev_uc_sync(struct net_device *to, struct net_device *from); int dev_uc_sync_multiple(struct net_device *to, struct net_device *from); void dev_uc_unsync(struct net_device *to, struct net_device *from); diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index a6723b306717..e3c80e044b8c 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -545,6 +545,26 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr, } EXPORT_SYMBOL(dev_addr_del); +static int get_addr_len(struct net_device *dev) +{ + return dev->addr_len + dev->vid_len; +} + +static int set_vid_addr(struct net_device *dev, const unsigned char *addr, + unsigned char *naddr) +{ + int i; + + if (!dev->vid_len) + return dev->addr_len; + + memcpy(naddr, addr, dev->addr_len); + for (i = 0; i < dev->vid_len; i++) + naddr[dev->addr_len + i] = 0; + + return get_addr_len(dev); +} + /* * Unicast list handling functions */ @@ -556,18 +576,22 @@ EXPORT_SYMBOL(dev_addr_del); */ int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr) { + unsigned char naddr[MAX_ADDR_LEN]; struct netdev_hw_addr *ha; - int err; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); list_for_each_entry(ha, &dev->uc.list, list) { - if (!memcmp(ha->addr, addr, dev->addr_len) && + if (!memcmp(ha->addr, addr, addr_len) && ha->type == NETDEV_HW_ADDR_T_UNICAST) { err = -EEXIST; goto out; } } - err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len, + err = __hw_addr_create_ex(&dev->uc, addr, addr_len, NETDEV_HW_ADDR_T_UNICAST, true, false); if (!err) __dev_set_rx_mode(dev); @@ -578,47 +602,89 @@ int dev_uc_add_excl(struct net_device *dev, const unsigned char *addr) EXPORT_SYMBOL(dev_uc_add_excl); /** - * dev_uc_add - Add a secondary unicast address + * dev_vid_uc_add - Add a secondary unicast address with tag * @dev: device - * @addr: address to add + * @addr: address to add, includes vid tag already * * Add a secondary unicast address to the device or increase * the reference count if it already exists. */ -int dev_uc_add(struct net_device *dev, const unsigned char *addr) +int dev_vid_uc_add(struct net_device *dev, const unsigned char *addr) { int err; netif_addr_lock_bh(dev); - err = __hw_addr_add(&dev->uc, addr, dev->addr_len, + err = __hw_addr_add(&dev->uc, addr, get_addr_len(dev), NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); netif_addr_unlock_bh(dev); return err; } +EXPORT_SYMBOL(dev_vid_uc_add); + +/** + * dev_uc_add - Add a secondary unicast address + * @dev: device + * @addr: address to add + * + * Add a secondary unicast address to the device or increase + * the reference count if it already exists. + */ +int dev_uc_add(struct net_device *dev, const unsigned char *addr) +{ + unsigned char naddr[MAX_ADDR_LEN]; + int err; + + set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; + + err = dev_vid_uc_add(dev, addr); + return err; +} EXPORT_SYMBOL(dev_uc_add); /** * dev_uc_del - Release secondary unicast address. * @dev: device - * @addr: address to delete + * @addr: address to delete, includes vid tag already * * Release reference to a secondary unicast address and remove it * from the device if the reference count drops to zero. */ -int dev_uc_del(struct net_device *dev, const unsigned char *addr) +int dev_vid_uc_del(struct net_device *dev, const unsigned char *addr) { int err; netif_addr_lock_bh(dev); - err = __hw_addr_del(&dev->uc, addr, dev->addr_len, + err = __hw_addr_del(&dev->uc, addr, get_addr_len(dev), NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); netif_addr_unlock_bh(dev); return err; } +EXPORT_SYMBOL(dev_vid_uc_del); + +/** + * dev_uc_del - Release secondary unicast address. + * @dev: device + * @addr: address to delete + * + * Release reference to a secondary unicast address and remove it + * from the device if the reference count drops to zero. + */ +int dev_uc_del(struct net_device *dev, const unsigned char *addr) +{ + unsigned char naddr[MAX_ADDR_LEN]; + int err; + + set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; + + err = dev_vid_uc_del(dev, addr); + return err; +} EXPORT_SYMBOL(dev_uc_del); /** @@ -642,7 +708,7 @@ int dev_uc_sync(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); + err = __hw_addr_sync(&to->uc, &from->uc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -672,7 +738,7 @@ int dev_uc_sync_multiple(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync_multiple(&to->uc, &from->uc, to->addr_len); + err = __hw_addr_sync_multiple(&to->uc, &from->uc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -696,7 +762,7 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from) netif_addr_lock_bh(from); netif_addr_lock_nested(to); - __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); + __hw_addr_unsync(&to->uc, &from->uc, get_addr_len(to)); __dev_set_rx_mode(to); netif_addr_unlock(to); netif_addr_unlock_bh(from); @@ -740,18 +806,22 @@ EXPORT_SYMBOL(dev_uc_init); */ int dev_mc_add_excl(struct net_device *dev, const unsigned char *addr) { + unsigned char naddr[MAX_ADDR_LEN]; struct netdev_hw_addr *ha; - int err; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); list_for_each_entry(ha, &dev->mc.list, list) { - if (!memcmp(ha->addr, addr, dev->addr_len) && + if (!memcmp(ha->addr, addr, addr_len) && ha->type == NETDEV_HW_ADDR_T_MULTICAST) { err = -EEXIST; goto out; } } - err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_create_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, true, false); if (!err) __dev_set_rx_mode(dev); @@ -764,10 +834,14 @@ EXPORT_SYMBOL(dev_mc_add_excl); static int __dev_mc_add(struct net_device *dev, const unsigned char *addr, bool global) { - int err; + unsigned char naddr[MAX_ADDR_LEN]; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); - err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_add_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, global, false, 0); if (!err) __dev_set_rx_mode(dev); @@ -804,10 +878,14 @@ EXPORT_SYMBOL(dev_mc_add_global); static int __dev_mc_del(struct net_device *dev, const unsigned char *addr, bool global) { - int err; + unsigned char naddr[MAX_ADDR_LEN]; + int addr_len, err; + + addr_len = set_vid_addr(dev, addr, naddr); + addr = dev->vid_len ? naddr : addr; netif_addr_lock_bh(dev); - err = __hw_addr_del_ex(&dev->mc, addr, dev->addr_len, + err = __hw_addr_del_ex(&dev->mc, addr, addr_len, NETDEV_HW_ADDR_T_MULTICAST, global, false); if (!err) __dev_set_rx_mode(dev); @@ -863,7 +941,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); + err = __hw_addr_sync(&to->mc, &from->mc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -893,7 +971,7 @@ int dev_mc_sync_multiple(struct net_device *to, struct net_device *from) return -EINVAL; netif_addr_lock_nested(to); - err = __hw_addr_sync_multiple(&to->mc, &from->mc, to->addr_len); + err = __hw_addr_sync_multiple(&to->mc, &from->mc, get_addr_len(to)); if (!err) __dev_set_rx_mode(to); netif_addr_unlock(to); @@ -917,7 +995,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) netif_addr_lock_bh(from); netif_addr_lock_nested(to); - __hw_addr_unsync(&to->mc, &from->mc, to->addr_len); + __hw_addr_unsync(&to->mc, &from->mc, get_addr_len(to)); __dev_set_rx_mode(to); netif_addr_unlock(to); netif_addr_unlock_bh(from); From patchwork Tue Feb 26 18:45:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048510 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CIH2QmCC"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44878h4nxHz9s7T for ; Wed, 27 Feb 2019 05:47:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729326AbfBZSrL (ORCPT ); Tue, 26 Feb 2019 13:47:11 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:34669 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729180AbfBZSqd (ORCPT ); Tue, 26 Feb 2019 13:46:33 -0500 Received: by mail-lj1-f194.google.com with SMTP id l5so11731981lje.1 for ; Tue, 26 Feb 2019 10:46:31 -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=d3cbNscAmta6sWyhidSJIEH4Xvw9ViTv0Lvbf9jCIz4=; b=CIH2QmCCZCCs32qNTeyozptPDcP9BRXpEMVOjiLuUu3k8YFfSlZYZvS3DjcZCiF6PU VLBikrm6rnmhVevf1eqgvGfW5LIN3D2PfbRPKwZeNdgGu25YUA4JI3Gst2lzwvEnhhvp Mn9qYARtk1C3EAJncK9anGk2BO421bRs46Q2kCWvffs5U6VrAZ54VuiZY4JGPD4rUv0I 4Ccc/2tSOjtjoMTmki9siTm/Ohtpf/xbLzfJYCbALe61AC8vvyvU1eEEbrzNaz4tFwXl Rz9LMYbNIykuJFCCKDRr3miheT8c5m+qqprnnrgIiXpYvhBTC0L4oF8FVW7nFQIC0s2u ausg== 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=d3cbNscAmta6sWyhidSJIEH4Xvw9ViTv0Lvbf9jCIz4=; b=uex/W69ufr1K9RfQ9ufp+HDTDfbl796vdSqfBPFOfNVD4dP/oKSnvEZ/aZvK3+4I9W /LukuK2iFZEZI11DBX68nXYfOBMNcrScTGfmXCZTPIvOwY8aW4AhyAm+jzntAKfLGW3h tSKSrIEmFmHIoxg5rGv0V9P4qqH5NnnlxnkK67RFm8bkixevJgmCfb3asSb2l7Yafhss 58SfyYwQjIKxBunr7HoCYRQpCSMpzUKSGTfyLsv8C4iYuGZtw8OooWSzawB/+eDdLTtM 8A9e6dxYDn6+9u90AUkQfRz9flZBO8uNmpYfPX0wC8eYAMxrgMJTRdSqH453JSPblWIY bEPw== X-Gm-Message-State: AHQUAubVUFXnmhzYjYSCQJNofFyB2GcE3Nzq5dwkd2Zm1LikNAZtz+Im t3TQmjv4YXg07uvO3k1+YbZoohv87Eo= X-Google-Smtp-Source: AHgI3IbnWE5M1mBdRq6irXftYOyuGKDcP+MkzG1oggdhZkp2SGSauOgxZ2bhHPYvpvd4D/72GmKU9A== X-Received: by 2002:a2e:8949:: with SMTP id b9mr14427888ljk.173.1551206790534; Tue, 26 Feb 2019 10:46:30 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:30 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 2/6] net: 8021q: vlan_dev: add vid tag to addresses of uc and mc lists Date: Tue, 26 Feb 2019 20:45:52 +0200 Message-Id: <20190226184556.16082-3-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Update vlan mc and uc addresses with VID tag while propagating addresses to lower devices, do this only if address is not synced. It allows at end driver level to distinguish addresses belonging to vlan devices. Signed-off-by: Ivan Khoronzhuk --- include/linux/if_vlan.h | 1 + net/8021q/vlan.h | 2 ++ net/8021q/vlan_core.c | 13 +++++++++++++ net/8021q/vlan_dev.c | 26 ++++++++++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 4cca4da7a6de..94657f3c483a 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -136,6 +136,7 @@ extern struct net_device *__vlan_find_dev_deep_rcu(struct net_device *real_dev, extern int vlan_for_each(struct net_device *dev, int (*action)(struct net_device *dev, int vid, void *arg), void *arg); +extern u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr); 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); diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index c46daf09a501..f083c43c508f 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -6,6 +6,8 @@ #include #include +#define NET_8021Q_VID_TSIZE 2 + /* if this changes, algorithm will have to be reworked because this * depends on completely exhausting the VLAN identifier space. Thus * it gives constant time look-up, but in many cases it wastes memory. diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index a313165e7a67..fe2ac64c13f8 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -454,6 +454,19 @@ bool vlan_uses_dev(const struct net_device *dev) } EXPORT_SYMBOL(vlan_uses_dev); +u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr) +{ + u16 vid = 0; + + if (dev->vid_len != NET_8021Q_VID_TSIZE) + return vid; + + vid = addr[dev->addr_len]; + vid |= (addr[dev->addr_len + 1] & 0xf) << 8; + return vid; +} +EXPORT_SYMBOL(vlan_dev_get_addr_vid); + static struct sk_buff *vlan_gro_receive(struct list_head *head, struct sk_buff *skb) { diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 15293c2a5dd8..93d20b1f4916 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -249,6 +249,14 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23); } +static void vlan_dev_set_addr_vid(struct net_device *vlan_dev, u8 *addr) +{ + u16 vid = vlan_dev_vlan_id(vlan_dev); + + addr[vlan_dev->addr_len] = vid & 0xff; + addr[vlan_dev->addr_len + 1] = (vid >> 8) & 0xf; +} + bool vlan_dev_inherit_address(struct net_device *dev, struct net_device *real_dev) { @@ -480,8 +488,26 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) } } +static void vlan_dev_align_addr_vid(struct net_device *vlan_dev) +{ + struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); + struct netdev_hw_addr *ha; + + if (!real_dev->vid_len) + return; + + netdev_for_each_mc_addr(ha, vlan_dev) + if (!ha->sync_cnt) + vlan_dev_set_addr_vid(vlan_dev, ha->addr); + + netdev_for_each_uc_addr(ha, vlan_dev) + if (!ha->sync_cnt) + vlan_dev_set_addr_vid(vlan_dev, ha->addr); +} + static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { + vlan_dev_align_addr_vid(vlan_dev); dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); } From patchwork Tue Feb 26 18:45:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048509 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="g74V4vHu"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44878N0bXNz9s71 for ; Wed, 27 Feb 2019 05:47:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729248AbfBZSqg (ORCPT ); Tue, 26 Feb 2019 13:46:36 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:42180 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729203AbfBZSqf (ORCPT ); Tue, 26 Feb 2019 13:46:35 -0500 Received: by mail-lj1-f194.google.com with SMTP id d14so11690170ljl.9 for ; Tue, 26 Feb 2019 10:46:32 -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=kqCaCMz7aNNRJKbo/Ni1R7ZUdFl7vBRhYGRNDh7GDoE=; b=g74V4vHubFNQ0sIH2cgAg3OSolmgq28k/qm/THOqpIAI6KTyPXD56AgCDHUG/IG+iZ iElF+NkHPkd2PpfnVQcMyx1yW/XQFBQX1aVCbXxFx/I5gkEl+jzyVJ01pdcq37zKod39 zn3FLpqhXkcAt2/6SabTaILQLCYnnoQh0RODjAggspapp0RZXzN4IAxSSU7bLWUbGco4 Q7ccjuMEBKxGOHYWMvHEl8YeXgy+IQXjxqu4TGOhMZuTbGyAjfJd6SLFxd4J6xp76Ktk IbpXp8mXyD4Hqr56uj+XywAeFzBJq60cvxIhGBlzvydsxGUJoiVEsPx4uNDC6ySV0vw2 6kxQ== 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=kqCaCMz7aNNRJKbo/Ni1R7ZUdFl7vBRhYGRNDh7GDoE=; b=MiZtIFl2PnrAqkRyEag8iTAr/0oaIApWxvwWgCj8UVpKhcJvvC6ygiK2nr7bkkVhqo qrsaSyuOcwQhKklErovG8YRaB+s2Q2VhR/ua7BqjADbH1oH9l/x6UCzZfGsAsWhK43lN gVO+NDRgThRtqVBFUD3qOOaVRUIEGXxrI9oU+aAExoTzqVN95XeIDtGJvWXYU0jmAnB1 BTp2qWe0FEXGfNJcF2Yh1b0gUv3Gq5E0KEED82RkApRBQz8ldHzvWXq2vUFBM2wCB57C woYZXvMYJYBEKmnOLOBPdG9HanIFRNK630Pp7+akVhdsK3yEGD9xR9Mmsuiqim2wf0Pe uN+w== X-Gm-Message-State: AHQUAuYJ0QII2zbUK1vuf2nv0qVCSkygg9ASGNBZK0fo2mGwzx2RDAMN 4BfddhTT/wUr06DTiXPam4sFAQ== X-Google-Smtp-Source: AHgI3Ia8IbOoKU+i0fAVsYKh8J9ZiuWgC/o10Ng33KlBakPJ1maBt7N6v/R2AvSQFuf2eg7OE5TIqQ== X-Received: by 2002:a2e:9c97:: with SMTP id x23mr14201695lji.13.1551206791798; Tue, 26 Feb 2019 10:46:31 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:31 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 3/6] net: 8021q: vlan_dev: add vid tag for vlan device own address Date: Tue, 26 Feb 2019 20:45:53 +0200 Message-Id: <20190226184556.16082-4-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The vlan device address is held separately from uc/mc lists and handled differently. The vlan dev address is bound with real device address only if it's inherited from init, in all other cases it's separate address entry in uc list. With vid set, the address becomes not inherited from real device after it's set manually as before, but is part of uc list any way, with appropriate vid tag set. If vid_len for real device is 0, the behaviour is the same as before this change, so shouldn't be any impact on systems w/o individual virtual device filtering (IVDF) enabled. This allows to control and sync vlan device address and disable concrete vlan packet income when vlan interface is down. Signed-off-by: Ivan Khoronzhuk --- net/8021q/vlan.c | 3 ++ net/8021q/vlan_dev.c | 76 +++++++++++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index dc4411165e43..9c72551a9a1e 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -295,6 +295,9 @@ static void vlan_sync_address(struct net_device *dev, if (vlan_dev_inherit_address(vlandev, dev)) goto out; + if (dev->vid_len) + goto out; + /* vlan address was different from the old address and is equal to * the new address */ if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) && diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 93d20b1f4916..634436e780f1 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -257,12 +257,61 @@ static void vlan_dev_set_addr_vid(struct net_device *vlan_dev, u8 *addr) addr[vlan_dev->addr_len + 1] = (vid >> 8) & 0xf; } +static int vlan_dev_add_addr(struct net_device *dev, u8 *addr) +{ + struct net_device *real_dev = vlan_dev_real_dev(dev); + unsigned char naddr[ETH_ALEN + NET_8021Q_VID_TSIZE]; + + if (real_dev->vid_len) { + memcpy(naddr, addr, dev->addr_len); + vlan_dev_set_addr_vid(dev, naddr); + return dev_vid_uc_add(real_dev, naddr); + } + + if (ether_addr_equal(addr, real_dev->dev_addr)) + return 0; + + return dev_uc_add(real_dev, addr); +} + +static void vlan_dev_del_addr(struct net_device *dev, u8 *addr) +{ + struct net_device *real_dev = vlan_dev_real_dev(dev); + unsigned char naddr[ETH_ALEN + NET_8021Q_VID_TSIZE]; + + if (real_dev->vid_len) { + memcpy(naddr, addr, dev->addr_len); + vlan_dev_set_addr_vid(dev, naddr); + dev_vid_uc_del(real_dev, naddr); + return; + } + + if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) + dev_uc_del(real_dev, addr); +} + +static int vlan_dev_subs_addr(struct net_device *dev, u8 *addr) +{ + int err; + + err = vlan_dev_add_addr(dev, addr); + if (err < 0) + return err; + + vlan_dev_del_addr(dev, dev->dev_addr); + return err; +} + bool vlan_dev_inherit_address(struct net_device *dev, struct net_device *real_dev) { if (dev->addr_assign_type != NET_ADDR_STOLEN) return false; + if (real_dev->vid_len) + if (vlan_dev_subs_addr(dev, real_dev->dev_addr)) + return false; + ether_addr_copy(dev->dev_addr, real_dev->dev_addr); call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); return true; @@ -278,9 +327,10 @@ static int vlan_dev_open(struct net_device *dev) !(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) return -ENETDOWN; - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) && - !vlan_dev_inherit_address(dev, real_dev)) { - err = dev_uc_add(real_dev, dev->dev_addr); + if (ether_addr_equal(dev->dev_addr, real_dev->dev_addr) || + (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) && + !vlan_dev_inherit_address(dev, real_dev))) { + err = vlan_dev_add_addr(dev, dev->dev_addr); if (err < 0) goto out; } @@ -312,8 +362,7 @@ static int vlan_dev_open(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(real_dev, -1); del_unicast: - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) - dev_uc_del(real_dev, dev->dev_addr); + vlan_dev_del_addr(dev, dev->dev_addr); out: netif_carrier_off(dev); return err; @@ -331,18 +380,14 @@ static int vlan_dev_stop(struct net_device *dev) if (dev->flags & IFF_PROMISC) dev_set_promiscuity(real_dev, -1); - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) - dev_uc_del(real_dev, dev->dev_addr); - + vlan_dev_del_addr(dev, dev->dev_addr); netif_carrier_off(dev); return 0; } static int vlan_dev_set_mac_address(struct net_device *dev, void *p) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; struct sockaddr *addr = p; - int err; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; @@ -350,15 +395,8 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p) if (!(dev->flags & IFF_UP)) goto out; - if (!ether_addr_equal(addr->sa_data, real_dev->dev_addr)) { - err = dev_uc_add(real_dev, addr->sa_data); - if (err < 0) - return err; - } - - if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) - dev_uc_del(real_dev, dev->dev_addr); - + if (vlan_dev_subs_addr(dev, addr->sa_data)) + return true; out: ether_addr_copy(dev->dev_addr, addr->sa_data); return 0; From patchwork Tue Feb 26 18:45:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048508 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="JyW6Njck"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44878J2VwTz9s7T for ; Wed, 27 Feb 2019 05:46:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729258AbfBZSqh (ORCPT ); Tue, 26 Feb 2019 13:46:37 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:38021 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729219AbfBZSqg (ORCPT ); Tue, 26 Feb 2019 13:46:36 -0500 Received: by mail-lj1-f194.google.com with SMTP id j19so11709881ljg.5 for ; Tue, 26 Feb 2019 10:46:33 -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=qB7J+KCADCQzZLQm80I7bfN1GrVDWJdsN+dYvepcy/4=; b=JyW6NjckmfTIek2crj1TZFYSEWIWmDKBFP8RbxlN+YSoxxhE4TDRGon3l5dfEJ54lo nocr1m6QLAeTaKuCI+0mX3zlacFZ1WFTAu7aB1v0uruTvz8YsLbwHKGTKKJSe0O/17yn 5wJW31P1WyW7hhzWPdK+k2/iSpbgNhk2cyVioYnOqAg5aW3O+J74PZ8MnvEEjyP5ged8 VgD0wa5Mjf9LYrkvOd/ISQqgkv6/+snyuN2p2TARZCI9ocTpQtFh7a0uMC626EZ5NZjV EzoUY9Zj96PUDO0dz4IHjZge6uo4A28X253NiNYhsvv7eEEKqN/qGkN3a1+gXtkbzzKb WWkA== 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=qB7J+KCADCQzZLQm80I7bfN1GrVDWJdsN+dYvepcy/4=; b=Ab449l2abECUONxlcXM6M3gp6sNaWmLJxT9gB5p1nk4awygMFHCzHKp02Bh6Ib8UQ2 zCnCRZnJqhCSRbJNP0QLgpGY7cXa4UUb3UJnEnmBbz3jYnV20hkLDa+Qwv6UFAnXfgAy QnG5sOw4DIfQJ4cZf5krN3B1IiYcm9Y178oKf5tUtr54G6O1juWCV2jwNLIWNpVVYs4P dy9ZOsw6F88mtpmIqLlnXcbiA7nA677HY0qRUpm6ZtsN4m1uF1xml+PMwxI1oWAk5RpP bskrOsS2XWM0MpviasDn2lS7S1hV2U7IuFKG+Es+fbNCqZP254u2habGixMGuEwPEGbL CNfA== X-Gm-Message-State: AHQUAubwQgGB80hV7Wa2Kv6ahYAhtMp6ue7zcJrEaHVpUzheMJDPS1KE TS53fa0YZzylyrpFFHJNNe+pcw== X-Google-Smtp-Source: AHgI3IYUeZthj+h1pUyn18jFgcqE+0skY/3PJmOKzRMjBKod5zboSkzIE1G7MMn8JbAsyXkPpMXxKg== X-Received: by 2002:a2e:6309:: with SMTP id x9mr13764811ljb.75.1551206792934; Tue, 26 Feb 2019 10:46:32 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:32 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 4/6] ethernet: eth: add default vid len for all ehternet kind devices Date: Tue, 26 Feb 2019 20:45:54 +0200 Message-Id: <20190226184556.16082-5-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org IVDF - individual virtual device filtering. Allows to set per vlan l2 address filters on end real network device (for unicast and for multicast) and drop redundant not expected packet income. If CONFIG_VLAN_8021Q_IVDF is enabled the following changes are applied, and only for ethernet network devices. By default every ethernet netdev needs vid len = 2 bytes to be able to hold up to 4096 vids. So set it for every eth device to be correct, except vlan devs. In order to shrink all addresses of devices above vlan, the vid_len for vlan dev = 0, as result all suckers sync their addresses to common base not taking in to account vid part (vid_len of "to" devices is important only). And only vlan device is the source of addresses with actual its vid set, propagating it to parent devices while rx_mode(). Also, don't bother those ethernet devices that at this moment are not moved to vlan addressing scheme, so while end ethernet device is created - set vid_len to 0, thus, while syncing, its address space is concatenated to one dimensional like usual, and who needs IVDF - set it to NET_8021Q_VID_TSIZE. There is another decision - is to inherit vid_len or some feature flag from end root device in order to all upper devices have vlan extended address space only if exact end real device have such capability. But I didn't, because it requires more changes and probably I'm not familiar with all places where it should be inherited, I would appreciate if someone can guid where it's applicable, then it could become a little bit more limited. Signed-off-by: Ivan Khoronzhuk --- include/linux/if_vlan.h | 1 + net/8021q/Kconfig | 12 ++++++++++++ net/8021q/vlan_core.c | 12 ++++++++++++ net/8021q/vlan_dev.c | 1 + net/ethernet/eth.c | 10 ++++++++-- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 94657f3c483a..9c914b31d208 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -137,6 +137,7 @@ extern int vlan_for_each(struct net_device *dev, int (*action)(struct net_device *dev, int vid, void *arg), void *arg); extern u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr); +extern void vlan_dev_ivdf_set(struct net_device *dev, int enable); 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); diff --git a/net/8021q/Kconfig b/net/8021q/Kconfig index 42320180967f..3e843045739c 100644 --- a/net/8021q/Kconfig +++ b/net/8021q/Kconfig @@ -38,3 +38,15 @@ config VLAN_8021Q_MVRP supersedes GVRP and is not backwards-compatible. If unsure, say N. + +config VLAN_8021Q_IVDF + bool "IVDF (Individual Virtual Device Filtering) support" + depends on VLAN_8021Q + help + Select this to enable IVDF addressing scheme support. IVDF is used + for automatic propagation of registered VLANs addresses to real end + devices. If no device supporting IVDF then disable this as it can + consume some memory in configuration with complex network device + structures to hold vlan addresses. + + If unsure, say N. diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index fe2ac64c13f8..310b6cd39f22 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -454,6 +454,18 @@ bool vlan_uses_dev(const struct net_device *dev) } EXPORT_SYMBOL(vlan_uses_dev); +void vlan_dev_ivdf_set(struct net_device *dev, int enable) +{ +#ifdef CONFIG_VLAN_8021Q_IVDF + if (enable) { + dev->vid_len = NET_8021Q_VID_TSIZE; + return; + } +#endif + dev->vid_len = 0; +} +EXPORT_SYMBOL(vlan_dev_ivdf_set); + u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr) { u16 vid = 0; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 634436e780f1..e4120aca4b9b 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -896,5 +896,6 @@ void vlan_setup(struct net_device *dev) dev->min_mtu = 0; dev->max_mtu = ETH_MAX_MTU; + vlan_dev_ivdf_set(dev, 0); eth_zero_addr(dev->broadcast); } diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index f7a3d7a171c7..95497cac24eb 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -381,6 +381,7 @@ void ether_setup(struct net_device *dev) dev->flags = IFF_BROADCAST|IFF_MULTICAST; dev->priv_flags |= IFF_TX_SKB_SHARING; + vlan_dev_ivdf_set(dev, 1); eth_broadcast_addr(dev->broadcast); } @@ -404,8 +405,13 @@ EXPORT_SYMBOL(ether_setup); struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs) { - return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN, - ether_setup, txqs, rxqs); + struct net_device *dev; + + dev = alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN, + ether_setup, txqs, rxqs); + + vlan_dev_ivdf_set(dev, 0); + return dev; } EXPORT_SYMBOL(alloc_etherdev_mqs); From patchwork Tue Feb 26 18:45:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048507 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="a56auifa"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44878D4c7pz9sBR for ; Wed, 27 Feb 2019 05:46:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729270AbfBZSqi (ORCPT ); Tue, 26 Feb 2019 13:46:38 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:34474 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729225AbfBZSqh (ORCPT ); Tue, 26 Feb 2019 13:46:37 -0500 Received: by mail-lf1-f67.google.com with SMTP id u21so10466062lfu.1 for ; Tue, 26 Feb 2019 10:46:35 -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=jy1VVBUzKtjrg74/rZ/KvvMy2H0d6BKBUN8LnXHZx/8=; b=a56auifaLwutXD9YhaJZGx66ZY4jM6tYPj22JS4j6c3jOhzqRkPxDu6bT69LvMpnF6 Iw5I7EsC/Pu4U0KrW069g5UOpPpP1uK36jMoF8xDi7qhsNgrQLYh0i2dlvZyJ8EPmEcM PLzj5cQSYO+3AXtmS8ucLgyAanEwZVyRZq3evb52jk4+tQ5a57BGCvfmZTkPOJF0VuRC 54Hc18YCDlXrDCE0BcYlCegiFQqlW5R27EMNysu8psnGxFk4F7HLMcfGWdMl8oOL9Uq3 tBUQu8ZHKKNM62Fx/yjAhVHZkgher1NJ2Fx3QDJWisPihemsKVeqAX7uWye/cKjAmv5D 1PVw== 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=jy1VVBUzKtjrg74/rZ/KvvMy2H0d6BKBUN8LnXHZx/8=; b=jN+BoManudB/eE6RtLon/KIGDSstUZ5R2XqhhSNBsjPnGD2DxE8TCgYXeh1aHBSZ61 f6/T/MTA3rkIc6olndNNwOS1TE2K9MPY1/BSLwGEzvkiObM99mLIn+mnZx8eXbg4WcPU oRTqv966n1yQ8FKPtIhpCpmi8iXFN9qbKazfhzLMRLDorHUZ+DFVYB5PoWgowT+6Qhw0 ajUK7W4use2WOOdkYjNDHaXsuITeilVt2APbdOBjeRSVm0iAeRh+yj0ADtQhCtfldraN 8tu3Fw6XMw4CKfSikyBKrUFUwCokqpFK64ZqrgHrFjHVANh52HcqhIFjIIgr3RrFtov6 C6zQ== X-Gm-Message-State: AHQUAuZQBkkCoujh4jn5gS7hLFYlfkBeItZKR3IniKBoPox8W05CT0sn +ozzBVxdl8Z89ol2a/B0UoQadQ== X-Google-Smtp-Source: AHgI3IY/4+ZOKb17l+HXYFs+GtTK4mGmSu7lJsDGVCRTUPiHs9Ot+2a6YD/d0Bz8aZvkPUgniFHR3g== X-Received: by 2002:ac2:54b6:: with SMTP id w22mr5515367lfk.132.1551206794139; Tue, 26 Feb 2019 10:46:34 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:33 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 5/6] net: ethernet: ti: cpsw: update mc filtering to use IVDF Date: Tue, 26 Feb 2019 20:45:55 +0200 Message-Id: <20190226184556.16082-6-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The cpsw can filter multicast addresses only per vlan. Thus if mcast address is set for one of them or only for real device it must be added for every created vlan consuming ALE table w/o reason. In order to simplify dispatching vlan filters, the IVDF recently added is resused. In case IVDF is disabled - mc is updated only for real device as before. The previous method is harder to reuse and vlan filtering is limited only for vlans directly connected to real netdev, so drop it in flavor of IVDF decision. Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/Kconfig | 1 + drivers/net/ethernet/ti/cpsw.c | 113 ++++---------------------------- 2 files changed, 13 insertions(+), 101 deletions(-) diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index bb126be1eb72..c99c08ece9a1 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -65,6 +65,7 @@ config TI_CPSW select TI_DAVINCI_CPDMA select TI_DAVINCI_MDIO select TI_CPSW_PHY_SEL + select VLAN_8021Q_IVDF select TI_CPSW_ALE select MFD_SYSCON select REGMAP diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index a591583d120e..fd76d1f12911 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -693,108 +693,21 @@ static int cpsw_set_mc(struct net_device *ndev, const u8 *addr, return ret; } -static int cpsw_update_vlan_mc(struct net_device *vdev, int vid, void *ctx) +static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr) { - 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); + u16 vid; + vid = vlan_dev_get_addr_vid(ndev, addr); + cpsw_set_mc(ndev, addr, vid ? vid : -1, 1); return 0; } -static int cpsw_purge_vlan_mc(struct net_device *vdev, int vid, void *ctx) +static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr) { - 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; - } - } - - 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); + u16 vid; + vid = vlan_dev_get_addr_vid(ndev, addr); + cpsw_set_mc(ndev, addr, vid ? vid : -1, 0); return 0; } @@ -816,8 +729,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) cpsw_ale_set_allmulti(cpsw->ale, ndev->flags & IFF_ALLMULTI); /* 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); + __dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr); } static void cpsw_intr_enable(struct cpsw_common *cpsw) @@ -1970,9 +1882,6 @@ 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; } @@ -2099,7 +2008,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"); - __hw_addr_ref_unsync_dev(&ndev->mc, ndev, cpsw_purge_all_mc); + __dev_mc_unsync(ndev, cpsw_del_mc_addr); netif_tx_stop_all_queues(priv->ndev); netif_carrier_off(priv->ndev); @@ -3435,6 +3344,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv) priv_sl2->emac_port = 1; cpsw->slaves[1].ndev = ndev; ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; + vlan_dev_ivdf_set(ndev, 1); ndev->netdev_ops = &cpsw_netdev_ops; ndev->ethtool_ops = &cpsw_ethtool_ops; @@ -3696,6 +3606,7 @@ static int cpsw_probe(struct platform_device *pdev) } ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; + vlan_dev_ivdf_set(ndev, 1); ndev->netdev_ops = &cpsw_netdev_ops; ndev->ethtool_ops = &cpsw_ethtool_ops; From patchwork Tue Feb 26 18:45:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 1048506 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="DU5Crjvh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 4487883YnGz9s71 for ; Wed, 27 Feb 2019 05:46:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729280AbfBZSqi (ORCPT ); Tue, 26 Feb 2019 13:46:38 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:44888 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729235AbfBZSqh (ORCPT ); Tue, 26 Feb 2019 13:46:37 -0500 Received: by mail-lj1-f196.google.com with SMTP id q128so11676801ljb.11 for ; Tue, 26 Feb 2019 10:46:36 -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=Q2OKdZERs/8jAWziFkYs/uIS+0wWtSfv5QZ7vRzwEFY=; b=DU5Crjvhw0VaZz+4UB44EKVB2DkEtQ03+SJ3M9IdzqteTvgTrTJoSqMxx9OKPvdaaP c+d2HHMpV47MLBrXSfcGo64o3/xCPa3+eqtvh9zSycDFLj0OdNjxcTZ7kGiQ6r1Fk4GB 74iAtrXQapvmFfK3QufjAUNplX2GrXG0TZCFvY6VRq+G8dnw1hpq3vusiweiD1XpSik/ EDl2orgZ33DPMghWxsqguLGIvNzNcoG00TRskHYX8mRqV+E32vRccLdsGcA65cF/zqmz zv/mWiXGhG1H8A7zyi5u9bbKs/V0FAVi2vK8OgQgK8XmY779SeINYGejHOdAb76w4/NM mmPA== 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=Q2OKdZERs/8jAWziFkYs/uIS+0wWtSfv5QZ7vRzwEFY=; b=C8wmbn8Y5rhkGX0m/9muH6YxHzReJ11x/oI8/mCEJtSssqlUrPa/eEgKB8rM7QBToY JpFAtpz5W+okpkyVfoyF+RjPXcKnQxdF6AnVgzrMaXwN8w0vTxR1WqPucBuBerkPlgPm MsJh3xZAdPUnqIoKI8jW+2pO2BdzcFEumYU86xvLANhRC+rq1PPyHUJki5s0zilJ1dn1 2/f+In5J76Q/7tr1LtJA/TOdY1K8HlQCbYBzQqmS5qCEYIw3rN4IyEHQP27Q4mqubd5S A1gvtIhVqTjDBYoezQdeAD9Ij54QoXjM7YdbtLRZxnmEJHOZzbR+CNYVhjd/GO5xdTbd 0CoQ== X-Gm-Message-State: AHQUAubRmoK9YcQfM58XC7PjVOdu+4Et5eXu7Zk4ZvElgKssh78I8RVC UFbUzH6/saUfeZFjVwcYhgmEHQ== X-Google-Smtp-Source: AHgI3IbznJ+DtGfmG9vIeDhwsmRW5wYSf1f8Je6D16idNJoVHhJDnVdKClxI0cfMkNytNeTqiGCQIQ== X-Received: by 2002:a2e:88d1:: with SMTP id a17mr14200214ljk.169.1551206795225; Tue, 26 Feb 2019 10:46:35 -0800 (PST) Received: from localhost.localdomain (59-201-94-178.pool.ukrtel.net. [178.94.201.59]) by smtp.gmail.com with ESMTPSA id s129sm3015190lja.49.2019.02.26.10.46.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Feb 2019 10:46:34 -0800 (PST) From: Ivan Khoronzhuk To: davem@davemloft.net, grygorii.strashko@ti.com, f.fainelli@gmail.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, jiri@mellanox.com, ilias.apalodimas@linaro.org, Ivan Khoronzhuk Subject: [PATCH net-next 6/6] net: ethernet: ti: cpsw: add macvlan and ucast/vlan filtering support Date: Tue, 26 Feb 2019 20:45:56 +0200 Message-Id: <20190226184556.16082-7-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> References: <20190226184556.16082-1-ivan.khoronzhuk@linaro.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The cpsw supports unicast filtering as for real as for vlan devices now, but has no flag set for that. As result, once macvlan or vlan adds new ucast address the cpsw is silently toggled to promiscuous mode. That's smth not expected, so patch fixes it. A unicast address for vlan has to be presented by vlan/unicast entry in ALE table. At this moment, while vlan address change, entry is not created in any form, even just like real device unicast used for macvlan, leaving only address inherited from real device created while vlan addition. Therefore, program unicast entries for vlans by using IVDF, it allows to add only vlan/unicast entries for vlans, omitting real device ucast entries unless they are added for macvans or so, as they are redundant for vlans and just consume forwarding table and in case of matching packet income - CPU time. So, after this patch, cpsw has ability to handle macvlan and vlan ucasts, synchronizing ucast tables for these devices with cpsw ALE table exclusively. Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 62 ++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index fd76d1f12911..c6d5ddc05299 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -693,6 +693,31 @@ static int cpsw_set_mc(struct net_device *ndev, const u8 *addr, return ret; } +static int cpsw_set_uc(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 flags, port, ret; + + if (vid < 0) { + if (cpsw->data.dual_emac) + vid = cpsw->slaves[priv->emac_port].port_vlan; + else + vid = 0; + } + + port = HOST_PORT_NUM; + flags = vid ? ALE_VLAN : 0; + + if (add) + ret = cpsw_ale_add_ucast(cpsw->ale, addr, port, flags, vid); + else + ret = cpsw_ale_del_ucast(cpsw->ale, addr, port, flags, vid); + + return ret; +} + static int cpsw_add_mc_addr(struct net_device *ndev, const u8 *addr) { u16 vid; @@ -711,6 +736,24 @@ static int cpsw_del_mc_addr(struct net_device *ndev, const u8 *addr) return 0; } +static int cpsw_add_uc_addr(struct net_device *ndev, const u8 *addr) +{ + u16 vid; + + vid = vlan_dev_get_addr_vid(ndev, addr); + cpsw_set_uc(ndev, addr, vid ? vid : -1, 1); + return 0; +} + +static int cpsw_del_uc_addr(struct net_device *ndev, const u8 *addr) +{ + u16 vid; + + vid = vlan_dev_get_addr_vid(ndev, addr); + cpsw_set_uc(ndev, addr, vid ? vid : -1, 0); + return 0; +} + static void cpsw_ndo_set_rx_mode(struct net_device *ndev) { struct cpsw_common *cpsw = ndev_to_cpsw(ndev); @@ -730,6 +773,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev) /* add/remove mcast address either for real netdev or for vlan */ __dev_mc_sync(ndev, cpsw_add_mc_addr, cpsw_del_mc_addr); + __dev_uc_sync(ndev, cpsw_add_uc_addr, cpsw_del_uc_addr); } static void cpsw_intr_enable(struct cpsw_common *cpsw) @@ -2009,6 +2053,7 @@ static int cpsw_ndo_stop(struct net_device *ndev) cpsw_info(priv, ifdown, "shutting down cpsw device\n"); __dev_mc_unsync(ndev, cpsw_del_mc_addr); + __dev_uc_unsync(ndev, cpsw_del_uc_addr); netif_tx_stop_all_queues(priv->ndev); netif_carrier_off(priv->ndev); @@ -2369,10 +2414,12 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, if (ret != 0) return ret; - ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, - HOST_PORT_NUM, ALE_VLAN, vid); - if (ret != 0) - goto clean_vid; + if (!priv->ndev->vid_len) { + ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr, + HOST_PORT_NUM, ALE_VLAN, vid); + if (ret != 0) + goto clean_vid; + } ret = cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast, mcast_mask, ALE_VLAN, vid, 0); @@ -2381,8 +2428,9 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv, return 0; clean_vlan_ucast: - cpsw_ale_del_ucast(cpsw->ale, priv->mac_addr, - HOST_PORT_NUM, ALE_VLAN, vid); + if (!priv->ndev->vid_len) + cpsw_ale_del_ucast(cpsw->ale, priv->mac_addr, + HOST_PORT_NUM, ALE_VLAN, vid); clean_vid: cpsw_ale_del_vlan(cpsw->ale, vid, 0); return ret; @@ -3344,6 +3392,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv) priv_sl2->emac_port = 1; cpsw->slaves[1].ndev = ndev; ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; + ndev->priv_flags |= IFF_UNICAST_FLT; vlan_dev_ivdf_set(ndev, 1); ndev->netdev_ops = &cpsw_netdev_ops; @@ -3606,6 +3655,7 @@ static int cpsw_probe(struct platform_device *pdev) } ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX; + ndev->priv_flags |= IFF_UNICAST_FLT; vlan_dev_ivdf_set(ndev, 1); ndev->netdev_ops = &cpsw_netdev_ops;