From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ido Schimmel Subject: [PATCH net-next 05/16] vxlan: Add hardware FDB learning Date: Wed, 21 Nov 2018 08:02:39 +0000 Message-ID: <20181121080141.16676-6-idosch@mellanox.com> References: <20181121080141.16676-1-idosch@mellanox.com> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Cc: "davem@davemloft.net" , Jiri Pirko , Petr Machata , "roopa@cumulusnetworks.com" , "nikolay@cumulusnetworks.com" , "stephen@networkplumber.org" , "ivecera@redhat.com" , mlxsw , Ido Schimmel To: "netdev@vger.kernel.org" , "bridge@lists.linux-foundation.org" Return-path: Received: from mail-eopbgr20054.outbound.protection.outlook.com ([40.107.2.54]:26130 "EHLO EUR02-VE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728337AbeKUSgX (ORCPT ); Wed, 21 Nov 2018 13:36:23 -0500 In-Reply-To: <20181121080141.16676-1-idosch@mellanox.com> Content-Language: en-US Sender: netdev-owner@vger.kernel.org List-ID: From: Petr Machata In order to allow devices to signal learning events to VXLAN, introduce two new switchdev messages: SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE and SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE. Listen to these notifications in the vxlan driver. The FDB entries learned this way have an NTF_EXT_LEARNED flag, and only entries marked as such can be unlearned by the _DEL_ event. They are also immediately marked as offloaded. This is the same behavior that the bridge driver observes. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel --- drivers/net/vxlan.c | 73 ++++++++++++++++++++++++++++++++++++++++- include/net/switchdev.h | 2 ++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index b50705a50686..03ba1b56ba6d 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3923,18 +3923,89 @@ vxlan_fdb_offloaded_set(struct net_device *dev, spin_unlock_bh(&vxlan->hash_lock); } =20 +static int +vxlan_fdb_external_learn_add(struct net_device *dev, + struct switchdev_notifier_vxlan_fdb_info *fdb_info) +{ + struct vxlan_dev *vxlan =3D netdev_priv(dev); + int err; + + spin_lock_bh(&vxlan->hash_lock); + err =3D vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip, + NUD_REACHABLE, + NLM_F_CREATE | NLM_F_REPLACE, + fdb_info->remote_port, + fdb_info->vni, + fdb_info->remote_vni, + fdb_info->remote_ifindex, + NTF_USE | NTF_SELF | NTF_EXT_LEARNED, + false); + spin_unlock_bh(&vxlan->hash_lock); + + return err; +} + +static int +vxlan_fdb_external_learn_del(struct net_device *dev, + struct switchdev_notifier_vxlan_fdb_info *fdb_info) +{ + struct vxlan_dev *vxlan =3D netdev_priv(dev); + struct vxlan_fdb *f; + int err =3D 0; + + spin_lock_bh(&vxlan->hash_lock); + + f =3D vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni); + if (!f) + err =3D -ENOENT; + else if (f->flags & NTF_EXT_LEARNED) + err =3D __vxlan_fdb_delete(vxlan, fdb_info->eth_addr, + fdb_info->remote_ip, + fdb_info->remote_port, + fdb_info->vni, + fdb_info->remote_vni, + fdb_info->remote_ifindex, + false); + + spin_unlock_bh(&vxlan->hash_lock); + + return err; +} + static int vxlan_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev =3D switchdev_notifier_info_to_dev(ptr); + struct switchdev_notifier_vxlan_fdb_info *fdb_info; + int err =3D 0; =20 switch (event) { case SWITCHDEV_VXLAN_FDB_OFFLOADED: vxlan_fdb_offloaded_set(dev, ptr); break; + case SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE: + fdb_info =3D ptr; + err =3D vxlan_fdb_external_learn_add(dev, fdb_info); + if (err) { + err =3D notifier_from_errno(err); + break; + } + fdb_info->offloaded =3D true; + vxlan_fdb_offloaded_set(dev, fdb_info); + break; + case SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE: + fdb_info =3D ptr; + err =3D vxlan_fdb_external_learn_del(dev, fdb_info); + if (err) { + err =3D notifier_from_errno(err); + break; + } + fdb_info->offloaded =3D false; + vxlan_fdb_offloaded_set(dev, fdb_info); + break; } =20 - return 0; + return err; } =20 static struct notifier_block vxlan_switchdev_notifier_block __read_mostly = =3D { diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 881ecb1555bf..7b371e7c4bc6 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -146,6 +146,8 @@ enum switchdev_notifier_type { SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_OFFLOADED, =20 + SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE, + SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE, SWITCHDEV_VXLAN_FDB_OFFLOADED, --=20 2.19.1