bridge: Reflect MDB entries to hardware
authorElad Raz <eladr@mellanox.com>
Sun, 10 Jan 2016 20:06:23 +0000 (21:06 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 10 Jan 2016 21:50:21 +0000 (16:50 -0500)
Offload MDB changes per port to hardware

Signed-off-by: Elad Raz <eladr@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_mdb.c

index cd8deea..30e105f 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/if_ether.h>
 #include <net/ip.h>
 #include <net/netlink.h>
+#include <net/switchdev.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6.h>
 #include <net/addrconf.h>
@@ -210,10 +211,32 @@ static inline size_t rtnl_mdb_nlmsg_size(void)
 static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry,
                            int type)
 {
+       struct switchdev_obj_port_mdb mdb = {
+               .obj = {
+                       .id = SWITCHDEV_OBJ_ID_PORT_MDB,
+                       .flags = SWITCHDEV_F_DEFER,
+               },
+               .vid = entry->vid,
+       };
+       struct net_device *port_dev;
        struct net *net = dev_net(dev);
        struct sk_buff *skb;
        int err = -ENOBUFS;
 
+       port_dev = __dev_get_by_index(net, entry->ifindex);
+       if (entry->addr.proto == htons(ETH_P_IP))
+               ip_eth_mc_map(entry->addr.u.ip4, mdb.addr);
+#if IS_ENABLED(CONFIG_IPV6)
+       else
+               ipv6_eth_mc_map(&entry->addr.u.ip6, mdb.addr);
+#endif
+
+       mdb.obj.orig_dev = port_dev;
+       if (port_dev && type == RTM_NEWMDB)
+               switchdev_port_obj_add(port_dev, &mdb.obj);
+       else if (port_dev && type == RTM_DELMDB)
+               switchdev_port_obj_del(port_dev, &mdb.obj);
+
        skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC);
        if (!skb)
                goto errout;