From 9a99735317866e821c75f957fc85c63d049d330c Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 17 Oct 2018 08:53:22 +0000 Subject: [PATCH] vxlan: Add switchdev notifications 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 Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- include/net/switchdev.h | 3 +++ include/net/vxlan.h | 11 +++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 0fc2b1d82d4c..de5caa2f6aac 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -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); diff --git a/include/net/switchdev.h b/include/net/switchdev.h index d574ce63bf22..47199a11c586 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -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 { diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 95227fa925e8..3f00877f5edf 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -6,6 +6,7 @@ #include #include #include +#include /* 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 -- 2.11.0