[<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