[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20190115194130.19896-11-f.fainelli@gmail.com>
Date: Tue, 15 Jan 2019 11:41:26 -0800
From: Florian Fainelli <f.fainelli@...il.com>
To: netdev@...r.kernel.org
Cc: Florian Fainelli <f.fainelli@...il.com>, andrew@...n.ch,
vivien.didelot@...il.com, davem@...emloft.net, idosch@...lanox.com,
jiri@...lanox.com, ilias.apalodimas@...aro.org,
ivan.khoronzhuk@...aro.org, roopa@...ulusnetworks.com,
nikolay@...ulusnetworks.com
Subject: [RFC net-next 10/14] net: vlan: Propagate MC addresses with VID through switchdev
The VLAN real device could be an Ethernet switch port and that switch
might have VLAN filtering globally enabled (because of a bridge
requesting VLAN filtering on the switch on another port) and so when
programming multicast addresses, we need the multicast filter
programming to be aware of the correct VLAN ID as well.
Ethernet drivers that do not implement switchdev_port_{add,del}
operations and do not specifically check for SWITCHDEV_OBJ_ID_HOST_MDB
are not affected by that change.
Signed-off-by: Florian Fainelli <f.fainelli@...il.com>
---
net/8021q/vlan_dev.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index b2d9c8f27cd7..ea2ef9d78dcb 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -312,6 +312,43 @@ static int vlan_dev_open(struct net_device *dev)
return err;
}
+static int vlan_dev_sync_unsync_mc_addr(struct net_device *dev,
+ const unsigned char *addr,
+ bool add)
+{
+ struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
+ struct switchdev_obj_port_mdb mdb = {
+ .obj = {
+ .orig_dev = dev,
+ .id = SWITCHDEV_OBJ_ID_HOST_MDB,
+ .flags = SWITCHDEV_F_DEFER,
+ },
+ .vid = vlan_dev_vlan_id(dev),
+ };
+ int ret = -EOPNOTSUPP;
+
+ ether_addr_copy(mdb.addr, addr);
+ if (add)
+ ret = switchdev_port_obj_add(real_dev, &mdb.obj, NULL);
+ else
+ ret = switchdev_port_obj_del(real_dev, &mdb.obj);
+
+ return ret;
+}
+
+static int vlan_dev_sync_mc_addr(struct net_device *dev,
+ const unsigned char *addr)
+{
+ return vlan_dev_sync_unsync_mc_addr(dev, addr, true);
+}
+
+static int vlan_dev_unsync_mc_addr(struct net_device *dev,
+ const unsigned char *addr)
+{
+ return vlan_dev_sync_unsync_mc_addr(dev, addr, false);
+}
+
+
static int vlan_dev_stop(struct net_device *dev)
{
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
@@ -319,6 +356,7 @@ static int vlan_dev_stop(struct net_device *dev)
dev_mc_unsync(real_dev, dev);
dev_uc_unsync(real_dev, dev);
+ __hw_addr_unsync_dev(&dev->mc, dev, vlan_dev_unsync_mc_addr);
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(real_dev, -1);
if (dev->flags & IFF_PROMISC)
@@ -483,6 +521,8 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
{
+ __hw_addr_sync_dev(&vlan_dev->mc, vlan_dev, vlan_dev_sync_mc_addr,
+ vlan_dev_unsync_mc_addr);
dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
}
--
2.17.1
Powered by blists - more mailing lists