All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
@ 2023-10-09 10:06 ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
support for FDB flushing in bridge driver. Extend VXLAN driver to support
FDB flushing also. Add support for filtering by fields which are relevant
for VXLAN FDBs:
* Source VNI
* Nexthop ID
* 'router' flag
* Destination VNI
* Destination Port
* Destination IP

Without this set, flush for VXLAN device fails:
$ bridge fdb flush dev vx10
RTNETLINK answers: Operation not supported

With this set, such flush works with the relevant arguments, for example:
$ bridge fdb flush dev vx10 vni 5000 dst 193.2.2.1
< flush all vx10 entries with VNI 5000 and destination IP 193.2.2.1>

Some preparations are required, handle them before adding flushing support
in VXLAN driver. See more details in commit messages.

Patch set overview:
Patch #1 prepares flush policy to be used by VXLAN driver
Patches #2-#3 are preparations in VXLAN driver
Patch #4 adds an initial support for flushing in VXLAN driver
Patches #5-#9 add support for filtering by several attributes
Patch #10 adds a test for FDB flush with VXLAN
Patch #11 extends the test to check FDB flush with bridge

Amit Cohen (11):
  net: Handle bulk delete policy in bridge driver
  vxlan: vxlan_core: Make vxlan_flush() more generic for future use
  vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by
    default
  vxlan: vxlan_core: Add support for FDB flush
  vxlan: vxlan_core: Support FDB flushing by source VNI
  vxlan: vxlan_core: Support FDB flushing by nexthop ID
  vxlan: vxlan_core: Support FDB flushing by destination VNI
  vxlan: vxlan_core: Support FDB flushing by destination port
  vxlan: vxlan_core: Support FDB flushing by destination IP
  selftests: Add test cases for FDB flush with VXLAN device
  selftests: fdb_flush: Add test cases for FDB flush with bridge device

 drivers/net/vxlan/vxlan_core.c           | 207 +++++-
 include/linux/netdevice.h                |   8 +-
 net/bridge/br_fdb.c                      |  29 +-
 net/bridge/br_private.h                  |   3 +-
 net/core/rtnetlink.c                     |  27 +-
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/fdb_flush.sh | 812 +++++++++++++++++++++++
 7 files changed, 1049 insertions(+), 38 deletions(-)
 create mode 100755 tools/testing/selftests/net/fdb_flush.sh

-- 
2.40.1


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
@ 2023-10-09 10:06 ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
support for FDB flushing in bridge driver. Extend VXLAN driver to support
FDB flushing also. Add support for filtering by fields which are relevant
for VXLAN FDBs:
* Source VNI
* Nexthop ID
* 'router' flag
* Destination VNI
* Destination Port
* Destination IP

Without this set, flush for VXLAN device fails:
$ bridge fdb flush dev vx10
RTNETLINK answers: Operation not supported

With this set, such flush works with the relevant arguments, for example:
$ bridge fdb flush dev vx10 vni 5000 dst 193.2.2.1
< flush all vx10 entries with VNI 5000 and destination IP 193.2.2.1>

Some preparations are required, handle them before adding flushing support
in VXLAN driver. See more details in commit messages.

Patch set overview:
Patch #1 prepares flush policy to be used by VXLAN driver
Patches #2-#3 are preparations in VXLAN driver
Patch #4 adds an initial support for flushing in VXLAN driver
Patches #5-#9 add support for filtering by several attributes
Patch #10 adds a test for FDB flush with VXLAN
Patch #11 extends the test to check FDB flush with bridge

Amit Cohen (11):
  net: Handle bulk delete policy in bridge driver
  vxlan: vxlan_core: Make vxlan_flush() more generic for future use
  vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by
    default
  vxlan: vxlan_core: Add support for FDB flush
  vxlan: vxlan_core: Support FDB flushing by source VNI
  vxlan: vxlan_core: Support FDB flushing by nexthop ID
  vxlan: vxlan_core: Support FDB flushing by destination VNI
  vxlan: vxlan_core: Support FDB flushing by destination port
  vxlan: vxlan_core: Support FDB flushing by destination IP
  selftests: Add test cases for FDB flush with VXLAN device
  selftests: fdb_flush: Add test cases for FDB flush with bridge device

 drivers/net/vxlan/vxlan_core.c           | 207 +++++-
 include/linux/netdevice.h                |   8 +-
 net/bridge/br_fdb.c                      |  29 +-
 net/bridge/br_private.h                  |   3 +-
 net/core/rtnetlink.c                     |  27 +-
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/fdb_flush.sh | 812 +++++++++++++++++++++++
 7 files changed, 1049 insertions(+), 38 deletions(-)
 create mode 100755 tools/testing/selftests/net/fdb_flush.sh

-- 
2.40.1


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH net-next 01/11] net: Handle bulk delete policy in bridge driver
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'")
added support for FDB flushing in bridge driver. The following patches
will extend VXLAN driver to support FDB flushing as well. The netlink
message for bulk delete is shared between the drivers. With the existing
implementation, there is no way to prevent user from flushing with
attributes that are not supported per driver. For example, when VNI will
be added, user will not get an error for flush FDB entries in bridge
with VNI, although this attribute is not relevant for bridge.

As preparation for support of FDB flush in VXLAN driver, move the policy
to be handled in bridge driver, later a new policy for VXLAN will be
added in VXLAN driver. Do not pass 'vid' as part of ndo_fdb_del_bulk(),
as this field is relevant only for bridge.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 include/linux/netdevice.h |  8 ++------
 net/bridge/br_fdb.c       | 29 ++++++++++++++++++++++++-----
 net/bridge/br_private.h   |  3 +--
 net/core/rtnetlink.c      | 27 ++++++++++-----------------
 4 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e070a4540fba..17b3c0e86bb4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1290,9 +1290,7 @@ struct netdev_net_notifier {
  *		      struct net_device *dev,
  *		      const unsigned char *addr, u16 vid)
  *	Deletes the FDB entry from dev coresponding to addr.
- * int (*ndo_fdb_del_bulk)(struct ndmsg *ndm, struct nlattr *tb[],
- *			   struct net_device *dev,
- *			   u16 vid,
+ * int (*ndo_fdb_del_bulk)(struct nlmsghdr *nlh, struct net_device *dev,
  *			   struct netlink_ext_ack *extack);
  * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
  *		       struct net_device *dev, struct net_device *filter_dev,
@@ -1567,10 +1565,8 @@ struct net_device_ops {
 					       struct net_device *dev,
 					       const unsigned char *addr,
 					       u16 vid, struct netlink_ext_ack *extack);
-	int			(*ndo_fdb_del_bulk)(struct ndmsg *ndm,
-						    struct nlattr *tb[],
+	int			(*ndo_fdb_del_bulk)(struct nlmsghdr *nlh,
 						    struct net_device *dev,
-						    u16 vid,
 						    struct netlink_ext_ack *extack);
 	int			(*ndo_fdb_dump)(struct sk_buff *skb,
 						struct netlink_callback *cb,
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e69a872bfc1d..a98ad763b368 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -661,14 +661,30 @@ static int __fdb_flush_validate_ifindex(const struct net_bridge *br,
 	return 0;
 }
 
-int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
-		       struct net_device *dev, u16 vid,
+static const struct nla_policy br_fdb_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_VLAN]	= NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
+	[NDA_IFINDEX]	= NLA_POLICY_MIN(NLA_S32, 1),
+	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
+	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
+};
+
+int br_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 		       struct netlink_ext_ack *extack)
 {
-	u8 ndm_flags = ndm->ndm_flags & ~FDB_FLUSH_IGNORED_NDM_FLAGS;
-	struct net_bridge_fdb_flush_desc desc = { .vlan_id = vid };
+	struct net_bridge_fdb_flush_desc desc = {};
+	struct ndmsg *ndm = nlmsg_data(nlh);
 	struct net_bridge_port *p = NULL;
+	struct nlattr *tb[NDA_MAX + 1];
 	struct net_bridge *br;
+	u8 ndm_flags;
+	int err;
+
+	ndm_flags = ndm->ndm_flags & ~FDB_FLUSH_IGNORED_NDM_FLAGS;
+
+	err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX,
+			  br_fdb_del_bulk_policy, extack);
+	if (err)
+		return err;
 
 	if (netif_is_bridge_master(dev)) {
 		br = netdev_priv(dev);
@@ -681,6 +697,9 @@ int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
 		br = p->br;
 	}
 
+	if (tb[NDA_VLAN])
+		desc.vlan_id = nla_get_u16(tb[NDA_VLAN]);
+
 	if (ndm_flags & ~FDB_FLUSH_ALLOWED_NDM_FLAGS) {
 		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm flag bits set");
 		return -EINVAL;
@@ -703,7 +722,7 @@ int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
 		desc.flags_mask |= __ndm_flags_to_fdb_flags(ndm_flags_mask);
 	}
 	if (tb[NDA_IFINDEX]) {
-		int err, ifidx = nla_get_s32(tb[NDA_IFINDEX]);
+		int ifidx = nla_get_s32(tb[NDA_IFINDEX]);
 
 		err = __fdb_flush_validate_ifindex(br, ifidx, extack);
 		if (err)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a1f4acfa6994..cbbe35278459 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -847,8 +847,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 		  struct net_device *dev, const unsigned char *addr, u16 vid,
 		  struct netlink_ext_ack *extack);
-int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
-		       struct net_device *dev, u16 vid,
+int br_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 		       struct netlink_ext_ack *extack);
 int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
 	       const unsigned char *addr, u16 vid, u16 nlh_flags,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 7452a6d190c5..eef7f7788996 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4367,13 +4367,6 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm,
 }
 EXPORT_SYMBOL(ndo_dflt_fdb_del);
 
-static const struct nla_policy fdb_del_bulk_policy[NDA_MAX + 1] = {
-	[NDA_VLAN]	= { .type = NLA_U16 },
-	[NDA_IFINDEX]	= NLA_POLICY_MIN(NLA_S32, 1),
-	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16  },
-	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
-};
-
 static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			struct netlink_ext_ack *extack)
 {
@@ -4394,8 +4387,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 		err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX,
 					     NULL, extack);
 	} else {
-		err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX,
-				  fdb_del_bulk_policy, extack);
+		/* For bulk delete, the drivers will parse the message with
+		 * policy.
+		 */
+		err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
 	}
 	if (err < 0)
 		return err;
@@ -4418,6 +4413,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			return -EINVAL;
 		}
 		addr = nla_data(tb[NDA_LLADDR]);
+
+		err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
+		if (err)
+			return err;
 	}
 
 	if (dev->type != ARPHRD_ETHER) {
@@ -4425,10 +4424,6 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 		return -EINVAL;
 	}
 
-	err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
-	if (err)
-		return err;
-
 	err = -EOPNOTSUPP;
 
 	/* Support fdb on master device the net/bridge default case */
@@ -4442,8 +4437,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 				err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid, extack);
 		} else {
 			if (ops->ndo_fdb_del_bulk)
-				err = ops->ndo_fdb_del_bulk(ndm, tb, dev, vid,
-							    extack);
+				err = ops->ndo_fdb_del_bulk(nlh, dev, extack);
 		}
 
 		if (err)
@@ -4464,8 +4458,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			/* in case err was cleared by NTF_MASTER call */
 			err = -EOPNOTSUPP;
 			if (ops->ndo_fdb_del_bulk)
-				err = ops->ndo_fdb_del_bulk(ndm, tb, dev, vid,
-							    extack);
+				err = ops->ndo_fdb_del_bulk(nlh, dev, extack);
 		}
 
 		if (!err) {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 01/11] net: Handle bulk delete policy in bridge driver
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'")
added support for FDB flushing in bridge driver. The following patches
will extend VXLAN driver to support FDB flushing as well. The netlink
message for bulk delete is shared between the drivers. With the existing
implementation, there is no way to prevent user from flushing with
attributes that are not supported per driver. For example, when VNI will
be added, user will not get an error for flush FDB entries in bridge
with VNI, although this attribute is not relevant for bridge.

As preparation for support of FDB flush in VXLAN driver, move the policy
to be handled in bridge driver, later a new policy for VXLAN will be
added in VXLAN driver. Do not pass 'vid' as part of ndo_fdb_del_bulk(),
as this field is relevant only for bridge.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 include/linux/netdevice.h |  8 ++------
 net/bridge/br_fdb.c       | 29 ++++++++++++++++++++++++-----
 net/bridge/br_private.h   |  3 +--
 net/core/rtnetlink.c      | 27 ++++++++++-----------------
 4 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e070a4540fba..17b3c0e86bb4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1290,9 +1290,7 @@ struct netdev_net_notifier {
  *		      struct net_device *dev,
  *		      const unsigned char *addr, u16 vid)
  *	Deletes the FDB entry from dev coresponding to addr.
- * int (*ndo_fdb_del_bulk)(struct ndmsg *ndm, struct nlattr *tb[],
- *			   struct net_device *dev,
- *			   u16 vid,
+ * int (*ndo_fdb_del_bulk)(struct nlmsghdr *nlh, struct net_device *dev,
  *			   struct netlink_ext_ack *extack);
  * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
  *		       struct net_device *dev, struct net_device *filter_dev,
@@ -1567,10 +1565,8 @@ struct net_device_ops {
 					       struct net_device *dev,
 					       const unsigned char *addr,
 					       u16 vid, struct netlink_ext_ack *extack);
-	int			(*ndo_fdb_del_bulk)(struct ndmsg *ndm,
-						    struct nlattr *tb[],
+	int			(*ndo_fdb_del_bulk)(struct nlmsghdr *nlh,
 						    struct net_device *dev,
-						    u16 vid,
 						    struct netlink_ext_ack *extack);
 	int			(*ndo_fdb_dump)(struct sk_buff *skb,
 						struct netlink_callback *cb,
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e69a872bfc1d..a98ad763b368 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -661,14 +661,30 @@ static int __fdb_flush_validate_ifindex(const struct net_bridge *br,
 	return 0;
 }
 
-int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
-		       struct net_device *dev, u16 vid,
+static const struct nla_policy br_fdb_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_VLAN]	= NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
+	[NDA_IFINDEX]	= NLA_POLICY_MIN(NLA_S32, 1),
+	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
+	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
+};
+
+int br_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 		       struct netlink_ext_ack *extack)
 {
-	u8 ndm_flags = ndm->ndm_flags & ~FDB_FLUSH_IGNORED_NDM_FLAGS;
-	struct net_bridge_fdb_flush_desc desc = { .vlan_id = vid };
+	struct net_bridge_fdb_flush_desc desc = {};
+	struct ndmsg *ndm = nlmsg_data(nlh);
 	struct net_bridge_port *p = NULL;
+	struct nlattr *tb[NDA_MAX + 1];
 	struct net_bridge *br;
+	u8 ndm_flags;
+	int err;
+
+	ndm_flags = ndm->ndm_flags & ~FDB_FLUSH_IGNORED_NDM_FLAGS;
+
+	err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX,
+			  br_fdb_del_bulk_policy, extack);
+	if (err)
+		return err;
 
 	if (netif_is_bridge_master(dev)) {
 		br = netdev_priv(dev);
@@ -681,6 +697,9 @@ int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
 		br = p->br;
 	}
 
+	if (tb[NDA_VLAN])
+		desc.vlan_id = nla_get_u16(tb[NDA_VLAN]);
+
 	if (ndm_flags & ~FDB_FLUSH_ALLOWED_NDM_FLAGS) {
 		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm flag bits set");
 		return -EINVAL;
@@ -703,7 +722,7 @@ int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
 		desc.flags_mask |= __ndm_flags_to_fdb_flags(ndm_flags_mask);
 	}
 	if (tb[NDA_IFINDEX]) {
-		int err, ifidx = nla_get_s32(tb[NDA_IFINDEX]);
+		int ifidx = nla_get_s32(tb[NDA_IFINDEX]);
 
 		err = __fdb_flush_validate_ifindex(br, ifidx, extack);
 		if (err)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a1f4acfa6994..cbbe35278459 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -847,8 +847,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
 		  struct net_device *dev, const unsigned char *addr, u16 vid,
 		  struct netlink_ext_ack *extack);
-int br_fdb_delete_bulk(struct ndmsg *ndm, struct nlattr *tb[],
-		       struct net_device *dev, u16 vid,
+int br_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 		       struct netlink_ext_ack *extack);
 int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
 	       const unsigned char *addr, u16 vid, u16 nlh_flags,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 7452a6d190c5..eef7f7788996 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4367,13 +4367,6 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm,
 }
 EXPORT_SYMBOL(ndo_dflt_fdb_del);
 
-static const struct nla_policy fdb_del_bulk_policy[NDA_MAX + 1] = {
-	[NDA_VLAN]	= { .type = NLA_U16 },
-	[NDA_IFINDEX]	= NLA_POLICY_MIN(NLA_S32, 1),
-	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16  },
-	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
-};
-
 static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			struct netlink_ext_ack *extack)
 {
@@ -4394,8 +4387,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 		err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX,
 					     NULL, extack);
 	} else {
-		err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX,
-				  fdb_del_bulk_policy, extack);
+		/* For bulk delete, the drivers will parse the message with
+		 * policy.
+		 */
+		err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
 	}
 	if (err < 0)
 		return err;
@@ -4418,6 +4413,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			return -EINVAL;
 		}
 		addr = nla_data(tb[NDA_LLADDR]);
+
+		err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
+		if (err)
+			return err;
 	}
 
 	if (dev->type != ARPHRD_ETHER) {
@@ -4425,10 +4424,6 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 		return -EINVAL;
 	}
 
-	err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
-	if (err)
-		return err;
-
 	err = -EOPNOTSUPP;
 
 	/* Support fdb on master device the net/bridge default case */
@@ -4442,8 +4437,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 				err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid, extack);
 		} else {
 			if (ops->ndo_fdb_del_bulk)
-				err = ops->ndo_fdb_del_bulk(ndm, tb, dev, vid,
-							    extack);
+				err = ops->ndo_fdb_del_bulk(nlh, dev, extack);
 		}
 
 		if (err)
@@ -4464,8 +4458,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
 			/* in case err was cleared by NTF_MASTER call */
 			err = -EOPNOTSUPP;
 			if (ops->ndo_fdb_del_bulk)
-				err = ops->ndo_fdb_del_bulk(ndm, tb, dev, vid,
-							    extack);
+				err = ops->ndo_fdb_del_bulk(nlh, dev, extack);
 		}
 
 		if (!err) {
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 02/11] vxlan: vxlan_core: Make vxlan_flush() more generic for future use
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

The function vxlan_flush() gets a boolean called 'do_all' and in case
that it is false, it does not flush entries with state 'NUD_PERMANENT'
or 'NUD_NOARP'. The following patches will add support for FDB flush
with parameters from user space. Make the function more generic, so it
can be used later.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 5b5597073b00..1c58fddb7df4 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3022,8 +3022,23 @@ static int vxlan_open(struct net_device *dev)
 	return ret;
 }
 
+struct vxlan_fdb_flush_desc {
+	unsigned long                   state;
+	unsigned long			state_mask;
+};
+
+static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
+				    const struct vxlan_fdb_flush_desc *desc)
+{
+	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
+		return false;
+
+	return true;
+}
+
 /* Purge the forwarding table */
-static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
+static void vxlan_flush(struct vxlan_dev *vxlan,
+			const struct vxlan_fdb_flush_desc *desc)
 {
 	unsigned int h;
 
@@ -3034,8 +3049,10 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
 		hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
 			struct vxlan_fdb *f
 				= container_of(p, struct vxlan_fdb, hlist);
-			if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
+
+			if (!vxlan_fdb_flush_matches(f, desc))
 				continue;
+
 			/* the all_zeros_mac entry is deleted at vxlan_uninit */
 			if (is_zero_ether_addr(f->eth_addr) &&
 			    f->vni == vxlan->cfg.vni)
@@ -3050,12 +3067,16 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
 static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {
+		.state = 0,
+		.state_mask = NUD_PERMANENT | NUD_NOARP,
+	};
 
 	vxlan_multicast_leave(vxlan);
 
 	del_timer_sync(&vxlan->age_timer);
 
-	vxlan_flush(vxlan, false);
+	vxlan_flush(vxlan, &desc);
 	vxlan_sock_release(vxlan);
 
 	return 0;
@@ -4294,8 +4315,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {};
 
-	vxlan_flush(vxlan, true);
+	vxlan_flush(vxlan, &desc);
 
 	list_del(&vxlan->next);
 	unregister_netdevice_queue(dev, head);
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 02/11] vxlan: vxlan_core: Make vxlan_flush() more generic for future use
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

The function vxlan_flush() gets a boolean called 'do_all' and in case
that it is false, it does not flush entries with state 'NUD_PERMANENT'
or 'NUD_NOARP'. The following patches will add support for FDB flush
with parameters from user space. Make the function more generic, so it
can be used later.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 5b5597073b00..1c58fddb7df4 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3022,8 +3022,23 @@ static int vxlan_open(struct net_device *dev)
 	return ret;
 }
 
+struct vxlan_fdb_flush_desc {
+	unsigned long                   state;
+	unsigned long			state_mask;
+};
+
+static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
+				    const struct vxlan_fdb_flush_desc *desc)
+{
+	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
+		return false;
+
+	return true;
+}
+
 /* Purge the forwarding table */
-static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
+static void vxlan_flush(struct vxlan_dev *vxlan,
+			const struct vxlan_fdb_flush_desc *desc)
 {
 	unsigned int h;
 
@@ -3034,8 +3049,10 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
 		hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
 			struct vxlan_fdb *f
 				= container_of(p, struct vxlan_fdb, hlist);
-			if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
+
+			if (!vxlan_fdb_flush_matches(f, desc))
 				continue;
+
 			/* the all_zeros_mac entry is deleted at vxlan_uninit */
 			if (is_zero_ether_addr(f->eth_addr) &&
 			    f->vni == vxlan->cfg.vni)
@@ -3050,12 +3067,16 @@ static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
 static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {
+		.state = 0,
+		.state_mask = NUD_PERMANENT | NUD_NOARP,
+	};
 
 	vxlan_multicast_leave(vxlan);
 
 	del_timer_sync(&vxlan->age_timer);
 
-	vxlan_flush(vxlan, false);
+	vxlan_flush(vxlan, &desc);
 	vxlan_sock_release(vxlan);
 
 	return 0;
@@ -4294,8 +4315,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {};
 
-	vxlan_flush(vxlan, true);
+	vxlan_flush(vxlan, &desc);
 
 	list_del(&vxlan->next);
 	unregister_netdevice_queue(dev, head);
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 03/11] vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by default
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

Currently, the function vxlan_flush() does not flush the default FDB entry
(an entry with all_zeros_mac and default VNI), as it is deleted at
vxlan_uninit(). When this function will be used for flushing FDB entries
from user space, it will have to flush also the default entry in case that
other parameters match (e.g., VNI, flags).

Extend 'struct vxlan_fdb_flush_desc' to include an indication whether
the default entry should be flushed or not. The default value (false)
indicates to flush it, adjust all the existing callers to set
'.ignore_default_entry' to true, so the current behavior will not be
changed.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 1c58fddb7df4..958960fdc011 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3023,16 +3023,27 @@ static int vxlan_open(struct net_device *dev)
 }
 
 struct vxlan_fdb_flush_desc {
+	bool				ignore_default_entry;
 	unsigned long                   state;
 	unsigned long			state_mask;
 };
 
+static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
+				       const struct vxlan_dev *vxlan)
+{
+	return is_zero_ether_addr(f->eth_addr) && f->vni == vxlan->cfg.vni;
+}
+
 static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
+				    const struct vxlan_dev *vxlan,
 				    const struct vxlan_fdb_flush_desc *desc)
 {
 	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
 		return false;
 
+	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
+		return false;
+
 	return true;
 }
 
@@ -3050,13 +3061,9 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 			struct vxlan_fdb *f
 				= container_of(p, struct vxlan_fdb, hlist);
 
-			if (!vxlan_fdb_flush_matches(f, desc))
+			if (!vxlan_fdb_flush_matches(f, vxlan, desc))
 				continue;
 
-			/* the all_zeros_mac entry is deleted at vxlan_uninit */
-			if (is_zero_ether_addr(f->eth_addr) &&
-			    f->vni == vxlan->cfg.vni)
-				continue;
 			vxlan_fdb_destroy(vxlan, f, true, true);
 		}
 		spin_unlock_bh(&vxlan->hash_lock[h]);
@@ -3068,6 +3075,8 @@ static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_fdb_flush_desc desc = {
+		/* Default entry is deleted at vxlan_uninit. */
+		.ignore_default_entry = true,
 		.state = 0,
 		.state_mask = NUD_PERMANENT | NUD_NOARP,
 	};
@@ -4315,7 +4324,10 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
-	struct vxlan_fdb_flush_desc desc = {};
+	struct vxlan_fdb_flush_desc desc = {
+		/* Default entry is deleted at vxlan_uninit. */
+		.ignore_default_entry = true,
+	};
 
 	vxlan_flush(vxlan, &desc);
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 03/11] vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by default
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Currently, the function vxlan_flush() does not flush the default FDB entry
(an entry with all_zeros_mac and default VNI), as it is deleted at
vxlan_uninit(). When this function will be used for flushing FDB entries
from user space, it will have to flush also the default entry in case that
other parameters match (e.g., VNI, flags).

Extend 'struct vxlan_fdb_flush_desc' to include an indication whether
the default entry should be flushed or not. The default value (false)
indicates to flush it, adjust all the existing callers to set
'.ignore_default_entry' to true, so the current behavior will not be
changed.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 1c58fddb7df4..958960fdc011 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3023,16 +3023,27 @@ static int vxlan_open(struct net_device *dev)
 }
 
 struct vxlan_fdb_flush_desc {
+	bool				ignore_default_entry;
 	unsigned long                   state;
 	unsigned long			state_mask;
 };
 
+static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
+				       const struct vxlan_dev *vxlan)
+{
+	return is_zero_ether_addr(f->eth_addr) && f->vni == vxlan->cfg.vni;
+}
+
 static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
+				    const struct vxlan_dev *vxlan,
 				    const struct vxlan_fdb_flush_desc *desc)
 {
 	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
 		return false;
 
+	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
+		return false;
+
 	return true;
 }
 
@@ -3050,13 +3061,9 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 			struct vxlan_fdb *f
 				= container_of(p, struct vxlan_fdb, hlist);
 
-			if (!vxlan_fdb_flush_matches(f, desc))
+			if (!vxlan_fdb_flush_matches(f, vxlan, desc))
 				continue;
 
-			/* the all_zeros_mac entry is deleted at vxlan_uninit */
-			if (is_zero_ether_addr(f->eth_addr) &&
-			    f->vni == vxlan->cfg.vni)
-				continue;
 			vxlan_fdb_destroy(vxlan, f, true, true);
 		}
 		spin_unlock_bh(&vxlan->hash_lock[h]);
@@ -3068,6 +3075,8 @@ static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_fdb_flush_desc desc = {
+		/* Default entry is deleted at vxlan_uninit. */
+		.ignore_default_entry = true,
 		.state = 0,
 		.state_mask = NUD_PERMANENT | NUD_NOARP,
 	};
@@ -4315,7 +4324,10 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
-	struct vxlan_fdb_flush_desc desc = {};
+	struct vxlan_fdb_flush_desc desc = {
+		/* Default entry is deleted at vxlan_uninit. */
+		.ignore_default_entry = true,
+	};
 
 	vxlan_flush(vxlan, &desc);
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 04/11] vxlan: vxlan_core: Add support for FDB flush
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'")
added support for FDB flushing in bridge driver only, the VXLAN driver does
not support such flushing. Extend VXLAN driver to support FDB flushing.
In this commit, add support for flushing with state and flags, which are
the fields that supported in the bridge driver.

Note that bridge driver supports 'NTF_USE' flag, but there is no point to
support this flag for flushing as it is ignored when flags are stored.
'NTF_STICKY' is not relevant for VXLAN driver.

'NTF_ROUTER' is not supported in bridge driver for flush as it is not
relevant for bridge, add it for VXLAN.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 56 ++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 958960fdc011..0aeb973e3da7 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3026,6 +3026,8 @@ struct vxlan_fdb_flush_desc {
 	bool				ignore_default_entry;
 	unsigned long                   state;
 	unsigned long			state_mask;
+	unsigned long                   flags;
+	unsigned long			flags_mask;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3041,6 +3043,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
 		return false;
 
+	if (desc->flags_mask && (f->flags & desc->flags_mask) != desc->flags)
+		return false;
+
 	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
 		return false;
 
@@ -3070,6 +3075,56 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 	}
 }
 
+static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
+	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
+};
+
+#define VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS (NTF_MASTER | NTF_SELF)
+#define VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES (NUD_PERMANENT | NUD_NOARP)
+#define VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS (NTF_EXT_LEARNED | NTF_OFFLOADED | \
+					   NTF_ROUTER)
+
+static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
+				 struct netlink_ext_ack *extack)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {};
+	struct ndmsg *ndm = nlmsg_data(nlh);
+	struct nlattr *tb[NDA_MAX + 1];
+	u8 ndm_flags;
+	int err;
+
+	ndm_flags = ndm->ndm_flags & ~VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS;
+
+	err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, vxlan_del_bulk_policy,
+			  extack);
+	if (err)
+		return err;
+
+	if (ndm_flags & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS) {
+		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm flag bits set");
+		return -EINVAL;
+	}
+	if (ndm->ndm_state & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES) {
+		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm state bits set");
+		return -EINVAL;
+	}
+
+	desc.state = ndm->ndm_state;
+	desc.flags = ndm_flags;
+
+	if (tb[NDA_NDM_STATE_MASK])
+		desc.state_mask = nla_get_u16(tb[NDA_NDM_STATE_MASK]);
+
+	if (tb[NDA_NDM_FLAGS_MASK])
+		desc.flags_mask = nla_get_u8(tb[NDA_NDM_FLAGS_MASK]);
+
+	vxlan_flush(vxlan, &desc);
+
+	return 0;
+}
+
 /* Cleanup timer and forwarding table on shutdown */
 static int vxlan_stop(struct net_device *dev)
 {
@@ -3172,6 +3227,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = {
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_fdb_add		= vxlan_fdb_add,
 	.ndo_fdb_del		= vxlan_fdb_delete,
+	.ndo_fdb_del_bulk	= vxlan_fdb_delete_bulk,
 	.ndo_fdb_dump		= vxlan_fdb_dump,
 	.ndo_fdb_get		= vxlan_fdb_get,
 	.ndo_mdb_add		= vxlan_mdb_add,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 04/11] vxlan: vxlan_core: Add support for FDB flush
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

The merge commit 92716869375b ("Merge branch 'br-flush-filtering'")
added support for FDB flushing in bridge driver only, the VXLAN driver does
not support such flushing. Extend VXLAN driver to support FDB flushing.
In this commit, add support for flushing with state and flags, which are
the fields that supported in the bridge driver.

Note that bridge driver supports 'NTF_USE' flag, but there is no point to
support this flag for flushing as it is ignored when flags are stored.
'NTF_STICKY' is not relevant for VXLAN driver.

'NTF_ROUTER' is not supported in bridge driver for flush as it is not
relevant for bridge, add it for VXLAN.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 56 ++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 958960fdc011..0aeb973e3da7 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3026,6 +3026,8 @@ struct vxlan_fdb_flush_desc {
 	bool				ignore_default_entry;
 	unsigned long                   state;
 	unsigned long			state_mask;
+	unsigned long                   flags;
+	unsigned long			flags_mask;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3041,6 +3043,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->state_mask && (f->state & desc->state_mask) != desc->state)
 		return false;
 
+	if (desc->flags_mask && (f->flags & desc->flags_mask) != desc->flags)
+		return false;
+
 	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
 		return false;
 
@@ -3070,6 +3075,56 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 	}
 }
 
+static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
+	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
+};
+
+#define VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS (NTF_MASTER | NTF_SELF)
+#define VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES (NUD_PERMANENT | NUD_NOARP)
+#define VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS (NTF_EXT_LEARNED | NTF_OFFLOADED | \
+					   NTF_ROUTER)
+
+static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
+				 struct netlink_ext_ack *extack)
+{
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	struct vxlan_fdb_flush_desc desc = {};
+	struct ndmsg *ndm = nlmsg_data(nlh);
+	struct nlattr *tb[NDA_MAX + 1];
+	u8 ndm_flags;
+	int err;
+
+	ndm_flags = ndm->ndm_flags & ~VXLAN_FDB_FLUSH_IGNORED_NDM_FLAGS;
+
+	err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, vxlan_del_bulk_policy,
+			  extack);
+	if (err)
+		return err;
+
+	if (ndm_flags & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_FLAGS) {
+		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm flag bits set");
+		return -EINVAL;
+	}
+	if (ndm->ndm_state & ~VXLAN_FDB_FLUSH_ALLOWED_NDM_STATES) {
+		NL_SET_ERR_MSG(extack, "Unsupported fdb flush ndm state bits set");
+		return -EINVAL;
+	}
+
+	desc.state = ndm->ndm_state;
+	desc.flags = ndm_flags;
+
+	if (tb[NDA_NDM_STATE_MASK])
+		desc.state_mask = nla_get_u16(tb[NDA_NDM_STATE_MASK]);
+
+	if (tb[NDA_NDM_FLAGS_MASK])
+		desc.flags_mask = nla_get_u8(tb[NDA_NDM_FLAGS_MASK]);
+
+	vxlan_flush(vxlan, &desc);
+
+	return 0;
+}
+
 /* Cleanup timer and forwarding table on shutdown */
 static int vxlan_stop(struct net_device *dev)
 {
@@ -3172,6 +3227,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = {
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_fdb_add		= vxlan_fdb_add,
 	.ndo_fdb_del		= vxlan_fdb_delete,
+	.ndo_fdb_del_bulk	= vxlan_fdb_delete_bulk,
 	.ndo_fdb_dump		= vxlan_fdb_dump,
 	.ndo_fdb_get		= vxlan_fdb_get,
 	.ndo_mdb_add		= vxlan_mdb_add,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 05/11] vxlan: vxlan_core: Support FDB flushing by source VNI
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

Add support for flush VXLAN FDB entries by source VNI.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 0aeb973e3da7..8214db56989d 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3028,6 +3028,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long			state_mask;
 	unsigned long                   flags;
 	unsigned long			flags_mask;
+	__be32				src_vni;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3049,6 +3050,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
 		return false;
 
+	if (desc->src_vni && f->vni != desc->src_vni)
+		return false;
+
 	return true;
 }
 
@@ -3076,6 +3080,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 }
 
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3120,6 +3125,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_NDM_FLAGS_MASK])
 		desc.flags_mask = nla_get_u8(tb[NDA_NDM_FLAGS_MASK]);
 
+	if (tb[NDA_SRC_VNI])
+		desc.src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 05/11] vxlan: vxlan_core: Support FDB flushing by source VNI
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Add support for flush VXLAN FDB entries by source VNI.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 0aeb973e3da7..8214db56989d 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3028,6 +3028,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long			state_mask;
 	unsigned long                   flags;
 	unsigned long			flags_mask;
+	__be32				src_vni;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3049,6 +3050,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->ignore_default_entry && vxlan_fdb_is_default_entry(f, vxlan))
 		return false;
 
+	if (desc->src_vni && f->vni != desc->src_vni)
+		return false;
+
 	return true;
 }
 
@@ -3076,6 +3080,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 }
 
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
+	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3120,6 +3125,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_NDM_FLAGS_MASK])
 		desc.flags_mask = nla_get_u8(tb[NDA_NDM_FLAGS_MASK]);
 
+	if (tb[NDA_SRC_VNI])
+		desc.src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 06/11] vxlan: vxlan_core: Support FDB flushing by nexthop ID
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

Add support for flush VXLAN FDB entries by nexthop ID.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 8214db56989d..ec7147409d99 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3029,6 +3029,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long                   flags;
 	unsigned long			flags_mask;
 	__be32				src_vni;
+	u32				nhid;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3037,6 +3038,13 @@ static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
 	return is_zero_ether_addr(f->eth_addr) && f->vni == vxlan->cfg.vni;
 }
 
+static bool vxlan_fdb_nhid_matches(const struct vxlan_fdb *f, u32 nhid)
+{
+	struct nexthop *nh = rtnl_dereference(f->nh);
+
+	return nh && nh->id == nhid;
+}
+
 static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 				    const struct vxlan_dev *vxlan,
 				    const struct vxlan_fdb_flush_desc *desc)
@@ -3053,6 +3061,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->src_vni && f->vni != desc->src_vni)
 		return false;
 
+	if (desc->nhid && !vxlan_fdb_nhid_matches(f, desc->nhid))
+		return false;
+
 	return true;
 }
 
@@ -3081,6 +3092,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
+	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3128,6 +3140,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_SRC_VNI])
 		desc.src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
 
+	if (tb[NDA_NH_ID])
+		desc.nhid = nla_get_u32(tb[NDA_NH_ID]);
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 06/11] vxlan: vxlan_core: Support FDB flushing by nexthop ID
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Add support for flush VXLAN FDB entries by nexthop ID.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 8214db56989d..ec7147409d99 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3029,6 +3029,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long                   flags;
 	unsigned long			flags_mask;
 	__be32				src_vni;
+	u32				nhid;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3037,6 +3038,13 @@ static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
 	return is_zero_ether_addr(f->eth_addr) && f->vni == vxlan->cfg.vni;
 }
 
+static bool vxlan_fdb_nhid_matches(const struct vxlan_fdb *f, u32 nhid)
+{
+	struct nexthop *nh = rtnl_dereference(f->nh);
+
+	return nh && nh->id == nhid;
+}
+
 static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 				    const struct vxlan_dev *vxlan,
 				    const struct vxlan_fdb_flush_desc *desc)
@@ -3053,6 +3061,9 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	if (desc->src_vni && f->vni != desc->src_vni)
 		return false;
 
+	if (desc->nhid && !vxlan_fdb_nhid_matches(f, desc->nhid))
+		return false;
+
 	return true;
 }
 
@@ -3081,6 +3092,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
+	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3128,6 +3140,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_SRC_VNI])
 		desc.src_vni = cpu_to_be32(nla_get_u32(tb[NDA_SRC_VNI]));
 
+	if (tb[NDA_NH_ID])
+		desc.nhid = nla_get_u32(tb[NDA_NH_ID]);
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 07/11] vxlan: vxlan_core: Support FDB flushing by destination VNI
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen, Petr Machata

Add support for flush VXLAN FDB entries by destination VNI. FDB entry is
stored as {MAC, SRC_VNI} + remote. The destination VNI is an attribute
of the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination VNI', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 4000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.2 vni 2000 self permanent

When user flush by VNI x, only the relevant remotes will be flushed:
$ bridge fdb flush dev vx10 vni 2000

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 4000 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 51 ++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index ec7147409d99..f16328a0f9fe 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3030,6 +3030,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long			flags_mask;
 	__be32				src_vni;
 	u32				nhid;
+	__be32				vni;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3067,10 +3068,46 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	return true;
 }
 
+static bool
+vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
+{
+	return !!desc->vni;
+}
+
+static bool
+vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
+			       const struct vxlan_rdst *rd)
+{
+	if (desc->vni && rd->remote_vni != desc->vni)
+		return false;
+
+	return true;
+}
+
+static void
+vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
+			      const struct vxlan_fdb_flush_desc *desc,
+			      bool *p_destroy_fdb)
+{
+	bool remotes_flushed = false;
+	struct vxlan_rdst *rd, *tmp;
+
+	list_for_each_entry_safe(rd, tmp, &f->remotes, list) {
+		if (!vxlan_fdb_flush_remote_matches(desc, rd))
+			continue;
+
+		vxlan_fdb_dst_destroy(vxlan, f, rd, true);
+		remotes_flushed = true;
+	}
+
+	*p_destroy_fdb = remotes_flushed && list_empty(&f->remotes);
+}
+
 /* Purge the forwarding table */
 static void vxlan_flush(struct vxlan_dev *vxlan,
 			const struct vxlan_fdb_flush_desc *desc)
 {
+	bool match_remotes = vxlan_fdb_flush_should_match_remotes(desc);
 	unsigned int h;
 
 	for (h = 0; h < FDB_HASH_SIZE; ++h) {
@@ -3084,6 +3121,16 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 			if (!vxlan_fdb_flush_matches(f, vxlan, desc))
 				continue;
 
+			if (match_remotes) {
+				bool destroy_fdb = false;
+
+				vxlan_fdb_flush_match_remotes(f, vxlan, desc,
+							      &destroy_fdb);
+
+				if (!destroy_fdb)
+					continue;
+			}
+
 			vxlan_fdb_destroy(vxlan, f, true, true);
 		}
 		spin_unlock_bh(&vxlan->hash_lock[h]);
@@ -3093,6 +3140,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NH_ID]	= { .type = NLA_U32 },
+	[NDA_VNI]	= { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3143,6 +3191,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_NH_ID])
 		desc.nhid = nla_get_u32(tb[NDA_NH_ID]);
 
+	if (tb[NDA_VNI])
+		desc.vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 07/11] vxlan: vxlan_core: Support FDB flushing by destination VNI
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: Petr Machata, razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Add support for flush VXLAN FDB entries by destination VNI. FDB entry is
stored as {MAC, SRC_VNI} + remote. The destination VNI is an attribute
of the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination VNI', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 4000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.2 vni 2000 self permanent

When user flush by VNI x, only the relevant remotes will be flushed:
$ bridge fdb flush dev vx10 vni 2000

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 4000 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 51 ++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index ec7147409d99..f16328a0f9fe 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3030,6 +3030,7 @@ struct vxlan_fdb_flush_desc {
 	unsigned long			flags_mask;
 	__be32				src_vni;
 	u32				nhid;
+	__be32				vni;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3067,10 +3068,46 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 	return true;
 }
 
+static bool
+vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
+{
+	return !!desc->vni;
+}
+
+static bool
+vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
+			       const struct vxlan_rdst *rd)
+{
+	if (desc->vni && rd->remote_vni != desc->vni)
+		return false;
+
+	return true;
+}
+
+static void
+vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
+			      const struct vxlan_fdb_flush_desc *desc,
+			      bool *p_destroy_fdb)
+{
+	bool remotes_flushed = false;
+	struct vxlan_rdst *rd, *tmp;
+
+	list_for_each_entry_safe(rd, tmp, &f->remotes, list) {
+		if (!vxlan_fdb_flush_remote_matches(desc, rd))
+			continue;
+
+		vxlan_fdb_dst_destroy(vxlan, f, rd, true);
+		remotes_flushed = true;
+	}
+
+	*p_destroy_fdb = remotes_flushed && list_empty(&f->remotes);
+}
+
 /* Purge the forwarding table */
 static void vxlan_flush(struct vxlan_dev *vxlan,
 			const struct vxlan_fdb_flush_desc *desc)
 {
+	bool match_remotes = vxlan_fdb_flush_should_match_remotes(desc);
 	unsigned int h;
 
 	for (h = 0; h < FDB_HASH_SIZE; ++h) {
@@ -3084,6 +3121,16 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 			if (!vxlan_fdb_flush_matches(f, vxlan, desc))
 				continue;
 
+			if (match_remotes) {
+				bool destroy_fdb = false;
+
+				vxlan_fdb_flush_match_remotes(f, vxlan, desc,
+							      &destroy_fdb);
+
+				if (!destroy_fdb)
+					continue;
+			}
+
 			vxlan_fdb_destroy(vxlan, f, true, true);
 		}
 		spin_unlock_bh(&vxlan->hash_lock[h]);
@@ -3093,6 +3140,7 @@ static void vxlan_flush(struct vxlan_dev *vxlan,
 static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NH_ID]	= { .type = NLA_U32 },
+	[NDA_VNI]	= { .type = NLA_U32 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3143,6 +3191,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_NH_ID])
 		desc.nhid = nla_get_u32(tb[NDA_NH_ID]);
 
+	if (tb[NDA_VNI])
+		desc.vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 08/11] vxlan: vxlan_core: Support FDB flushing by destination port
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

Add support for flush VXLAN FDB entries by destination port. FDB entry
is stored as {MAC, SRC_VNI} + remote. The destination port is an attribute
of the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination port', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 port 1111 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 port 1111 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 port 2222 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent

When user flush by port x, only the relevant remotes will be flushed:
$ bridge fdb flush dev vx10 port 1111

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 port 2222 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index f16328a0f9fe..1d6efca4ec4a 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3031,6 +3031,7 @@ struct vxlan_fdb_flush_desc {
 	__be32				src_vni;
 	u32				nhid;
 	__be32				vni;
+	__be16				port;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3071,7 +3072,7 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 static bool
 vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
 {
-	return !!desc->vni;
+	return desc->vni || desc->port;
 }
 
 static bool
@@ -3081,6 +3082,9 @@ vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
 	if (desc->vni && rd->remote_vni != desc->vni)
 		return false;
 
+	if (desc->port && rd->remote_port != desc->port)
+		return false;
+
 	return true;
 }
 
@@ -3141,6 +3145,7 @@ static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_VNI]	= { .type = NLA_U32 },
+	[NDA_PORT]	= { .type = NLA_U16 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3194,6 +3199,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_VNI])
 		desc.vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
 
+	if (tb[NDA_PORT])
+		desc.port = nla_get_be16(tb[NDA_PORT]);
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 08/11] vxlan: vxlan_core: Support FDB flushing by destination port
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Add support for flush VXLAN FDB entries by destination port. FDB entry
is stored as {MAC, SRC_VNI} + remote. The destination port is an attribute
of the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination port', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 port 1111 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 port 1111 vni 3000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 port 2222 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent

When user flush by port x, only the relevant remotes will be flushed:
$ bridge fdb flush dev vx10 port 1111

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.1 port 2222 vni 2000 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 3000 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index f16328a0f9fe..1d6efca4ec4a 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3031,6 +3031,7 @@ struct vxlan_fdb_flush_desc {
 	__be32				src_vni;
 	u32				nhid;
 	__be32				vni;
+	__be16				port;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3071,7 +3072,7 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 static bool
 vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
 {
-	return !!desc->vni;
+	return desc->vni || desc->port;
 }
 
 static bool
@@ -3081,6 +3082,9 @@ vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
 	if (desc->vni && rd->remote_vni != desc->vni)
 		return false;
 
+	if (desc->port && rd->remote_port != desc->port)
+		return false;
+
 	return true;
 }
 
@@ -3141,6 +3145,7 @@ static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_SRC_VNI]   = { .type = NLA_U32 },
 	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_VNI]	= { .type = NLA_U32 },
+	[NDA_PORT]	= { .type = NLA_U16 },
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3194,6 +3199,9 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_VNI])
 		desc.vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI]));
 
+	if (tb[NDA_PORT])
+		desc.port = nla_get_be16(tb[NDA_PORT]);
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 09/11] vxlan: vxlan_core: Support FDB flushing by destination IP
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

Add support for flush VXLAN FDB entries by destination IP. FDB entry is
stored as {MAC, SRC_VNI} + remote. The destination IP is an attribute of
the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination IP', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.3 self permanent
00:00:00:00:00:00 dst 192.1.1.1 self permanent
00:00:00:00:00:00 dst 192.1.1.2 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 1000 self permanent

When user flush by destination IP x, only the relevant remotes will be
flushed:
$ bridge fdb flush dev vx10 dst 192.1.1.1

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.3 self permanent
00:00:00:00:00:00 dst 192.1.1.2 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 1d6efca4ec4a..ece377b1b6bd 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3032,6 +3032,7 @@ struct vxlan_fdb_flush_desc {
 	u32				nhid;
 	__be32				vni;
 	__be16				port;
+	union vxlan_addr		dst_ip;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3072,7 +3073,7 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 static bool
 vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
 {
-	return desc->vni || desc->port;
+	return desc->vni || desc->port || desc->dst_ip.sa.sa_family;
 }
 
 static bool
@@ -3085,6 +3086,10 @@ vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
 	if (desc->port && rd->remote_port != desc->port)
 		return false;
 
+	if (desc->dst_ip.sa.sa_family &&
+	    !vxlan_addr_equal(&rd->remote_ip, &desc->dst_ip))
+		return false;
+
 	return true;
 }
 
@@ -3146,6 +3151,8 @@ static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_VNI]	= { .type = NLA_U32 },
 	[NDA_PORT]	= { .type = NLA_U16 },
+	[NDA_DST]	= NLA_POLICY_RANGE(NLA_BINARY, sizeof(struct in_addr),
+					   sizeof(struct in6_addr)),
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3202,6 +3209,18 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_PORT])
 		desc.port = nla_get_be16(tb[NDA_PORT]);
 
+	if (tb[NDA_DST]) {
+		union vxlan_addr ip;
+
+		err = vxlan_nla_get_addr(&ip, tb[NDA_DST]);
+		if (err) {
+			NL_SET_ERR_MSG_ATTR(extack, tb[NDA_DST],
+					    "Unsupported address family");
+			return err;
+		}
+		desc.dst_ip = ip;
+	}
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 09/11] vxlan: vxlan_core: Support FDB flushing by destination IP
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Add support for flush VXLAN FDB entries by destination IP. FDB entry is
stored as {MAC, SRC_VNI} + remote. The destination IP is an attribute of
the remote. For multicast entries, the VXLAN driver stores a linked list
of remotes for a given key.

In user space, each remote is represented as a separate entry, so when
flush is sent with filter of 'destination IP', flush only the match
remotes. In case that there are no additional remotes, destroy the entry.

For example, the following are stored as one entry with several remotes:
$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.3 self permanent
00:00:00:00:00:00 dst 192.1.1.1 self permanent
00:00:00:00:00:00 dst 192.1.1.2 self permanent
00:00:00:00:00:00 dst 192.1.1.1 vni 1000 self permanent

When user flush by destination IP x, only the relevant remotes will be
flushed:
$ bridge fdb flush dev vx10 dst 192.1.1.1

$ bridge fdb show dev vx10
00:00:00:00:00:00 dst 192.1.1.3 self permanent
00:00:00:00:00:00 dst 192.1.1.2 self permanent

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 1d6efca4ec4a..ece377b1b6bd 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3032,6 +3032,7 @@ struct vxlan_fdb_flush_desc {
 	u32				nhid;
 	__be32				vni;
 	__be16				port;
+	union vxlan_addr		dst_ip;
 };
 
 static bool vxlan_fdb_is_default_entry(const struct vxlan_fdb *f,
@@ -3072,7 +3073,7 @@ static bool vxlan_fdb_flush_matches(const struct vxlan_fdb *f,
 static bool
 vxlan_fdb_flush_should_match_remotes(const struct vxlan_fdb_flush_desc *desc)
 {
-	return desc->vni || desc->port;
+	return desc->vni || desc->port || desc->dst_ip.sa.sa_family;
 }
 
 static bool
@@ -3085,6 +3086,10 @@ vxlan_fdb_flush_remote_matches(const struct vxlan_fdb_flush_desc *desc,
 	if (desc->port && rd->remote_port != desc->port)
 		return false;
 
+	if (desc->dst_ip.sa.sa_family &&
+	    !vxlan_addr_equal(&rd->remote_ip, &desc->dst_ip))
+		return false;
+
 	return true;
 }
 
@@ -3146,6 +3151,8 @@ static const struct nla_policy vxlan_del_bulk_policy[NDA_MAX + 1] = {
 	[NDA_NH_ID]	= { .type = NLA_U32 },
 	[NDA_VNI]	= { .type = NLA_U32 },
 	[NDA_PORT]	= { .type = NLA_U16 },
+	[NDA_DST]	= NLA_POLICY_RANGE(NLA_BINARY, sizeof(struct in_addr),
+					   sizeof(struct in6_addr)),
 	[NDA_NDM_STATE_MASK]	= { .type = NLA_U16 },
 	[NDA_NDM_FLAGS_MASK]	= { .type = NLA_U8 },
 };
@@ -3202,6 +3209,18 @@ static int vxlan_fdb_delete_bulk(struct nlmsghdr *nlh, struct net_device *dev,
 	if (tb[NDA_PORT])
 		desc.port = nla_get_be16(tb[NDA_PORT]);
 
+	if (tb[NDA_DST]) {
+		union vxlan_addr ip;
+
+		err = vxlan_nla_get_addr(&ip, tb[NDA_DST]);
+		if (err) {
+			NL_SET_ERR_MSG_ATTR(extack, tb[NDA_DST],
+					    "Unsupported address family");
+			return err;
+		}
+		desc.dst_ip = ip;
+	}
+
 	vxlan_flush(vxlan, &desc);
 
 	return 0;
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 10/11] selftests: Add test cases for FDB flush with VXLAN device
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

Test all the supported arguments for FDB flush. The test checks
configuration, not traffic. Note that the flag 'offloaded' is not checked
as it is not relevant when there is no hardware.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
---
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/fdb_flush.sh | 716 +++++++++++++++++++++++
 2 files changed, 717 insertions(+)
 create mode 100755 tools/testing/selftests/net/fdb_flush.sh

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 8b017070960d..61939a695f95 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -89,6 +89,7 @@ TEST_PROGS += test_vxlan_mdb.sh
 TEST_PROGS += test_bridge_neigh_suppress.sh
 TEST_PROGS += test_vxlan_nolocalbypass.sh
 TEST_PROGS += test_bridge_backup_port.sh
+TEST_PROGS += fdb_flush.sh
 
 TEST_FILES := settings
 
diff --git a/tools/testing/selftests/net/fdb_flush.sh b/tools/testing/selftests/net/fdb_flush.sh
new file mode 100755
index 000000000000..3050b031f46d
--- /dev/null
+++ b/tools/testing/selftests/net/fdb_flush.sh
@@ -0,0 +1,716 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# This test is for checking functionality of flushing FDB entries.
+# Check that flush works as expected with all the supported arguments and verify
+# some combinations of arguments.
+
+FLUSH_BY_STATE_TESTS="
+	vxlan_test_flush_by_permanent
+	vxlan_test_flush_by_nopermanent
+	vxlan_test_flush_by_static
+	vxlan_test_flush_by_nostatic
+	vxlan_test_flush_by_dynamic
+	vxlan_test_flush_by_nodynamic
+"
+
+FLUSH_BY_FLAG_TESTS="
+	vxlan_test_flush_by_extern_learn
+	vxlan_test_flush_by_noextern_learn
+	vxlan_test_flush_by_router
+	vxlan_test_flush_by_norouter
+"
+
+TESTS="
+	vxlan_test_flush_by_dev
+	vxlan_test_flush_by_vni
+	vxlan_test_flush_by_src_vni
+	vxlan_test_flush_by_port
+	vxlan_test_flush_by_dst_ip
+	vxlan_test_flush_by_nhid
+	$FLUSH_BY_STATE_TESTS
+	$FLUSH_BY_FLAG_TESTS
+	vxlan_test_flush_by_several_args
+	vxlan_test_flush_by_remote_attributes
+"
+
+: ${VERBOSE:=0}
+: ${PAUSE_ON_FAIL:=no}
+: ${PAUSE:=no}
+: ${VXPORT:=4789}
+
+run_cmd()
+{
+	local cmd="$1"
+	local out
+	local rc
+	local stderr="2>/dev/null"
+
+	if [ "$VERBOSE" = "1" ]; then
+		printf "COMMAND: $cmd\n"
+		stderr=
+	fi
+
+	out=$(eval $cmd $stderr)
+	rc=$?
+	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
+		echo "    $out"
+	fi
+
+	return $rc
+}
+
+log_test()
+{
+	local rc=$1
+	local expected=$2
+	local msg="$3"
+	local nsuccess
+	local nfail
+	local ret
+
+	if [ ${rc} -eq ${expected} ]; then
+		printf "TEST: %-60s  [ OK ]\n" "${msg}"
+		nsuccess=$((nsuccess+1))
+	else
+		ret=1
+		nfail=$((nfail+1))
+		printf "TEST: %-60s  [FAIL]\n" "${msg}"
+		if [ "$VERBOSE" = "1" ]; then
+			echo "    rc=$rc, expected $expected"
+		fi
+
+		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+		echo
+			echo "hit enter to continue, 'q' to quit"
+			read a
+			[ "$a" = "q" ] && exit 1
+		fi
+	fi
+
+	if [ "${PAUSE}" = "yes" ]; then
+		echo
+		echo "hit enter to continue, 'q' to quit"
+		read a
+		[ "$a" = "q" ] && exit 1
+	fi
+
+	[ "$VERBOSE" = "1" ] && echo
+}
+
+MAC_POOL_1="
+	de:ad:be:ef:13:10
+	de:ad:be:ef:13:11
+	de:ad:be:ef:13:12
+	de:ad:be:ef:13:13
+	de:ad:be:ef:13:14
+"
+mac_pool_1_len=$(echo "$MAC_POOL_1" | grep -c .)
+
+MAC_POOL_2="
+	ca:fe:be:ef:13:10
+	ca:fe:be:ef:13:11
+	ca:fe:be:ef:13:12
+	ca:fe:be:ef:13:13
+	ca:fe:be:ef:13:14
+"
+mac_pool_2_len=$(echo "$MAC_POOL_2" | grep -c .)
+
+fdb_add_mac_pool_1()
+{
+	local dev=$1; shift
+	local args="$@"
+
+	for mac in $MAC_POOL_1
+	do
+		$BRIDGE fdb add $mac dev $dev $args
+	done
+}
+
+fdb_add_mac_pool_2()
+{
+	local dev=$1; shift
+	local args="$@"
+
+	for mac in $MAC_POOL_2
+	do
+		$BRIDGE fdb add $mac dev $dev $args
+	done
+}
+
+fdb_check_n_entries_by_dev_filter()
+{
+	local dev=$1; shift
+	local exp_entries=$1; shift
+	local filter="$@"
+
+	local entries=$($BRIDGE fdb show dev $dev | grep "$filter" | wc -l)
+
+	[[ $entries -eq $exp_entries ]]
+	rc=$?
+
+	log_test $rc 0 "$dev: Expected $exp_entries FDB entries, got $entries"
+	return $rc
+}
+
+vxlan_test_flush_by_dev()
+{
+	local vni=3000
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 vni $vni dst $dst_ip
+	fdb_add_mac_pool_2 vx20 vni $vni dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len
+	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
+
+	run_cmd "$BRIDGE fdb flush dev vx10"
+	log_test $? 0 "Flush FDB by dev vx10"
+
+	fdb_check_n_entries_by_dev_filter vx10 0
+	log_test $? 0 "Flush FDB by dev vx10 - test vx10 entries"
+
+	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
+	log_test $? 0 "Flush FDB by dev vx10 - test vx20 entries"
+}
+
+vxlan_test_flush_by_vni()
+{
+	local vni_1=3000
+	local vni_2=4000
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 vni $vni_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 vni $vni_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len vni $vni_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 vni $vni_2"
+	log_test $? 0 "Flush FDB by dev vx10 and vni $vni_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
+	log_test $? 0 "Test entries with vni $vni_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 vni $vni_2
+	log_test $? 0 "Test entries with vni $vni_2"
+}
+
+vxlan_test_flush_by_src_vni()
+{
+	# Set some entries with {vni=x,src_vni=y} and some with the opposite -
+	# {vni=y,src_vni=x}, to verify that when we flush by src_vni=x, entries
+	# with vni=x are not flused.
+	local vni_1=3000
+	local vni_2=4000
+	local src_vni_1=4000
+	local src_vni_2=3000
+	local dst_ip=192.0.2.1
+
+	# Reconfigure vx10 with 'external' to get 'src_vni' details in
+	# 'bridge fdb' output
+	$IP link del dev vx10
+	$IP link add name vx10 type vxlan dstport "$VXPORT" external
+
+	fdb_add_mac_pool_1 vx10 vni $vni_1 src_vni $src_vni_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 vni $vni_2 src_vni $src_vni_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
+		src_vni $src_vni_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len \
+		src_vni $src_vni_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 src_vni $src_vni_2"
+	log_test $? 0 "Flush FDB by dev vx10 and src_vni $src_vni_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
+		src_vni $src_vni_1
+	log_test $? 0 "Test entries with src_vni $src_vni_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 src_vni $src_vni_2
+	log_test $? 0 "Test entries with src_vni $src_vni_2"
+}
+
+vxlan_test_flush_by_port()
+{
+	local port_1=1234
+	local port_2=4321
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 port $port_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 port $port_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len port $port_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 port $port_2"
+	log_test $? 0 "Flush FDB by dev vx10 and port $port_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
+	log_test $? 0 "Test entries with port $port_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 port $port_2
+	log_test $? 0 "Test entries with port $port_2"
+}
+
+vxlan_test_flush_by_dst_ip()
+{
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 dst $dst_ip_2"
+	log_test $? 0 "Flush FDB by dev vx10 and dst $dst_ip_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	log_test $? 0 "Test entries with dst $dst_ip_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
+	log_test $? 0 "Test entries with dst $dst_ip_2"
+}
+
+nexthops_add()
+{
+	local nhid_1=$1; shift
+	local nhid_2=$1; shift
+
+	$IP nexthop add id 10 via 192.0.2.1 fdb
+	$IP nexthop add id $nhid_1 group 10 fdb
+
+	$IP nexthop add id 20 via 192.0.2.2 fdb
+	$IP nexthop add id $nhid_2 group 20 fdb
+}
+
+vxlan_test_flush_by_nhid()
+{
+	local nhid_1=100
+	local nhid_2=200
+
+	nexthops_add $nhid_1 $nhid_2
+
+	fdb_add_mac_pool_1 vx10 nhid $nhid_1
+	fdb_add_mac_pool_2 vx10 nhid $nhid_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len nhid $nhid_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_2"
+	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
+	log_test $? 0 "Test entries with nhid $nhid_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 nhid $nhid_2
+	log_test $? 0 "Test entries with nhid $nhid_2"
+
+	# Flush also entries with $nhid_1, and then verify that flushing by
+	# 'nhid' does not return an error when there are no entries with
+	# nexthops.
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
+	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 nhid
+	log_test $? 0 "Test entries with 'nhid' keyword"
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
+	log_test $? 0 "Flush FDB by nhid when there are no entries with nexthop"
+}
+
+vxlan_test_flush_by_state()
+{
+	local flush_by_state=$1; shift
+	local state_1=$1; shift
+	local exp_state_1=$1; shift
+	local state_2=$1; shift
+	local exp_state_2=$1; shift
+
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $state_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $state_2
+
+	# Check the entries by dst_ip as not all states appear in 'bridge fdb'
+	# output.
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_state"
+	log_test $? 0 "Flush FDB by dev vx10 and state $flush_by_state"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_state_1 dst $dst_ip_1
+	log_test $? 0 "Test entries with state $state_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_state_2 dst $dst_ip_2
+	log_test $? 0 "Test entries with state $state_2"
+}
+
+vxlan_test_flush_by_permanent()
+{
+	# Entries that are added without state get 'permanent' state by
+	# default, add some entries with flag 'extern_learn' instead of state,
+	# so they will be added with 'permanent' and should be flushed also.
+	local flush_by_state="permanent"
+	local state_1="permanent"
+	local exp_state_1=0
+	local state_2="extern_learn"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nopermanent()
+{
+	local flush_by_state="nopermanent"
+	local state_1="permanent"
+	local exp_state_1=$mac_pool_1_len
+	local state_2="static"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_static()
+{
+	local flush_by_state="static"
+	local state_1="static"
+	local exp_state_1=0
+	local state_2="dynamic"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nostatic()
+{
+	local flush_by_state="nostatic"
+	local state_1="permanent"
+	local exp_state_1=$mac_pool_1_len
+	local state_2="dynamic"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_dynamic()
+{
+	local flush_by_state="dynamic"
+	local state_1="dynamic"
+	local exp_state_1=0
+	local state_2="static"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nodynamic()
+{
+	local flush_by_state="nodynamic"
+	local state_1="permanent"
+	local exp_state_1=0
+	local state_2="dynamic"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_flag()
+{
+	local flush_by_flag=$1; shift
+	local flag_1=$1; shift
+	local exp_flag_1=$1; shift
+	local flag_2=$1; shift
+	local exp_flag_2=$1; shift
+
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $flag_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $flag_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $flag_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $flag_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_flag"
+	log_test $? 0 "Flush FDB by dev vx10 and flag $flush_by_flag"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_1 dst $dst_ip_1
+	log_test $? 0 "Test entries with flag $flag_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_2 dst $dst_ip_2
+	log_test $? 0 "Test entries with flag $flag_2"
+}
+
+vxlan_test_flush_by_extern_learn()
+{
+	local flush_by_flag="extern_learn"
+	local flag_1="extern_learn"
+	local exp_flag_1=0
+	local flag_2="router"
+	local exp_flag_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_noextern_learn()
+{
+	local flush_by_flag="noextern_learn"
+	local flag_1="extern_learn"
+	local exp_flag_1=$mac_pool_1_len
+	local flag_2="router"
+	local exp_flag_2=0
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_router()
+{
+	local flush_by_flag="router"
+	local flag_1="router"
+	local exp_flag_1=0
+	local flag_2="extern_learn"
+	local exp_flag_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_norouter()
+{
+
+	local flush_by_flag="norouter"
+	local flag_1="router"
+	local exp_flag_1=$mac_pool_1_len
+	local flag_2="extern_learn"
+	local exp_flag_2=0
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_several_args()
+{
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+	local state_1=permanent
+	local state_2=static
+	local vni=3000
+	local port=1234
+	local nhid=100
+	local flag=router
+	local flush_args
+
+	################### Flush by 2 args - nhid and flag ####################
+	$IP nexthop add id 10 via 192.0.2.1 fdb
+	$IP nexthop add id $nhid group 10 fdb
+
+	fdb_add_mac_pool_1 vx10 nhid $nhid $flag $state_1
+	fdb_add_mac_pool_2 vx10 nhid $nhid $flag $state_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $state_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $state_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid $flag"
+	log_test $? 0 "Flush FDB by dev vx10 nhid $nhid $flag"
+
+	# All entries should be flushed as 'state' is not an argument for flush
+	# filtering.
+	fdb_check_n_entries_by_dev_filter vx10 0 $state_1
+	log_test $? 0 "Test entries with state $state_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $state_2
+	log_test $? 0 "Test entries with state $state_2"
+
+	################ Flush by 3 args - VNI, port and dst_ip ################
+	fdb_add_mac_pool_1 vx10 vni $vni port $port dst $dst_ip_1
+	fdb_add_mac_pool_2 vx10 vni $vni port $port dst $dst_ip_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	flush_args="vni $vni port $port dst $dst_ip_2"
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	# Only entries with $dst_ip_2 should be flushed, even the rest arguments
+	# match the filter, the flush should be AND of all the arguments.
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	log_test $? 0 "Test entries with dst $dst_ip_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
+	log_test $? 0 "Test entries with dst $dst_ip_2"
+}
+
+multicast_fdb_entries_add()
+{
+	mac=00:00:00:00:00:00
+	vnis=(2000 3000)
+
+	for vni in "${vnis[@]}"; do
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
+			src_vni 5000
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
+			port 1111
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.2 vni $vni \
+			port 2222
+	done
+}
+
+vxlan_test_flush_by_remote_attributes()
+{
+	local flush_args
+
+	# Reconfigure vx10 with 'external' to get 'src_vni' details in
+	# 'bridge fdb' output
+	$IP link del dev vx10
+	$IP link add name vx10 type vxlan dstport "$VXPORT" external
+
+	# For multicat FDB entries, the VXLAN driver stores a linked list of
+	# remotes for a given key. Verify that only the expected remotes are
+	# flushed.
+	multicast_fdb_entries_add
+
+	## Flush by 3 remote's attributes - destination IP, port and VNI ##
+	flush_args="dst 192.0.2.1 port 1111 vni 2000"
+	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries - 1))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	## Flush by 2 remote's attributes - destination IP and port ##
+	flush_args="dst 192.0.2.2 port 2222"
+
+	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries - 2))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	## Flush by source VNI, which is not remote's attribute and VNI ##
+	flush_args="vni 3000 src_vni 5000"
+
+	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries -1))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	# Flush by 1 remote's attribute - destination IP ##
+	flush_args="dst 192.0.2.1"
+
+	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries -2))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+}
+
+setup()
+{
+	IP="ip -netns ns1"
+	BRIDGE="bridge -netns ns1"
+
+	ip netns add ns1
+
+	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
+	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
+}
+
+cleanup()
+{
+	$IP link del dev vx20
+	$IP link del dev vx10
+
+	ip netns del ns1
+}
+
+################################################################################
+# main
+
+while getopts :t:pPhvw: o
+do
+	case $o in
+		t) TESTS=$OPTARG;;
+		p) PAUSE_ON_FAIL=yes;;
+		P) PAUSE=yes;;
+		v) VERBOSE=$(($VERBOSE + 1));;
+		w) PING_TIMEOUT=$OPTARG;;
+		h) usage; exit 0;;
+		*) usage; exit 1;;
+	esac
+done
+
+# make sure we don't pause twice
+[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
+
+if [ "$(id -u)" -ne 0 ];then
+	echo "SKIP: Need root privileges"
+	exit $ksft_skip;
+fi
+
+if [ ! -x "$(command -v ip)" ]; then
+	echo "SKIP: Could not run test without ip tool"
+	exit $ksft_skip
+fi
+
+# Check a flag that is added to flush command as part of VXLAN flush support
+bridge fdb help 2>&1 | grep -q "\[no\]router"
+if [ $? -ne 0 ]; then
+	echo "SKIP: iproute2 too old, missing flush command for VXLAN"
+	exit $ksft_skip
+fi
+
+ip link add dev vx10 type vxlan id 1000 2> /dev/null
+out=$(bridge fdb flush dev vx10 2>&1 | grep -q "Operation not supported")
+if [ $? -eq 0 ]; then
+	echo "SKIP: kernel lacks vxlan flush support"
+	exit $ksft_skip
+fi
+ip link del dev vx10
+
+for t in $TESTS
+do
+	setup; $t; cleanup;
+done
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 10/11] selftests: Add test cases for FDB flush with VXLAN device
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Test all the supported arguments for FDB flush. The test checks
configuration, not traffic. Note that the flag 'offloaded' is not checked
as it is not relevant when there is no hardware.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
---
 tools/testing/selftests/net/Makefile     |   1 +
 tools/testing/selftests/net/fdb_flush.sh | 716 +++++++++++++++++++++++
 2 files changed, 717 insertions(+)
 create mode 100755 tools/testing/selftests/net/fdb_flush.sh

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 8b017070960d..61939a695f95 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -89,6 +89,7 @@ TEST_PROGS += test_vxlan_mdb.sh
 TEST_PROGS += test_bridge_neigh_suppress.sh
 TEST_PROGS += test_vxlan_nolocalbypass.sh
 TEST_PROGS += test_bridge_backup_port.sh
+TEST_PROGS += fdb_flush.sh
 
 TEST_FILES := settings
 
diff --git a/tools/testing/selftests/net/fdb_flush.sh b/tools/testing/selftests/net/fdb_flush.sh
new file mode 100755
index 000000000000..3050b031f46d
--- /dev/null
+++ b/tools/testing/selftests/net/fdb_flush.sh
@@ -0,0 +1,716 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# This test is for checking functionality of flushing FDB entries.
+# Check that flush works as expected with all the supported arguments and verify
+# some combinations of arguments.
+
+FLUSH_BY_STATE_TESTS="
+	vxlan_test_flush_by_permanent
+	vxlan_test_flush_by_nopermanent
+	vxlan_test_flush_by_static
+	vxlan_test_flush_by_nostatic
+	vxlan_test_flush_by_dynamic
+	vxlan_test_flush_by_nodynamic
+"
+
+FLUSH_BY_FLAG_TESTS="
+	vxlan_test_flush_by_extern_learn
+	vxlan_test_flush_by_noextern_learn
+	vxlan_test_flush_by_router
+	vxlan_test_flush_by_norouter
+"
+
+TESTS="
+	vxlan_test_flush_by_dev
+	vxlan_test_flush_by_vni
+	vxlan_test_flush_by_src_vni
+	vxlan_test_flush_by_port
+	vxlan_test_flush_by_dst_ip
+	vxlan_test_flush_by_nhid
+	$FLUSH_BY_STATE_TESTS
+	$FLUSH_BY_FLAG_TESTS
+	vxlan_test_flush_by_several_args
+	vxlan_test_flush_by_remote_attributes
+"
+
+: ${VERBOSE:=0}
+: ${PAUSE_ON_FAIL:=no}
+: ${PAUSE:=no}
+: ${VXPORT:=4789}
+
+run_cmd()
+{
+	local cmd="$1"
+	local out
+	local rc
+	local stderr="2>/dev/null"
+
+	if [ "$VERBOSE" = "1" ]; then
+		printf "COMMAND: $cmd\n"
+		stderr=
+	fi
+
+	out=$(eval $cmd $stderr)
+	rc=$?
+	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
+		echo "    $out"
+	fi
+
+	return $rc
+}
+
+log_test()
+{
+	local rc=$1
+	local expected=$2
+	local msg="$3"
+	local nsuccess
+	local nfail
+	local ret
+
+	if [ ${rc} -eq ${expected} ]; then
+		printf "TEST: %-60s  [ OK ]\n" "${msg}"
+		nsuccess=$((nsuccess+1))
+	else
+		ret=1
+		nfail=$((nfail+1))
+		printf "TEST: %-60s  [FAIL]\n" "${msg}"
+		if [ "$VERBOSE" = "1" ]; then
+			echo "    rc=$rc, expected $expected"
+		fi
+
+		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
+		echo
+			echo "hit enter to continue, 'q' to quit"
+			read a
+			[ "$a" = "q" ] && exit 1
+		fi
+	fi
+
+	if [ "${PAUSE}" = "yes" ]; then
+		echo
+		echo "hit enter to continue, 'q' to quit"
+		read a
+		[ "$a" = "q" ] && exit 1
+	fi
+
+	[ "$VERBOSE" = "1" ] && echo
+}
+
+MAC_POOL_1="
+	de:ad:be:ef:13:10
+	de:ad:be:ef:13:11
+	de:ad:be:ef:13:12
+	de:ad:be:ef:13:13
+	de:ad:be:ef:13:14
+"
+mac_pool_1_len=$(echo "$MAC_POOL_1" | grep -c .)
+
+MAC_POOL_2="
+	ca:fe:be:ef:13:10
+	ca:fe:be:ef:13:11
+	ca:fe:be:ef:13:12
+	ca:fe:be:ef:13:13
+	ca:fe:be:ef:13:14
+"
+mac_pool_2_len=$(echo "$MAC_POOL_2" | grep -c .)
+
+fdb_add_mac_pool_1()
+{
+	local dev=$1; shift
+	local args="$@"
+
+	for mac in $MAC_POOL_1
+	do
+		$BRIDGE fdb add $mac dev $dev $args
+	done
+}
+
+fdb_add_mac_pool_2()
+{
+	local dev=$1; shift
+	local args="$@"
+
+	for mac in $MAC_POOL_2
+	do
+		$BRIDGE fdb add $mac dev $dev $args
+	done
+}
+
+fdb_check_n_entries_by_dev_filter()
+{
+	local dev=$1; shift
+	local exp_entries=$1; shift
+	local filter="$@"
+
+	local entries=$($BRIDGE fdb show dev $dev | grep "$filter" | wc -l)
+
+	[[ $entries -eq $exp_entries ]]
+	rc=$?
+
+	log_test $rc 0 "$dev: Expected $exp_entries FDB entries, got $entries"
+	return $rc
+}
+
+vxlan_test_flush_by_dev()
+{
+	local vni=3000
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 vni $vni dst $dst_ip
+	fdb_add_mac_pool_2 vx20 vni $vni dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len
+	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
+
+	run_cmd "$BRIDGE fdb flush dev vx10"
+	log_test $? 0 "Flush FDB by dev vx10"
+
+	fdb_check_n_entries_by_dev_filter vx10 0
+	log_test $? 0 "Flush FDB by dev vx10 - test vx10 entries"
+
+	fdb_check_n_entries_by_dev_filter vx20 $mac_pool_2_len
+	log_test $? 0 "Flush FDB by dev vx10 - test vx20 entries"
+}
+
+vxlan_test_flush_by_vni()
+{
+	local vni_1=3000
+	local vni_2=4000
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 vni $vni_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 vni $vni_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len vni $vni_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 vni $vni_2"
+	log_test $? 0 "Flush FDB by dev vx10 and vni $vni_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni $vni_1
+	log_test $? 0 "Test entries with vni $vni_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 vni $vni_2
+	log_test $? 0 "Test entries with vni $vni_2"
+}
+
+vxlan_test_flush_by_src_vni()
+{
+	# Set some entries with {vni=x,src_vni=y} and some with the opposite -
+	# {vni=y,src_vni=x}, to verify that when we flush by src_vni=x, entries
+	# with vni=x are not flused.
+	local vni_1=3000
+	local vni_2=4000
+	local src_vni_1=4000
+	local src_vni_2=3000
+	local dst_ip=192.0.2.1
+
+	# Reconfigure vx10 with 'external' to get 'src_vni' details in
+	# 'bridge fdb' output
+	$IP link del dev vx10
+	$IP link add name vx10 type vxlan dstport "$VXPORT" external
+
+	fdb_add_mac_pool_1 vx10 vni $vni_1 src_vni $src_vni_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 vni $vni_2 src_vni $src_vni_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
+		src_vni $src_vni_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len \
+		src_vni $src_vni_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 src_vni $src_vni_2"
+	log_test $? 0 "Flush FDB by dev vx10 and src_vni $src_vni_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len \
+		src_vni $src_vni_1
+	log_test $? 0 "Test entries with src_vni $src_vni_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 src_vni $src_vni_2
+	log_test $? 0 "Test entries with src_vni $src_vni_2"
+}
+
+vxlan_test_flush_by_port()
+{
+	local port_1=1234
+	local port_2=4321
+	local dst_ip=192.0.2.1
+
+	fdb_add_mac_pool_1 vx10 port $port_1 dst $dst_ip
+	fdb_add_mac_pool_2 vx10 port $port_2 dst $dst_ip
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len port $port_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 port $port_2"
+	log_test $? 0 "Flush FDB by dev vx10 and port $port_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len port $port_1
+	log_test $? 0 "Test entries with port $port_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 port $port_2
+	log_test $? 0 "Test entries with port $port_2"
+}
+
+vxlan_test_flush_by_dst_ip()
+{
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 dst $dst_ip_2"
+	log_test $? 0 "Flush FDB by dev vx10 and dst $dst_ip_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	log_test $? 0 "Test entries with dst $dst_ip_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
+	log_test $? 0 "Test entries with dst $dst_ip_2"
+}
+
+nexthops_add()
+{
+	local nhid_1=$1; shift
+	local nhid_2=$1; shift
+
+	$IP nexthop add id 10 via 192.0.2.1 fdb
+	$IP nexthop add id $nhid_1 group 10 fdb
+
+	$IP nexthop add id 20 via 192.0.2.2 fdb
+	$IP nexthop add id $nhid_2 group 20 fdb
+}
+
+vxlan_test_flush_by_nhid()
+{
+	local nhid_1=100
+	local nhid_2=200
+
+	nexthops_add $nhid_1 $nhid_2
+
+	fdb_add_mac_pool_1 vx10 nhid $nhid_1
+	fdb_add_mac_pool_2 vx10 nhid $nhid_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len nhid $nhid_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_2"
+	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_2"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len nhid $nhid_1
+	log_test $? 0 "Test entries with nhid $nhid_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 nhid $nhid_2
+	log_test $? 0 "Test entries with nhid $nhid_2"
+
+	# Flush also entries with $nhid_1, and then verify that flushing by
+	# 'nhid' does not return an error when there are no entries with
+	# nexthops.
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
+	log_test $? 0 "Flush FDB by dev vx10 and nhid $nhid_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 nhid
+	log_test $? 0 "Test entries with 'nhid' keyword"
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid_1"
+	log_test $? 0 "Flush FDB by nhid when there are no entries with nexthop"
+}
+
+vxlan_test_flush_by_state()
+{
+	local flush_by_state=$1; shift
+	local state_1=$1; shift
+	local exp_state_1=$1; shift
+	local state_2=$1; shift
+	local exp_state_2=$1; shift
+
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $state_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $state_2
+
+	# Check the entries by dst_ip as not all states appear in 'bridge fdb'
+	# output.
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_state"
+	log_test $? 0 "Flush FDB by dev vx10 and state $flush_by_state"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_state_1 dst $dst_ip_1
+	log_test $? 0 "Test entries with state $state_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_state_2 dst $dst_ip_2
+	log_test $? 0 "Test entries with state $state_2"
+}
+
+vxlan_test_flush_by_permanent()
+{
+	# Entries that are added without state get 'permanent' state by
+	# default, add some entries with flag 'extern_learn' instead of state,
+	# so they will be added with 'permanent' and should be flushed also.
+	local flush_by_state="permanent"
+	local state_1="permanent"
+	local exp_state_1=0
+	local state_2="extern_learn"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nopermanent()
+{
+	local flush_by_state="nopermanent"
+	local state_1="permanent"
+	local exp_state_1=$mac_pool_1_len
+	local state_2="static"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_static()
+{
+	local flush_by_state="static"
+	local state_1="static"
+	local exp_state_1=0
+	local state_2="dynamic"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nostatic()
+{
+	local flush_by_state="nostatic"
+	local state_1="permanent"
+	local exp_state_1=$mac_pool_1_len
+	local state_2="dynamic"
+	local exp_state_2=0
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_dynamic()
+{
+	local flush_by_state="dynamic"
+	local state_1="dynamic"
+	local exp_state_1=0
+	local state_2="static"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_nodynamic()
+{
+	local flush_by_state="nodynamic"
+	local state_1="permanent"
+	local exp_state_1=0
+	local state_2="dynamic"
+	local exp_state_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_state $flush_by_state $state_1 $exp_state_1 \
+		$state_2 $exp_state_2
+}
+
+vxlan_test_flush_by_flag()
+{
+	local flush_by_flag=$1; shift
+	local flag_1=$1; shift
+	local exp_flag_1=$1; shift
+	local flag_2=$1; shift
+	local exp_flag_2=$1; shift
+
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+
+	fdb_add_mac_pool_1 vx10 dst $dst_ip_1 $flag_1
+	fdb_add_mac_pool_2 vx10 dst $dst_ip_2 $flag_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $flag_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $flag_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_by_flag"
+	log_test $? 0 "Flush FDB by dev vx10 and flag $flush_by_flag"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_1 dst $dst_ip_1
+	log_test $? 0 "Test entries with flag $flag_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $exp_flag_2 dst $dst_ip_2
+	log_test $? 0 "Test entries with flag $flag_2"
+}
+
+vxlan_test_flush_by_extern_learn()
+{
+	local flush_by_flag="extern_learn"
+	local flag_1="extern_learn"
+	local exp_flag_1=0
+	local flag_2="router"
+	local exp_flag_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_noextern_learn()
+{
+	local flush_by_flag="noextern_learn"
+	local flag_1="extern_learn"
+	local exp_flag_1=$mac_pool_1_len
+	local flag_2="router"
+	local exp_flag_2=0
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_router()
+{
+	local flush_by_flag="router"
+	local flag_1="router"
+	local exp_flag_1=0
+	local flag_2="extern_learn"
+	local exp_flag_2=$mac_pool_2_len
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_norouter()
+{
+
+	local flush_by_flag="norouter"
+	local flag_1="router"
+	local exp_flag_1=$mac_pool_1_len
+	local flag_2="extern_learn"
+	local exp_flag_2=0
+
+	vxlan_test_flush_by_flag $flush_by_flag $flag_1 $exp_flag_1 \
+		$flag_2 $exp_flag_2
+}
+
+vxlan_test_flush_by_several_args()
+{
+	local dst_ip_1=192.0.2.1
+	local dst_ip_2=192.0.2.2
+	local state_1=permanent
+	local state_2=static
+	local vni=3000
+	local port=1234
+	local nhid=100
+	local flag=router
+	local flush_args
+
+	################### Flush by 2 args - nhid and flag ####################
+	$IP nexthop add id 10 via 192.0.2.1 fdb
+	$IP nexthop add id $nhid group 10 fdb
+
+	fdb_add_mac_pool_1 vx10 nhid $nhid $flag $state_1
+	fdb_add_mac_pool_2 vx10 nhid $nhid $flag $state_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len $state_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len $state_2
+
+	run_cmd "$BRIDGE fdb flush dev vx10 nhid $nhid $flag"
+	log_test $? 0 "Flush FDB by dev vx10 nhid $nhid $flag"
+
+	# All entries should be flushed as 'state' is not an argument for flush
+	# filtering.
+	fdb_check_n_entries_by_dev_filter vx10 0 $state_1
+	log_test $? 0 "Test entries with state $state_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $state_2
+	log_test $? 0 "Test entries with state $state_2"
+
+	################ Flush by 3 args - VNI, port and dst_ip ################
+	fdb_add_mac_pool_1 vx10 vni $vni port $port dst $dst_ip_1
+	fdb_add_mac_pool_2 vx10 vni $vni port $port dst $dst_ip_2
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_2_len dst $dst_ip_2
+
+	flush_args="vni $vni port $port dst $dst_ip_2"
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	# Only entries with $dst_ip_2 should be flushed, even the rest arguments
+	# match the filter, the flush should be AND of all the arguments.
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip_1
+	log_test $? 0 "Test entries with dst $dst_ip_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 dst $dst_ip_2
+	log_test $? 0 "Test entries with dst $dst_ip_2"
+}
+
+multicast_fdb_entries_add()
+{
+	mac=00:00:00:00:00:00
+	vnis=(2000 3000)
+
+	for vni in "${vnis[@]}"; do
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
+			src_vni 5000
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.1 vni $vni \
+			port 1111
+		$BRIDGE fdb append $mac dev vx10 dst 192.0.2.2 vni $vni \
+			port 2222
+	done
+}
+
+vxlan_test_flush_by_remote_attributes()
+{
+	local flush_args
+
+	# Reconfigure vx10 with 'external' to get 'src_vni' details in
+	# 'bridge fdb' output
+	$IP link del dev vx10
+	$IP link add name vx10 type vxlan dstport "$VXPORT" external
+
+	# For multicat FDB entries, the VXLAN driver stores a linked list of
+	# remotes for a given key. Verify that only the expected remotes are
+	# flushed.
+	multicast_fdb_entries_add
+
+	## Flush by 3 remote's attributes - destination IP, port and VNI ##
+	flush_args="dst 192.0.2.1 port 1111 vni 2000"
+	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries - 1))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	## Flush by 2 remote's attributes - destination IP and port ##
+	flush_args="dst 192.0.2.2 port 2222"
+
+	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries - 2))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	## Flush by source VNI, which is not remote's attribute and VNI ##
+	flush_args="vni 3000 src_vni 5000"
+
+	fdb_check_n_entries_by_dev_filter vx10 1 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries -1))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+
+	# Flush by 1 remote's attribute - destination IP ##
+	flush_args="dst 192.0.2.1"
+
+	fdb_check_n_entries_by_dev_filter vx10 2 $flush_args
+
+	t0_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	run_cmd "$BRIDGE fdb flush dev vx10 $flush_args"
+	log_test $? 0 "Flush FDB by dev vx10 $flush_args"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 $flush_args
+
+	exp_n_entries=$((t0_n_entries -2))
+	t1_n_entries=$($BRIDGE fdb show dev vx10 | wc -l)
+	[[ $t1_n_entries -eq $exp_n_entries ]]
+	log_test $? 0 "Check how many entries were flushed"
+}
+
+setup()
+{
+	IP="ip -netns ns1"
+	BRIDGE="bridge -netns ns1"
+
+	ip netns add ns1
+
+	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
+	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
+}
+
+cleanup()
+{
+	$IP link del dev vx20
+	$IP link del dev vx10
+
+	ip netns del ns1
+}
+
+################################################################################
+# main
+
+while getopts :t:pPhvw: o
+do
+	case $o in
+		t) TESTS=$OPTARG;;
+		p) PAUSE_ON_FAIL=yes;;
+		P) PAUSE=yes;;
+		v) VERBOSE=$(($VERBOSE + 1));;
+		w) PING_TIMEOUT=$OPTARG;;
+		h) usage; exit 0;;
+		*) usage; exit 1;;
+	esac
+done
+
+# make sure we don't pause twice
+[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
+
+if [ "$(id -u)" -ne 0 ];then
+	echo "SKIP: Need root privileges"
+	exit $ksft_skip;
+fi
+
+if [ ! -x "$(command -v ip)" ]; then
+	echo "SKIP: Could not run test without ip tool"
+	exit $ksft_skip
+fi
+
+# Check a flag that is added to flush command as part of VXLAN flush support
+bridge fdb help 2>&1 | grep -q "\[no\]router"
+if [ $? -ne 0 ]; then
+	echo "SKIP: iproute2 too old, missing flush command for VXLAN"
+	exit $ksft_skip
+fi
+
+ip link add dev vx10 type vxlan id 1000 2> /dev/null
+out=$(bridge fdb flush dev vx10 2>&1 | grep -q "Operation not supported")
+if [ $? -eq 0 ]; then
+	echo "SKIP: kernel lacks vxlan flush support"
+	exit $ksft_skip
+fi
+ip link del dev vx10
+
+for t in $TESTS
+do
+	setup; $t; cleanup;
+done
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH net-next 11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-09 10:06   ` Amit Cohen
  -1 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah, pabeni,
	bridge, linux-kselftest, Amit Cohen

Extend the test to check flushing with bridge device, test flush by device
and by VID.

Add test case for flushing with "self" and "master" and attributes that are
supported only in one driver, this is unrecommended configuration, check it
to verify that user gets an error.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
---
 tools/testing/selftests/net/fdb_flush.sh | 96 ++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/tools/testing/selftests/net/fdb_flush.sh b/tools/testing/selftests/net/fdb_flush.sh
index 3050b031f46d..90e7a29e0476 100755
--- a/tools/testing/selftests/net/fdb_flush.sh
+++ b/tools/testing/selftests/net/fdb_flush.sh
@@ -32,6 +32,9 @@ TESTS="
 	$FLUSH_BY_FLAG_TESTS
 	vxlan_test_flush_by_several_args
 	vxlan_test_flush_by_remote_attributes
+	bridge_test_flush_by_dev
+	bridge_test_flush_by_vlan
+	bridge_vxlan_test_flush
 "
 
 : ${VERBOSE:=0}
@@ -647,6 +650,93 @@ vxlan_test_flush_by_remote_attributes()
 	log_test $? 0 "Check how many entries were flushed"
 }
 
+bridge_test_flush_by_dev()
+{
+	local dst_ip=192.0.2.1
+	local br0_n_ent_t0=$($BRIDGE fdb show dev br0 | wc -l)
+	local br1_n_ent_t0=$($BRIDGE fdb show dev br1 | wc -l)
+
+	fdb_add_mac_pool_1 br0 dst $dst_ip
+	fdb_add_mac_pool_2 br1 dst $dst_ip
+
+	# Each 'fdb add' command adds one extra entry in the bridge with the
+	# default vlan.
+	local exp_br0_n_ent=$(($br0_n_ent_t0 + 2 * $mac_pool_1_len))
+	local exp_br1_n_ent=$(($br1_n_ent_t0 + 2 * $mac_pool_2_len))
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_br0_n_ent
+	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
+
+	run_cmd "$BRIDGE fdb flush dev br0"
+	log_test $? 0 "Flush FDB by dev br0"
+
+	# The default entry should not be flushed
+	fdb_check_n_entries_by_dev_filter br0 1
+	log_test $? 0 "Flush FDB by dev br0 - test br0 entries"
+
+	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
+	log_test $? 0 "Flush FDB by dev br0 - test br1 entries"
+}
+
+bridge_test_flush_by_vlan()
+{
+	local vlan_1=10
+	local vlan_2=20
+	local vlan_1_ent_t0
+	local vlan_2_ent_t0
+
+	$BRIDGE vlan add vid $vlan_1 dev br0 self
+	$BRIDGE vlan add vid $vlan_2 dev br0 self
+
+	vlan_1_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_1" | wc -l)
+	vlan_2_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_2" | wc -l)
+
+	fdb_add_mac_pool_1 br0 vlan $vlan_1
+	fdb_add_mac_pool_2 br0 vlan $vlan_2
+
+	local exp_vlan_1_ent=$(($vlan_1_ent_t0 + $mac_pool_1_len))
+	local exp_vlan_2_ent=$(($vlan_2_ent_t0 + $mac_pool_2_len))
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_1_ent vlan $vlan_1
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
+
+	run_cmd "$BRIDGE fdb flush dev br0 vlan $vlan_1"
+	log_test $? 0 "Flush FDB by dev br0 and vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter br0 0 vlan $vlan_1
+	log_test $? 0 "Test entries with vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
+	log_test $? 0 "Test entries with vlan $vlan_2"
+}
+
+bridge_vxlan_test_flush()
+{
+	local vlan_1=10
+	local dst_ip=192.0.2.1
+
+	$IP link set dev vx10 master br0
+	$BRIDGE vlan add vid $vlan_1 dev br0 self
+	$BRIDGE vlan add vid $vlan_1 dev vx10
+
+	fdb_add_mac_pool_1 vx10 vni 3000 dst $dst_ip self master
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vlan $vlan_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni 3000
+
+	# Such command should fail in VXLAN driver as vlan is not supported,
+	# but the command should flush the entries in the bridge
+	run_cmd "$BRIDGE fdb flush dev vx10 vlan $vlan_1 master self"
+	log_test $? 255 \
+		"Flush FDB by dev vx10, vlan $vlan_1, master and self"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 vlan $vlan_1
+	log_test $? 0 "Test entries with vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip
+	log_test $? 0 "Test entries with dst $dst_ip"
+}
+
 setup()
 {
 	IP="ip -netns ns1"
@@ -656,10 +746,16 @@ setup()
 
 	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
 	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
+
+	$IP link add br0 type bridge vlan_filtering 1
+	$IP link add br1 type bridge vlan_filtering 1
 }
 
 cleanup()
 {
+	$IP link del dev br1
+	$IP link del dev br0
+
 	$IP link del dev vx20
 	$IP link del dev vx10
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Bridge] [PATCH net-next 11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device
@ 2023-10-09 10:06   ` Amit Cohen
  0 siblings, 0 replies; 29+ messages in thread
From: Amit Cohen @ 2023-10-09 10:06 UTC (permalink / raw)
  To: netdev
  Cc: razor, Amit Cohen, mlxsw, dsahern, bridge, idosch,
	linux-kselftest, roopa, kuba, pabeni, shuah, davem

Extend the test to check flushing with bridge device, test flush by device
and by VID.

Add test case for flushing with "self" and "master" and attributes that are
supported only in one driver, this is unrecommended configuration, check it
to verify that user gets an error.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
---
 tools/testing/selftests/net/fdb_flush.sh | 96 ++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/tools/testing/selftests/net/fdb_flush.sh b/tools/testing/selftests/net/fdb_flush.sh
index 3050b031f46d..90e7a29e0476 100755
--- a/tools/testing/selftests/net/fdb_flush.sh
+++ b/tools/testing/selftests/net/fdb_flush.sh
@@ -32,6 +32,9 @@ TESTS="
 	$FLUSH_BY_FLAG_TESTS
 	vxlan_test_flush_by_several_args
 	vxlan_test_flush_by_remote_attributes
+	bridge_test_flush_by_dev
+	bridge_test_flush_by_vlan
+	bridge_vxlan_test_flush
 "
 
 : ${VERBOSE:=0}
@@ -647,6 +650,93 @@ vxlan_test_flush_by_remote_attributes()
 	log_test $? 0 "Check how many entries were flushed"
 }
 
+bridge_test_flush_by_dev()
+{
+	local dst_ip=192.0.2.1
+	local br0_n_ent_t0=$($BRIDGE fdb show dev br0 | wc -l)
+	local br1_n_ent_t0=$($BRIDGE fdb show dev br1 | wc -l)
+
+	fdb_add_mac_pool_1 br0 dst $dst_ip
+	fdb_add_mac_pool_2 br1 dst $dst_ip
+
+	# Each 'fdb add' command adds one extra entry in the bridge with the
+	# default vlan.
+	local exp_br0_n_ent=$(($br0_n_ent_t0 + 2 * $mac_pool_1_len))
+	local exp_br1_n_ent=$(($br1_n_ent_t0 + 2 * $mac_pool_2_len))
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_br0_n_ent
+	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
+
+	run_cmd "$BRIDGE fdb flush dev br0"
+	log_test $? 0 "Flush FDB by dev br0"
+
+	# The default entry should not be flushed
+	fdb_check_n_entries_by_dev_filter br0 1
+	log_test $? 0 "Flush FDB by dev br0 - test br0 entries"
+
+	fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
+	log_test $? 0 "Flush FDB by dev br0 - test br1 entries"
+}
+
+bridge_test_flush_by_vlan()
+{
+	local vlan_1=10
+	local vlan_2=20
+	local vlan_1_ent_t0
+	local vlan_2_ent_t0
+
+	$BRIDGE vlan add vid $vlan_1 dev br0 self
+	$BRIDGE vlan add vid $vlan_2 dev br0 self
+
+	vlan_1_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_1" | wc -l)
+	vlan_2_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_2" | wc -l)
+
+	fdb_add_mac_pool_1 br0 vlan $vlan_1
+	fdb_add_mac_pool_2 br0 vlan $vlan_2
+
+	local exp_vlan_1_ent=$(($vlan_1_ent_t0 + $mac_pool_1_len))
+	local exp_vlan_2_ent=$(($vlan_2_ent_t0 + $mac_pool_2_len))
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_1_ent vlan $vlan_1
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
+
+	run_cmd "$BRIDGE fdb flush dev br0 vlan $vlan_1"
+	log_test $? 0 "Flush FDB by dev br0 and vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter br0 0 vlan $vlan_1
+	log_test $? 0 "Test entries with vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
+	log_test $? 0 "Test entries with vlan $vlan_2"
+}
+
+bridge_vxlan_test_flush()
+{
+	local vlan_1=10
+	local dst_ip=192.0.2.1
+
+	$IP link set dev vx10 master br0
+	$BRIDGE vlan add vid $vlan_1 dev br0 self
+	$BRIDGE vlan add vid $vlan_1 dev vx10
+
+	fdb_add_mac_pool_1 vx10 vni 3000 dst $dst_ip self master
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vlan $vlan_1
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni 3000
+
+	# Such command should fail in VXLAN driver as vlan is not supported,
+	# but the command should flush the entries in the bridge
+	run_cmd "$BRIDGE fdb flush dev vx10 vlan $vlan_1 master self"
+	log_test $? 255 \
+		"Flush FDB by dev vx10, vlan $vlan_1, master and self"
+
+	fdb_check_n_entries_by_dev_filter vx10 0 vlan $vlan_1
+	log_test $? 0 "Test entries with vlan $vlan_1"
+
+	fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip
+	log_test $? 0 "Test entries with dst $dst_ip"
+}
+
 setup()
 {
 	IP="ip -netns ns1"
@@ -656,10 +746,16 @@ setup()
 
 	$IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
 	$IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
+
+	$IP link add br0 type bridge vlan_filtering 1
+	$IP link add br1 type bridge vlan_filtering 1
 }
 
 cleanup()
 {
+	$IP link del dev br1
+	$IP link del dev br0
+
 	$IP link del dev vx20
 	$IP link del dev vx10
 
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-10 18:50   ` Nikolay Aleksandrov
  -1 siblings, 0 replies; 29+ messages in thread
From: Nikolay Aleksandrov @ 2023-10-10 18:50 UTC (permalink / raw)
  To: Amit Cohen, netdev
  Cc: mlxsw, idosch, kuba, davem, dsahern, roopa, shuah, pabeni,
	bridge, linux-kselftest

On 10/9/23 13:06, Amit Cohen wrote:
> The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
> support for FDB flushing in bridge driver. Extend VXLAN driver to support
> FDB flushing also. Add support for filtering by fields which are relevant
> for VXLAN FDBs:
> * Source VNI
> * Nexthop ID
> * 'router' flag
> * Destination VNI
> * Destination Port
> * Destination IP
> 
> Without this set, flush for VXLAN device fails:
> $ bridge fdb flush dev vx10
> RTNETLINK answers: Operation not supported
> 
> With this set, such flush works with the relevant arguments, for example:
> $ bridge fdb flush dev vx10 vni 5000 dst 193.2.2.1
> < flush all vx10 entries with VNI 5000 and destination IP 193.2.2.1>
> 
> Some preparations are required, handle them before adding flushing support
> in VXLAN driver. See more details in commit messages.
> 
> Patch set overview:
> Patch #1 prepares flush policy to be used by VXLAN driver
> Patches #2-#3 are preparations in VXLAN driver
> Patch #4 adds an initial support for flushing in VXLAN driver
> Patches #5-#9 add support for filtering by several attributes
> Patch #10 adds a test for FDB flush with VXLAN
> Patch #11 extends the test to check FDB flush with bridge
> 
> Amit Cohen (11):
>    net: Handle bulk delete policy in bridge driver
>    vxlan: vxlan_core: Make vxlan_flush() more generic for future use
>    vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by
>      default
>    vxlan: vxlan_core: Add support for FDB flush
>    vxlan: vxlan_core: Support FDB flushing by source VNI
>    vxlan: vxlan_core: Support FDB flushing by nexthop ID
>    vxlan: vxlan_core: Support FDB flushing by destination VNI
>    vxlan: vxlan_core: Support FDB flushing by destination port
>    vxlan: vxlan_core: Support FDB flushing by destination IP
>    selftests: Add test cases for FDB flush with VXLAN device
>    selftests: fdb_flush: Add test cases for FDB flush with bridge device
> 
>   drivers/net/vxlan/vxlan_core.c           | 207 +++++-
>   include/linux/netdevice.h                |   8 +-
>   net/bridge/br_fdb.c                      |  29 +-
>   net/bridge/br_private.h                  |   3 +-
>   net/core/rtnetlink.c                     |  27 +-
>   tools/testing/selftests/net/Makefile     |   1 +
>   tools/testing/selftests/net/fdb_flush.sh | 812 +++++++++++++++++++++++
>   7 files changed, 1049 insertions(+), 38 deletions(-)
>   create mode 100755 tools/testing/selftests/net/fdb_flush.sh
> 

Nice use of the flush api. :)
The set looks good to me. For the set:
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Bridge] [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
@ 2023-10-10 18:50   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 29+ messages in thread
From: Nikolay Aleksandrov @ 2023-10-10 18:50 UTC (permalink / raw)
  To: Amit Cohen, netdev
  Cc: mlxsw, dsahern, bridge, idosch, linux-kselftest, roopa, kuba,
	pabeni, shuah, davem

On 10/9/23 13:06, Amit Cohen wrote:
> The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
> support for FDB flushing in bridge driver. Extend VXLAN driver to support
> FDB flushing also. Add support for filtering by fields which are relevant
> for VXLAN FDBs:
> * Source VNI
> * Nexthop ID
> * 'router' flag
> * Destination VNI
> * Destination Port
> * Destination IP
> 
> Without this set, flush for VXLAN device fails:
> $ bridge fdb flush dev vx10
> RTNETLINK answers: Operation not supported
> 
> With this set, such flush works with the relevant arguments, for example:
> $ bridge fdb flush dev vx10 vni 5000 dst 193.2.2.1
> < flush all vx10 entries with VNI 5000 and destination IP 193.2.2.1>
> 
> Some preparations are required, handle them before adding flushing support
> in VXLAN driver. See more details in commit messages.
> 
> Patch set overview:
> Patch #1 prepares flush policy to be used by VXLAN driver
> Patches #2-#3 are preparations in VXLAN driver
> Patch #4 adds an initial support for flushing in VXLAN driver
> Patches #5-#9 add support for filtering by several attributes
> Patch #10 adds a test for FDB flush with VXLAN
> Patch #11 extends the test to check FDB flush with bridge
> 
> Amit Cohen (11):
>    net: Handle bulk delete policy in bridge driver
>    vxlan: vxlan_core: Make vxlan_flush() more generic for future use
>    vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by
>      default
>    vxlan: vxlan_core: Add support for FDB flush
>    vxlan: vxlan_core: Support FDB flushing by source VNI
>    vxlan: vxlan_core: Support FDB flushing by nexthop ID
>    vxlan: vxlan_core: Support FDB flushing by destination VNI
>    vxlan: vxlan_core: Support FDB flushing by destination port
>    vxlan: vxlan_core: Support FDB flushing by destination IP
>    selftests: Add test cases for FDB flush with VXLAN device
>    selftests: fdb_flush: Add test cases for FDB flush with bridge device
> 
>   drivers/net/vxlan/vxlan_core.c           | 207 +++++-
>   include/linux/netdevice.h                |   8 +-
>   net/bridge/br_fdb.c                      |  29 +-
>   net/bridge/br_private.h                  |   3 +-
>   net/core/rtnetlink.c                     |  27 +-
>   tools/testing/selftests/net/Makefile     |   1 +
>   tools/testing/selftests/net/fdb_flush.sh | 812 +++++++++++++++++++++++
>   7 files changed, 1049 insertions(+), 38 deletions(-)
>   create mode 100755 tools/testing/selftests/net/fdb_flush.sh
> 

Nice use of the flush api. :)
The set looks good to me. For the set:
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Bridge] [PATCH net-next 11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device
  2023-10-09 10:06   ` [Bridge] " Amit Cohen
  (?)
@ 2023-10-10 19:11   ` Scott Wadkins
  -1 siblings, 0 replies; 29+ messages in thread
From: Scott Wadkins @ 2023-10-10 19:11 UTC (permalink / raw)
  To: Amit Cohen
  Cc: netdev, razor, bridge, roopa, davem, mlxsw, linux-kselftest,
	idosch, kuba, pabeni, shuah, dsahern

[-- Attachment #1: Type: text/plain, Size: 5088 bytes --]

On Tue, Oct 10, 2023, 11:53 AM Amit Cohen via Bridge <
bridge@lists.linux-foundation.org> wrote:

> Extend the test to check flushing with bridge device, test flush by device
> and by VID.
>
> Add test case for flushing with "self" and "master" and attributes that are
> supported only in one driver, this is unrecommended configuration, check it
> to verify that user gets an error.
>
> Signed-off-by: Amit Cohen <amcohen@nvidia.com>
> ---
>  tools/testing/selftests/net/fdb_flush.sh | 96 ++++++++++++++++++++++++
>  1 file changed, 96 insertions(+)
>
> diff --git a/tools/testing/selftests/net/fdb_flush.sh
> b/tools/testing/selftests/net/fdb_flush.sh
> index 3050b031f46d..90e7a29e0476 100755
> --- a/tools/testing/selftests/net/fdb_flush.sh
> +++ b/tools/testing/selftests/net/fdb_flush.sh
> @@ -32,6 +32,9 @@ TESTS="
>         $FLUSH_BY_FLAG_TESTS
>         vxlan_test_flush_by_several_args
>         vxlan_test_flush_by_remote_attributes
> +       bridge_test_flush_by_dev
> +       bridge_test_flush_by_vlan
> +       bridge_vxlan_test_flush
>  "
>
>  : ${VERBOSE:=0}
> @@ -647,6 +650,93 @@ vxlan_test_flush_by_remote_attributes()
>         log_test $? 0 "Check how many entries were flushed"
>  }
>
> +bridge_test_flush_by_dev()
> +{
> +       local dst_ip=192.0.2.1
> +       local br0_n_ent_t0=$($BRIDGE fdb show dev br0 | wc -l)
> +       local br1_n_ent_t0=$($BRIDGE fdb show dev br1 | wc -l)
> +
> +       fdb_add_mac_pool_1 br0 dst $dst_ip
> +       fdb_add_mac_pool_2 br1 dst $dst_ip
> +
> +       # Each 'fdb add' command adds one extra entry in the bridge with
> the
> +       # default vlan.
> +       local exp_br0_n_ent=$(($br0_n_ent_t0 + 2 * $mac_pool_1_len))
> +       local exp_br1_n_ent=$(($br1_n_ent_t0 + 2 * $mac_pool_2_len))
> +
> +       fdb_check_n_entries_by_dev_filter br0 $exp_br0_n_ent
> +       fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
> +
> +       run_cmd "$BRIDGE fdb flush dev br0"
> +       log_test $? 0 "Flush FDB by dev br0"
> +
> +       # The default entry should not be flushed
> +       fdb_check_n_entries_by_dev_filter br0 1
> +       log_test $? 0 "Flush FDB by dev br0 - test br0 entries"
> +
> +       fdb_check_n_entries_by_dev_filter br1 $exp_br1_n_ent
> +       log_test $? 0 "Flush FDB by dev br0 - test br1 entries"
> +}
> +
> +bridge_test_flush_by_vlan()
> +{
> +       local vlan_1=10
> +       local vlan_2=20
> +       local vlan_1_ent_t0
> +       local vlan_2_ent_t0
> +
> +       $BRIDGE vlan add vid $vlan_1 dev br0 self
> +       $BRIDGE vlan add vid $vlan_2 dev br0 self
> +
> +       vlan_1_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_1" |
> wc -l)
> +       vlan_2_ent_t0=$($BRIDGE fdb show dev br0 | grep "vlan $vlan_2" |
> wc -l)
> +
> +       fdb_add_mac_pool_1 br0 vlan $vlan_1
> +       fdb_add_mac_pool_2 br0 vlan $vlan_2
> +
> +       local exp_vlan_1_ent=$(($vlan_1_ent_t0 + $mac_pool_1_len))
> +       local exp_vlan_2_ent=$(($vlan_2_ent_t0 + $mac_pool_2_len))
> +
> +       fdb_check_n_entries_by_dev_filter br0 $exp_vlan_1_ent vlan $vlan_1
> +       fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
> +
> +       run_cmd "$BRIDGE fdb flush dev br0 vlan $vlan_1"
> +       log_test $? 0 "Flush FDB by dev br0 and vlan $vlan_1"
> +
> +       fdb_check_n_entries_by_dev_filter br0 0 vlan $vlan_1
> +       log_test $? 0 "Test entries with vlan $vlan_1"
> +
> +       fdb_check_n_entries_by_dev_filter br0 $exp_vlan_2_ent vlan $vlan_2
> +       log_test $? 0 "Test entries with vlan $vlan_2"
> +}
> +
> +bridge_vxlan_test_flush()
> +{
> +       local vlan_1=10
> +       local dst_ip=192.0.2.1
> +
> +       $IP link set dev vx10 master br0
> +       $BRIDGE vlan add vid $vlan_1 dev br0 self
> +       $BRIDGE vlan add vid $vlan_1 dev vx10
> +
> +       fdb_add_mac_pool_1 vx10 vni 3000 dst $dst_ip self master
> +
> +       fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vlan $vlan_1
> +       fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len vni 3000
> +
> +       # Such command should fail in VXLAN driver as vlan is not
> supported,
> +       # but the command should flush the entries in the bridge
> +       run_cmd "$BRIDGE fdb flush dev vx10 vlan $vlan_1 master self"
> +       log_test $? 255 \
> +               "Flush FDB by dev vx10, vlan $vlan_1, master and self"
> +
> +       fdb_check_n_entries_by_dev_filter vx10 0 vlan $vlan_1
> +       log_test $? 0 "Test entries with vlan $vlan_1"
> +
> +       fdb_check_n_entries_by_dev_filter vx10 $mac_pool_1_len dst $dst_ip
> +       log_test $? 0 "Test entries with dst $dst_ip"
> +}
> +
>  setup()
>  {
>         IP="ip -netns ns1"
> @@ -656,10 +746,16 @@ setup()
>
>         $IP link add name vx10 type vxlan id 1000 dstport "$VXPORT"
>         $IP link add name vx20 type vxlan id 2000 dstport "$VXPORT"
> +
> +       $IP link add br0 type bridge vlan_filtering 1
> +       $IP link add br1 type bridge vlan_filtering 1
>  }
>
>  cleanup()
>  {
> +       $IP link del dev br1
> +       $IP link del dev br0
> +
>         $IP link del dev vx20
>         $IP link del dev vx10
>
> --
> 2.40.1
>
>

[-- Attachment #2: Type: text/html, Size: 6377 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
  2023-10-09 10:06 ` [Bridge] " Amit Cohen
@ 2023-10-13  9:10   ` patchwork-bot+netdevbpf
  -1 siblings, 0 replies; 29+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-10-13  9:10 UTC (permalink / raw)
  To: Amit Cohen
  Cc: netdev, mlxsw, idosch, kuba, davem, dsahern, roopa, razor, shuah,
	pabeni, bridge, linux-kselftest

Hello:

This series was applied to netdev/net-next.git (main)
by David S. Miller <davem@davemloft.net>:

On Mon, 9 Oct 2023 13:06:07 +0300 you wrote:
> The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
> support for FDB flushing in bridge driver. Extend VXLAN driver to support
> FDB flushing also. Add support for filtering by fields which are relevant
> for VXLAN FDBs:
> * Source VNI
> * Nexthop ID
> * 'router' flag
> * Destination VNI
> * Destination Port
> * Destination IP
> 
> [...]

Here is the summary with links:
  - [net-next,01/11] net: Handle bulk delete policy in bridge driver
    https://git.kernel.org/netdev/net-next/c/38985e8c278b
  - [net-next,02/11] vxlan: vxlan_core: Make vxlan_flush() more generic for future use
    https://git.kernel.org/netdev/net-next/c/bfe36bf7811c
  - [net-next,03/11] vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by default
    https://git.kernel.org/netdev/net-next/c/77b613efcc81
  - [net-next,04/11] vxlan: vxlan_core: Add support for FDB flush
    https://git.kernel.org/netdev/net-next/c/d324eb9cec84
  - [net-next,05/11] vxlan: vxlan_core: Support FDB flushing by source VNI
    https://git.kernel.org/netdev/net-next/c/a0f89d5e68b6
  - [net-next,06/11] vxlan: vxlan_core: Support FDB flushing by nexthop ID
    https://git.kernel.org/netdev/net-next/c/36c111233b56
  - [net-next,07/11] vxlan: vxlan_core: Support FDB flushing by destination VNI
    https://git.kernel.org/netdev/net-next/c/c499fccb71cb
  - [net-next,08/11] vxlan: vxlan_core: Support FDB flushing by destination port
    https://git.kernel.org/netdev/net-next/c/ac0db4ddd0cb
  - [net-next,09/11] vxlan: vxlan_core: Support FDB flushing by destination IP
    https://git.kernel.org/netdev/net-next/c/2dcd22023cab
  - [net-next,10/11] selftests: Add test cases for FDB flush with VXLAN device
    https://git.kernel.org/netdev/net-next/c/96eece693330
  - [net-next,11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device
    https://git.kernel.org/netdev/net-next/c/f826f2a2ee1e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Bridge] [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing
@ 2023-10-13  9:10   ` patchwork-bot+netdevbpf
  0 siblings, 0 replies; 29+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-10-13  9:10 UTC (permalink / raw)
  To: Amit Cohen
  Cc: bridge, razor, netdev, dsahern, roopa, mlxsw, linux-kselftest,
	idosch, kuba, pabeni, shuah, davem

Hello:

This series was applied to netdev/net-next.git (main)
by David S. Miller <davem@davemloft.net>:

On Mon, 9 Oct 2023 13:06:07 +0300 you wrote:
> The merge commit 92716869375b ("Merge branch 'br-flush-filtering'") added
> support for FDB flushing in bridge driver. Extend VXLAN driver to support
> FDB flushing also. Add support for filtering by fields which are relevant
> for VXLAN FDBs:
> * Source VNI
> * Nexthop ID
> * 'router' flag
> * Destination VNI
> * Destination Port
> * Destination IP
> 
> [...]

Here is the summary with links:
  - [net-next,01/11] net: Handle bulk delete policy in bridge driver
    https://git.kernel.org/netdev/net-next/c/38985e8c278b
  - [net-next,02/11] vxlan: vxlan_core: Make vxlan_flush() more generic for future use
    https://git.kernel.org/netdev/net-next/c/bfe36bf7811c
  - [net-next,03/11] vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by default
    https://git.kernel.org/netdev/net-next/c/77b613efcc81
  - [net-next,04/11] vxlan: vxlan_core: Add support for FDB flush
    https://git.kernel.org/netdev/net-next/c/d324eb9cec84
  - [net-next,05/11] vxlan: vxlan_core: Support FDB flushing by source VNI
    https://git.kernel.org/netdev/net-next/c/a0f89d5e68b6
  - [net-next,06/11] vxlan: vxlan_core: Support FDB flushing by nexthop ID
    https://git.kernel.org/netdev/net-next/c/36c111233b56
  - [net-next,07/11] vxlan: vxlan_core: Support FDB flushing by destination VNI
    https://git.kernel.org/netdev/net-next/c/c499fccb71cb
  - [net-next,08/11] vxlan: vxlan_core: Support FDB flushing by destination port
    https://git.kernel.org/netdev/net-next/c/ac0db4ddd0cb
  - [net-next,09/11] vxlan: vxlan_core: Support FDB flushing by destination IP
    https://git.kernel.org/netdev/net-next/c/2dcd22023cab
  - [net-next,10/11] selftests: Add test cases for FDB flush with VXLAN device
    https://git.kernel.org/netdev/net-next/c/96eece693330
  - [net-next,11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device
    https://git.kernel.org/netdev/net-next/c/f826f2a2ee1e

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2023-10-13  9:10 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-09 10:06 [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing Amit Cohen
2023-10-09 10:06 ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 01/11] net: Handle bulk delete policy in bridge driver Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 02/11] vxlan: vxlan_core: Make vxlan_flush() more generic for future use Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 03/11] vxlan: vxlan_core: Do not skip default entry in vxlan_flush() by default Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 04/11] vxlan: vxlan_core: Add support for FDB flush Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 05/11] vxlan: vxlan_core: Support FDB flushing by source VNI Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 06/11] vxlan: vxlan_core: Support FDB flushing by nexthop ID Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 07/11] vxlan: vxlan_core: Support FDB flushing by destination VNI Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 08/11] vxlan: vxlan_core: Support FDB flushing by destination port Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 09/11] vxlan: vxlan_core: Support FDB flushing by destination IP Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 10/11] selftests: Add test cases for FDB flush with VXLAN device Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-09 10:06 ` [PATCH net-next 11/11] selftests: fdb_flush: Add test cases for FDB flush with bridge device Amit Cohen
2023-10-09 10:06   ` [Bridge] " Amit Cohen
2023-10-10 19:11   ` Scott Wadkins
2023-10-10 18:50 ` [PATCH net-next 00/11] Extend VXLAN driver to support FDB flushing Nikolay Aleksandrov
2023-10-10 18:50   ` [Bridge] " Nikolay Aleksandrov
2023-10-13  9:10 ` patchwork-bot+netdevbpf
2023-10-13  9:10   ` [Bridge] " patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.