public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb
@ 2025-08-16  3:11 Mrinmoy Ghosh
  2025-08-16 16:20 ` Stephen Hemminger
  0 siblings, 1 reply; 3+ messages in thread
From: Mrinmoy Ghosh @ 2025-08-16  3:11 UTC (permalink / raw)
  To: netdev; +Cc: bridge, mrghosh, mrinmoy_g, Mike Mallin, Patrice Brissette

From: Mrinmoy Ghosh <mrinmoy_g@hotmail.com>

This is to add optional "protocol" field for bridge fdb entries.
The introduction of the 'protocol' field in the bridge FDB for EVPN Multihome, addresses the need to distinguish between MAC addresses learned via the control plane and those learned via the data plane with data plane aging. Specifically:
* A MAC address in an EVPN Multihome environment can be learned either through the control plane (static MAC) or the data plane (dynamic MAC with aging).
* The 'protocol' field uses values such as 'HW' for data plane dynamic MACs and 'ZEBRA' for control plane static MACs.
* This distinction allows the application to manage the MAC address state machine effectively during transitions, which can occur due to traffic hashing between EVPN Multihome peers or mobility of MAC addresses across EVPN peers.
* By identifying the source of the MAC learning (control plane vs. data plane), the system can handle MAC aging and mobility more accurately, ensuring synchronization between control and data planes and improving stability and reliability in MAC route handling.

This mechanism supports the complex state transitions and synchronization required in EVPN Multihome scenarios, where MAC addresses may move or be learned differently depending on network events and traffic patterns.

This change:
fdb.c: Allows 'bridge fdb [add | replace]' with optional protocol field.

e.g:

$ bridge -d fdb show dev hostbond2 | grep 00:00:00:00:00:88
00:00:00:00:00:88 vlan 1000 extern_learn master br1000 proto hw

$ bridge -d -j -p fdb show dev hostbond2

...

[ {
        "mac": "00:00:00:00:00:88",
        "vlan": 1000,
        "flags": [ "extern_learn" ],
        "master": "br1000",
        "flags_ext": [ ],
        "protocol": "hw",
        "state": ""
    },{
...

Transition to Zebra:

$ bridge -d fdb show dev hostbond2 | grep 00:00:00:00:00:88
00:00:00:00:00:88 vlan 1000 extern_learn master br1000 proto zebra

$ bridge -d -j -p fdb show dev hostbond2
...
[ {
        "mac": "00:00:00:00:00:88",
        "vlan": 1000,
        "flags": [ "extern_learn" ],
        "master": "br1000",
        "flags_ext": [ ],
        "protocol": "zebra",
        "state": ""
    },
...

Signed-off-by: Mrinmoy Ghosh <mrghosh@cisco.com>
Co-authored-by: Mrinmoy Ghosh <mrinmoy_g@hotmail.com>
Co-authored-by: Mike Mallin <mmallin@cisco.com>
Co-authored-by: Patrice Brissette <pbrisset@cisco.com>
---
 bridge/fdb.c                   | 20 +++++++++++++++++++-
 include/uapi/linux/rtnetlink.h |  1 +
 lib/rt_names.c                 |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index d57b5750..9c5dd763 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -41,7 +41,7 @@ static void usage(void)
 		"              [ sticky ] [ local | static | dynamic ] [ vlan VID ]\n"
 		"              { [ dst IPADDR ] [ port PORT] [ vni VNI ] | [ nhid NHID ] }\n"
 		"	       [ via DEV ] [ src_vni VNI ] [ activity_notify ]\n"
-		"	       [ inactive ] [ norefresh ]\n"
+		"	       [ inactive ] [ norefresh ] [ protocol PROTO ]\n"
 		"       bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ]\n"
 		"              [ state STATE ] [ dynamic ] ]\n"
 		"       bridge fdb get [ to ] LLADDR [ br BRDEV ] { brport | dev } DEV\n"
@@ -306,8 +306,18 @@ int print_fdb(struct nlmsghdr *n, void *arg)
 		print_string(PRINT_ANY, "master", "master %s ",
 			     ll_index_to_name(rta_getattr_u32(tb[NDA_MASTER])));
 
+	if (tb[NDA_PROTOCOL]) {
+		__u8 proto = rta_getattr_u8(tb[NDA_PROTOCOL]);
+		if (proto != RTPROT_UNSPEC) {
+			SPRINT_BUF(b1);
+			print_string(PRINT_ANY, "protocol", "proto %s ",
+					 rtnl_rtprot_n2a(proto, b1, sizeof(b1)));
+		}
+	}
 	print_string(PRINT_ANY, "state", "%s\n",
 			   state_n2a(r->ndm_state));
+
+
 	close_json_object();
 	fflush(fp);
 	return 0;
@@ -478,6 +488,7 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
 	char *endptr;
 	short vid = -1;
 	__u32 nhid = 0;
+	__u32 proto = RTPROT_UNSPEC;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "dev") == 0) {
@@ -555,6 +566,10 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
 			inactive = true;
 		} else if (strcmp(*argv, "norefresh") == 0) {
 			norefresh = true;
+		} else if (matches(*argv, "protocol") == 0) {
+			NEXT_ARG();
+			if (rtnl_rtprot_a2n(&proto, *argv))
+				invarg("\"protocol\" value is invalid\n", *argv);
 		} else {
 			if (strcmp(*argv, "to") == 0)
 				NEXT_ARG();
@@ -615,6 +630,9 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
 	if (via)
 		addattr32(&req.n, sizeof(req), NDA_IFINDEX, via);
 
+	if (proto != RTPROT_UNSPEC)
+		addattr8(&req.n, sizeof(req), NDA_PROTOCOL, proto);
+
 	req.ndm.ndm_ifindex = ll_name_to_index(d);
 	if (!req.ndm.ndm_ifindex)
 		return nodev(d);
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 085bb139..1ff9dbee 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -314,6 +314,7 @@ enum {
 #define RTPROT_OSPF		188	/* OSPF Routes */
 #define RTPROT_RIP		189	/* RIP Routes */
 #define RTPROT_EIGRP		192	/* EIGRP Routes */
+#define RTPROT_HW		193	/* HW Generated Routes */
 
 /* rtm_scope
 
diff --git a/lib/rt_names.c b/lib/rt_names.c
index 7dc194b1..b9bc1b50 100644
--- a/lib/rt_names.c
+++ b/lib/rt_names.c
@@ -148,6 +148,7 @@ static char *rtnl_rtprot_tab[256] = {
 	[RTPROT_OSPF]	    = "ospf",
 	[RTPROT_RIP]	    = "rip",
 	[RTPROT_EIGRP]	    = "eigrp",
+	[RTPROT_HW]	    = "hw",
 };
 
 struct tabhash {
-- 
2.43.0


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

* Re: [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb
  2025-08-16  3:11 [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb Mrinmoy Ghosh
@ 2025-08-16 16:20 ` Stephen Hemminger
  2025-08-18 19:47   ` Mrinmoy Ghosh (mrghosh)
  0 siblings, 1 reply; 3+ messages in thread
From: Stephen Hemminger @ 2025-08-16 16:20 UTC (permalink / raw)
  To: Mrinmoy Ghosh; +Cc: netdev, bridge, mrinmoy_g, Mike Mallin, Patrice Brissette

On Sat, 16 Aug 2025 03:11:45 +0000
Mrinmoy Ghosh <mrghosh@cisco.com> wrote:

> diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
> index 085bb139..1ff9dbee 100644
> --- a/include/uapi/linux/rtnetlink.h
> +++ b/include/uapi/linux/rtnetlink.h
> @@ -314,6 +314,7 @@ enum {
>  #define RTPROT_OSPF		188	/* OSPF Routes */
>  #define RTPROT_RIP		189	/* RIP Routes */
>  #define RTPROT_EIGRP		192	/* EIGRP Routes */
> +#define RTPROT_HW		193	/* HW Generated Routes */
>  
>  /* rtm_scope
>  
> diff --git a/lib/rt_names.c b/lib/rt_names.c
> index 7dc194b1..b9bc1b50 100644
> --- a/lib/rt_names.c
> +++ b/lib/rt_names.c
> @@ -148,6 +148,7 @@ static char *rtnl_rtprot_tab[256] = {
>  	[RTPROT_OSPF]	    = "ospf",
>  	[RTPROT_RIP]	    = "rip",
>  	[RTPROT_EIGRP]	    = "eigrp",
> +	[RTPROT_HW]	    = "hw",
>  };
>  
>  struct tabhash {

This is iproute2-next material.

Where is the kernel patch for this?
Iproute headers are synced from kernel headers.

If you add new RTPROT entry also need new line into etc/iproute2/rt_protos



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

* RE: [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb
  2025-08-16 16:20 ` Stephen Hemminger
@ 2025-08-18 19:47   ` Mrinmoy Ghosh (mrghosh)
  0 siblings, 0 replies; 3+ messages in thread
From: Mrinmoy Ghosh (mrghosh) @ 2025-08-18 19:47 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev@vger.kernel.org, bridge@lists.linux-foundation.org,
	mrinmoy_g@hotmail.com, Patrice Brissette (pbrisset)

Hi Stephen,

Thanks for the review.
The kernel patch is in:
https://lore.kernel.org/netdev/20250818175258.275997-1-mrghosh@cisco.com/T/#u

I have created a new patch review request for iproute2-next. Updated, the etc/iproute2/rt_protos based on your review comments:
https://lore.kernel.org/netdev/20250818193756.277327-1-mrghosh@cisco.com/T/#u

Thanks,
Mrinmoy

-----Original Message-----
From: Stephen Hemminger <stephen@networkplumber.org> 
Sent: Saturday, August 16, 2025 12:21 PM
To: Mrinmoy Ghosh (mrghosh) <mrghosh@cisco.com>
Cc: netdev@vger.kernel.org; bridge@lists.linux-foundation.org; mrinmoy_g@hotmail.com; Mike Mallin (mmallin) <mmallin@cisco.com>; Patrice Brissette (pbrisset) <pbrisset@cisco.com>
Subject: Re: [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb

On Sat, 16 Aug 2025 03:11:45 +0000
Mrinmoy Ghosh <mrghosh@cisco.com> wrote:

> diff --git a/include/uapi/linux/rtnetlink.h 
> b/include/uapi/linux/rtnetlink.h index 085bb139..1ff9dbee 100644
> --- a/include/uapi/linux/rtnetlink.h
> +++ b/include/uapi/linux/rtnetlink.h
> @@ -314,6 +314,7 @@ enum {
>  #define RTPROT_OSPF		188	/* OSPF Routes */
>  #define RTPROT_RIP		189	/* RIP Routes */
>  #define RTPROT_EIGRP		192	/* EIGRP Routes */
> +#define RTPROT_HW		193	/* HW Generated Routes */
>  
>  /* rtm_scope
>  
> diff --git a/lib/rt_names.c b/lib/rt_names.c index 7dc194b1..b9bc1b50 
> 100644
> --- a/lib/rt_names.c
> +++ b/lib/rt_names.c
> @@ -148,6 +148,7 @@ static char *rtnl_rtprot_tab[256] = {
>  	[RTPROT_OSPF]	    = "ospf",
>  	[RTPROT_RIP]	    = "rip",
>  	[RTPROT_EIGRP]	    = "eigrp",
> +	[RTPROT_HW]	    = "hw",
>  };
>  
>  struct tabhash {

This is iproute2-next material.

Where is the kernel patch for this?
Iproute headers are synced from kernel headers.

If you add new RTPROT entry also need new line into etc/iproute2/rt_protos



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

end of thread, other threads:[~2025-08-18 19:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-16  3:11 [PATCH iproute2] bridge:fdb: Protocol field in bridge fdb Mrinmoy Ghosh
2025-08-16 16:20 ` Stephen Hemminger
2025-08-18 19:47   ` Mrinmoy Ghosh (mrghosh)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox