diff options
author | Andrew Lunn <andrew@lunn.ch> | 2017-11-09 17:10:59 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-09 23:41:40 -0500 |
commit | 47d5b6db2afa766d7af85db684d0b5f092e4fc46 (patch) | |
tree | 2d710f17684c36624cffa32452369007d46cdbb8 | |
parent | 2a26028d119267a2386733dd71d256f269e70f52 (diff) |
net: bridge: Add/del switchdev object on host join/leave
When the host joins or leaves a multicast group, use switchdev to add
an object to the hardware to forward traffic for the group to the
host.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/switchdev.h | 1 | ||||
-rw-r--r-- | net/bridge/br_mdb.c | 43 | ||||
-rw-r--r-- | net/switchdev/switchdev.c | 2 |
3 files changed, 46 insertions, 0 deletions
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index d756fbe46625..39bc855d7fee 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h | |||
@@ -76,6 +76,7 @@ enum switchdev_obj_id { | |||
76 | SWITCHDEV_OBJ_ID_UNDEFINED, | 76 | SWITCHDEV_OBJ_ID_UNDEFINED, |
77 | SWITCHDEV_OBJ_ID_PORT_VLAN, | 77 | SWITCHDEV_OBJ_ID_PORT_VLAN, |
78 | SWITCHDEV_OBJ_ID_PORT_MDB, | 78 | SWITCHDEV_OBJ_ID_PORT_MDB, |
79 | SWITCHDEV_OBJ_ID_HOST_MDB, | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | struct switchdev_obj { | 82 | struct switchdev_obj { |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 702408d2a93c..b0f4c734900b 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
@@ -292,6 +292,46 @@ err: | |||
292 | kfree(priv); | 292 | kfree(priv); |
293 | } | 293 | } |
294 | 294 | ||
295 | static void br_mdb_switchdev_host_port(struct net_device *dev, | ||
296 | struct net_device *lower_dev, | ||
297 | struct br_mdb_entry *entry, int type) | ||
298 | { | ||
299 | struct switchdev_obj_port_mdb mdb = { | ||
300 | .obj = { | ||
301 | .id = SWITCHDEV_OBJ_ID_HOST_MDB, | ||
302 | .flags = SWITCHDEV_F_DEFER, | ||
303 | }, | ||
304 | .vid = entry->vid, | ||
305 | }; | ||
306 | |||
307 | if (entry->addr.proto == htons(ETH_P_IP)) | ||
308 | ip_eth_mc_map(entry->addr.u.ip4, mdb.addr); | ||
309 | #if IS_ENABLED(CONFIG_IPV6) | ||
310 | else | ||
311 | ipv6_eth_mc_map(&entry->addr.u.ip6, mdb.addr); | ||
312 | #endif | ||
313 | |||
314 | mdb.obj.orig_dev = dev; | ||
315 | switch (type) { | ||
316 | case RTM_NEWMDB: | ||
317 | switchdev_port_obj_add(lower_dev, &mdb.obj); | ||
318 | break; | ||
319 | case RTM_DELMDB: | ||
320 | switchdev_port_obj_del(lower_dev, &mdb.obj); | ||
321 | break; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | static void br_mdb_switchdev_host(struct net_device *dev, | ||
326 | struct br_mdb_entry *entry, int type) | ||
327 | { | ||
328 | struct net_device *lower_dev; | ||
329 | struct list_head *iter; | ||
330 | |||
331 | netdev_for_each_lower_dev(dev, lower_dev, iter) | ||
332 | br_mdb_switchdev_host_port(dev, lower_dev, entry, type); | ||
333 | } | ||
334 | |||
295 | static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, | 335 | static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, |
296 | struct br_mdb_entry *entry, int type) | 336 | struct br_mdb_entry *entry, int type) |
297 | { | 337 | { |
@@ -331,6 +371,9 @@ static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, | |||
331 | switchdev_port_obj_del(port_dev, &mdb.obj); | 371 | switchdev_port_obj_del(port_dev, &mdb.obj); |
332 | } | 372 | } |
333 | 373 | ||
374 | if (!p) | ||
375 | br_mdb_switchdev_host(dev, entry, type); | ||
376 | |||
334 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); | 377 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); |
335 | if (!skb) | 378 | if (!skb) |
336 | goto errout; | 379 | goto errout; |
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 0531b41d1f2d..74b9d916a58b 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -345,6 +345,8 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj) | |||
345 | return sizeof(struct switchdev_obj_port_vlan); | 345 | return sizeof(struct switchdev_obj_port_vlan); |
346 | case SWITCHDEV_OBJ_ID_PORT_MDB: | 346 | case SWITCHDEV_OBJ_ID_PORT_MDB: |
347 | return sizeof(struct switchdev_obj_port_mdb); | 347 | return sizeof(struct switchdev_obj_port_mdb); |
348 | case SWITCHDEV_OBJ_ID_HOST_MDB: | ||
349 | return sizeof(struct switchdev_obj_port_mdb); | ||
348 | default: | 350 | default: |
349 | BUG(); | 351 | BUG(); |
350 | } | 352 | } |