diff options
author | Petr Machata <petrm@mellanox.com> | 2018-12-07 19:55:04 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-12-07 12:59:08 -0800 |
commit | 4f89f5b5353cae2e056713e823819f24cad92bc3 (patch) | |
tree | 6059aa62100cffc3add52b9a1651fa3cb6524fec | |
parent | ff23b91ce1ae686e436e9926de1fda3342ef26f8 (diff) | |
download | linux-4f89f5b5353cae2e056713e823819f24cad92bc3.tar.bz2 |
vxlan: Add vxlan_fdb_replay()
When a VXLAN device becomes relevant to a driver (such as when it is
attached to an offloaded bridge), the driver will generally need to walk
the existing FDB entries and offload them.
Add a function vxlan_fdb_replay() to call a given notifier block for
each FDB entry with a given VNI.
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>
-rw-r--r-- | drivers/net/vxlan.c | 47 | ||||
-rw-r--r-- | include/net/vxlan.h | 9 |
2 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d3db0313c97e..d9cb0d903283 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -552,6 +552,53 @@ out: } EXPORT_SYMBOL_GPL(vxlan_fdb_find_uc); +static int vxlan_fdb_notify_one(struct notifier_block *nb, + const struct vxlan_dev *vxlan, + const struct vxlan_fdb *f, + const struct vxlan_rdst *rdst) +{ + struct switchdev_notifier_vxlan_fdb_info fdb_info; + int rc; + + vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, &fdb_info); + rc = nb->notifier_call(nb, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, + &fdb_info); + return notifier_to_errno(rc); +} + +int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, + struct notifier_block *nb) +{ + struct vxlan_dev *vxlan; + struct vxlan_rdst *rdst; + struct vxlan_fdb *f; + unsigned int h; + int rc = 0; + + if (!netif_is_vxlan(dev)) + return -EINVAL; + vxlan = netdev_priv(dev); + + spin_lock_bh(&vxlan->hash_lock); + for (h = 0; h < FDB_HASH_SIZE; ++h) { + hlist_for_each_entry(f, &vxlan->fdb_head[h], hlist) { + if (f->vni == vni) { + list_for_each_entry(rdst, &f->remotes, list) { + rc = vxlan_fdb_notify_one(nb, vxlan, + f, rdst); + if (rc) + goto out; + } + } + } + } + +out: + spin_unlock_bh(&vxlan->hash_lock); + return rc; +} +EXPORT_SYMBOL_GPL(vxlan_fdb_replay); + /* Replace destination of unicast mac */ static int vxlan_fdb_replace(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, diff --git a/include/net/vxlan.h b/include/net/vxlan.h index b73c670df184..f49aa9afe598 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -427,6 +427,9 @@ struct switchdev_notifier_vxlan_fdb_info { #if IS_ENABLED(CONFIG_VXLAN) int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, struct switchdev_notifier_vxlan_fdb_info *fdb_info); +int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, + struct notifier_block *nb); + #else static inline int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, @@ -434,6 +437,12 @@ vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, { return -ENOENT; } + +static inline int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, + struct notifier_block *nb) +{ + return -EOPNOTSUPP; +} #endif #endif |