Skip to content

Commit 705aa42

Browse files
authored
Merge pull request #1199 from hedrok/T8426-evpn-anycast-arp
T8426: FRR support for EVPN Anycast
2 parents 0b27f39 + f67c560 commit 705aa42

1 file changed

Lines changed: 207 additions & 0 deletions

File tree

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
From 0ed0db22759e229698ce266c6535be407c865737 Mon Sep 17 00:00:00 2001
2+
From: Kyrylo Yatsenko <hedrok@gmail.com>
3+
Date: Wed, 27 May 2026 18:21:04 +0300
4+
Subject: [PATCH] zebra: enhance MACVLAN support in EVPN
5+
6+
MACVLAN interface can be used in EVPN anycast topology.
7+
8+
To support this:
9+
10+
* Add MACVLAN support to zebra_neigh_ipaddr_update: get linked
11+
interface, and process this linked interface as SVI in the rest of
12+
function
13+
* In zebra_evpn_read_mac_neigh call neigh_read_for_vlan for VRR
14+
interface too
15+
* Add ARP entry on VRR interface in zebra_evpn_rem_neigh_install and
16+
zebra_evpn_neigh_uninstall
17+
18+
Signed-off-by: Kyrylo Yatsenko <hedrok@gmail.com>
19+
---
20+
zebra/zebra_evpn.c | 10 +++----
21+
zebra/zebra_evpn_neigh.c | 11 ++++++++
22+
zebra/zebra_neigh.c | 56 +++++++++++++++++++++++++++++-----------
23+
3 files changed, 57 insertions(+), 20 deletions(-)
24+
25+
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
26+
index 258e818ec5..7f8f77b2c2 100644
27+
--- a/zebra/zebra_evpn.c
28+
+++ b/zebra/zebra_evpn.c
29+
@@ -963,13 +963,13 @@ void zebra_evpn_read_mac_neigh(struct zebra_evpn *zevpn, struct interface *ifp)
30+
zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
31+
32+
/* Add VRR MAC-IP - if any*/
33+
- if (advertise_gw_macip_enabled(zevpn)) {
34+
- vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
35+
- if (vrr_if)
36+
- zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
37+
- }
38+
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
39+
+ if (vrr_if && advertise_gw_macip_enabled(zevpn))
40+
+ zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
41+
42+
neigh_read_for_vlan(zns, vlan_if);
43+
+ if (vrr_if)
44+
+ neigh_read_for_vlan(zns, vrr_if);
45+
}
46+
}
47+
48+
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
49+
index d66aad50d8..b21aae76aa 100644
50+
--- a/zebra/zebra_evpn_neigh.c
51+
+++ b/zebra/zebra_evpn_neigh.c
52+
@@ -30,6 +30,7 @@
53+
#include "zebra/zebra_evpn_mh.h"
54+
#include "zebra/zebra_evpn_neigh.h"
55+
#include "zebra/zebra_evpn_mac.h"
56+
+#include "zebra/zebra_evpn_vxlan.h"
57+
58+
DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "EVI Neighbor");
59+
60+
@@ -149,6 +150,7 @@ int zebra_evpn_rem_neigh_install(struct zebra_evpn *zevpn,
61+
struct zebra_neigh *n, bool was_static)
62+
{
63+
struct interface *vlan_if;
64+
+ struct interface *vrr_if = NULL;
65+
int flags;
66+
int ret = 0;
67+
68+
@@ -166,6 +168,10 @@ int zebra_evpn_rem_neigh_install(struct zebra_evpn *zevpn,
69+
70+
dplane_rem_neigh_add(vlan_if, &n->ip, &n->emac, flags, was_static);
71+
72+
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
73+
+ if (vrr_if)
74+
+ dplane_rem_neigh_add(vrr_if, &n->ip, &n->emac, flags, was_static);
75+
+
76+
return ret;
77+
}
78+
79+
@@ -858,6 +864,7 @@ static int zebra_evpn_neigh_uninstall(struct zebra_evpn *zevpn,
80+
struct zebra_neigh *n)
81+
{
82+
struct interface *vlan_if;
83+
+ struct interface *vrr_if = NULL;
84+
85+
if (!(n->flags & ZEBRA_NEIGH_REMOTE))
86+
return 0;
87+
@@ -871,6 +878,10 @@ static int zebra_evpn_neigh_uninstall(struct zebra_evpn *zevpn,
88+
89+
dplane_rem_neigh_delete(vlan_if, &n->ip);
90+
91+
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
92+
+ if (vrr_if)
93+
+ dplane_rem_neigh_delete(vrr_if, &n->ip);
94+
+
95+
return 0;
96+
}
97+
98+
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
99+
index 6ba4aed7f9..dfb951da8b 100644
100+
--- a/zebra/zebra_neigh.c
101+
+++ b/zebra/zebra_neigh.c
102+
@@ -370,12 +370,14 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
103+
ns_id_t ns_id;
104+
int32_t ndm_ifindex;
105+
struct interface *ifp;
106+
+ struct interface *svi_ifp;
107+
struct zebra_if *zif;
108+
+ struct zebra_if *zsvi_if;
109+
uint16_t ndm_state;
110+
uint32_t ndm_family;
111+
int l2_len;
112+
union sockunion link_layer_ipv4;
113+
- struct interface *link_if;
114+
+ struct interface *link_if = NULL;
115+
struct ethaddr mac;
116+
bool is_own;
117+
bool is_router;
118+
@@ -432,6 +434,28 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
119+
if (op == DPLANE_OP_NEIGH_DISCOVER)
120+
return;
121+
122+
+ /* First preprocess MACVLAN case: just set svi_ifp to linked interface if
123+
+ * it is MACVLAN
124+
+ */
125+
+ if (IS_ZEBRA_IF_MACVLAN(ifp)) {
126+
+ svi_ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), zif->link_ifindex);
127+
+ if (svi_ifp && svi_ifp->info) {
128+
+ zsvi_if = (struct zebra_if *)svi_ifp->info;
129+
+ if (IS_ZEBRA_DEBUG_KERNEL)
130+
+ zlog_debug(" Neighbor Entry received on MACVLAN %s, processing on SVI %s",
131+
+ ifp->name, svi_ifp->name);
132+
+ } else {
133+
+ svi_ifp = NULL;
134+
+ zsvi_if = NULL;
135+
+ if (IS_ZEBRA_DEBUG_KERNEL)
136+
+ zlog_debug(" Neighbor Entry received on MACVLAN %s, but linked interface not found, ignoring",
137+
+ ifp->name);
138+
+ }
139+
+ } else {
140+
+ svi_ifp = ifp;
141+
+ zsvi_if = zif;
142+
+ }
143+
+
144+
/* The neighbor is present on an SVI. From this, we locate the
145+
* underlying
146+
* bridge because we're only interested in neighbors on a VxLAN bridge.
147+
@@ -443,17 +467,19 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
148+
* interface
149+
* itself
150+
*/
151+
- if (IS_ZEBRA_IF_VLAN(ifp)) {
152+
- link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), zif->link_ifindex);
153+
- if (!link_if)
154+
- return;
155+
- } else if (IS_ZEBRA_IF_BRIDGE(ifp))
156+
- link_if = ifp;
157+
- else {
158+
- link_if = NULL;
159+
- if (IS_ZEBRA_DEBUG_KERNEL)
160+
- zlog_debug(
161+
- " Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
162+
+ if (svi_ifp) {
163+
+ if (IS_ZEBRA_IF_VLAN(svi_ifp)) {
164+
+ link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
165+
+ zsvi_if->link_ifindex);
166+
+ if (!link_if)
167+
+ return;
168+
+ } else if (IS_ZEBRA_IF_BRIDGE(svi_ifp))
169+
+ link_if = svi_ifp;
170+
+ else {
171+
+ if (IS_ZEBRA_DEBUG_KERNEL)
172+
+ zlog_debug(
173+
+ " Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
174+
+ }
175+
}
176+
177+
if (op == DPLANE_OP_NEIGH_IP_INSTALL) {
178+
@@ -477,7 +503,7 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
179+
zebra_neigh_add(ifp, &ip, &mac);
180+
181+
if (link_if)
182+
- zebra_vxlan_handle_kernel_neigh_update(ifp, link_if, &ip, &mac,
183+
+ zebra_vxlan_handle_kernel_neigh_update(svi_ifp, link_if, &ip, &mac,
184+
ndm_state, is_own, is_router,
185+
local_inactive, dp_static);
186+
return;
187+
@@ -485,7 +511,7 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
188+
189+
zebra_neigh_del(ifp, &ip);
190+
if (link_if)
191+
- zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
192+
+ zebra_vxlan_handle_kernel_neigh_del(svi_ifp, link_if, &ip);
193+
return;
194+
}
195+
196+
@@ -499,7 +525,7 @@ static void zebra_neigh_ipaddr_update(struct zebra_dplane_ctx *ctx)
197+
*/
198+
zebra_neigh_del(ifp, &ip);
199+
if (link_if)
200+
- zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
201+
+ zebra_vxlan_handle_kernel_neigh_del(svi_ifp, link_if, &ip);
202+
}
203+
204+
static void zebra_neigh_macfdb_update(struct zebra_dplane_ctx *ctx)
205+
--
206+
2.51.2
207+

0 commit comments

Comments
 (0)