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