lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250818193756.277327-1-mrghosh@cisco.com>
Date: Mon, 18 Aug 2025 19:37:56 +0000
From: Mrinmoy Ghosh <mrghosh@...co.com>
To: netdev@...r.kernel.org,
	stephen@...workplumber.org
Cc: bridge@...ts.linux-foundation.org,
	Mrinmoy Ghosh <mrghosh@...co.com>,
	Mrinmoy Ghosh <mrinmoy_g@...mail.com>,
	Mike Mallin <mmallin@...co.com>,
	Patrice Brissette <pbrisset@...co.com>
Subject: [PATCH iproute2-next] bridge:fdb: Protocol field in bridge fdb

This is to add optional "protocol" field for bridge fdb entries.
The introduction of the 'protocol' field in the bridge FDB for EVPN Multihome,
resses the need to distinguish between MAC addresses learned via the control p
 and those learned via the data plane with data plane aging. Specifically:
    * A MAC address in an EVPN Multihome environment can be learned either thr
 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 MAC
d 'ZEBRA' for control plane static MACs.
    * This distinction allows the application to manage the MAC address state
ine effectively during transitions, which can occur due to traffic hashing bet
 EVPN Multihome peers or mobility of MAC addresses across EVPN peers.
    * By identifying the source of the MAC learning (control plane vs. data pl
, the system can handle MAC aging and mobility more accurately, ensuring synch
zation between control and data planes and improving stability and reliability
MAC route handling.

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

Change Summary:
fdb.c: Allows 'bridge fdb [add | replac ]' with optional protocol field.
       print 'proto' with 'bridge fdb show' except if proto is RTPROT_UNSPEC
rt_protos : new RT proto 'hw'
rtnetlink.h: new RT Proto RTPROT_HW definition
rt_names.c: String representation of new RT proto 'hw' definition

e.g:
 $ bridge fdb add 00:00:00:00:00:88 dev hostbond2 vlan 1000 master dynamic extern_learn proto hw

$ 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 fdb replace  00:00:00:00:00:88 dev hostbond2 vlan 1000 master dynamic extern_learn proto 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": ""
    },
...

Kernel Change Patch review: https://lore.kernel.org/netdev/20250818175258.275997-1-mrghosh@cisco.com/T/#u

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

diff --git a/bridge/fdb.c b/bridge/fdb.c
index d57b5750..b308fe7d 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,6 +306,14 @@ 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();
@@ -478,6 +486,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 +564,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 +628,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/etc/iproute2/rt_protos b/etc/iproute2/rt_protos
index 48ab9746..7ec06e1e 100644
--- a/etc/iproute2/rt_protos
+++ b/etc/iproute2/rt_protos
@@ -24,3 +24,4 @@
 188	ospf
 189	rip
 192	eigrp
+193	hw
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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ