vxlan: Add switchdev notifications
authorPetr Machata <petrm@mellanox.com>
Wed, 17 Oct 2018 08:53:22 +0000 (08:53 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2018 00:45:08 +0000 (17:45 -0700)
When offloading VXLAN devices, drivers need to know about events in
VXLAN FDB database. Since VXLAN models a bridge, it is natural to
distribute the VXLAN FDB notifications using the pre-existing switchdev
notification mechanism.

To that end, introduce two new notification types:
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE and SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE.
Introduce a new function, vxlan_fdb_switchdev_call_notifiers() to send
the new notifier types, and a struct switchdev_notifier_vxlan_fdb_info
to communicate the details of the FDB entry under consideration.

Invoke the new function from vxlan_fdb_notify().

Signed-off-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan.c
include/net/switchdev.h
include/net/vxlan.h

index 0fc2b1d82d4c185abfa8989201c98351d1e3e09c..de5caa2f6aac58199c7d03f002845f682628a051 100644 (file)
@@ -327,8 +327,8 @@ static inline size_t vxlan_nlmsg_size(void)
                + nla_total_size(sizeof(struct nda_cacheinfo));
 }
 
-static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
-                            struct vxlan_rdst *rd, int type)
+static void __vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
+                              struct vxlan_rdst *rd, int type)
 {
        struct net *net = dev_net(vxlan->dev);
        struct sk_buff *skb;
@@ -353,6 +353,48 @@ errout:
                rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 }
 
+static void vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan,
+                                              struct vxlan_fdb *fdb,
+                                              struct vxlan_rdst *rd,
+                                              bool adding)
+{
+       struct switchdev_notifier_vxlan_fdb_info info;
+       enum switchdev_notifier_type notifier_type;
+
+       if (WARN_ON(!rd))
+               return;
+
+       notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE
+                              : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE;
+
+       info = (struct switchdev_notifier_vxlan_fdb_info){
+               .remote_ip = rd->remote_ip,
+               .remote_port = rd->remote_port,
+               .remote_vni = rd->remote_vni,
+               .remote_ifindex = rd->remote_ifindex,
+               .vni = fdb->vni,
+       };
+       memcpy(info.eth_addr, fdb->eth_addr, ETH_ALEN);
+
+       call_switchdev_notifiers(notifier_type, vxlan->dev,
+                                &info.info);
+}
+
+static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
+                            struct vxlan_rdst *rd, int type)
+{
+       switch (type) {
+       case RTM_NEWNEIGH:
+               vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, true);
+               break;
+       case RTM_DELNEIGH:
+               vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, false);
+               break;
+       }
+
+       __vxlan_fdb_notify(vxlan, fdb, rd, type);
+}
+
 static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
index d574ce63bf220d1069d2d2a5fa7177496984d92f..47199a11c586827283db816a091538d666b02e4b 100644 (file)
@@ -145,6 +145,9 @@ enum switchdev_notifier_type {
        SWITCHDEV_FDB_ADD_TO_DEVICE,
        SWITCHDEV_FDB_DEL_TO_DEVICE,
        SWITCHDEV_FDB_OFFLOADED,
+
+       SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
+       SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE,
 };
 
 struct switchdev_notifier_info {
index 95227fa925e8c94953b3f33b2a08028e1b44cbe1..3f00877f5edf9651ec4002c04ecc2510aa92f3a7 100644 (file)
@@ -6,6 +6,7 @@
 #include <net/udp_tunnel.h>
 #include <net/dst_metadata.h>
 #include <net/rtnetlink.h>
+#include <net/switchdev.h>
 
 /* VXLAN protocol (RFC 7348) header:
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -409,4 +410,14 @@ static inline bool netif_is_vxlan(const struct net_device *dev)
               !strcmp(dev->rtnl_link_ops->kind, "vxlan");
 }
 
+struct switchdev_notifier_vxlan_fdb_info {
+       struct switchdev_notifier_info info; /* must be first */
+       union vxlan_addr remote_ip;
+       __be16 remote_port;
+       __be32 remote_vni;
+       u32 remote_ifindex;
+       u8 eth_addr[ETH_ALEN];
+       __be32 vni;
+};
+
 #endif