vxlan: Add vxlan_fdb_find_uc() for FDB querying
authorPetr Machata <petrm@mellanox.com>
Wed, 17 Oct 2018 08:53:24 +0000 (08:53 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2018 00:45:08 +0000 (17:45 -0700)
A switchdev-capable driver that is aware of VXLAN may need to query
VXLAN FDB. In the particular case of mlxsw, this functionality is
limited to querying UC FDBs. Those being easier to deal with than the
general case of RDST chain traversal, introduce an interface to query
specifically UC FDBs: vxlan_fdb_find_uc().

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/vxlan.h

index de5caa2f6aac58199c7d03f002845f682628a051..410eee23c50ce12247b203a82a7daf0eab8e93a8 100644 (file)
@@ -504,6 +504,46 @@ static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f,
        return NULL;
 }
 
+int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
+                     struct switchdev_notifier_vxlan_fdb_info *fdb_info)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       u8 eth_addr[ETH_ALEN + 2] = { 0 };
+       struct vxlan_rdst *rdst;
+       struct vxlan_fdb *f;
+       int rc = 0;
+
+       if (is_multicast_ether_addr(mac) ||
+           is_zero_ether_addr(mac))
+               return -EINVAL;
+
+       ether_addr_copy(eth_addr, mac);
+
+       rcu_read_lock();
+
+       f = __vxlan_find_mac(vxlan, eth_addr, vni);
+       if (!f) {
+               rc = -ENOENT;
+               goto out;
+       }
+
+       rdst = first_remote_rcu(f);
+
+       memset(fdb_info, 0, sizeof(*fdb_info));
+       fdb_info->info.dev = dev;
+       fdb_info->remote_ip = rdst->remote_ip;
+       fdb_info->remote_port = rdst->remote_port;
+       fdb_info->remote_vni = rdst->remote_vni;
+       fdb_info->remote_ifindex = rdst->remote_ifindex;
+       fdb_info->vni = vni;
+       ether_addr_copy(fdb_info->eth_addr, mac);
+
+out:
+       rcu_read_unlock();
+       return rc;
+}
+EXPORT_SYMBOL_GPL(vxlan_fdb_find_uc);
+
 /* Replace destination of unicast mac */
 static int vxlan_fdb_replace(struct vxlan_fdb *f,
                             union vxlan_addr *ip, __be16 port, __be32 vni,
index 3f00877f5edf9651ec4002c04ecc2510aa92f3a7..1828d686ac4fe4115d54dda3975c83f84c8b5b3b 100644 (file)
@@ -420,4 +420,16 @@ struct switchdev_notifier_vxlan_fdb_info {
        __be32 vni;
 };
 
+#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);
+#else
+static inline int
+vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
+                 struct switchdev_notifier_vxlan_fdb_info *fdb_info)
+{
+       return -ENOENT;
+}
+#endif
+
 #endif