]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vxlan.c
Merge pull request #11843 from ARShreenidhi/ecmp_testcase
[mirror_frr.git] / zebra / zebra_vxlan.c
CommitLineData
13d60d35 1/*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
43e52561 25#include "hash.h"
13d60d35 26#include "if.h"
43e52561 27#include "jhash.h"
13d60d35 28#include "linklist.h"
43e52561
QY
29#include "log.h"
30#include "memory.h"
31#include "prefix.h"
13d60d35 32#include "stream.h"
43e52561 33#include "table.h"
13d60d35 34#include "vlan.h"
35#include "vxlan.h"
68e33151
CS
36#ifdef GNU_LINUX
37#include <linux/neighbour.h>
38#endif
9bee0232 39#include "lib/printfrr.h"
13d60d35 40
89272910 41#include "zebra/zebra_router.h"
43e52561
QY
42#include "zebra/debug.h"
43#include "zebra/interface.h"
13d60d35 44#include "zebra/rib.h"
45#include "zebra/rt.h"
43e52561
QY
46#include "zebra/rt_netlink.h"
47#include "zebra/zebra_errors.h"
48#include "zebra/zebra_l2.h"
13d60d35 49#include "zebra/zebra_ns.h"
13d60d35 50#include "zebra/zebra_vrf.h"
13d60d35 51#include "zebra/zebra_vxlan.h"
b2998086
PR
52#include "zebra/zebra_evpn.h"
53#include "zebra/zebra_evpn_mac.h"
54#include "zebra/zebra_evpn_neigh.h"
43e52561 55#include "zebra/zebra_vxlan_private.h"
ce5160c0 56#include "zebra/zebra_evpn_mh.h"
8b5fdf2e 57#include "zebra/zebra_evpn_vxlan.h"
3801e764 58#include "zebra/zebra_router.h"
13d60d35 59
6134fd82 60DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
b7cfce93 61DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
b2998086 62DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC");
7cbae20a 63DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor");
8a93734c 64DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");
db889978 65DEFINE_MTYPE_STATIC(ZEBRA, EVPN_VTEP, "zebra VxLAN VTEP IP");
13d60d35 66
3198b2b3 67DEFINE_HOOK(zebra_rmac_update,
05843a27 68 (struct zebra_mac * rmac, struct zebra_l3vni *zl3vni, bool delete,
3198b2b3
DS
69 const char *reason),
70 (rmac, zl3vni, delete, reason));
a780a738 71
13d60d35 72/* static function declarations */
87d76d54
PR
73static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
74 void **args);
72de4110 75static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
c0e519d3 76 json_object *json);
3198b2b3 77static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
316f4ca4 78 json_object *json);
87d76d54 79static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt);
d62a17ae 80
b7cfce93 81/* l3-vni next-hop neigh related APIs */
72de4110
DS
82static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
83 const struct ipaddr *ip);
b7cfce93 84static void *zl3vni_nh_alloc(void *p);
72de4110
DS
85static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
86 const struct ipaddr *vtep_ip,
87 const struct ethaddr *rmac);
88static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
89static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n);
90static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
91 struct zebra_neigh *n);
b7cfce93
MK
92
93/* l3-vni rmac related APIs */
e3b78da8 94static void zl3vni_print_rmac_hash(struct hash_bucket *, void *);
05843a27 95static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
3198b2b3 96 const struct ethaddr *rmac);
b7cfce93 97static void *zl3vni_rmac_alloc(void *p);
05843a27 98static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
3198b2b3 99 const struct ethaddr *rmac);
05843a27
DS
100static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac);
101static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
102 struct zebra_mac *zrmac);
103static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
3198b2b3 104 struct zebra_mac *zrmac);
b7cfce93
MK
105
106/* l3-vni related APIs*/
b7cfce93 107static void *zl3vni_alloc(void *p);
05843a27
DS
108static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
109static int zl3vni_del(struct zebra_l3vni *zl3vni);
110static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
111static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
b7cfce93 112
87d76d54 113static void zevpn_build_hash_table(void);
d8b87afe 114static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
015d264c
AK
115static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
116static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
117 struct in_addr sip, struct in_addr mcast_grp);
847f168d
DS
118static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
119 struct in_addr sip,
120 struct in_addr mcast_grp);
abfa0a96
AK
121static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
122 struct in_addr mcast_grp);
123static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
124 struct in_addr mcast_grp);
0c16fb72 125static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);
13d60d35 126
b2ee2b71
AK
127bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
128{
129 return zvrf->dup_addr_detect && zebra_evpn_mh_do_dup_addr_detect();
130}
131
13d60d35 132/* Private functions */
5e1b0650 133static int host_rb_entry_compare(const struct host_rb_entry *hle1,
85442b09 134 const struct host_rb_entry *hle2)
5e1b0650
DS
135{
136 if (hle1->p.family < hle2->p.family)
137 return -1;
138
139 if (hle1->p.family > hle2->p.family)
140 return 1;
141
142 if (hle1->p.prefixlen < hle2->p.prefixlen)
143 return -1;
144
145 if (hle1->p.prefixlen > hle2->p.prefixlen)
146 return 1;
147
148 if (hle1->p.family == AF_INET) {
149 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
150 return -1;
151
152 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
153 return 1;
154
155 return 0;
2acc2310
DS
156 } else if (hle1->p.family == AF_INET6) {
157 return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
158 IPV6_MAX_BYTELEN);
7bfa7d02 159 } else if (hle1->p.family == AF_EVPN) {
82732723
AK
160 uint8_t family1;
161 uint8_t family2;
162
163 /* two (v4/v6) dummy prefixes of route_type BGP_EVPN_AD_ROUTE
164 * are used for all nexthops associated with a non-zero ESI
7bfa7d02 165 */
82732723
AK
166 family1 = is_evpn_prefix_ipaddr_v4(
167 (const struct prefix_evpn *)&hle1->p)
168 ? AF_INET
169 : AF_INET6;
170 family2 = is_evpn_prefix_ipaddr_v4(
171 (const struct prefix_evpn *)&hle2->p)
172 ? AF_INET
173 : AF_INET6;
174
175
176 if (family1 < family2)
177 return -1;
178
179 if (family1 > family2)
180 return 1;
181
7bfa7d02 182 return 0;
5e1b0650 183 } else {
15569c58
DA
184 zlog_debug("%s: Unexpected family type: %d", __func__,
185 hle1->p.family);
5e1b0650
DS
186 return 0;
187 }
188}
85442b09 189RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
5e1b0650 190
85442b09 191static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
5e1b0650
DS
192{
193 struct host_rb_entry *hle;
194 uint32_t count = 0;
195
85442b09 196 RB_FOREACH (hle, host_rb_tree_entry, hrbe)
5e1b0650
DS
197 count++;
198
199 return count;
200}
13d60d35 201
db889978
CS
202static int l3vni_rmac_nh_list_cmp(void *p1, void *p2)
203{
204 const struct ipaddr *vtep_ip1 = p1;
205 const struct ipaddr *vtep_ip2 = p2;
206
207 return !ipaddr_cmp(vtep_ip1, vtep_ip2);
208}
209
210static void l3vni_rmac_nh_free(struct ipaddr *vtep_ip)
211{
212 XFREE(MTYPE_EVPN_VTEP, vtep_ip);
213}
214
215static void l3vni_rmac_nh_list_nh_delete(struct zebra_l3vni *zl3vni,
216 struct zebra_mac *zrmac,
217 struct ipaddr *vtep_ip)
218{
219 struct listnode *node = NULL, *nnode = NULL;
220 struct ipaddr *vtep = NULL;
221
222 for (ALL_LIST_ELEMENTS(zrmac->nh_list, node, nnode, vtep)) {
223 if (ipaddr_cmp(vtep, vtep_ip) == 0)
224 break;
225 }
226
227 if (node) {
228 l3vni_rmac_nh_free(vtep);
229 list_delete_node(zrmac->nh_list, node);
230 }
231}
232
cec2e17d 233/*
87d76d54 234 * Print neighbors for all EVPN.
cec2e17d 235 */
87d76d54 236static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket,
cd233079 237 void **args)
cec2e17d 238{
d62a17ae 239 struct vty *vty;
87d76d54 240 json_object *json = NULL, *json_evpn = NULL;
f6371c34 241 struct zebra_evpn *zevpn;
d7c0a89a 242 uint32_t num_neigh;
d62a17ae 243 struct neigh_walk_ctx wctx;
cd233079 244 char vni_str[VNI_STR_LEN];
1374d4db 245 uint32_t print_dup;
cd233079
CS
246
247 vty = (struct vty *)args[0];
248 json = (json_object *)args[1];
1374d4db 249 print_dup = (uint32_t)(uintptr_t)args[2];
cec2e17d 250
f6371c34 251 zevpn = (struct zebra_evpn *)bucket->data;
9ea660be 252
87d76d54 253 num_neigh = hashcount(zevpn->neigh_table);
1374d4db
CS
254
255 if (print_dup)
87d76d54 256 num_neigh = num_dup_detected_neighs(zevpn);
1374d4db 257
68e33151 258 if (json == NULL) {
cd233079
CS
259 vty_out(vty,
260 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
87d76d54 261 zevpn->vni, num_neigh);
68e33151 262 } else {
87d76d54
PR
263 json_evpn = json_object_new_object();
264 json_object_int_add(json_evpn, "numArpNd", num_neigh);
265 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
cd233079 266 }
1374d4db 267
cd233079
CS
268 if (!num_neigh) {
269 if (json)
87d76d54 270 json_object_object_add(json, vni_str, json_evpn);
d62a17ae 271 return;
cd233079 272 }
cec2e17d 273
d62a17ae 274 /* Since we have IPv6 addresses to deal with which can vary widely in
275 * size, we try to be a bit more elegant in display by first computing
276 * the maximum width.
277 */
6006b807 278 memset(&wctx, 0, sizeof(wctx));
87d76d54 279 wctx.zevpn = zevpn;
d62a17ae 280 wctx.vty = vty;
281 wctx.addr_width = 15;
87d76d54 282 wctx.json = json_evpn;
7cbae20a
PR
283 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
284 &wctx);
cec2e17d 285
b169fd6f 286 if (json == NULL)
7cbae20a 287 zebra_evpn_print_neigh_hdr(vty, &wctx);
b169fd6f 288
1374d4db 289 if (print_dup)
7cbae20a
PR
290 hash_iterate(zevpn->neigh_table,
291 zebra_evpn_print_dad_neigh_hash, &wctx);
1374d4db 292 else
7cbae20a
PR
293 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash,
294 &wctx);
cd233079
CS
295
296 if (json)
87d76d54 297 json_object_object_add(json, vni_str, json_evpn);
cec2e17d 298}
299
e3fac919 300/*
87d76d54 301 * Print neighbors for all EVPNs in detail.
e3fac919 302 */
87d76d54 303static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket,
e3fac919
NS
304 void **args)
305{
306 struct vty *vty;
87d76d54 307 json_object *json = NULL, *json_evpn = NULL;
f6371c34 308 struct zebra_evpn *zevpn;
e3fac919
NS
309 uint32_t num_neigh;
310 struct neigh_walk_ctx wctx;
311 char vni_str[VNI_STR_LEN];
312 uint32_t print_dup;
313
314 vty = (struct vty *)args[0];
315 json = (json_object *)args[1];
316 print_dup = (uint32_t)(uintptr_t)args[2];
317
f6371c34 318 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 319 if (!zevpn) {
e3fac919
NS
320 if (json)
321 vty_out(vty, "{}\n");
322 return;
323 }
87d76d54 324 num_neigh = hashcount(zevpn->neigh_table);
e3fac919 325
87d76d54 326 if (print_dup && num_dup_detected_neighs(zevpn) == 0)
e3fac919
NS
327 return;
328
329 if (json == NULL) {
330 vty_out(vty,
331 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
87d76d54 332 zevpn->vni, num_neigh);
e3fac919 333 } else {
87d76d54
PR
334 json_evpn = json_object_new_object();
335 json_object_int_add(json_evpn, "numArpNd", num_neigh);
336 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
e3fac919
NS
337 }
338 if (!num_neigh) {
339 if (json)
87d76d54 340 json_object_object_add(json, vni_str, json_evpn);
e3fac919
NS
341 return;
342 }
343
6006b807 344 memset(&wctx, 0, sizeof(wctx));
87d76d54 345 wctx.zevpn = zevpn;
e3fac919
NS
346 wctx.vty = vty;
347 wctx.addr_width = 15;
87d76d54 348 wctx.json = json_evpn;
e3fac919
NS
349
350 if (print_dup)
87d76d54 351 hash_iterate(zevpn->neigh_table,
7cbae20a 352 zebra_evpn_print_dad_neigh_hash_detail, &wctx);
e3fac919 353 else
7cbae20a
PR
354 hash_iterate(zevpn->neigh_table,
355 zebra_evpn_print_neigh_hash_detail, &wctx);
e3fac919
NS
356
357 if (json)
87d76d54 358 json_object_object_add(json, vni_str, json_evpn);
e3fac919
NS
359}
360
9aa741ea 361/* print a specific next hop for an l3vni */
72de4110 362static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
c0e519d3 363 json_object *json)
9aa741ea
MK
364{
365 char buf1[ETHER_ADDR_STRLEN];
366 char buf2[INET6_ADDRSTRLEN];
c0e519d3 367 json_object *json_hosts = NULL;
f2a503f0 368 struct host_rb_entry *hle;
9aa741ea 369
c0e519d3
MK
370 if (!json) {
371 vty_out(vty, "Ip: %s\n",
372 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
373 vty_out(vty, " RMAC: %s\n",
996c9314 374 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
f2a503f0
DS
375 vty_out(vty, " Refcount: %d\n",
376 rb_host_count(&n->host_rb));
4cce389e 377 vty_out(vty, " Prefixes:\n");
85442b09 378 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
2dbe669b 379 vty_out(vty, " %pFX\n", &hle->p);
c0e519d3
MK
380 } else {
381 json_hosts = json_object_new_array();
996c9314
LB
382 json_object_string_add(
383 json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
384 json_object_string_add(
385 json, "routerMac",
386 prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
f2a503f0
DS
387 json_object_int_add(json, "refCount",
388 rb_host_count(&n->host_rb));
85442b09 389 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
c0e519d3 390 json_object_array_add(json_hosts,
996c9314 391 json_object_new_string(prefix2str(
f2a503f0 392 &hle->p, buf2, sizeof(buf2))));
4cce389e 393 json_object_object_add(json, "prefixList", json_hosts);
c0e519d3 394 }
9aa741ea
MK
395}
396
397/* Print a specific RMAC entry */
3198b2b3 398static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
316f4ca4 399 json_object *json)
9aa741ea 400{
4a8e182a
CS
401 struct listnode *node = NULL;
402 struct ipaddr *vtep = NULL;
403 json_object *json_nhs = NULL;
9aa741ea 404
316f4ca4 405 if (!json) {
3d43b95c 406 vty_out(vty, "MAC: %pEA\n", &zrmac->macaddr);
9bcef951
MS
407 vty_out(vty, " Remote VTEP: %pI4\n",
408 &zrmac->fwd_info.r_vtep_ip);
316f4ca4 409 } else {
4a8e182a 410 json_nhs = json_object_new_array();
3d43b95c
CS
411 json_object_string_addf(json, "routerMac", "%pEA",
412 &zrmac->macaddr);
08edf9c6
DA
413 json_object_string_addf(json, "vtepIp", "%pI4",
414 &zrmac->fwd_info.r_vtep_ip);
4a8e182a 415 for (ALL_LIST_ELEMENTS_RO(zrmac->nh_list, node, vtep)) {
3d43b95c
CS
416 json_object_array_add(json_nhs, json_object_new_stringf(
417 "%pIA", vtep));
4a8e182a
CS
418 }
419 json_object_object_add(json, "nexthops", json_nhs);
316f4ca4 420 }
9aa741ea
MK
421}
422
cec2e17d 423/*
87d76d54 424 * Print MACs for all EVPNs.
cec2e17d 425 */
87d76d54 426static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt)
cec2e17d 427{
d62a17ae 428 struct vty *vty;
87d76d54 429 json_object *json = NULL, *json_evpn = NULL;
cd233079 430 json_object *json_mac = NULL;
f6371c34 431 struct zebra_evpn *zevpn;
d7c0a89a 432 uint32_t num_macs;
d62a17ae 433 struct mac_walk_ctx *wctx = ctxt;
cd233079 434 char vni_str[VNI_STR_LEN];
cec2e17d 435
c4efd0f4
DA
436 vty = wctx->vty;
437 json = wctx->json;
cec2e17d 438
f6371c34 439 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 440 wctx->zevpn = zevpn;
cec2e17d 441
d62a17ae 442 /*We are iterating over a new VNI, set the count to 0*/
443 wctx->count = 0;
cec2e17d 444
87d76d54 445 num_macs = num_valid_macs(zevpn);
d62a17ae 446 if (!num_macs)
447 return;
cd233079 448
1374d4db 449 if (wctx->print_dup)
87d76d54 450 num_macs = num_dup_detected_macs(zevpn);
1374d4db 451
cd233079 452 if (json) {
87d76d54 453 json_evpn = json_object_new_object();
cd233079 454 json_mac = json_object_new_object();
87d76d54 455 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
d62a17ae 456 }
cec2e17d 457
cd233079
CS
458 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
459 if (json == NULL) {
460 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
87d76d54 461 zevpn->vni, num_macs);
b169fd6f
AK
462 vty_out(vty,
463 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
464 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
465 "Type", "Flags", "Intf/Remote ES/VTEP",
466 "VLAN", "Seq #'s");
cd233079 467 } else
87d76d54 468 json_object_int_add(json_evpn, "numMacs", num_macs);
cd233079 469 }
1374d4db
CS
470
471 if (!num_macs) {
472 if (json) {
87d76d54
PR
473 json_object_int_add(json_evpn, "numMacs", num_macs);
474 json_object_object_add(json, vni_str, json_evpn);
1374d4db
CS
475 }
476 return;
477 }
478
87d76d54
PR
479 /* assign per-evpn to wctx->json object to fill macs
480 * under the evpn. Re-assign primary json object to fill
481 * next evpn information.
cd233079
CS
482 */
483 wctx->json = json_mac;
1374d4db 484 if (wctx->print_dup)
b2998086
PR
485 hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash,
486 wctx);
1374d4db 487 else
b2998086 488 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, wctx);
cd233079
CS
489 wctx->json = json;
490 if (json) {
491 if (wctx->count)
87d76d54
PR
492 json_object_object_add(json_evpn, "macs", json_mac);
493 json_object_object_add(json, vni_str, json_evpn);
cd233079 494 }
cec2e17d 495}
496
cffe7580 497/*
87d76d54 498 * Print MACs in detail for all EVPNs.
cffe7580 499 */
87d76d54 500static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket,
cffe7580
NS
501 void *ctxt)
502{
503 struct vty *vty;
87d76d54 504 json_object *json = NULL, *json_evpn = NULL;
cffe7580 505 json_object *json_mac = NULL;
f6371c34 506 struct zebra_evpn *zevpn;
cffe7580
NS
507 uint32_t num_macs;
508 struct mac_walk_ctx *wctx = ctxt;
509 char vni_str[VNI_STR_LEN];
510
c4efd0f4
DA
511 vty = wctx->vty;
512 json = wctx->json;
cffe7580 513
f6371c34 514 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 515 if (!zevpn) {
cffe7580
NS
516 if (json)
517 vty_out(vty, "{}\n");
518 return;
519 }
87d76d54 520 wctx->zevpn = zevpn;
cffe7580 521
87d76d54 522 /*We are iterating over a new EVPN, set the count to 0*/
cffe7580
NS
523 wctx->count = 0;
524
87d76d54 525 num_macs = num_valid_macs(zevpn);
cffe7580
NS
526 if (!num_macs)
527 return;
528
87d76d54 529 if (wctx->print_dup && (num_dup_detected_macs(zevpn) == 0))
cffe7580
NS
530 return;
531
532 if (json) {
87d76d54 533 json_evpn = json_object_new_object();
cffe7580 534 json_mac = json_object_new_object();
87d76d54 535 snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni);
cffe7580
NS
536 }
537
538 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
539 if (json == NULL) {
540 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
87d76d54 541 zevpn->vni, num_macs);
cffe7580 542 } else
87d76d54 543 json_object_int_add(json_evpn, "numMacs", num_macs);
cffe7580 544 }
87d76d54
PR
545 /* assign per-evpn to wctx->json object to fill macs
546 * under the evpn. Re-assign primary json object to fill
547 * next evpn information.
cffe7580
NS
548 */
549 wctx->json = json_mac;
550 if (wctx->print_dup)
b2998086
PR
551 hash_iterate(zevpn->mac_table,
552 zebra_evpn_print_dad_mac_hash_detail, wctx);
cffe7580 553 else
b2998086
PR
554 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail,
555 wctx);
cffe7580
NS
556 wctx->json = json;
557 if (json) {
558 if (wctx->count)
87d76d54
PR
559 json_object_object_add(json_evpn, "macs", json_mac);
560 json_object_object_add(json, vni_str, json_evpn);
cffe7580
NS
561 }
562}
563
e3b78da8 564static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93
MK
565{
566 struct nh_walk_ctx *wctx = NULL;
567 struct vty *vty = NULL;
87d76d54 568 struct json_object *json_evpn = NULL;
b7cfce93 569 struct json_object *json_nh = NULL;
72de4110 570 struct zebra_neigh *n = NULL;
b7cfce93 571 char buf1[ETHER_ADDR_STRLEN];
2dbad57f 572 char buf2[INET6_ADDRSTRLEN];
b7cfce93
MK
573
574 wctx = (struct nh_walk_ctx *)ctx;
575 vty = wctx->vty;
87d76d54
PR
576 json_evpn = wctx->json;
577 if (json_evpn)
b7cfce93 578 json_nh = json_object_new_object();
72de4110 579 n = (struct zebra_neigh *)bucket->data;
b7cfce93 580
87d76d54 581 if (!json_evpn) {
4cce389e 582 vty_out(vty, "%-15s %-17s\n",
2dbad57f 583 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
4cce389e 584 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
b7cfce93 585 } else {
4cce389e 586 json_object_string_add(json_nh, "nexthopIp",
32798965 587 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
996c9314
LB
588 json_object_string_add(
589 json_nh, "routerMac",
590 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
87d76d54 591 json_object_object_add(json_evpn,
32798965
MK
592 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
593 json_nh);
b7cfce93
MK
594 }
595}
596
e3b78da8 597static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket,
32798965 598 void **args)
2dbad57f 599{
600 struct vty *vty = NULL;
601 json_object *json = NULL;
87d76d54 602 json_object *json_evpn = NULL;
05843a27 603 struct zebra_l3vni *zl3vni = NULL;
2dbad57f 604 uint32_t num_nh = 0;
32798965 605 struct nh_walk_ctx wctx;
2dbad57f 606 char vni_str[VNI_STR_LEN];
607
32798965
MK
608 vty = (struct vty *)args[0];
609 json = (struct json_object *)args[1];
2dbad57f 610
05843a27 611 zl3vni = (struct zebra_l3vni *)bucket->data;
2dbad57f 612
613 num_nh = hashcount(zl3vni->nh_table);
614 if (!num_nh)
615 return;
616
617 if (json) {
87d76d54
PR
618 json_evpn = json_object_new_object();
619 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
2dbad57f 620 }
621
622 if (json == NULL) {
996c9314 623 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
4cce389e 624 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
2dbad57f 625 } else
87d76d54 626 json_object_int_add(json_evpn, "numNextHops", num_nh);
2dbad57f 627
6006b807 628 memset(&wctx, 0, sizeof(wctx));
32798965 629 wctx.vty = vty;
87d76d54 630 wctx.json = json_evpn;
32798965
MK
631 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
632 if (json)
87d76d54 633 json_object_object_add(json, vni_str, json_evpn);
2dbad57f 634}
635
e3b78da8 636static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket,
c0b4eaa4 637 void **args)
b7cfce93
MK
638{
639 struct vty *vty = NULL;
640 json_object *json = NULL;
87d76d54 641 json_object *json_evpn = NULL;
05843a27 642 struct zebra_l3vni *zl3vni = NULL;
d7c0a89a 643 uint32_t num_rmacs;
c0b4eaa4 644 struct rmac_walk_ctx wctx;
b7cfce93
MK
645 char vni_str[VNI_STR_LEN];
646
c0b4eaa4
MK
647 vty = (struct vty *)args[0];
648 json = (struct json_object *)args[1];
b7cfce93 649
05843a27 650 zl3vni = (struct zebra_l3vni *)bucket->data;
b7cfce93
MK
651
652 num_rmacs = hashcount(zl3vni->rmac_table);
653 if (!num_rmacs)
654 return;
655
656 if (json) {
87d76d54
PR
657 json_evpn = json_object_new_object();
658 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
b7cfce93
MK
659 }
660
661 if (json == NULL) {
996c9314 662 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
4cce389e 663 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
b7cfce93 664 } else
87d76d54 665 json_object_int_add(json_evpn, "numRmacs", num_rmacs);
b7cfce93
MK
666
667 /* assign per-vni to wctx->json object to fill macs
668 * under the vni. Re-assign primary json object to fill
669 * next vni information.
670 */
6006b807 671 memset(&wctx, 0, sizeof(wctx));
c0b4eaa4 672 wctx.vty = vty;
87d76d54 673 wctx.json = json_evpn;
c0b4eaa4
MK
674 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
675 if (json)
87d76d54 676 json_object_object_add(json, vni_str, json_evpn);
b7cfce93
MK
677}
678
e3b78da8 679static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
b7cfce93 680{
3198b2b3 681 struct zebra_mac *zrmac = NULL;
b7cfce93
MK
682 struct rmac_walk_ctx *wctx = NULL;
683 struct vty *vty = NULL;
684 struct json_object *json = NULL;
685 struct json_object *json_rmac = NULL;
9bcef951 686 char buf[PREFIX_STRLEN];
b7cfce93
MK
687
688 wctx = (struct rmac_walk_ctx *)ctx;
689 vty = wctx->vty;
690 json = wctx->json;
691 if (json)
692 json_rmac = json_object_new_object();
3198b2b3 693 zrmac = (struct zebra_mac *)bucket->data;
b7cfce93
MK
694
695 if (!json) {
9bcef951 696 vty_out(vty, "%-17s %-21pI4\n",
b7cfce93 697 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
9bcef951 698 &zrmac->fwd_info.r_vtep_ip);
b7cfce93 699 } else {
996c9314
LB
700 json_object_string_add(
701 json_rmac, "routerMac",
702 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
08edf9c6
DA
703 json_object_string_addf(json_rmac, "vtepIp", "%pI4",
704 &zrmac->fwd_info.r_vtep_ip);
996c9314
LB
705 json_object_object_add(
706 json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
707 json_rmac);
b7cfce93
MK
708 }
709}
710
711/* print a specific L3 VNI entry */
05843a27 712static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
b7cfce93 713{
9bcef951 714 char buf[PREFIX_STRLEN];
b7cfce93
MK
715 struct vty *vty = NULL;
716 json_object *json = NULL;
f6371c34 717 struct zebra_evpn *zevpn = NULL;
87d76d54 718 json_object *json_evpn_list = NULL;
b7cfce93
MK
719 struct listnode *node = NULL, *nnode = NULL;
720
721 vty = ctx[0];
722 json = ctx[1];
723
724 if (!json) {
725 vty_out(vty, "VNI: %u\n", zl3vni->vni);
4cce389e 726 vty_out(vty, " Type: %s\n", "L3");
996c9314 727 vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
9bcef951
MS
728 vty_out(vty, " Local Vtep Ip: %pI4\n",
729 &zl3vni->local_vtep_ip);
b7cfce93
MK
730 vty_out(vty, " Vxlan-Intf: %s\n",
731 zl3vni_vxlan_if_name(zl3vni));
996c9314
LB
732 vty_out(vty, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
733 vty_out(vty, " State: %s\n", zl3vni_state2str(zl3vni));
c48d9f5f 734 vty_out(vty, " VNI Filter: %s\n",
996c9314
LB
735 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
736 ? "prefix-routes-only"
737 : "none");
28ad0501
CS
738 vty_out(vty, " System MAC: %s\n",
739 zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 740 vty_out(vty, " Router MAC: %s\n",
b7cfce93 741 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 742 vty_out(vty, " L2 VNIs: ");
87d76d54
PR
743 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn))
744 vty_out(vty, "%u ", zevpn->vni);
b7cfce93
MK
745 vty_out(vty, "\n");
746 } else {
87d76d54 747 json_evpn_list = json_object_new_array();
b7cfce93 748 json_object_int_add(json, "vni", zl3vni->vni);
4cce389e 749 json_object_string_add(json, "type", "L3");
08edf9c6
DA
750 json_object_string_addf(json, "localVtepIp", "%pI4",
751 &zl3vni->local_vtep_ip);
4cce389e 752 json_object_string_add(json, "vxlanIntf",
b7cfce93 753 zl3vni_vxlan_if_name(zl3vni));
4cce389e 754 json_object_string_add(json, "sviIntf",
b7cfce93 755 zl3vni_svi_if_name(zl3vni));
996c9314
LB
756 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
757 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
28ad0501
CS
758 json_object_string_add(
759 json, "sysMac",
760 zl3vni_sysmac2str(zl3vni, buf, sizeof(buf)));
996c9314
LB
761 json_object_string_add(
762 json, "routerMac",
763 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
764 json_object_string_add(
765 json, "vniFilter",
766 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
767 ? "prefix-routes-only"
768 : "none");
87d76d54
PR
769 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) {
770 json_object_array_add(json_evpn_list,
771 json_object_new_int(zevpn->vni));
b7cfce93 772 }
87d76d54 773 json_object_object_add(json, "l2Vnis", json_evpn_list);
b7cfce93
MK
774 }
775}
776
b7cfce93 777/* print a L3 VNI hash entry */
e3b78da8 778static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])
b7cfce93 779{
b7cfce93
MK
780 struct vty *vty = NULL;
781 json_object *json = NULL;
87d76d54 782 json_object *json_evpn = NULL;
05843a27 783 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 784
51d8de8f
MK
785 vty = (struct vty *)ctx[0];
786 json = (json_object *)ctx[1];
b7cfce93 787
05843a27 788 zl3vni = (struct zebra_l3vni *)bucket->data;
b7cfce93
MK
789
790 if (!json) {
996c9314
LB
791 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
792 zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
4cce389e 793 hashcount(zl3vni->rmac_table),
996c9314 794 hashcount(zl3vni->nh_table), "n/a",
4cce389e 795 zl3vni_vrf_name(zl3vni));
b7cfce93 796 } else {
51d8de8f
MK
797 char vni_str[VNI_STR_LEN];
798
87d76d54
PR
799 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
800 json_evpn = json_object_new_object();
801 json_object_int_add(json_evpn, "vni", zl3vni->vni);
802 json_object_string_add(json_evpn, "vxlanIf",
b7cfce93 803 zl3vni_vxlan_if_name(zl3vni));
87d76d54 804 json_object_int_add(json_evpn, "numMacs",
4cce389e 805 hashcount(zl3vni->rmac_table));
87d76d54 806 json_object_int_add(json_evpn, "numArpNd",
4cce389e 807 hashcount(zl3vni->nh_table));
87d76d54
PR
808 json_object_string_add(json_evpn, "numRemoteVteps", "n/a");
809 json_object_string_add(json_evpn, "type", "L3");
810 json_object_string_add(json_evpn, "tenantVrf",
b7cfce93 811 zl3vni_vrf_name(zl3vni));
87d76d54 812 json_object_object_add(json, vni_str, json_evpn);
b7cfce93 813 }
b7cfce93
MK
814}
815
09af6961 816/* print a L3 VNI hash entry in detail*/
e3b78da8 817static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
09af6961
NS
818{
819 struct vty *vty = NULL;
05843a27 820 struct zebra_l3vni *zl3vni = NULL;
06931fdb 821 json_object *json_array = NULL;
09af6961 822 bool use_json = false;
8b5fdf2e 823 struct zebra_evpn_show *zes = data;
09af6961
NS
824
825 vty = zes->vty;
06931fdb
LK
826 json_array = zes->json;
827 use_json = zes->use_json;
09af6961 828
05843a27 829 zl3vni = (struct zebra_l3vni *)bucket->data;
09af6961 830
06931fdb
LK
831 zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni,
832 use_json, json_array);
833
834 if (!use_json)
835 vty_out(vty, "\n");
09af6961
NS
836}
837
2961d060 838static int zvni_map_to_svi_ns(struct ns *ns,
a237058f
PG
839 void *_in_param,
840 void **_p_ifp)
841{
2961d060 842 struct zebra_ns *zns = ns->info;
a237058f
PG
843 struct route_node *rn;
844 struct zebra_from_svi_param *in_param =
845 (struct zebra_from_svi_param *)_in_param;
846 struct zebra_l2info_vlan *vl;
847 struct interface *tmp_if = NULL;
848 struct interface **p_ifp = (struct interface **)_p_ifp;
849 struct zebra_if *zif;
850
df447830 851 assert(in_param && p_ifp);
a237058f
PG
852
853 /* TODO: Optimize with a hash. */
854 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
855 tmp_if = (struct interface *)rn->info;
856 /* Check oper status of the SVI. */
857 if (!tmp_if || !if_is_operative(tmp_if))
858 continue;
859 zif = tmp_if->info;
860 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
861 || zif->link != in_param->br_if)
862 continue;
863 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
864
865 if (vl->vid == in_param->vid) {
df447830 866 *p_ifp = tmp_if;
2961d060 867 return NS_WALK_STOP;
a237058f
PG
868 }
869 }
2961d060 870 return NS_WALK_CONTINUE;
a237058f
PG
871}
872
8b5fdf2e
PR
873/* Map to SVI on bridge corresponding to specified VLAN. This can be one
874 * of two cases:
875 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
876 * linked to the bridge
877 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
878 * itself
09af6961 879 */
8b5fdf2e 880struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
13d60d35 881{
7cbae20a 882 struct interface *tmp_if = NULL;
8b5fdf2e
PR
883 struct zebra_if *zif;
884 struct zebra_l2info_bridge *br;
a237058f
PG
885 struct zebra_from_svi_param in_param;
886 struct interface **p_ifp;
8b5fdf2e
PR
887 /* Defensive check, caller expected to invoke only with valid bridge. */
888 if (!br_if)
889 return NULL;
1a98c087 890
8b5fdf2e
PR
891 /* Determine if bridge is VLAN-aware or not */
892 zif = br_if->info;
893 assert(zif);
894 br = &zif->l2info.br;
a237058f 895 in_param.bridge_vlan_aware = br->vlan_aware;
8b5fdf2e 896 /* Check oper status of the SVI. */
a237058f 897 if (!in_param.bridge_vlan_aware)
8b5fdf2e 898 return if_is_operative(br_if) ? br_if : NULL;
d62a17ae 899
a237058f
PG
900 in_param.vid = vid;
901 in_param.br_if = br_if;
902 in_param.zif = NULL;
903 p_ifp = &tmp_if;
bf69e212 904 /* Identify corresponding VLAN interface. */
2961d060
PG
905 ns_walk_func(zvni_map_to_svi_ns, (void *)&in_param,
906 (void **)p_ifp);
a237058f 907 return tmp_if;
8b5fdf2e 908}
2232a77c 909
f6371c34 910static int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
8b5fdf2e
PR
911{
912 zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);
2232a77c 913
8b5fdf2e
PR
914 /* Remove references to the BUM mcast grp */
915 zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp);
2232a77c 916
8b5fdf2e 917 return zebra_evpn_del(zevpn);
2232a77c 918}
07509878 919
2961d060 920static int zevpn_build_hash_table_zns(struct ns *ns,
07509878
PG
921 void *param_in __attribute__((unused)),
922 void **param_out __attribute__((unused)))
2232a77c 923{
2961d060 924 struct zebra_ns *zns = ns->info;
2853fed6 925 struct route_node *rn;
d62a17ae 926 struct interface *ifp;
07509878
PG
927 struct zebra_vrf *zvrf;
928
929 zvrf = zebra_vrf_get_evpn();
930
87d76d54 931 /* Walk VxLAN interfaces and create EVPN hash. */
2853fed6 932 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
b7cfce93 933 vni_t vni;
f6371c34 934 struct zebra_evpn *zevpn = NULL;
05843a27 935 struct zebra_l3vni *zl3vni = NULL;
d62a17ae 936 struct zebra_if *zif;
937 struct zebra_l2info_vxlan *vxl;
2232a77c 938
2853fed6 939 ifp = (struct interface *)rn->info;
940 if (!ifp)
941 continue;
d62a17ae 942 zif = ifp->info;
943 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
944 continue;
2232a77c 945
b7cfce93 946 vxl = &zif->l2info.vxl;
d62a17ae 947 vni = vxl->vni;
07509878
PG
948 /* link of VXLAN interface should be in zebra_evpn_vrf */
949 if (zvrf->zns->ns_id != vxl->link_nsid) {
950 if (IS_ZEBRA_DEBUG_VXLAN)
951 zlog_debug(
952 "Intf %s(%u) VNI %u, link not in same "
953 "namespace than BGP EVPN core instance ",
954 ifp->name, ifp->ifindex, vni);
955 continue;
956 }
643215ce 957 /* L3-VNI and L2-VNI are handled seperately */
958 zl3vni = zl3vni_lookup(vni);
959 if (zl3vni) {
2232a77c 960
b7cfce93 961 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
962 zlog_debug(
963 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
964 ifp->name, ifp->ifindex, vni);
2232a77c 965
b7cfce93 966 /* associate with vxlan_if */
b67a60d2 967 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93 968 zl3vni->vxlan_if = ifp;
2232a77c 969
523cafc4 970 /*
971 * we need to associate with SVI.
b7cfce93 972 * we can associate with svi-if only after association
523cafc4 973 * with vxlan-intf is complete
974 */
b7cfce93
MK
975 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
976
06d9cde5
CS
977 /* Associate l3vni to mac-vlan and extract VRR MAC */
978 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
979
980 if (IS_ZEBRA_DEBUG_VXLAN)
981 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
982 vni, zl3vni->svi_if ? zl3vni->svi_if->name
983 : "NIL",
984 zl3vni->mac_vlan_if ?
985 zl3vni->mac_vlan_if->name : "NIL");
986
b7cfce93
MK
987 if (is_l3vni_oper_up(zl3vni))
988 zebra_vxlan_process_l3vni_oper_up(zl3vni);
989
990 } else {
b7cfce93
MK
991 struct interface *vlan_if = NULL;
992
993 if (IS_ZEBRA_DEBUG_VXLAN)
994 zlog_debug(
9bcef951 995 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
b7cfce93 996 ifp->name, ifp->ifindex, vni,
9bcef951 997 &vxl->vtep_ip);
b7cfce93 998
87d76d54 999 /* EVPN hash entry is expected to exist, if the BGP process is killed */
8b5fdf2e 1000 zevpn = zebra_evpn_lookup(vni);
87d76d54 1001 if (zevpn) {
9df414fe 1002 zlog_debug(
87d76d54 1003 "EVPN hash already present for IF %s(%u) L2-VNI %u",
b7cfce93 1004 ifp->name, ifp->ifindex, vni);
b7cfce93 1005
27627f9a
KA
1006 /*
1007 * Inform BGP if intf is up and mapped to
1008 * bridge.
1009 */
1010 if (if_is_operative(ifp) &&
1011 zif->brslave_info.br_if)
8b5fdf2e 1012 zebra_evpn_send_add_to_client(zevpn);
b7cfce93 1013
27627f9a 1014 /* Send Local MAC-entries to client */
b2998086 1015 zebra_evpn_send_mac_list_to_client(zevpn);
27627f9a
KA
1016
1017 /* Send Loval Neighbor entries to client */
7cbae20a 1018 zebra_evpn_send_neigh_to_client(zevpn);
27627f9a 1019 } else {
8b5fdf2e 1020 zevpn = zebra_evpn_add(vni);
87d76d54 1021 if (!zevpn) {
27627f9a 1022 zlog_debug(
87d76d54 1023 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
27627f9a 1024 ifp->name, ifp->ifindex, vni);
2961d060 1025 return NS_WALK_CONTINUE;
27627f9a 1026 }
b7cfce93 1027
87d76d54 1028 if (zevpn->local_vtep_ip.s_addr !=
27627f9a 1029 vxl->vtep_ip.s_addr ||
87d76d54 1030 zevpn->mcast_grp.s_addr !=
27627f9a
KA
1031 vxl->mcast_grp.s_addr) {
1032 zebra_vxlan_sg_deref(
87d76d54
PR
1033 zevpn->local_vtep_ip,
1034 zevpn->mcast_grp);
27627f9a
KA
1035 zebra_vxlan_sg_ref(vxl->vtep_ip,
1036 vxl->mcast_grp);
87d76d54
PR
1037 zevpn->local_vtep_ip = vxl->vtep_ip;
1038 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
1039 /* on local vtep-ip check if ES
1040 * orig-ip needs to be updated
1041 */
87d76d54 1042 zebra_evpn_es_set_base_evpn(zevpn);
27627f9a 1043 }
87d76d54 1044 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
7cbae20a
PR
1045 vlan_if = zvni_map_to_svi(
1046 vxl->access_vlan,
1047 zif->brslave_info.br_if);
27627f9a 1048 if (vlan_if) {
9daa5d47 1049 zevpn->svi_if = vlan_if;
096f7609 1050 zevpn->vrf_id = vlan_if->vrf->vrf_id;
27627f9a 1051 zl3vni = zl3vni_from_vrf(
096f7609 1052 vlan_if->vrf->vrf_id);
27627f9a
KA
1053 if (zl3vni)
1054 listnode_add_sort(
87d76d54 1055 zl3vni->l2vnis, zevpn);
27627f9a 1056 }
b7cfce93 1057
27627f9a
KA
1058 /*
1059 * Inform BGP if intf is up and mapped to
1060 * bridge.
1061 */
1062 if (if_is_operative(ifp) &&
1063 zif->brslave_info.br_if)
8b5fdf2e 1064 zebra_evpn_send_add_to_client(zevpn);
27627f9a 1065 }
b7cfce93 1066 }
d62a17ae 1067 }
2961d060 1068 return NS_WALK_CONTINUE;
07509878
PG
1069}
1070
1071/*
1072 * Build the VNI hash table by going over the VxLAN interfaces. This
1073 * is called when EVPN (advertise-all-vni) is enabled.
1074 */
1075
1076static void zevpn_build_hash_table(void)
1077{
8998807f 1078 ns_walk_func(zevpn_build_hash_table_zns, NULL, NULL);
2232a77c 1079}
1080
2232a77c 1081/*
87d76d54 1082 * Cleanup EVPN/VTEP and update kernel
2232a77c 1083 */
8b5fdf2e 1084static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket *bucket, void *arg)
2232a77c 1085{
f6371c34 1086 struct zebra_evpn *zevpn = NULL;
05843a27 1087 struct zebra_l3vni *zl3vni = NULL;
2232a77c 1088
f6371c34 1089 zevpn = (struct zebra_evpn *)bucket->data;
2232a77c 1090
b27be4db
CS
1091 /* remove l2vni from l2vni's tenant-vrf l3-vni list */
1092 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
b7cfce93 1093 if (zl3vni)
87d76d54 1094 listnode_delete(zl3vni->l2vnis, zevpn);
b7cfce93 1095
8b5fdf2e 1096 zebra_evpn_cleanup_all(bucket, arg);
2232a77c 1097}
1098
655b04d1 1099/* cleanup L3VNI */
e3b78da8 1100static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args)
655b04d1 1101{
05843a27 1102 struct zebra_l3vni *zl3vni = NULL;
655b04d1 1103
05843a27 1104 zl3vni = (struct zebra_l3vni *)bucket->data;
655b04d1
MK
1105
1106 zebra_vxlan_process_l3vni_oper_down(zl3vni);
1107}
1108
85442b09 1109static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
e4a1ec74 1110 const struct prefix *host)
5e1b0650
DS
1111{
1112 struct host_rb_entry lookup;
1113 struct host_rb_entry *hle;
1114
1115 memset(&lookup, 0, sizeof(lookup));
1116 memcpy(&lookup.p, host, sizeof(*host));
1117
85442b09 1118 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
5e1b0650
DS
1119 if (hle)
1120 return;
1121
1122 hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
1123 memcpy(hle, &lookup, sizeof(lookup));
1124
85442b09 1125 RB_INSERT(host_rb_tree_entry, hrbe, hle);
5e1b0650
DS
1126}
1127
85442b09 1128static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
5e1b0650
DS
1129{
1130 struct host_rb_entry lookup;
1131 struct host_rb_entry *hle;
1132
1133 memset(&lookup, 0, sizeof(lookup));
1134 memcpy(&lookup.p, host, sizeof(*host));
1135
85442b09 1136 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
10ac2516 1137 if (hle) {
85442b09 1138 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
10ac2516
DS
1139 XFREE(MTYPE_HOST_PREFIX, hle);
1140 }
5e1b0650
DS
1141
1142 return;
1143}
1144
b7cfce93
MK
1145/*
1146 * Look up MAC hash entry.
1147 */
05843a27 1148static struct zebra_mac *zl3vni_rmac_lookup(struct zebra_l3vni *zl3vni,
3198b2b3 1149 const struct ethaddr *rmac)
b7cfce93 1150{
3198b2b3
DS
1151 struct zebra_mac tmp;
1152 struct zebra_mac *pmac;
b7cfce93
MK
1153
1154 memset(&tmp, 0, sizeof(tmp));
1155 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
1156 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
2232a77c 1157
b7cfce93 1158 return pmac;
2dbad57f 1159}
2232a77c 1160
cec2e17d 1161/*
b7cfce93 1162 * Callback to allocate RMAC hash entry.
cec2e17d 1163 */
2dbad57f 1164static void *zl3vni_rmac_alloc(void *p)
d62a17ae 1165{
3198b2b3
DS
1166 const struct zebra_mac *tmp_rmac = p;
1167 struct zebra_mac *zrmac;
d62a17ae 1168
3198b2b3 1169 zrmac = XCALLOC(MTYPE_L3VNI_MAC, sizeof(struct zebra_mac));
b7cfce93 1170 *zrmac = *tmp_rmac;
d62a17ae 1171
b7cfce93 1172 return ((void *)zrmac);
2dbad57f 1173}
cd233079 1174
b7cfce93
MK
1175/*
1176 * Add RMAC entry to l3-vni
1177 */
05843a27 1178static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
3198b2b3 1179 const struct ethaddr *rmac)
b7cfce93 1180{
3198b2b3
DS
1181 struct zebra_mac tmp_rmac;
1182 struct zebra_mac *zrmac = NULL;
d62a17ae 1183
6006b807 1184 memset(&tmp_rmac, 0, sizeof(tmp_rmac));
b7cfce93
MK
1185 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
1186 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
db889978
CS
1187 zrmac->nh_list = list_new();
1188 zrmac->nh_list->cmp = (int (*)(void *, void *))l3vni_rmac_nh_list_cmp;
1189 zrmac->nh_list->del = (void (*)(void *))l3vni_rmac_nh_free;
b7cfce93 1190
2dbad57f 1191 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
1192 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
1193
b7cfce93 1194 return zrmac;
2dbad57f 1195}
cec2e17d 1196
1197/*
b7cfce93 1198 * Delete MAC entry.
cec2e17d 1199 */
05843a27 1200static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac)
cec2e17d 1201{
3198b2b3 1202 struct zebra_mac *tmp_rmac;
cd233079 1203
db889978
CS
1204 /* free the list of nh list*/
1205 list_delete(&zrmac->nh_list);
cd233079 1206
b7cfce93 1207 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
b2998086 1208 XFREE(MTYPE_L3VNI_MAC, tmp_rmac);
cd233079 1209
b7cfce93 1210 return 0;
2dbad57f 1211}
cec2e17d 1212
1213/*
036d93c0 1214 * Install remote RMAC into the forwarding plane.
cec2e17d 1215 */
05843a27
DS
1216static int zl3vni_rmac_install(struct zebra_l3vni *zl3vni,
1217 struct zebra_mac *zrmac)
cec2e17d 1218{
478566d6
MS
1219 const struct zebra_if *zif = NULL, *br_zif = NULL;
1220 const struct zebra_l2info_vxlan *vxl = NULL;
1221 const struct interface *br_ifp;
036d93c0 1222 enum zebra_dplane_result res;
478566d6 1223 vlanid_t vid;
cec2e17d 1224
996c9314
LB
1225 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
1226 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
1227 return 0;
1228
1229 zif = zl3vni->vxlan_if->info;
1230 if (!zif)
1231 return -1;
1232
478566d6
MS
1233 br_ifp = zif->brslave_info.br_if;
1234 if (br_ifp == NULL)
1235 return -1;
1236
b7cfce93
MK
1237 vxl = &zif->l2info.vxl;
1238
478566d6
MS
1239 br_zif = (const struct zebra_if *)br_ifp->info;
1240
1241 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1242 vid = vxl->access_vlan;
1243 else
1244 vid = 0;
1245
f188e68e
AK
1246 res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid,
1247 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0,
1248 false /*was_static*/);
036d93c0
MS
1249 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
1250 return 0;
1251 else
1252 return -1;
2dbad57f 1253}
b7cfce93
MK
1254
1255/*
036d93c0 1256 * Uninstall remote RMAC from the forwarding plane.
b7cfce93 1257 */
05843a27
DS
1258static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
1259 struct zebra_mac *zrmac)
b7cfce93 1260{
478566d6
MS
1261 const struct zebra_if *zif = NULL, *br_zif;
1262 const struct zebra_l2info_vxlan *vxl = NULL;
1263 const struct interface *br_ifp;
1264 vlanid_t vid;
036d93c0 1265 enum zebra_dplane_result res;
b7cfce93 1266
996c9314
LB
1267 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
1268 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
b7cfce93
MK
1269 return 0;
1270
1271 if (!zl3vni->vxlan_if) {
e0e140a7
MS
1272 if (IS_ZEBRA_DEBUG_VXLAN)
1273 zlog_debug(
ef7b8be4
DL
1274 "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
1275 &zrmac->macaddr, zl3vni->vni, zl3vni);
b7cfce93
MK
1276 return -1;
1277 }
1278
1279 zif = zl3vni->vxlan_if->info;
1280 if (!zif)
1281 return -1;
1282
478566d6
MS
1283 br_ifp = zif->brslave_info.br_if;
1284 if (br_ifp == NULL)
1285 return -1;
1286
b7cfce93
MK
1287 vxl = &zif->l2info.vxl;
1288
478566d6
MS
1289 br_zif = (const struct zebra_if *)br_ifp->info;
1290 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif))
1291 vid = vxl->access_vlan;
1292 else
1293 vid = 0;
1294
f188e68e 1295 res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid,
036d93c0
MS
1296 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
1297 if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
1298 return 0;
1299 else
1300 return -1;
2dbad57f 1301}
1302
1303/* handle rmac add */
05843a27 1304static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
e4a1ec74 1305 const struct ethaddr *rmac,
3d43b95c 1306 const struct ipaddr *vtep_ip)
2dbad57f 1307{
3198b2b3 1308 struct zebra_mac *zrmac = NULL;
db889978 1309 struct ipaddr *vtep = NULL;
2dbad57f 1310
1311 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
1312 if (!zrmac) {
1313
651fa905 1314 /* Create the RMAC entry, or update its vtep, if necessary. */
2dbad57f 1315 zrmac = zl3vni_rmac_add(zl3vni, rmac);
1316 if (!zrmac) {
9df414fe 1317 zlog_debug(
3d43b95c
CS
1318 "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA",
1319 rmac, zl3vni->vni, vtep_ip);
2dbad57f 1320 return -1;
1321 }
1322 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
1323 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
1324
db889978
CS
1325 vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
1326 memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
1327 if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
1328 XFREE(MTYPE_EVPN_VTEP, vtep);
1329
a780a738
AD
1330 /* Send RMAC for FPM processing */
1331 hook_call(zebra_rmac_update, zrmac, zl3vni, false,
1332 "new RMAC added");
1333
651fa905
CS
1334 /* install rmac in kernel */
1335 zl3vni_rmac_install(zl3vni, zrmac);
1336 } else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
1337 &vtep_ip->ipaddr_v4)) {
1338 if (IS_ZEBRA_DEBUG_VXLAN)
1339 zlog_debug(
3d43b95c 1340 "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
ef7b8be4 1341 zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
3d43b95c 1342 vtep_ip, rmac);
651fa905
CS
1343
1344 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
1345
db889978
CS
1346 vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
1347 memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
1348 if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
1349 XFREE(MTYPE_EVPN_VTEP, vtep);
1350
2dbad57f 1351 /* install rmac in kernel */
1352 zl3vni_rmac_install(zl3vni, zrmac);
1353 }
6134fd82 1354
2dbad57f 1355 return 0;
1356}
1357
1358
1359/* handle rmac delete */
05843a27 1360static void zl3vni_remote_rmac_del(struct zebra_l3vni *zl3vni,
3198b2b3 1361 struct zebra_mac *zrmac,
3d43b95c 1362 struct ipaddr *vtep_ip)
2dbad57f 1363{
db889978 1364 struct ipaddr ipv4_vtep;
2dbad57f 1365
ae9e6bea 1366 if (!zl3vni_nh_lookup(zl3vni, vtep_ip)) {
6006b807 1367 memset(&ipv4_vtep, 0, sizeof(ipv4_vtep));
db889978
CS
1368 ipv4_vtep.ipa_type = IPADDR_V4;
1369 if (vtep_ip->ipa_type == IPADDR_V6)
1370 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
1371 &ipv4_vtep.ipaddr_v4);
1372 else
1373 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
1374 sizeof(struct in_addr));
2dbad57f 1375
db889978
CS
1376 /* remove nh from rmac's list */
1377 l3vni_rmac_nh_list_nh_delete(zl3vni, zrmac, &ipv4_vtep);
1378 /* delete nh is same as current selected, fall back to
1379 * one present in the list
1380 */
1381 if (IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
1382 &ipv4_vtep.ipaddr_v4) &&
1383 listcount(zrmac->nh_list)) {
1384 struct ipaddr *vtep;
a780a738 1385
db889978
CS
1386 vtep = listgetdata(listhead(zrmac->nh_list));
1387 zrmac->fwd_info.r_vtep_ip = vtep->ipaddr_v4;
1388 if (IS_ZEBRA_DEBUG_VXLAN)
1389 zlog_debug(
3d43b95c 1390 "L3VNI %u Remote VTEP nh change(%pIA -> %pI4) for RMAC %pEA",
db889978
CS
1391 zl3vni->vni, &ipv4_vtep,
1392 &zrmac->fwd_info.r_vtep_ip,
3d43b95c 1393 &zrmac->macaddr);
db889978
CS
1394
1395 /* install rmac in kernel */
1396 zl3vni_rmac_install(zl3vni, zrmac);
1397 }
ae9e6bea
CS
1398
1399 if (!listcount(zrmac->nh_list)) {
1400 /* uninstall from kernel */
1401 zl3vni_rmac_uninstall(zl3vni, zrmac);
1402
1403 /* Send RMAC for FPM processing */
1404 hook_call(zebra_rmac_update, zrmac, zl3vni, true,
1405 "RMAC deleted");
1406
1407 if (IS_ZEBRA_DEBUG_VXLAN)
1408 zlog_debug(
1409 "L3VNI %u RMAC %pEA vtep_ip %pIA delete",
1410 zl3vni->vni, &zrmac->macaddr, vtep_ip);
1411
1412 /* del the rmac entry */
1413 zl3vni_rmac_del(zl3vni, zrmac);
1414 }
2dbad57f 1415 }
2dbad57f 1416}
b7cfce93
MK
1417
1418/*
1419 * Look up nh hash entry on a l3-vni.
1420 */
72de4110
DS
1421static struct zebra_neigh *zl3vni_nh_lookup(struct zebra_l3vni *zl3vni,
1422 const struct ipaddr *ip)
b7cfce93 1423{
72de4110
DS
1424 struct zebra_neigh tmp;
1425 struct zebra_neigh *n;
b7cfce93
MK
1426
1427 memset(&tmp, 0, sizeof(tmp));
1428 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
1429 n = hash_lookup(zl3vni->nh_table, &tmp);
1430
1431 return n;
2dbad57f 1432}
b7cfce93
MK
1433
1434
1435/*
1436 * Callback to allocate NH hash entry on L3-VNI.
1437 */
2dbad57f 1438static void *zl3vni_nh_alloc(void *p)
b7cfce93 1439{
72de4110
DS
1440 const struct zebra_neigh *tmp_n = p;
1441 struct zebra_neigh *n;
b7cfce93 1442
72de4110 1443 n = XCALLOC(MTYPE_L3NEIGH, sizeof(struct zebra_neigh));
b7cfce93
MK
1444 *n = *tmp_n;
1445
1446 return ((void *)n);
2dbad57f 1447}
b7cfce93
MK
1448
1449/*
1450 * Add neighbor entry.
1451 */
72de4110
DS
1452static struct zebra_neigh *zl3vni_nh_add(struct zebra_l3vni *zl3vni,
1453 const struct ipaddr *ip,
1454 const struct ethaddr *mac)
b7cfce93 1455{
72de4110
DS
1456 struct zebra_neigh tmp_n;
1457 struct zebra_neigh *n = NULL;
b7cfce93 1458
6006b807 1459 memset(&tmp_n, 0, sizeof(tmp_n));
b7cfce93
MK
1460 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
1461 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
b7cfce93 1462
85442b09 1463 RB_INIT(host_rb_tree_entry, &n->host_rb);
6134fd82 1464
b7cfce93 1465 memcpy(&n->emac, mac, ETH_ALEN);
2dbad57f 1466 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
1467 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
b7cfce93
MK
1468
1469 return n;
2dbad57f 1470}
b7cfce93
MK
1471
1472/*
1473 * Delete neighbor entry.
1474 */
72de4110 1475static int zl3vni_nh_del(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
b7cfce93 1476{
72de4110 1477 struct zebra_neigh *tmp_n;
f2a503f0 1478 struct host_rb_entry *hle;
b7cfce93 1479
85442b09
DS
1480 while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
1481 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
f2a503f0 1482
85442b09 1483 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
f2a503f0
DS
1484 XFREE(MTYPE_HOST_PREFIX, hle);
1485 }
55aabf6f 1486
b7cfce93 1487 tmp_n = hash_release(zl3vni->nh_table, n);
7cbae20a 1488 XFREE(MTYPE_L3NEIGH, tmp_n);
b7cfce93
MK
1489
1490 return 0;
2dbad57f 1491}
b7cfce93
MK
1492
1493/*
1494 * Install remote nh as neigh into the kernel.
1495 */
72de4110 1496static int zl3vni_nh_install(struct zebra_l3vni *zl3vni, struct zebra_neigh *n)
b7cfce93 1497{
68e33151
CS
1498 uint8_t flags;
1499 int ret = 0;
1500
b7cfce93
MK
1501 if (!is_l3vni_oper_up(zl3vni))
1502 return -1;
1503
996c9314
LB
1504 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
1505 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93 1506 return 0;
931fa60c
MS
1507
1508 flags = DPLANE_NTF_EXT_LEARNED;
68e33151 1509 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
931fa60c
MS
1510 flags |= DPLANE_NTF_ROUTER;
1511
f188e68e
AK
1512 dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags,
1513 false /*was_static*/);
931fa60c 1514
68e33151 1515 return ret;
2dbad57f 1516}
b7cfce93
MK
1517
1518/*
1519 * Uninstall remote nh from the kernel.
1520 */
72de4110
DS
1521static int zl3vni_nh_uninstall(struct zebra_l3vni *zl3vni,
1522 struct zebra_neigh *n)
b7cfce93 1523{
996c9314
LB
1524 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
1525 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
b7cfce93
MK
1526 return 0;
1527
fa409e1e 1528 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
1529 return 0;
1530
f188e68e 1531 dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip);
931fa60c
MS
1532
1533 return 0;
2dbad57f 1534}
1535
1536/* add remote vtep as a neigh entry */
05843a27 1537static int zl3vni_remote_nh_add(struct zebra_l3vni *zl3vni,
e4a1ec74
MS
1538 const struct ipaddr *vtep_ip,
1539 const struct ethaddr *rmac,
1540 const struct prefix *host_prefix)
2dbad57f 1541{
72de4110 1542 struct zebra_neigh *nh = NULL;
2dbad57f 1543
651fa905 1544 /* Create the next hop entry, or update its mac, if necessary. */
2dbad57f 1545 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
1546 if (!nh) {
1547 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
1548 if (!nh) {
9df414fe 1549 zlog_debug(
ef7b8be4
DL
1550 "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
1551 vtep_ip, rmac, zl3vni->vni, host_prefix);
2dbad57f 1552 return -1;
1553 }
1554
1555 /* install the nh neigh in kernel */
1556 zl3vni_nh_install(zl3vni, nh);
651fa905
CS
1557 } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) {
1558 if (IS_ZEBRA_DEBUG_VXLAN)
2dbe669b 1559 zlog_debug(
ef7b8be4
DL
1560 "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
1561 zl3vni->vni, &nh->emac, rmac, vtep_ip,
2dbe669b 1562 host_prefix);
651fa905
CS
1563
1564 memcpy(&nh->emac, rmac, ETH_ALEN);
1565 /* install (update) the nh neigh in kernel */
1566 zl3vni_nh_install(zl3vni, nh);
2dbad57f 1567 }
6134fd82 1568
f2a503f0 1569 rb_find_or_add_host(&nh->host_rb, host_prefix);
6134fd82 1570
2dbad57f 1571 return 0;
1572}
1573
1574/* handle nh neigh delete */
72de4110
DS
1575static void zl3vni_remote_nh_del(struct zebra_l3vni *zl3vni,
1576 struct zebra_neigh *nh,
22e63104 1577 struct prefix *host_prefix)
2dbad57f 1578{
f2a503f0 1579 rb_delete_host(&nh->host_rb, host_prefix);
2dbad57f 1580
85442b09 1581 if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
2dbad57f 1582 /* uninstall from kernel */
1583 zl3vni_nh_uninstall(zl3vni, nh);
1584
1585 /* delete the nh entry */
1586 zl3vni_nh_del(zl3vni, nh);
1587 }
2dbad57f 1588}
b7cfce93 1589
3bcbba10 1590/* handle neigh update from kernel - the only thing of interest is to
1591 * readd stale entries.
1592 */
05843a27
DS
1593static int zl3vni_local_nh_add_update(struct zebra_l3vni *zl3vni,
1594 struct ipaddr *ip, uint16_t state)
3bcbba10 1595{
c05a738b 1596#ifdef GNU_LINUX
72de4110 1597 struct zebra_neigh *n = NULL;
3bcbba10 1598
1599 n = zl3vni_nh_lookup(zl3vni, ip);
1600 if (!n)
1601 return 0;
1602
1603 /* all next hop neigh are remote and installed by frr.
1604 * If the kernel has aged this entry, re-install.
1605 */
1606 if (state & NUD_STALE)
1607 zl3vni_nh_install(zl3vni, n);
c05a738b 1608#endif
3bcbba10 1609 return 0;
1610}
1611
8c9b80b9 1612/* handle neigh delete from kernel */
05843a27 1613static int zl3vni_local_nh_del(struct zebra_l3vni *zl3vni, struct ipaddr *ip)
8c9b80b9 1614{
72de4110 1615 struct zebra_neigh *n = NULL;
8c9b80b9
MK
1616
1617 n = zl3vni_nh_lookup(zl3vni, ip);
1618 if (!n)
1619 return 0;
1620
1621 /* all next hop neigh are remote and installed by frr.
1622 * If we get an age out notification for these neigh entries, we have to
523cafc4 1623 * install it back
1624 */
8c9b80b9
MK
1625 zl3vni_nh_install(zl3vni, n);
1626
1627 return 0;
1628}
1629
b7cfce93
MK
1630/*
1631 * Hash function for L3 VNI.
1632 */
d8b87afe 1633static unsigned int l3vni_hash_keymake(const void *p)
b7cfce93 1634{
05843a27 1635 const struct zebra_l3vni *zl3vni = p;
b7cfce93
MK
1636
1637 return jhash_1word(zl3vni->vni, 0);
1638}
1639
1640/*
1641 * Compare 2 L3 VNI hash entries.
1642 */
74df8d6d 1643static bool l3vni_hash_cmp(const void *p1, const void *p2)
b7cfce93 1644{
05843a27
DS
1645 const struct zebra_l3vni *zl3vni1 = p1;
1646 const struct zebra_l3vni *zl3vni2 = p2;
b7cfce93
MK
1647
1648 return (zl3vni1->vni == zl3vni2->vni);
1649}
1650
1651/*
1652 * Callback to allocate L3 VNI hash entry.
1653 */
1654static void *zl3vni_alloc(void *p)
1655{
05843a27
DS
1656 struct zebra_l3vni *zl3vni = NULL;
1657 const struct zebra_l3vni *tmp_l3vni = p;
b7cfce93 1658
05843a27 1659 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(struct zebra_l3vni));
b7cfce93
MK
1660 zl3vni->vni = tmp_l3vni->vni;
1661 return ((void *)zl3vni);
1662}
1663
1664/*
1665 * Look up L3 VNI hash entry.
1666 */
05843a27 1667struct zebra_l3vni *zl3vni_lookup(vni_t vni)
b7cfce93 1668{
05843a27
DS
1669 struct zebra_l3vni tmp_l3vni;
1670 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1671
6006b807 1672 memset(&tmp_l3vni, 0, sizeof(tmp_l3vni));
b7cfce93 1673 tmp_l3vni.vni = vni;
89272910 1674 zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni);
b7cfce93
MK
1675
1676 return zl3vni;
1677}
1678
1679/*
1680 * Add L3 VNI hash entry.
1681 */
05843a27 1682static struct zebra_l3vni *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
b7cfce93 1683{
05843a27
DS
1684 struct zebra_l3vni tmp_zl3vni;
1685 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1686
6006b807 1687 memset(&tmp_zl3vni, 0, sizeof(tmp_zl3vni));
b7cfce93
MK
1688 tmp_zl3vni.vni = vni;
1689
89272910 1690 zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc);
b7cfce93
MK
1691
1692 zl3vni->vrf_id = vrf_id;
1693 zl3vni->svi_if = NULL;
1694 zl3vni->vxlan_if = NULL;
1695 zl3vni->l2vnis = list_new();
8b5fdf2e 1696 zl3vni->l2vnis->cmp = zebra_evpn_list_cmp;
b7cfce93
MK
1697
1698 /* Create hash table for remote RMAC */
b2998086 1699 zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
b7cfce93
MK
1700
1701 /* Create hash table for neighbors */
7cbae20a 1702 zl3vni->nh_table = zebra_neigh_db_create("Zebra L3-VNI next-hop table");
b7cfce93
MK
1703
1704 return zl3vni;
1705}
1706
1707/*
1708 * Delete L3 VNI hash entry.
1709 */
05843a27 1710static int zl3vni_del(struct zebra_l3vni *zl3vni)
b7cfce93 1711{
05843a27 1712 struct zebra_l3vni *tmp_zl3vni;
b7cfce93 1713
b7cfce93 1714 /* free the list of l2vnis */
6a154c88 1715 list_delete(&zl3vni->l2vnis);
b7cfce93
MK
1716 zl3vni->l2vnis = NULL;
1717
1718 /* Free the rmac table */
1719 hash_free(zl3vni->rmac_table);
1720 zl3vni->rmac_table = NULL;
1721
1722 /* Free the nh table */
1723 hash_free(zl3vni->nh_table);
1724 zl3vni->nh_table = NULL;
1725
1726 /* Free the VNI hash entry and allocated memory. */
89272910 1727 tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
0a22ddfb 1728 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
b7cfce93
MK
1729
1730 return 0;
1731}
1732
2961d060
PG
1733static int zl3vni_map_to_vxlan_if_ns(struct ns *ns,
1734 void *_zl3vni,
1735 void **_pifp)
b7cfce93 1736{
2961d060 1737 struct zebra_ns *zns = ns->info;
05843a27 1738 struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)_zl3vni;
b7cfce93
MK
1739 struct route_node *rn = NULL;
1740 struct interface *ifp = NULL;
07509878
PG
1741 struct zebra_vrf *zvrf;
1742
1743 zvrf = zebra_vrf_get_evpn();
1744
44a84850 1745 assert(_pifp);
1746
b7cfce93 1747 /* loop through all vxlan-interface */
b7cfce93
MK
1748 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1749
1750 struct zebra_if *zif = NULL;
1751 struct zebra_l2info_vxlan *vxl = NULL;
1752
1753 ifp = (struct interface *)rn->info;
1754 if (!ifp)
1755 continue;
1756
1757 zif = ifp->info;
1758 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1759 continue;
1760
1761 vxl = &zif->l2info.vxl;
07509878
PG
1762 if (vxl->vni != zl3vni->vni)
1763 continue;
1764
1765 /* link of VXLAN interface should be in zebra_evpn_vrf */
1766 if (zvrf->zns->ns_id != vxl->link_nsid) {
1767 if (IS_ZEBRA_DEBUG_VXLAN)
1768 zlog_debug(
1769 "Intf %s(%u) VNI %u, link not in same "
1770 "namespace than BGP EVPN core instance ",
1771 ifp->name, ifp->ifindex, vxl->vni);
1772 continue;
b67a60d2 1773 }
07509878
PG
1774
1775
1776 zl3vni->local_vtep_ip = vxl->vtep_ip;
44a84850 1777 *_pifp = (void *)ifp;
2961d060 1778 return NS_WALK_STOP;
b7cfce93
MK
1779 }
1780
2961d060 1781 return NS_WALK_CONTINUE;
07509878
PG
1782}
1783
05843a27 1784struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni)
07509878
PG
1785{
1786 struct interface **p_ifp;
1787 struct interface *ifp = NULL;
1788
1789 p_ifp = &ifp;
1790
2961d060
PG
1791 ns_walk_func(zl3vni_map_to_vxlan_if_ns,
1792 (void *)zl3vni, (void **)p_ifp);
07509878 1793 return ifp;
b7cfce93
MK
1794}
1795
05843a27 1796struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni)
b7cfce93 1797{
996c9314 1798 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
b7cfce93
MK
1799 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
1800
2aeb403d 1801 if (!zl3vni)
1802 return NULL;
1803
b7cfce93
MK
1804 if (!zl3vni->vxlan_if)
1805 return NULL;
1806
1807 zif = zl3vni->vxlan_if->info;
1808 if (!zif)
1809 return NULL;
1810
1811 vxl = &zif->l2info.vxl;
1812
7cbae20a 1813 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
b7cfce93
MK
1814}
1815
05843a27 1816struct interface *zl3vni_map_to_mac_vlan_if(struct zebra_l3vni *zl3vni)
06d9cde5
CS
1817{
1818 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
1819
1820 if (!zl3vni)
1821 return NULL;
1822
1823 if (!zl3vni->vxlan_if)
1824 return NULL;
1825
1826 zif = zl3vni->vxlan_if->info;
1827 if (!zif)
1828 return NULL;
1829
8b5fdf2e
PR
1830 return zebra_evpn_map_to_macvlan(zif->brslave_info.br_if,
1831 zl3vni->svi_if);
06d9cde5
CS
1832}
1833
1834
05843a27 1835struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id)
b7cfce93
MK
1836{
1837 struct zebra_vrf *zvrf = NULL;
1838
1839 zvrf = zebra_vrf_lookup_by_id(vrf_id);
1840 if (!zvrf)
1841 return NULL;
1842
1843 return zl3vni_lookup(zvrf->l3vni);
1844}
1845
24907262
PG
1846static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
1847{
24907262
PG
1848 struct zebra_ns *zns = ns->info;
1849 struct zebra_l3vni **p_zl3vni = (struct zebra_l3vni **)_p_zl3vni;
1850 struct zebra_from_svi_param *in_param =
1851 (struct zebra_from_svi_param *)_in_param;
1852 struct route_node *rn = NULL;
1853 struct interface *tmp_if = NULL;
1854 struct zebra_if *zif = NULL;
1855 struct zebra_l2info_vxlan *vxl = NULL;
1856
44a84850 1857 assert(in_param && p_zl3vni);
24907262
PG
1858
1859 /* loop through all vxlan-interface */
1860 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
1861 tmp_if = (struct interface *)rn->info;
1862 if (!tmp_if)
1863 continue;
1864 zif = tmp_if->info;
1865 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
1866 continue;
1867 if (!if_is_operative(tmp_if))
1868 continue;
1869 vxl = &zif->l2info.vxl;
1870
1871 if (zif->brslave_info.br_if != in_param->br_if)
1872 continue;
1873
1874 if (!in_param->bridge_vlan_aware
1875 || vxl->access_vlan == in_param->vid) {
44a84850 1876 *p_zl3vni = zl3vni_lookup(vxl->vni);
1877 return NS_WALK_STOP;
24907262
PG
1878 }
1879 }
1880
44a84850 1881 return NS_WALK_CONTINUE;
24907262
PG
1882}
1883
b7cfce93
MK
1884/*
1885 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1886 * neighbor notifications, to see if they are of interest.
1887 */
05843a27
DS
1888static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
1889 struct interface *br_if)
b7cfce93 1890{
05843a27 1891 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 1892 struct zebra_if *zif = NULL;
b7cfce93 1893 struct zebra_l2info_bridge *br = NULL;
24907262
PG
1894 struct zebra_from_svi_param in_param = {};
1895 struct zebra_l3vni **p_zl3vni;
b7cfce93
MK
1896
1897 if (!br_if)
1898 return NULL;
1899
1900 /* Make sure the linked interface is a bridge. */
1901 if (!IS_ZEBRA_IF_BRIDGE(br_if))
1902 return NULL;
24907262 1903 in_param.br_if = br_if;
b7cfce93
MK
1904
1905 /* Determine if bridge is VLAN-aware or not */
1906 zif = br_if->info;
1907 assert(zif);
1908 br = &zif->l2info.br;
24907262
PG
1909 in_param.bridge_vlan_aware = br->vlan_aware;
1910 if (in_param.bridge_vlan_aware) {
b7cfce93
MK
1911 struct zebra_l2info_vlan *vl;
1912
1913 if (!IS_ZEBRA_IF_VLAN(ifp))
1914 return NULL;
1915
1916 zif = ifp->info;
1917 assert(zif);
1918 vl = &zif->l2info.vl;
24907262 1919 in_param.vid = vl->vid;
b7cfce93
MK
1920 }
1921
1922 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1923 /* TODO: Optimize with a hash. */
b7cfce93 1924
24907262 1925 p_zl3vni = &zl3vni;
b7cfce93 1926
24907262 1927 ns_walk_func(zl3vni_from_svi_ns, (void *)&in_param, (void **)p_zl3vni);
b7cfce93
MK
1928 return zl3vni;
1929}
1930
1b09e77e
AD
1931vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if)
1932{
1933 vni_t vni = 0;
f6371c34 1934 struct zebra_evpn *zevpn = NULL;
05843a27 1935 struct zebra_l3vni *zl3vni = NULL;
1b09e77e
AD
1936
1937 /* Check if an L3VNI belongs to this SVI interface.
1938 * If not, check if an L2VNI belongs to this SVI interface.
1939 */
1940 zl3vni = zl3vni_from_svi(ifp, br_if);
1941 if (zl3vni)
1942 vni = zl3vni->vni;
1943 else {
1944 zevpn = zebra_evpn_from_svi(ifp, br_if);
1945 if (zevpn)
1946 vni = zevpn->vni;
1947 }
1948
1949 return vni;
1950}
1951
05843a27 1952static inline void zl3vni_get_vrr_rmac(struct zebra_l3vni *zl3vni,
06d9cde5
CS
1953 struct ethaddr *rmac)
1954{
1955 if (!zl3vni)
1956 return;
1957
1958 if (!is_l3vni_oper_up(zl3vni))
1959 return;
1960
1961 if (zl3vni->mac_vlan_if && if_is_operative(zl3vni->mac_vlan_if))
1962 memcpy(rmac->octet, zl3vni->mac_vlan_if->hw_addr, ETH_ALEN);
1963}
1964
b7cfce93
MK
1965/*
1966 * Inform BGP about l3-vni.
1967 */
05843a27 1968static int zl3vni_send_add_to_client(struct zebra_l3vni *zl3vni)
b7cfce93
MK
1969{
1970 struct stream *s = NULL;
1971 struct zserv *client = NULL;
06d9cde5
CS
1972 struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
1973 struct zebra_vrf *zvrf;
06d9cde5 1974 bool is_anycast_mac = true;
b7cfce93 1975
21ccc0cf 1976 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
1977 /* BGP may not be running. */
1978 if (!client)
1979 return 0;
1980
06d9cde5
CS
1981 zvrf = zebra_vrf_lookup_by_id(zl3vni->vrf_id);
1982 assert(zvrf);
1983
1984 /* get the svi and vrr rmac values */
6006b807 1985 memset(&svi_rmac, 0, sizeof(svi_rmac));
06d9cde5
CS
1986 zl3vni_get_svi_rmac(zl3vni, &svi_rmac);
1987 zl3vni_get_vrr_rmac(zl3vni, &vrr_rmac);
1988
1989 /* In absence of vrr mac use svi mac as anycast MAC value */
1990 if (is_zero_mac(&vrr_rmac)) {
1991 memcpy(&vrr_rmac, &svi_rmac, ETH_ALEN);
1992 is_anycast_mac = false;
1993 }
b7cfce93 1994
1002497a 1995 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 1996
06d9cde5
CS
1997 /* The message is used for both vni add and/or update like
1998 * vrr mac is added for l3vni SVI.
1999 */
996c9314 2000 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
b7cfce93 2001 stream_putl(s, zl3vni->vni);
06d9cde5 2002 stream_put(s, &svi_rmac, sizeof(struct ethaddr));
b67a60d2 2003 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
c48d9f5f 2004 stream_put(s, &zl3vni->filter, sizeof(int));
0483af6e 2005 stream_putl(s, zl3vni->svi_if->ifindex);
06d9cde5
CS
2006 stream_put(s, &vrr_rmac, sizeof(struct ethaddr));
2007 stream_putl(s, is_anycast_mac);
b7cfce93
MK
2008
2009 /* Write packet size. */
2010 stream_putw_at(s, 0, stream_get_endp(s));
2011
2012 if (IS_ZEBRA_DEBUG_VXLAN)
c48d9f5f 2013 zlog_debug(
ef7b8be4 2014 "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
996c9314 2015 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
ef7b8be4 2016 &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
996c9314
LB
2017 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
2018 ? "prefix-routes-only"
2019 : "none",
2020 zebra_route_string(client->proto));
b7cfce93
MK
2021
2022 client->l3vniadd_cnt++;
21ccc0cf 2023 return zserv_send_message(client, s);
b7cfce93
MK
2024}
2025
2026/*
2027 * Inform BGP about local l3-VNI deletion.
2028 */
05843a27 2029static int zl3vni_send_del_to_client(struct zebra_l3vni *zl3vni)
b7cfce93
MK
2030{
2031 struct stream *s = NULL;
2032 struct zserv *client = NULL;
2033
21ccc0cf 2034 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
b7cfce93
MK
2035 /* BGP may not be running. */
2036 if (!client)
2037 return 0;
2038
1002497a 2039 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
b7cfce93 2040
996c9314 2041 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
b7cfce93
MK
2042 stream_putl(s, zl3vni->vni);
2043
2044 /* Write packet size. */
2045 stream_putw_at(s, 0, stream_get_endp(s));
2046
2047 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 2048 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
b7cfce93
MK
2049 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
2050 zebra_route_string(client->proto));
2051
2052 client->l3vnidel_cnt++;
21ccc0cf 2053 return zserv_send_message(client, s);
b7cfce93
MK
2054}
2055
05843a27 2056static void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni)
b7cfce93 2057{
2aeb403d 2058 if (!zl3vni)
2059 return;
2060
b7cfce93
MK
2061 /* send l3vni add to BGP */
2062 zl3vni_send_add_to_client(zl3vni);
2063}
2064
05843a27 2065static void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni)
b7cfce93 2066{
2aeb403d 2067 if (!zl3vni)
2068 return;
2069
b7cfce93
MK
2070 /* send l3-vni del to BGP*/
2071 zl3vni_send_del_to_client(zl3vni);
2072}
2073
7cbae20a 2074static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
b169fd6f 2075{
f6371c34 2076 struct zebra_evpn *zevpn = (struct zebra_evpn *)bucket->data;
05843a27 2077 struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)ctxt;
b169fd6f 2078
7cbae20a
PR
2079 if (zevpn->vrf_id == zl3vni_vrf_id(zl3vni))
2080 listnode_add_sort(zl3vni->l2vnis, zevpn);
b169fd6f
AK
2081}
2082
7cbae20a 2083/*
3b0a590b
AD
2084 * Handle transition of vni from l2 to l3 and vice versa.
2085 * This function handles only the L2VNI add/delete part of
2086 * the above transition.
2087 * L3VNI add/delete is handled by the calling functions.
7cbae20a
PR
2088 */
2089static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
2090 int add)
b169fd6f 2091{
f6371c34 2092 struct zebra_evpn *zevpn = NULL;
b169fd6f 2093
7cbae20a
PR
2094 /* There is a possibility that VNI notification was already received
2095 * from kernel and we programmed it as L2-VNI
2096 * In such a case we need to delete this L2-VNI first, so
2097 * that it can be reprogrammed as L3-VNI in the system. It is also
2098 * possible that the vrf-vni mapping is removed from FRR while the vxlan
2099 * interface is still present in kernel. In this case to keep it
2100 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
2101 */
2102 if (add) {
2103 /* Locate hash entry */
8b5fdf2e 2104 zevpn = zebra_evpn_lookup(vni);
7cbae20a
PR
2105 if (!zevpn)
2106 return 0;
b169fd6f 2107
7cbae20a
PR
2108 if (IS_ZEBRA_DEBUG_VXLAN)
2109 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
b169fd6f 2110
7cbae20a 2111 /* Delete EVPN from BGP. */
8b5fdf2e 2112 zebra_evpn_send_del_to_client(zevpn);
b169fd6f 2113
7cbae20a
PR
2114 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
2115 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
b169fd6f 2116
7cbae20a 2117 /* Free up all remote VTEPs, if any. */
2fe5a02e 2118 zebra_evpn_vtep_del_all(zevpn, 1);
b169fd6f 2119
7cbae20a 2120 /* Delete the hash entry. */
8b5fdf2e 2121 if (zebra_evpn_vxlan_del(zevpn)) {
7cbae20a
PR
2122 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
2123 "Failed to del EVPN hash %p, VNI %u", zevpn,
2124 zevpn->vni);
2125 return -1;
b169fd6f 2126 }
7cbae20a 2127 } else {
3b0a590b
AD
2128 struct zebra_ns *zns;
2129 struct route_node *rn;
2130 struct interface *ifp;
2131 struct zebra_if *zif;
2132 struct zebra_l2info_vxlan *vxl;
2133 struct interface *vlan_if;
2134 bool found = false;
2135
2136 if (IS_ZEBRA_DEBUG_VXLAN)
2137 zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
2138 vni);
2139
2140 /* Find VxLAN interface for this VNI. */
2141 zns = zebra_ns_lookup(NS_DEFAULT);
2142 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
2143 ifp = (struct interface *)rn->info;
2144 if (!ifp)
2145 continue;
2146 zif = ifp->info;
2147 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
2148 continue;
2149
2150 vxl = &zif->l2info.vxl;
2151 if (vxl->vni == vni) {
2152 found = true;
2153 break;
2154 }
2155 }
2156
2157 if (!found) {
2158 if (IS_ZEBRA_DEBUG_VXLAN)
2159 zlog_err(
2160 "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
2161 vni);
2162 return -1;
2163 }
2164
2165 /* Create VNI hash entry for L2VNI */
2166 zevpn = zebra_evpn_lookup(vni);
2167 if (zevpn)
2168 return 0;
2169
2170 zevpn = zebra_evpn_add(vni);
3b0a590b
AD
2171
2172 /* Find bridge interface for the VNI */
2173 vlan_if = zvni_map_to_svi(vxl->access_vlan,
2174 zif->brslave_info.br_if);
2175 if (vlan_if)
096f7609 2176 zevpn->vrf_id = vlan_if->vrf->vrf_id;
3b0a590b
AD
2177
2178 zevpn->vxlan_if = ifp;
2179 zevpn->local_vtep_ip = vxl->vtep_ip;
2180
2181 /* Inform BGP if the VNI is up and mapped to a bridge. */
2182 if (if_is_operative(ifp) && zif->brslave_info.br_if) {
2183 zebra_evpn_send_add_to_client(zevpn);
2184 zebra_evpn_read_mac_neigh(zevpn, ifp);
2185 }
b169fd6f
AK
2186 }
2187
7cbae20a 2188 return 0;
b169fd6f
AK
2189}
2190
7cbae20a
PR
2191/* delete and uninstall rmac hash entry */
2192static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
b169fd6f 2193{
3198b2b3 2194 struct zebra_mac *zrmac = NULL;
05843a27 2195 struct zebra_l3vni *zl3vni = NULL;
b169fd6f 2196
3198b2b3 2197 zrmac = (struct zebra_mac *)bucket->data;
05843a27 2198 zl3vni = (struct zebra_l3vni *)ctx;
7cbae20a 2199 zl3vni_rmac_uninstall(zl3vni, zrmac);
b169fd6f 2200
7cbae20a
PR
2201 /* Send RMAC for FPM processing */
2202 hook_call(zebra_rmac_update, zrmac, zl3vni, true, "RMAC deleted");
b169fd6f 2203
7cbae20a 2204 zl3vni_rmac_del(zl3vni, zrmac);
b169fd6f
AK
2205}
2206
7cbae20a
PR
2207/* delete and uninstall nh hash entry */
2208static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
b169fd6f 2209{
72de4110 2210 struct zebra_neigh *n = NULL;
05843a27 2211 struct zebra_l3vni *zl3vni = NULL;
b169fd6f 2212
72de4110 2213 n = (struct zebra_neigh *)bucket->data;
05843a27 2214 zl3vni = (struct zebra_l3vni *)ctx;
7cbae20a
PR
2215 zl3vni_nh_uninstall(zl3vni, n);
2216 zl3vni_nh_del(zl3vni, n);
2217}
b169fd6f 2218
7cbae20a 2219/* re-add remote rmac if needed */
05843a27 2220static int zebra_vxlan_readd_remote_rmac(struct zebra_l3vni *zl3vni,
7cbae20a
PR
2221 struct ethaddr *rmac)
2222{
3198b2b3 2223 struct zebra_mac *zrmac = NULL;
7cbae20a
PR
2224
2225 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
2226 if (!zrmac)
2227 return 0;
2228
2229 if (IS_ZEBRA_DEBUG_VXLAN)
ef7b8be4
DL
2230 zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
2231 rmac, zl3vni->vni);
7cbae20a
PR
2232
2233 zl3vni_rmac_install(zl3vni, zrmac);
2234 return 0;
b169fd6f
AK
2235}
2236
b7cfce93
MK
2237/* Public functions */
2238
c48d9f5f
MK
2239int is_l3vni_for_prefix_routes_only(vni_t vni)
2240{
05843a27 2241 struct zebra_l3vni *zl3vni = NULL;
c48d9f5f
MK
2242
2243 zl3vni = zl3vni_lookup(vni);
2244 if (!zl3vni)
2245 return 0;
2246
2247 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
2248}
2249
2dbad57f 2250/* handle evpn route in vrf table */
e4a1ec74
MS
2251void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
2252 const struct ipaddr *vtep_ip,
2253 const struct prefix *host_prefix)
2dbad57f 2254{
05843a27 2255 struct zebra_l3vni *zl3vni = NULL;
f50dc5e6 2256 struct ipaddr ipv4_vtep;
2dbad57f 2257
2258 zl3vni = zl3vni_from_vrf(vrf_id);
2259 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
2260 return;
2261
3518f352 2262 /*
f50dc5e6
MK
2263 * add the next hop neighbor -
2264 * neigh to be installed is the ipv6 nexthop neigh
2265 */
3518f352 2266 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
2dbad57f 2267
f50dc5e6
MK
2268 /*
2269 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
2270 * address. Rmac is programmed against the ipv4 vtep because we only
2271 * support ipv4 tunnels in the h/w right now
2272 */
6006b807 2273 memset(&ipv4_vtep, 0, sizeof(ipv4_vtep));
f50dc5e6
MK
2274 ipv4_vtep.ipa_type = IPADDR_V4;
2275 if (vtep_ip->ipa_type == IPADDR_V6)
2276 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
2277 &(ipv4_vtep.ipaddr_v4));
2278 else
2279 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
2280 sizeof(struct in_addr));
2281
3518f352
DS
2282 /*
2283 * add the rmac - remote rmac to be installed is against the ipv4
f50dc5e6
MK
2284 * nexthop address
2285 */
3d43b95c 2286 zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep);
2dbad57f 2287}
2288
2289/* handle evpn vrf route delete */
22e63104 2290void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
996c9314
LB
2291 struct ipaddr *vtep_ip,
2292 struct prefix *host_prefix)
2dbad57f 2293{
05843a27 2294 struct zebra_l3vni *zl3vni = NULL;
72de4110 2295 struct zebra_neigh *nh = NULL;
3198b2b3 2296 struct zebra_mac *zrmac = NULL;
2dbad57f 2297
2298 zl3vni = zl3vni_from_vrf(vrf_id);
5e06422c 2299 if (!zl3vni)
2dbad57f 2300 return;
2301
22e63104 2302 /* find the next hop entry and rmac entry */
2303 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
2304 if (!nh)
2305 return;
2306 zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
2307
2dbad57f 2308 /* delete the next hop entry */
22e63104 2309 zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
2dbad57f 2310
2311 /* delete the rmac entry */
22e63104 2312 if (zrmac)
3d43b95c 2313 zl3vni_remote_rmac_del(zl3vni, zrmac, vtep_ip);
2dbad57f 2314}
2315
996c9314 2316void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
9f049418 2317 struct ethaddr *rmac, bool use_json)
9aa741ea 2318{
05843a27 2319 struct zebra_l3vni *zl3vni = NULL;
3198b2b3 2320 struct zebra_mac *zrmac = NULL;
316f4ca4 2321 json_object *json = NULL;
9aa741ea 2322
316f4ca4
MK
2323 if (!is_evpn_enabled()) {
2324 if (use_json)
2325 vty_out(vty, "{}\n");
9aa741ea 2326 return;
316f4ca4
MK
2327 }
2328
2329 if (use_json)
2330 json = json_object_new_object();
9aa741ea
MK
2331
2332 zl3vni = zl3vni_lookup(l3vni);
2333 if (!zl3vni) {
316f4ca4
MK
2334 if (use_json)
2335 vty_out(vty, "{}\n");
2336 else
0437e105 2337 vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
9aa741ea
MK
2338 return;
2339 }
2340
2341 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
2342 if (!zrmac) {
316f4ca4
MK
2343 if (use_json)
2344 vty_out(vty, "{}\n");
2345 else
2346 vty_out(vty,
db889978 2347 "%% Requested RMAC doesn't exist in L3-VNI %u\n",
316f4ca4 2348 l3vni);
9aa741ea
MK
2349 return;
2350 }
2351
316f4ca4
MK
2352 zl3vni_print_rmac(zrmac, vty, json);
2353
c48349e3 2354 if (use_json)
962af8a8 2355 vty_json(vty, json);
9aa741ea 2356}
2dbad57f 2357
9f049418 2358void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93 2359{
05843a27 2360 struct zebra_l3vni *zl3vni;
d7c0a89a 2361 uint32_t num_rmacs;
b7cfce93
MK
2362 struct rmac_walk_ctx wctx;
2363 json_object *json = NULL;
b7cfce93
MK
2364
2365 if (!is_evpn_enabled())
2366 return;
2367
2368 zl3vni = zl3vni_lookup(l3vni);
2369 if (!zl3vni) {
2370 if (use_json)
2371 vty_out(vty, "{}\n");
2372 else
2373 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
2374 return;
2375 }
2376 num_rmacs = hashcount(zl3vni->rmac_table);
2377 if (!num_rmacs)
2378 return;
2379
75223c9e 2380 if (use_json)
b7cfce93 2381 json = json_object_new_object();
b7cfce93 2382
6006b807 2383 memset(&wctx, 0, sizeof(wctx));
b7cfce93 2384 wctx.vty = vty;
75223c9e 2385 wctx.json = json;
b7cfce93 2386 if (!use_json) {
996c9314 2387 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
b7cfce93 2388 num_rmacs);
4cce389e 2389 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
b7cfce93
MK
2390 } else
2391 json_object_int_add(json, "numRmacs", num_rmacs);
2392
2393 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
2394
c48349e3 2395 if (use_json)
962af8a8 2396 vty_json(vty, json);
b7cfce93
MK
2397}
2398
9f049418 2399void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 2400{
b7cfce93 2401 json_object *json = NULL;
c0b4eaa4 2402 void *args[2];
b7cfce93
MK
2403
2404 if (!is_evpn_enabled()) {
2405 if (use_json)
2406 vty_out(vty, "{}\n");
2407 return;
2408 }
2409
b7cfce93
MK
2410 if (use_json)
2411 json = json_object_new_object();
2412
c0b4eaa4
MK
2413 args[0] = vty;
2414 args[1] = json;
89272910 2415 hash_iterate(zrouter.l3vni_table,
e3b78da8 2416 (void (*)(struct hash_bucket *,
c0b4eaa4
MK
2417 void *))zl3vni_print_rmac_hash_all_vni,
2418 args);
b7cfce93 2419
c48349e3 2420 if (use_json)
962af8a8 2421 vty_json(vty, json);
b7cfce93
MK
2422}
2423
996c9314 2424void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
9f049418 2425 struct ipaddr *ip, bool use_json)
9aa741ea 2426{
05843a27 2427 struct zebra_l3vni *zl3vni = NULL;
72de4110 2428 struct zebra_neigh *n = NULL;
c0e519d3 2429 json_object *json = NULL;
9aa741ea 2430
c0e519d3
MK
2431 if (!is_evpn_enabled()) {
2432 if (use_json)
2433 vty_out(vty, "{}\n");
9aa741ea 2434 return;
c0e519d3
MK
2435 }
2436
2437 if (use_json)
2438 json = json_object_new_object();
9aa741ea
MK
2439
2440 zl3vni = zl3vni_lookup(l3vni);
2441 if (!zl3vni) {
c0e519d3
MK
2442 if (use_json)
2443 vty_out(vty, "{}\n");
2444 else
2445 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
9aa741ea
MK
2446 return;
2447 }
2448
2449 n = zl3vni_nh_lookup(zl3vni, ip);
2450 if (!n) {
c0e519d3
MK
2451 if (use_json)
2452 vty_out(vty, "{}\n");
2453 else
2454 vty_out(vty,
2455 "%% Requested next-hop not present for L3-VNI %u",
2456 l3vni);
9aa741ea
MK
2457 return;
2458 }
2459
c0e519d3
MK
2460 zl3vni_print_nh(n, vty, json);
2461
c48349e3 2462 if (use_json)
962af8a8 2463 vty_json(vty, json);
9aa741ea
MK
2464}
2465
9f049418 2466void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
b7cfce93 2467{
d7c0a89a 2468 uint32_t num_nh;
2dbad57f 2469 struct nh_walk_ctx wctx;
b7cfce93 2470 json_object *json = NULL;
05843a27 2471 struct zebra_l3vni *zl3vni = NULL;
b7cfce93
MK
2472
2473 if (!is_evpn_enabled())
2474 return;
2475
2476 zl3vni = zl3vni_lookup(l3vni);
2477 if (!zl3vni) {
2478 if (use_json)
2479 vty_out(vty, "{}\n");
2480 else
2481 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
2482 return;
2483 }
2484
2485 num_nh = hashcount(zl3vni->nh_table);
2486 if (!num_nh)
2487 return;
2488
9187f600 2489 if (use_json)
b7cfce93 2490 json = json_object_new_object();
b7cfce93 2491
2dbad57f 2492 wctx.vty = vty;
9187f600 2493 wctx.json = json;
b7cfce93 2494 if (!use_json) {
996c9314 2495 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
b7cfce93 2496 num_nh);
4cce389e 2497 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
b7cfce93 2498 } else
4cce389e 2499 json_object_int_add(json, "numNextHops", num_nh);
b7cfce93
MK
2500
2501 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
2502
c48349e3 2503 if (use_json)
962af8a8 2504 vty_json(vty, json);
b7cfce93
MK
2505}
2506
9f049418 2507void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
b7cfce93 2508{
2dbad57f 2509 json_object *json = NULL;
32798965 2510 void *args[2];
2dbad57f 2511
2512 if (!is_evpn_enabled()) {
2513 if (use_json)
2514 vty_out(vty, "{}\n");
2515 return;
2516 }
2517
2dbad57f 2518 if (use_json)
2519 json = json_object_new_object();
2520
32798965
MK
2521 args[0] = vty;
2522 args[1] = json;
89272910 2523 hash_iterate(zrouter.l3vni_table,
e3b78da8 2524 (void (*)(struct hash_bucket *,
32798965
MK
2525 void *))zl3vni_print_nh_hash_all_vni,
2526 args);
2dbad57f 2527
c48349e3 2528 if (use_json)
962af8a8 2529 vty_json(vty, json);
b7cfce93
MK
2530}
2531
2532/*
2533 * Display L3 VNI information (VTY command handler).
2534 */
9f049418 2535void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
b7cfce93
MK
2536{
2537 void *args[2];
2538 json_object *json = NULL;
05843a27 2539 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 2540
b2ee5a13
MK
2541 if (!is_evpn_enabled()) {
2542 if (use_json)
2543 vty_out(vty, "{}\n");
b7cfce93 2544 return;
b2ee5a13 2545 }
b7cfce93
MK
2546
2547 zl3vni = zl3vni_lookup(vni);
2548 if (!zl3vni) {
2549 if (use_json)
2550 vty_out(vty, "{}\n");
2551 else
2552 vty_out(vty, "%% VNI %u does not exist\n", vni);
2553 return;
2554 }
2555
2556 if (use_json)
2557 json = json_object_new_object();
2558
b2ee5a13
MK
2559 args[0] = vty;
2560 args[1] = json;
b7cfce93
MK
2561 zl3vni_print(zl3vni, (void *)args);
2562
c48349e3 2563 if (use_json)
962af8a8 2564 vty_json(vty, json);
b7cfce93
MK
2565}
2566
4cce389e
MK
2567void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
2568 json_object *json_vrfs)
b7cfce93 2569{
4cce389e 2570 char buf[ETHER_ADDR_STRLEN];
05843a27 2571 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 2572
4cce389e
MK
2573 zl3vni = zl3vni_lookup(zvrf->l3vni);
2574 if (!zl3vni)
b7cfce93 2575 return;
b7cfce93 2576
4cce389e
MK
2577 if (!json_vrfs) {
2578 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
996c9314 2579 zvrf_name(zvrf), zl3vni->vni,
4cce389e 2580 zl3vni_vxlan_if_name(zl3vni),
996c9314 2581 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
4cce389e 2582 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
b7cfce93 2583 } else {
4cce389e 2584 json_object *json_vrf = NULL;
9df2b997 2585
4cce389e 2586 json_vrf = json_object_new_object();
996c9314 2587 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
4cce389e
MK
2588 json_object_int_add(json_vrf, "vni", zl3vni->vni);
2589 json_object_string_add(json_vrf, "vxlanIntf",
2590 zl3vni_vxlan_if_name(zl3vni));
2591 json_object_string_add(json_vrf, "sviIntf",
2592 zl3vni_svi_if_name(zl3vni));
2593 json_object_string_add(json_vrf, "state",
2594 zl3vni_state2str(zl3vni));
996c9314
LB
2595 json_object_string_add(
2596 json_vrf, "routerMac",
2597 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
4cce389e 2598 json_object_array_add(json_vrfs, json_vrf);
b7cfce93
MK
2599 }
2600}
2601
2602/*
2603 * Display Neighbors for a VNI (VTY command handler).
2604 */
2605void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 2606 vni_t vni, bool use_json)
b7cfce93 2607{
f6371c34 2608 struct zebra_evpn *zevpn;
d7c0a89a 2609 uint32_t num_neigh;
b7cfce93
MK
2610 struct neigh_walk_ctx wctx;
2611 json_object *json = NULL;
2612
2613 if (!is_evpn_enabled())
2614 return;
8b5fdf2e 2615 zevpn = zebra_evpn_lookup(vni);
87d76d54 2616 if (!zevpn) {
b7cfce93
MK
2617 if (use_json)
2618 vty_out(vty, "{}\n");
2619 else
2620 vty_out(vty, "%% VNI %u does not exist\n", vni);
2621 return;
2622 }
87d76d54 2623 num_neigh = hashcount(zevpn->neigh_table);
b7cfce93
MK
2624 if (!num_neigh)
2625 return;
2626
2627 if (use_json)
2628 json = json_object_new_object();
2629
2630 /* Since we have IPv6 addresses to deal with which can vary widely in
2631 * size, we try to be a bit more elegant in display by first computing
2632 * the maximum width.
2633 */
6006b807 2634 memset(&wctx, 0, sizeof(wctx));
87d76d54 2635 wctx.zevpn = zevpn;
b7cfce93
MK
2636 wctx.vty = vty;
2637 wctx.addr_width = 15;
2638 wctx.json = json;
7cbae20a
PR
2639 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2640 &wctx);
b7cfce93
MK
2641
2642 if (!use_json) {
2643 vty_out(vty,
2644 "Number of ARPs (local and remote) known for this VNI: %u\n",
2645 num_neigh);
7cbae20a 2646 zebra_evpn_print_neigh_hdr(vty, &wctx);
b7cfce93
MK
2647 } else
2648 json_object_int_add(json, "numArpNd", num_neigh);
2649
7cbae20a 2650 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
c48349e3 2651 if (use_json)
962af8a8 2652 vty_json(vty, json);
b7cfce93
MK
2653}
2654
2655/*
2656 * Display neighbors across all VNIs (VTY command handler).
2657 */
2658void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 2659 bool print_dup, bool use_json)
b7cfce93
MK
2660{
2661 json_object *json = NULL;
1374d4db 2662 void *args[3];
b7cfce93
MK
2663
2664 if (!is_evpn_enabled())
2665 return;
2666
2667 if (use_json)
2668 json = json_object_new_object();
2669
2670 args[0] = vty;
2671 args[1] = json;
1374d4db
CS
2672 args[2] = (void *)(ptrdiff_t)print_dup;
2673
87d76d54 2674 hash_iterate(zvrf->evpn_table,
e3b78da8 2675 (void (*)(struct hash_bucket *,
87d76d54 2676 void *))zevpn_print_neigh_hash_all_evpn,
b7cfce93 2677 args);
c48349e3 2678 if (use_json)
962af8a8 2679 vty_json(vty, json);
b7cfce93
MK
2680}
2681
e3fac919
NS
2682/*
2683 * Display neighbors across all VNIs in detail(VTY command handler).
2684 */
2685void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
2686 struct zebra_vrf *zvrf,
2687 bool print_dup, bool use_json)
2688{
2689 json_object *json = NULL;
2690 void *args[3];
2691
2692 if (!is_evpn_enabled())
2693 return;
2694
2695 if (use_json)
2696 json = json_object_new_object();
2697
2698 args[0] = vty;
2699 args[1] = json;
2700 args[2] = (void *)(ptrdiff_t)print_dup;
2701
87d76d54 2702 hash_iterate(zvrf->evpn_table,
e3b78da8 2703 (void (*)(struct hash_bucket *,
87d76d54 2704 void *))zevpn_print_neigh_hash_all_evpn_detail,
e3fac919 2705 args);
c48349e3 2706 if (use_json)
962af8a8 2707 vty_json(vty, json);
e3fac919
NS
2708}
2709
b7cfce93
MK
2710/*
2711 * Display specific neighbor for a VNI, if present (VTY command handler).
2712 */
2713void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
2714 struct zebra_vrf *zvrf, vni_t vni,
9f049418 2715 struct ipaddr *ip, bool use_json)
b7cfce93 2716{
f6371c34 2717 struct zebra_evpn *zevpn;
72de4110 2718 struct zebra_neigh *n;
b7cfce93
MK
2719 json_object *json = NULL;
2720
2721 if (!is_evpn_enabled())
2722 return;
8b5fdf2e 2723 zevpn = zebra_evpn_lookup(vni);
87d76d54 2724 if (!zevpn) {
b7cfce93 2725 if (use_json)
cd233079
CS
2726 vty_out(vty, "{}\n");
2727 else
2728 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2729 return;
2730 }
7cbae20a 2731 n = zebra_evpn_neigh_lookup(zevpn, ip);
d62a17ae 2732 if (!n) {
cd233079
CS
2733 if (!use_json)
2734 vty_out(vty,
2735 "%% Requested neighbor does not exist in VNI %u\n",
2736 vni);
d62a17ae 2737 return;
2738 }
cd233079
CS
2739 if (use_json)
2740 json = json_object_new_object();
2741
7cbae20a 2742 zebra_evpn_print_neigh(n, vty, json);
cec2e17d 2743
c48349e3 2744 if (use_json)
962af8a8 2745 vty_json(vty, json);
cec2e17d 2746}
2747
2748/*
2749 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2750 * By definition, these are remote neighbors.
2751 */
d62a17ae 2752void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 2753 vni_t vni, struct in_addr vtep_ip,
9f049418 2754 bool use_json)
cec2e17d 2755{
f6371c34 2756 struct zebra_evpn *zevpn;
d7c0a89a 2757 uint32_t num_neigh;
d62a17ae 2758 struct neigh_walk_ctx wctx;
cd233079 2759 json_object *json = NULL;
cec2e17d 2760
2853fed6 2761 if (!is_evpn_enabled())
d62a17ae 2762 return;
8b5fdf2e 2763 zevpn = zebra_evpn_lookup(vni);
87d76d54 2764 if (!zevpn) {
cd233079
CS
2765 if (use_json)
2766 vty_out(vty, "{}\n");
2767 else
2768 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2769 return;
2770 }
87d76d54 2771 num_neigh = hashcount(zevpn->neigh_table);
d62a17ae 2772 if (!num_neigh)
2773 return;
cec2e17d 2774
1cc5b093
PR
2775 if (use_json)
2776 json = json_object_new_object();
2777
6006b807 2778 memset(&wctx, 0, sizeof(wctx));
87d76d54 2779 wctx.zevpn = zevpn;
d62a17ae 2780 wctx.vty = vty;
68e33151 2781 wctx.addr_width = 15;
d62a17ae 2782 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
2783 wctx.r_vtep_ip = vtep_ip;
cd233079 2784 wctx.json = json;
7cbae20a
PR
2785 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2786 &wctx);
2787 hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx);
cd233079 2788
c48349e3 2789 if (use_json)
962af8a8 2790 vty_json(vty, json);
cec2e17d 2791}
2792
1374d4db
CS
2793/*
2794 * Display Duplicate detected Neighbors for a VNI
2795 * (VTY command handler).
2796 */
2797void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
2798 struct zebra_vrf *zvrf,
2799 vni_t vni,
2800 bool use_json)
2801{
f6371c34 2802 struct zebra_evpn *zevpn;
1374d4db
CS
2803 uint32_t num_neigh;
2804 struct neigh_walk_ctx wctx;
2805 json_object *json = NULL;
2806
2807 if (!is_evpn_enabled())
2808 return;
2809
8b5fdf2e 2810 zevpn = zebra_evpn_lookup(vni);
87d76d54 2811 if (!zevpn) {
1374d4db
CS
2812 vty_out(vty, "%% VNI %u does not exist\n", vni);
2813 return;
2814 }
2815
87d76d54 2816 num_neigh = hashcount(zevpn->neigh_table);
1374d4db
CS
2817 if (!num_neigh)
2818 return;
2819
87d76d54 2820 num_neigh = num_dup_detected_neighs(zevpn);
1374d4db
CS
2821 if (!num_neigh)
2822 return;
2823
2824 if (use_json)
2825 json = json_object_new_object();
2826
2827 /* Since we have IPv6 addresses to deal with which can vary widely in
2828 * size, we try to be a bit more elegant in display by first computing
2829 * the maximum width.
2830 */
6006b807 2831 memset(&wctx, 0, sizeof(wctx));
87d76d54 2832 wctx.zevpn = zevpn;
1374d4db
CS
2833 wctx.vty = vty;
2834 wctx.addr_width = 15;
2835 wctx.json = json;
7cbae20a
PR
2836 hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width,
2837 &wctx);
1374d4db
CS
2838
2839 if (!use_json) {
2840 vty_out(vty,
2841 "Number of ARPs (local and remote) known for this VNI: %u\n",
2842 num_neigh);
ce5160c0 2843 vty_out(vty, "%*s %-6s %-8s %-17s %-30s\n",
1374d4db 2844 -wctx.addr_width, "IP", "Type",
ce5160c0 2845 "State", "MAC", "Remote ES/VTEP");
1374d4db
CS
2846 } else
2847 json_object_int_add(json, "numArpNd", num_neigh);
2848
7cbae20a
PR
2849 hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash,
2850 &wctx);
1374d4db 2851
c48349e3 2852 if (use_json)
962af8a8 2853 vty_json(vty, json);
1374d4db
CS
2854}
2855
cec2e17d 2856/*
2857 * Display MACs for a VNI (VTY command handler).
2858 */
d62a17ae 2859void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 2860 vni_t vni, bool use_json)
cec2e17d 2861{
f6371c34 2862 struct zebra_evpn *zevpn;
d7c0a89a 2863 uint32_t num_macs;
d62a17ae 2864 struct mac_walk_ctx wctx;
cd233079
CS
2865 json_object *json = NULL;
2866 json_object *json_mac = NULL;
cec2e17d 2867
2853fed6 2868 if (!is_evpn_enabled())
d62a17ae 2869 return;
8b5fdf2e 2870 zevpn = zebra_evpn_lookup(vni);
87d76d54 2871 if (!zevpn) {
cd233079
CS
2872 if (use_json)
2873 vty_out(vty, "{}\n");
2874 else
2875 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 2876 return;
2877 }
87d76d54 2878 num_macs = num_valid_macs(zevpn);
d62a17ae 2879 if (!num_macs)
2880 return;
cec2e17d 2881
cd233079
CS
2882 if (use_json) {
2883 json = json_object_new_object();
2884 json_mac = json_object_new_object();
2885 }
2886
6006b807 2887 memset(&wctx, 0, sizeof(wctx));
87d76d54 2888 wctx.zevpn = zevpn;
d62a17ae 2889 wctx.vty = vty;
cd233079 2890 wctx.json = json_mac;
cec2e17d 2891
cd233079
CS
2892 if (!use_json) {
2893 vty_out(vty,
2894 "Number of MACs (local and remote) known for this VNI: %u\n",
2895 num_macs);
00a7710c
AK
2896 vty_out(vty,
2897 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
2898 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", "Type",
2899 "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
cd233079
CS
2900 } else
2901 json_object_int_add(json, "numMacs", num_macs);
cec2e17d 2902
b2998086 2903 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
cd233079
CS
2904
2905 if (use_json) {
2906 json_object_object_add(json, "macs", json_mac);
962af8a8 2907 vty_json(vty, json);
cd233079 2908 }
cec2e17d 2909}
2910
2911/*
2912 * Display MACs for all VNIs (VTY command handler).
2913 */
cd233079 2914void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
1374d4db 2915 bool print_dup, bool use_json)
cec2e17d 2916{
d62a17ae 2917 struct mac_walk_ctx wctx;
cd233079 2918 json_object *json = NULL;
cec2e17d 2919
2853fed6 2920 if (!is_evpn_enabled()) {
cd233079
CS
2921 if (use_json)
2922 vty_out(vty, "{}\n");
d62a17ae 2923 return;
cd233079
CS
2924 }
2925 if (use_json)
2926 json = json_object_new_object();
2927
6006b807 2928 memset(&wctx, 0, sizeof(wctx));
d62a17ae 2929 wctx.vty = vty;
cd233079 2930 wctx.json = json;
1374d4db 2931 wctx.print_dup = print_dup;
87d76d54 2932 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
cd233079 2933
c48349e3 2934 if (use_json)
962af8a8 2935 vty_json(vty, json);
cec2e17d 2936}
2937
cffe7580
NS
2938/*
2939 * Display MACs in detail for all VNIs (VTY command handler).
2940 */
2941void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
2942 struct zebra_vrf *zvrf,
2943 bool print_dup, bool use_json)
2944{
2945 struct mac_walk_ctx wctx;
2946 json_object *json = NULL;
2947
2948 if (!is_evpn_enabled()) {
2949 if (use_json)
2950 vty_out(vty, "{}\n");
2951 return;
2952 }
2953 if (use_json)
2954 json = json_object_new_object();
2955
6006b807 2956 memset(&wctx, 0, sizeof(wctx));
cffe7580
NS
2957 wctx.vty = vty;
2958 wctx.json = json;
2959 wctx.print_dup = print_dup;
87d76d54 2960 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail,
cffe7580
NS
2961 &wctx);
2962
c48349e3 2963 if (use_json)
962af8a8 2964 vty_json(vty, json);
cffe7580
NS
2965}
2966
cec2e17d 2967/*
2968 * Display MACs for all VNIs (VTY command handler).
2969 */
d62a17ae 2970void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
2971 struct zebra_vrf *zvrf,
9f049418 2972 struct in_addr vtep_ip, bool use_json)
cec2e17d 2973{
d62a17ae 2974 struct mac_walk_ctx wctx;
cd233079 2975 json_object *json = NULL;
cec2e17d 2976
2853fed6 2977 if (!is_evpn_enabled())
d62a17ae 2978 return;
cd233079
CS
2979
2980 if (use_json)
2981 json = json_object_new_object();
2982
6006b807 2983 memset(&wctx, 0, sizeof(wctx));
d62a17ae 2984 wctx.vty = vty;
2985 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
2986 wctx.r_vtep_ip = vtep_ip;
cd233079 2987 wctx.json = json;
87d76d54 2988 hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx);
cd233079 2989
c48349e3 2990 if (use_json)
962af8a8 2991 vty_json(vty, json);
cec2e17d 2992}
2993
2994/*
2995 * Display specific MAC for a VNI, if present (VTY command handler).
2996 */
d62a17ae 2997void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
24cdbd0d
DS
2998 vni_t vni, struct ethaddr *macaddr,
2999 bool use_json)
cec2e17d 3000{
f6371c34 3001 struct zebra_evpn *zevpn;
3198b2b3 3002 struct zebra_mac *mac;
24cdbd0d 3003 json_object *json = NULL;
cec2e17d 3004
2853fed6 3005 if (!is_evpn_enabled())
d62a17ae 3006 return;
24cdbd0d 3007
8b5fdf2e 3008 zevpn = zebra_evpn_lookup(vni);
87d76d54 3009 if (!zevpn) {
24cdbd0d
DS
3010 if (use_json)
3011 vty_out(vty, "{}\n");
3012 else
3013 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 3014 return;
3015 }
b2998086 3016 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 3017 if (!mac) {
24cdbd0d
DS
3018 if (use_json)
3019 vty_out(vty, "{}\n");
3020 else
3021 vty_out(vty,
3022 "%% Requested MAC does not exist in VNI %u\n",
3023 vni);
d62a17ae 3024 return;
3025 }
cec2e17d 3026
24cdbd0d
DS
3027 if (use_json)
3028 json = json_object_new_object();
3029
b2998086 3030 zebra_evpn_print_mac(mac, vty, json);
c48349e3 3031 if (use_json)
962af8a8 3032 vty_json(vty, json);
cec2e17d 3033}
3034
1374d4db
CS
3035/* Print Duplicate MACs per VNI */
3036void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
3037 struct zebra_vrf *zvrf,
3038 vni_t vni, bool use_json)
3039{
f6371c34 3040 struct zebra_evpn *zevpn;
1374d4db
CS
3041 struct mac_walk_ctx wctx;
3042 uint32_t num_macs;
3043 json_object *json = NULL;
3044 json_object *json_mac = NULL;
3045
3046 if (!is_evpn_enabled())
3047 return;
3048
8b5fdf2e 3049 zevpn = zebra_evpn_lookup(vni);
87d76d54 3050 if (!zevpn) {
1374d4db
CS
3051 vty_out(vty, "%% VNI %u does not exist\n", vni);
3052 return;
3053 }
3054
87d76d54 3055 num_macs = num_valid_macs(zevpn);
1374d4db
CS
3056 if (!num_macs)
3057 return;
3058
87d76d54 3059 num_macs = num_dup_detected_macs(zevpn);
1374d4db
CS
3060 if (!num_macs)
3061 return;
3062
3063 if (use_json) {
3064 json = json_object_new_object();
3065 json_mac = json_object_new_object();
3066 }
3067
6006b807 3068 memset(&wctx, 0, sizeof(wctx));
87d76d54 3069 wctx.zevpn = zevpn;
1374d4db
CS
3070 wctx.vty = vty;
3071 wctx.json = json_mac;
3072
3073 if (!use_json) {
3074 vty_out(vty,
3075 "Number of MACs (local and remote) known for this VNI: %u\n",
3076 num_macs);
b169fd6f
AK
3077 vty_out(vty, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
3078 "Flags", "Intf/Remote ES/VTEP", "VLAN");
1374d4db
CS
3079 } else
3080 json_object_int_add(json, "numMacs", num_macs);
3081
b2998086 3082 hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, &wctx);
1374d4db
CS
3083
3084 if (use_json) {
3085 json_object_object_add(json, "macs", json_mac);
962af8a8 3086 vty_json(vty, json);
1374d4db
CS
3087 }
3088
3089}
3090
e20755b2 3091int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni,
9bee0232
CS
3092 struct ethaddr *macaddr, char *errmsg,
3093 size_t errmsg_len)
09de9258 3094{
f6371c34 3095 struct zebra_evpn *zevpn;
3198b2b3 3096 struct zebra_mac *mac;
09de9258 3097 struct listnode *node = NULL;
72de4110 3098 struct zebra_neigh *nbr = NULL;
09de9258
CS
3099
3100 if (!is_evpn_enabled())
e20755b2 3101 return 0;
1883de66 3102
8b5fdf2e 3103 zevpn = zebra_evpn_lookup(vni);
87d76d54 3104 if (!zevpn) {
9bee0232 3105 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist", vni);
e20755b2 3106 return -1;
09de9258
CS
3107 }
3108
b2998086 3109 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
09de9258 3110 if (!mac) {
9bee0232
CS
3111 snprintf(errmsg, errmsg_len,
3112 "Requested MAC does not exist in VNI %u\n", vni);
e20755b2 3113 return -1;
09de9258
CS
3114 }
3115
3116 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
9bee0232
CS
3117 snprintfrr(errmsg, errmsg_len,
3118 "Requested MAC is not duplicate detected\n");
e20755b2 3119 return -1;
09de9258
CS
3120 }
3121
3122 /* Remove all IPs as duplicate associcated with this MAC */
3123 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
3124 /* For local neigh mark inactive so MACIP update is generated
3125 * to BGP. This is a scenario where MAC update received
3126 * and detected as duplicate which marked neigh as duplicate.
3127 * Later local neigh update did not get a chance to relay
3128 * to BGP. Similarly remote macip update, neigh needs to be
3129 * installed locally.
3130 */
d4199657
CS
3131 if (zvrf->dad_freeze &&
3132 CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
09de9258
CS
3133 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
3134 ZEBRA_NEIGH_SET_INACTIVE(nbr);
3135 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
b2998086
PR
3136 zebra_evpn_rem_neigh_install(
3137 zevpn, nbr, false /*was_static*/);
09de9258
CS
3138 }
3139
3140 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3141 nbr->dad_count = 0;
3142 nbr->detect_start_time.tv_sec = 0;
3143 nbr->dad_dup_detect_time = 0;
3144 }
3145
3146 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
3147 mac->dad_count = 0;
3148 mac->detect_start_time.tv_sec = 0;
3149 mac->detect_start_time.tv_usec = 0;
3150 mac->dad_dup_detect_time = 0;
3151 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
3152
d4199657
CS
3153 /* warn-only action return */
3154 if (!zvrf->dad_freeze)
e20755b2 3155 return 0;
d4199657 3156
09de9258
CS
3157 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3158 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3159 /* Inform to BGP */
b2998086
PR
3160 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
3161 mac->flags, mac->loc_seq,
3162 mac->es))
e20755b2 3163 return 0;
09de9258
CS
3164
3165 /* Process all neighbors associated with this MAC. */
b2998086
PR
3166 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
3167 0 /*es_change*/);
09de9258
CS
3168
3169 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b2998086 3170 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
09de9258
CS
3171
3172 /* Install the entry. */
b2998086 3173 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
09de9258
CS
3174 }
3175
e20755b2 3176 return 0;
09de9258
CS
3177}
3178
e20755b2 3179int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni,
9bee0232
CS
3180 struct ipaddr *ip, char *errmsg,
3181 size_t errmsg_len)
09de9258 3182{
f6371c34 3183 struct zebra_evpn *zevpn;
72de4110 3184 struct zebra_neigh *nbr;
3198b2b3 3185 struct zebra_mac *mac;
09de9258
CS
3186 char buf[INET6_ADDRSTRLEN];
3187 char buf2[ETHER_ADDR_STRLEN];
3188
3189 if (!is_evpn_enabled())
e20755b2 3190 return 0;
09de9258 3191
8b5fdf2e 3192 zevpn = zebra_evpn_lookup(vni);
87d76d54 3193 if (!zevpn) {
9bee0232 3194 snprintfrr(errmsg, errmsg_len, "VNI %u does not exist\n", vni);
e20755b2 3195 return -1;
09de9258
CS
3196 }
3197
7cbae20a 3198 nbr = zebra_evpn_neigh_lookup(zevpn, ip);
09de9258 3199 if (!nbr) {
9bee0232
CS
3200 snprintfrr(errmsg, errmsg_len,
3201 "Requested host IP does not exist in VNI %u\n", vni);
e20755b2 3202 return -1;
09de9258
CS
3203 }
3204
3205 ipaddr2str(&nbr->ip, buf, sizeof(buf));
3206
3207 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
9bee0232
CS
3208 snprintfrr(errmsg, errmsg_len,
3209 "Requested host IP %s is not duplicate detected\n",
3210 buf);
e20755b2 3211 return -1;
09de9258
CS
3212 }
3213
b2998086 3214 mac = zebra_evpn_mac_lookup(zevpn, &nbr->emac);
09de9258
CS
3215
3216 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
9bee0232
CS
3217 snprintfrr(
3218 errmsg, errmsg_len,
e20755b2 3219 "Requested IP's associated MAC %s is still in duplicate state\n",
09de9258 3220 prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
e20755b2 3221 return -1;
09de9258
CS
3222 }
3223
3224 if (IS_ZEBRA_DEBUG_VXLAN)
3225 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
15569c58 3226 __func__, buf, nbr->flags, nbr->loc_seq);
09de9258
CS
3227
3228 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3229 nbr->dad_count = 0;
3230 nbr->detect_start_time.tv_sec = 0;
3231 nbr->detect_start_time.tv_usec = 0;
3232 nbr->dad_dup_detect_time = 0;
3233 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
3234
3235 if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
7cbae20a
PR
3236 zebra_evpn_neigh_send_add_to_client(zevpn->vni, ip, &nbr->emac,
3237 nbr->mac, nbr->flags,
3238 nbr->loc_seq);
09de9258 3239 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
b2998086 3240 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
09de9258
CS
3241 }
3242
e20755b2 3243 return 0;
09de9258
CS
3244}
3245
87d76d54 3246static void zevpn_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt)
09de9258
CS
3247{
3248 struct mac_walk_ctx *wctx = ctxt;
3198b2b3 3249 struct zebra_mac *mac;
f6371c34 3250 struct zebra_evpn *zevpn;
09de9258 3251 struct listnode *node = NULL;
72de4110 3252 struct zebra_neigh *nbr = NULL;
09de9258 3253
3198b2b3 3254 mac = (struct zebra_mac *)bucket->data;
09de9258
CS
3255 if (!mac)
3256 return;
3257
87d76d54 3258 zevpn = wctx->zevpn;
09de9258
CS
3259
3260 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
3261 return;
3262
3263 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
3264 mac->dad_count = 0;
3265 mac->detect_start_time.tv_sec = 0;
3266 mac->detect_start_time.tv_usec = 0;
3267 mac->dad_dup_detect_time = 0;
3268 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
3269
3270 /* Remove all IPs as duplicate associcated with this MAC */
3271 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
3272 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
3273 && nbr->dad_count)
3274 ZEBRA_NEIGH_SET_INACTIVE(nbr);
3275
3276 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
3277 nbr->dad_count = 0;
3278 nbr->detect_start_time.tv_sec = 0;
3279 nbr->dad_dup_detect_time = 0;
3280 }
3281
3282 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3283 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
3284 /* Inform to BGP */
b2998086
PR
3285 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
3286 mac->flags, mac->loc_seq,
3287 mac->es))
09de9258
CS
3288 return;
3289
3290 /* Process all neighbors associated with this MAC. */
b2998086
PR
3291 zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
3292 0 /*es_change*/);
09de9258
CS
3293
3294 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
b2998086 3295 zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
09de9258
CS
3296
3297 /* Install the entry. */
b2998086 3298 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
09de9258
CS
3299 }
3300}
3301
87d76d54 3302static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket,
09de9258
CS
3303 void **args)
3304{
f6371c34 3305 struct zebra_evpn *zevpn;
09de9258
CS
3306 struct zebra_vrf *zvrf;
3307 struct mac_walk_ctx m_wctx;
3308 struct neigh_walk_ctx n_wctx;
3309
f6371c34 3310 zevpn = (struct zebra_evpn *)bucket->data;
87d76d54 3311 if (!zevpn)
09de9258
CS
3312 return;
3313
e20755b2 3314 zvrf = (struct zebra_vrf *)args[0];
09de9258 3315
87d76d54 3316 if (hashcount(zevpn->neigh_table)) {
6006b807 3317 memset(&n_wctx, 0, sizeof(n_wctx));
87d76d54 3318 n_wctx.zevpn = zevpn;
09de9258 3319 n_wctx.zvrf = zvrf;
7cbae20a
PR
3320 hash_iterate(zevpn->neigh_table,
3321 zebra_evpn_clear_dup_neigh_hash, &n_wctx);
09de9258
CS
3322 }
3323
87d76d54 3324 if (num_valid_macs(zevpn)) {
6006b807 3325 memset(&m_wctx, 0, sizeof(m_wctx));
87d76d54 3326 m_wctx.zevpn = zevpn;
09de9258 3327 m_wctx.zvrf = zvrf;
87d76d54 3328 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
09de9258
CS
3329 }
3330
3331}
3332
e20755b2 3333int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf *zvrf)
09de9258 3334{
e20755b2 3335 void *args[1];
09de9258
CS
3336
3337 if (!is_evpn_enabled())
e20755b2 3338 return 0;
09de9258 3339
e20755b2 3340 args[0] = zvrf;
09de9258 3341
87d76d54 3342 hash_iterate(zvrf->evpn_table,
e3b78da8 3343 (void (*)(struct hash_bucket *, void *))
87d76d54 3344 zevpn_clear_dup_detect_hash_vni_all, args);
09de9258 3345
e20755b2 3346 return 0;
09de9258
CS
3347}
3348
e20755b2 3349int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni)
09de9258 3350{
f6371c34 3351 struct zebra_evpn *zevpn;
09de9258
CS
3352 struct mac_walk_ctx m_wctx;
3353 struct neigh_walk_ctx n_wctx;
3354
3355 if (!is_evpn_enabled())
e20755b2 3356 return 0;
09de9258 3357
8b5fdf2e 3358 zevpn = zebra_evpn_lookup(vni);
87d76d54 3359 if (!zevpn) {
1d5453d6 3360 zlog_warn("VNI %u does not exist", vni);
87d76d54 3361 return CMD_WARNING;
09de9258
CS
3362 }
3363
87d76d54 3364 if (hashcount(zevpn->neigh_table)) {
6006b807 3365 memset(&n_wctx, 0, sizeof(n_wctx));
87d76d54 3366 n_wctx.zevpn = zevpn;
09de9258 3367 n_wctx.zvrf = zvrf;
7cbae20a
PR
3368 hash_iterate(zevpn->neigh_table,
3369 zebra_evpn_clear_dup_neigh_hash, &n_wctx);
09de9258
CS
3370 }
3371
87d76d54 3372 if (num_valid_macs(zevpn)) {
6006b807 3373 memset(&m_wctx, 0, sizeof(m_wctx));
87d76d54 3374 m_wctx.zevpn = zevpn;
09de9258 3375 m_wctx.zvrf = zvrf;
87d76d54 3376 hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx);
09de9258
CS
3377 }
3378
e20755b2 3379 return 0;
09de9258
CS
3380}
3381
cec2e17d 3382/*
3383 * Display MACs for a VNI from specific VTEP (VTY command handler).
3384 */
d62a17ae 3385void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
cd233079 3386 vni_t vni, struct in_addr vtep_ip,
9f049418 3387 bool use_json)
cec2e17d 3388{
f6371c34 3389 struct zebra_evpn *zevpn;
d7c0a89a 3390 uint32_t num_macs;
d62a17ae 3391 struct mac_walk_ctx wctx;
cd233079
CS
3392 json_object *json = NULL;
3393 json_object *json_mac = NULL;
cec2e17d 3394
2853fed6 3395 if (!is_evpn_enabled())
d62a17ae 3396 return;
8b5fdf2e 3397 zevpn = zebra_evpn_lookup(vni);
87d76d54 3398 if (!zevpn) {
cd233079
CS
3399 if (use_json)
3400 vty_out(vty, "{}\n");
3401 else
3402 vty_out(vty, "%% VNI %u does not exist\n", vni);
d62a17ae 3403 return;
3404 }
87d76d54 3405 num_macs = num_valid_macs(zevpn);
d62a17ae 3406 if (!num_macs)
3407 return;
cd233079
CS
3408
3409 if (use_json) {
3410 json = json_object_new_object();
3411 json_mac = json_object_new_object();
3412 }
3413
6006b807 3414 memset(&wctx, 0, sizeof(wctx));
87d76d54 3415 wctx.zevpn = zevpn;
d62a17ae 3416 wctx.vty = vty;
3417 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
3418 wctx.r_vtep_ip = vtep_ip;
cd233079 3419 wctx.json = json_mac;
b2998086 3420 hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx);
cd233079
CS
3421
3422 if (use_json) {
3423 json_object_int_add(json, "numMacs", wctx.count);
3424 if (wctx.count)
3425 json_object_object_add(json, "macs", json_mac);
962af8a8 3426 vty_json(vty, json);
cd233079 3427 }
cec2e17d 3428}
3429
3430
3431/*
3432 * Display VNI information (VTY command handler).
06931fdb
LK
3433 *
3434 * use_json flag indicates that output should be in JSON format.
3435 * json_array is non NULL when JSON output needs to be aggregated (by the
3436 * caller) and then printed, otherwise, JSON evpn vni info is printed
3437 * right away.
cec2e17d 3438 */
cd233079 3439void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
06931fdb 3440 bool use_json, json_object *json_array)
cec2e17d 3441{
cd233079
CS
3442 json_object *json = NULL;
3443 void *args[2];
05843a27 3444 struct zebra_l3vni *zl3vni = NULL;
f6371c34 3445 struct zebra_evpn *zevpn = NULL;
cec2e17d 3446
2853fed6 3447 if (!is_evpn_enabled())
d62a17ae 3448 return;
4cce389e 3449
cd233079
CS
3450 if (use_json)
3451 json = json_object_new_object();
06931fdb 3452
cd233079
CS
3453 args[0] = vty;
3454 args[1] = json;
4cce389e 3455
1f2129ec 3456 zl3vni = zl3vni_lookup(vni);
3457 if (zl3vni) {
4cce389e
MK
3458 zl3vni_print(zl3vni, (void *)args);
3459 } else {
8b5fdf2e 3460 zevpn = zebra_evpn_lookup(vni);
87d76d54 3461 if (zevpn)
8b5fdf2e 3462 zebra_evpn_print(zevpn, (void *)args);
06931fdb
LK
3463 else if (!json)
3464 vty_out(vty, "%% VNI %u does not exist\n", vni);
4cce389e
MK
3465 }
3466
cd233079 3467 if (use_json) {
06931fdb
LK
3468 /*
3469 * Each "json" object contains info about 1 VNI.
3470 * When "json_array" is non-null, we aggreggate the json output
3471 * into json_array and print it as a JSON array.
3472 */
3473 if (json_array)
3474 json_object_array_add(json_array, json);
c48349e3 3475 else
962af8a8 3476 vty_json(vty, json);
cd233079 3477 }
cec2e17d 3478}
3479
4cce389e 3480/* Display all global details for EVPN */
088f1098 3481void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
cec2e17d 3482{
4cce389e
MK
3483 int num_l2vnis = 0;
3484 int num_l3vnis = 0;
d4454626 3485 int num_vnis = 0;
cd233079 3486 json_object *json = NULL;
4cce389e 3487 struct zebra_vrf *zvrf = NULL;
cec2e17d 3488
2853fed6 3489 if (!is_evpn_enabled())
d62a17ae 3490 return;
4cce389e 3491
530db8dc 3492 zvrf = zebra_vrf_get_evpn();
4cce389e 3493
89272910 3494 num_l3vnis = hashcount(zrouter.l3vni_table);
87d76d54 3495 num_l2vnis = hashcount(zvrf->evpn_table);
d4454626 3496 num_vnis = num_l2vnis + num_l3vnis;
4cce389e
MK
3497
3498 if (uj) {
cd233079 3499 json = json_object_new_object();
ddd16ed5
MK
3500 json_object_string_add(json, "advertiseGatewayMacip",
3501 zvrf->advertise_gw_macip ? "Yes" : "No");
d4454626 3502 json_object_int_add(json, "numVnis", num_vnis);
4cce389e
MK
3503 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3504 json_object_int_add(json, "numL3Vnis", num_l3vnis);
b2ee2b71 3505 if (zebra_evpn_do_dup_addr_detect(zvrf))
61d46eda
CS
3506 json_object_boolean_true_add(json,
3507 "isDuplicateAddrDetection");
3508 else
3509 json_object_boolean_false_add(json,
3510 "isDuplicateAddrDetection");
3511 json_object_int_add(json, "maxMoves", zvrf->dad_max_moves);
3512 json_object_int_add(json, "detectionTime", zvrf->dad_time);
3513 json_object_int_add(json, "detectionFreezeTime",
3514 zvrf->dad_freeze_time);
c36e442c 3515 zebra_evpn_mh_json(json);
cd233079 3516 } else {
4cce389e
MK
3517 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
3518 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
ddd16ed5
MK
3519 vty_out(vty, "Advertise gateway mac-ip: %s\n",
3520 zvrf->advertise_gw_macip ? "Yes" : "No");
278e26de
CS
3521 vty_out(vty, "Advertise svi mac-ip: %s\n",
3522 zvrf->advertise_svi_macip ? "Yes" : "No");
243b74ed
AK
3523 vty_out(vty, "Advertise svi mac: %s\n",
3524 zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
61d46eda 3525 vty_out(vty, "Duplicate address detection: %s\n",
b2ee2b71
AK
3526 zebra_evpn_do_dup_addr_detect(zvrf) ? "Enable"
3527 : "Disable");
61d46eda
CS
3528 vty_out(vty, " Detection max-moves %u, time %d\n",
3529 zvrf->dad_max_moves, zvrf->dad_time);
3530 if (zvrf->dad_freeze) {
3531 if (zvrf->dad_freeze_time)
3532 vty_out(vty, " Detection freeze %u\n",
3533 zvrf->dad_freeze_time);
3534 else
3535 vty_out(vty, " Detection freeze %s\n",
3536 "permanent");
3537 }
c36e442c 3538 zebra_evpn_mh_print(vty);
cd233079 3539 }
4cce389e 3540
c48349e3 3541 if (uj)
962af8a8 3542 vty_json(vty, json);
4cce389e
MK
3543}
3544
3545/*
3546 * Display VNI hash table (VTY command handler).
3547 */
3548void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
9f049418 3549 bool use_json)
4cce389e
MK
3550{
3551 json_object *json = NULL;
4cce389e
MK
3552 void *args[2];
3553
3554 if (!is_evpn_enabled())
3555 return;
3556
4cce389e
MK
3557 if (use_json)
3558 json = json_object_new_object();
3559 else
996c9314
LB
3560 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
3561 "Type", "VxLAN IF", "# MACs", "# ARPs",
3562 "# Remote VTEPs", "Tenant VRF");
4cce389e 3563
cd233079
CS
3564 args[0] = vty;
3565 args[1] = json;
3566
4cce389e 3567 /* Display all L2-VNIs */
8b5fdf2e
PR
3568 hash_iterate(
3569 zvrf->evpn_table,
3570 (void (*)(struct hash_bucket *, void *))zebra_evpn_print_hash,
3571 args);
cd233079 3572
4cce389e 3573 /* Display all L3-VNIs */
89272910 3574 hash_iterate(zrouter.l3vni_table,
e3b78da8 3575 (void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
4cce389e
MK
3576 args);
3577
c48349e3 3578 if (use_json)
962af8a8 3579 vty_json(vty, json);
cec2e17d 3580}
3581
3950b52c
CS
3582void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
3583{
3584 struct stream *s;
3585 int time = 0;
3586 uint32_t max_moves = 0;
3587 uint32_t freeze_time = 0;
3588 bool dup_addr_detect = false;
3589 bool freeze = false;
b2ee2b71 3590 bool old_addr_detect;
3950b52c
CS
3591
3592 s = msg;
3593 STREAM_GETL(s, dup_addr_detect);
3594 STREAM_GETL(s, time);
3595 STREAM_GETL(s, max_moves);
3596 STREAM_GETL(s, freeze);
3597 STREAM_GETL(s, freeze_time);
3598
b2ee2b71
AK
3599 old_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
3600 zvrf->dup_addr_detect = dup_addr_detect;
3601 dup_addr_detect = zebra_evpn_do_dup_addr_detect(zvrf);
3602
09de9258
CS
3603 /* DAD previous state was enabled, and new state is disable,
3604 * clear all duplicate detected addresses.
3605 */
b2ee2b71 3606 if (old_addr_detect && !dup_addr_detect)
e20755b2 3607 zebra_vxlan_clear_dup_detect_vni_all(zvrf);
09de9258 3608
3950b52c
CS
3609 zvrf->dad_time = time;
3610 zvrf->dad_max_moves = max_moves;
3611 zvrf->dad_freeze = freeze;
3612 zvrf->dad_freeze_time = freeze_time;
3613
3614 if (IS_ZEBRA_DEBUG_VXLAN)
3615 zlog_debug(
6005fe55
CS
3616 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
3617 vrf_id_to_name(zvrf->vrf->vrf_id),
b2ee2b71
AK
3618 dup_addr_detect ? "enable" : "disable",
3619 zvrf->dad_max_moves, zvrf->dad_time,
3950b52c
CS
3620 zvrf->dad_freeze ? "enable" : "disable",
3621 zvrf->dad_freeze_time);
3622
3623stream_failure:
3624 return;
3625}
3626
09af6961
NS
3627/*
3628 * Display VNI hash table in detail(VTY command handler).
3629 */
3630void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
3631 bool use_json)
3632{
06931fdb 3633 json_object *json_array = NULL;
09af6961 3634 struct zebra_ns *zns = NULL;
8b5fdf2e 3635 struct zebra_evpn_show zes;
09af6961
NS
3636
3637 if (!is_evpn_enabled())
3638 return;
3639
3640 zns = zebra_ns_lookup(NS_DEFAULT);
3641 if (!zns)
3642 return;
3643
09af6961 3644 if (use_json)
06931fdb 3645 json_array = json_object_new_array();
09af6961
NS
3646
3647 zes.vty = vty;
06931fdb 3648 zes.json = json_array;
09af6961 3649 zes.zvrf = zvrf;
06931fdb 3650 zes.use_json = use_json;
09af6961
NS
3651
3652 /* Display all L2-VNIs */
8b5fdf2e
PR
3653 hash_iterate(zvrf->evpn_table,
3654 (void (*)(struct hash_bucket *,
3655 void *))zebra_evpn_print_hash_detail,
3656 &zes);
09af6961
NS
3657
3658 /* Display all L3-VNIs */
3659 hash_iterate(zrouter.l3vni_table,
e3b78da8 3660 (void (*)(struct hash_bucket *,
09af6961
NS
3661 void *))zl3vni_print_hash_detail,
3662 &zes);
3663
c48349e3 3664 if (use_json)
962af8a8 3665 vty_json(vty, json_array);
09af6961
NS
3666}
3667
2232a77c 3668/*
ee69da27
MK
3669 * Handle neighbor delete notification from the kernel (on a VLAN device
3670 * / L3 interface). This may result in either the neighbor getting deleted
3671 * from our database or being re-added to the kernel (if it is a valid
2232a77c 3672 * remote neighbor).
3673 */
ee69da27
MK
3674int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
3675 struct interface *link_if,
3676 struct ipaddr *ip)
d62a17ae 3677{
f6371c34 3678 struct zebra_evpn *zevpn = NULL;
05843a27 3679 struct zebra_l3vni *zl3vni = NULL;
b7cfce93 3680
8c9b80b9 3681 /* check if this is a remote neigh entry corresponding to remote
523cafc4 3682 * next-hop
3683 */
8c9b80b9
MK
3684 zl3vni = zl3vni_from_svi(ifp, link_if);
3685 if (zl3vni)
3686 return zl3vni_local_nh_del(zl3vni, ip);
d62a17ae 3687
3688 /* We are only interested in neighbors on an SVI that resides on top
3689 * of a VxLAN bridge.
3690 */
8b5fdf2e 3691 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 3692 if (!zevpn) {
6041b686 3693 if (IS_ZEBRA_DEBUG_VXLAN)
15569c58 3694 zlog_debug(
ef7b8be4
DL
3695 "%s: Del neighbor %pIA EVPN is not present for interface %s",
3696 __func__, ip, ifp->name);
d62a17ae 3697 return 0;
6041b686 3698 }
8c9b80b9 3699
87d76d54 3700 if (!zevpn->vxlan_if) {
9df414fe 3701 zlog_debug(
d62a17ae 3702 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
87d76d54 3703 zevpn->vni, zevpn);
d62a17ae 3704 return -1;
3705 }
3706
3707 if (IS_ZEBRA_DEBUG_VXLAN)
ef7b8be4
DL
3708 zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
3709 ip, ifp->name, ifp->ifindex, zevpn->vni);
d62a17ae 3710
33064a62 3711 return zebra_evpn_neigh_del_ip(zevpn, ip);
2232a77c 3712}
3713
3714/*
ee69da27
MK
3715 * Handle neighbor add or update notification from the kernel (on a VLAN
3716 * device / L3 interface). This is typically for a local neighbor but can
3717 * also be for a remote neighbor (e.g., ageout notification). It could
3718 * also be a "move" scenario.
2232a77c 3719 */
ee69da27
MK
3720int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
3721 struct interface *link_if,
3722 struct ipaddr *ip,
3723 struct ethaddr *macaddr,
3724 uint16_t state,
a37f4598 3725 bool is_ext,
b169fd6f
AK
3726 bool is_router,
3727 bool local_inactive, bool dp_static)
d62a17ae 3728{
f6371c34 3729 struct zebra_evpn *zevpn = NULL;
05843a27 3730 struct zebra_l3vni *zl3vni = NULL;
3bcbba10 3731
3732 /* check if this is a remote neigh entry corresponding to remote
3733 * next-hop
3734 */
3735 zl3vni = zl3vni_from_svi(ifp, link_if);
3736 if (zl3vni)
3737 return zl3vni_local_nh_add_update(zl3vni, ip, state);
b7cfce93 3738
d62a17ae 3739 /* We are only interested in neighbors on an SVI that resides on top
3740 * of a VxLAN bridge.
3741 */
8b5fdf2e 3742 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 3743 if (!zevpn)
d62a17ae 3744 return 0;
3745
b169fd6f 3746 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
d62a17ae 3747 zlog_debug(
ef7b8be4
DL
3748 "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
3749 ip, macaddr, ifp->name,
a37f4598 3750 ifp->ifindex, state, is_ext ? "ext-learned " : "",
3751 is_router ? "router " : "",
b169fd6f 3752 local_inactive ? "local_inactive " : "",
7c0e4dc6 3753 dp_static ? "peer_sync " : "", zevpn->vni);
d62a17ae 3754
ee69da27 3755 /* Is this about a local neighbor or a remote one? */
a37f4598 3756 if (!is_ext)
7cbae20a
PR
3757 return zebra_evpn_local_neigh_update(zevpn, ifp, ip, macaddr,
3758 is_router, local_inactive,
3759 dp_static);
b7cfce93 3760
7cbae20a 3761 return zebra_evpn_remote_neigh_update(zevpn, ifp, ip, macaddr, state);
2232a77c 3762}
3763
0bd371c6
DS
3764static int32_t
3765zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni,
3766 struct ethaddr *macaddr, uint16_t *ipa_len,
3767 struct ipaddr *ip, struct in_addr *vtep_ip,
ce5160c0 3768 uint8_t *flags, uint32_t *seq, esi_t *esi)
0bd371c6
DS
3769{
3770 uint16_t l = 0;
3771
3772 /*
3773 * Obtain each remote MACIP and process.
3774 * Message contains VNI, followed by MAC followed by IP (if any)
3775 * followed by remote VTEP IP.
3776 */
3777 memset(ip, 0, sizeof(*ip));
3778 STREAM_GETL(s, *vni);
3779 STREAM_GET(macaddr->octet, s, ETH_ALEN);
0ffd0fb5 3780 STREAM_GETW(s, *ipa_len);
0bd371c6
DS
3781
3782 if (*ipa_len) {
3783 if (*ipa_len == IPV4_MAX_BYTELEN)
3784 ip->ipa_type = IPADDR_V4;
3785 else if (*ipa_len == IPV6_MAX_BYTELEN)
3786 ip->ipa_type = IPADDR_V6;
3787 else {
3788 if (IS_ZEBRA_DEBUG_VXLAN)
3789 zlog_debug(
3790 "ipa_len *must* be %d or %d bytes in length not %d",
3791 IPV4_MAX_BYTELEN, IPV6_MAX_BYTELEN,
3792 *ipa_len);
3793 goto stream_failure;
3794 }
3795
3796 STREAM_GET(&ip->ip.addr, s, *ipa_len);
3797 }
3798 l += 4 + ETH_ALEN + 4 + *ipa_len;
3799 STREAM_GET(&vtep_ip->s_addr, s, IPV4_MAX_BYTELEN);
3800 l += IPV4_MAX_BYTELEN;
3801
3802 if (add) {
3803 STREAM_GETC(s, *flags);
3804 STREAM_GETL(s, *seq);
3805 l += 5;
ce5160c0
AK
3806 STREAM_GET(esi, s, sizeof(esi_t));
3807 l += sizeof(esi_t);
0bd371c6
DS
3808 }
3809
3810 return l;
3811
3812stream_failure:
3813 return -1;
3814}
b682f6de 3815
2232a77c 3816/*
3817 * Handle message from client to delete a remote MACIP for a VNI.
3818 */
89f4e507 3819void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
d62a17ae 3820{
3821 struct stream *s;
3822 vni_t vni;
3823 struct ethaddr macaddr;
3824 struct ipaddr ip;
3825 struct in_addr vtep_ip;
9df2b997 3826 uint16_t l = 0, ipa_len;
d62a17ae 3827 char buf1[INET6_ADDRSTRLEN];
3828
1002497a 3829 s = msg;
d62a17ae 3830
89f4e507 3831 while (l < hdr->length) {
0bd371c6
DS
3832 int res_length = zebra_vxlan_remote_macip_helper(
3833 false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL,
ce5160c0 3834 NULL, NULL);
4824d144 3835
0bd371c6
DS
3836 if (res_length == -1)
3837 goto stream_failure;
d62a17ae 3838
0bd371c6 3839 l += res_length;
d62a17ae 3840 if (IS_ZEBRA_DEBUG_VXLAN)
3841 zlog_debug(
ef7b8be4
DL
3842 "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
3843 vni, &macaddr,
f07e1c99 3844 ipa_len ? " IP " : "",
3845 ipa_len ?
3846 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
9bcef951 3847 &vtep_ip, zebra_route_string(client->proto));
d62a17ae 3848
7f7e49d1
MS
3849 /* Enqueue to workqueue for processing */
3850 zebra_rib_queue_evpn_rem_macip_del(vni, &macaddr, &ip, vtep_ip);
d62a17ae 3851 }
3852
ec93aa12 3853stream_failure:
8068a649 3854 return;
2232a77c 3855}
3856
3857/*
3858 * Handle message from client to add a remote MACIP for a VNI. This
3859 * could be just the add of a MAC address or the add of a neighbor
3860 * (IP+MAC).
3861 */
89f4e507 3862void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
d62a17ae 3863{
3864 struct stream *s;
3865 vni_t vni;
3866 struct ethaddr macaddr;
3867 struct ipaddr ip;
3868 struct in_addr vtep_ip;
9df2b997 3869 uint16_t l = 0, ipa_len;
f07e1c99 3870 uint8_t flags = 0;
3871 uint32_t seq;
d62a17ae 3872 char buf1[INET6_ADDRSTRLEN];
ce5160c0
AK
3873 esi_t esi;
3874 char esi_buf[ESI_STR_LEN];
d62a17ae 3875
ec93aa12 3876 if (!EVPN_ENABLED(zvrf)) {
9df414fe 3877 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
8068a649 3878 return;
ec93aa12 3879 }
d62a17ae 3880
1002497a 3881 s = msg;
d62a17ae 3882
89f4e507 3883 while (l < hdr->length) {
7f7e49d1 3884
0bd371c6
DS
3885 int res_length = zebra_vxlan_remote_macip_helper(
3886 true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip,
ce5160c0 3887 &flags, &seq, &esi);
d62a17ae 3888
0bd371c6
DS
3889 if (res_length == -1)
3890 goto stream_failure;
d62a17ae 3891
0bd371c6 3892 l += res_length;
ce5160c0
AK
3893 if (IS_ZEBRA_DEBUG_VXLAN) {
3894 if (memcmp(&esi, zero_esi, sizeof(esi_t)))
3895 esi_to_str(&esi, esi_buf, sizeof(esi_buf));
3896 else
9e0c2fd1 3897 strlcpy(esi_buf, "-", ESI_STR_LEN);
d62a17ae 3898 zlog_debug(
ef7b8be4 3899 "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
b169fd6f
AK
3900 (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ?
3901 "sync-" : "",
ef7b8be4 3902 vni, &macaddr,
f07e1c99 3903 ipa_len ? " IP " : "",
3904 ipa_len ?
3905 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
9bcef951 3906 flags, seq, &vtep_ip, esi_buf,
d62a17ae 3907 zebra_route_string(client->proto));
ce5160c0 3908 }
d62a17ae 3909
7f7e49d1
MS
3910 /* Enqueue to workqueue for processing */
3911 zebra_rib_queue_evpn_rem_macip_add(vni, &macaddr, &ip, flags,
3912 seq, vtep_ip, &esi);
d62a17ae 3913 }
3914
ec93aa12 3915stream_failure:
8068a649 3916 return;
13d60d35 3917}
3918
4b3f26f4 3919/*
3920 * Handle remote vtep delete by kernel; re-add the vtep if we have it
3921 */
3922int zebra_vxlan_check_readd_vtep(struct interface *ifp,
3923 struct in_addr vtep_ip)
3924{
3925 struct zebra_if *zif;
3926 struct zebra_vrf *zvrf = NULL;
3927 struct zebra_l2info_vxlan *vxl;
3928 vni_t vni;
f6371c34 3929 struct zebra_evpn *zevpn = NULL;
c172c032 3930 struct zebra_vtep *zvtep = NULL;
4b3f26f4 3931
3932 zif = ifp->info;
3933 assert(zif);
3934 vxl = &zif->l2info.vxl;
3935 vni = vxl->vni;
3936
3937 /* If EVPN is not enabled, nothing to do. */
3938 if (!is_evpn_enabled())
3939 return 0;
3940
3941 /* Locate VRF corresponding to interface. */
096f7609 3942 zvrf = ifp->vrf->info;
4b3f26f4 3943 if (!zvrf)
3944 return -1;
3945
3946 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 3947 zevpn = zebra_evpn_lookup(vni);
87d76d54 3948 if (!zevpn)
4b3f26f4 3949 return 0;
3950
3951 /* If the remote vtep entry doesn't exists nothing to do */
8b5fdf2e 3952 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4b3f26f4 3953 if (!zvtep)
3954 return 0;
3955
3956 if (IS_ZEBRA_DEBUG_VXLAN)
3957 zlog_debug(
9bcef951
MS
3958 "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
3959 &vtep_ip, ifp->name, ifp->ifindex, vni);
4b3f26f4 3960
8b5fdf2e 3961 zebra_evpn_vtep_install(zevpn, zvtep);
4b3f26f4 3962 return 0;
3963}
3964
13d60d35 3965/*
2232a77c 3966 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
3967 * us, this must involve a multihoming scenario. Treat this as implicit delete
3968 * of any prior local MAC.
13d60d35 3969 */
15400f95
AK
3970static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
3971 struct interface *br_if,
3972 struct ethaddr *macaddr,
3973 vlanid_t vid)
13d60d35 3974{
d62a17ae 3975 struct zebra_if *zif;
d62a17ae 3976 struct zebra_l2info_vxlan *vxl;
3977 vni_t vni;
f6371c34 3978 struct zebra_evpn *zevpn;
3198b2b3 3979 struct zebra_mac *mac;
13d60d35 3980
d62a17ae 3981 zif = ifp->info;
3982 assert(zif);
3983 vxl = &zif->l2info.vxl;
3984 vni = vxl->vni;
13d60d35 3985
2853fed6 3986 /* Check if EVPN is enabled. */
3987 if (!is_evpn_enabled())
d62a17ae 3988 return 0;
13d60d35 3989
d62a17ae 3990 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 3991 zevpn = zebra_evpn_lookup(vni);
87d76d54 3992 if (!zevpn)
d62a17ae 3993 return 0;
13d60d35 3994
d62a17ae 3995 /* If entry doesn't exist, nothing to do. */
b2998086 3996 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 3997 if (!mac)
3998 return 0;
13d60d35 3999
d62a17ae 4000 /* Is it a local entry? */
4001 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
4002 return 0;
13d60d35 4003
d62a17ae 4004 if (IS_ZEBRA_DEBUG_VXLAN)
4005 zlog_debug(
ef7b8be4
DL
4006 "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
4007 macaddr, ifp->name, ifp->ifindex, vni, mac->flags);
13d60d35 4008
d62a17ae 4009 /* Remove MAC from BGP. */
b2998086
PR
4010 zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
4011 false /* force */);
13d60d35 4012
b6938a74
MK
4013 /*
4014 * If there are no neigh associated with the mac delete the mac
4015 * else mark it as AUTO for forward reference
4016 */
4017 if (!listcount(mac->neigh_list)) {
b2998086 4018 zebra_evpn_mac_del(zevpn, mac);
b6938a74 4019 } else {
8b07f173 4020 zebra_evpn_mac_clear_fwd_info(mac);
b169fd6f 4021 UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
5756dd1d 4022 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
b6938a74
MK
4023 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
4024 }
13d60d35 4025
d62a17ae 4026 return 0;
13d60d35 4027}
4028
15400f95
AK
4029/* MAC notification from the dataplane with a network dest port -
4030 * 1. This can be a local MAC on a down ES (if fast-failover is not possible
4031 * 2. Or it can be a remote MAC
4032 */
4033int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
4034 struct interface *br_if,
4035 struct ethaddr *macaddr, vlanid_t vid,
4036 uint32_t nhg_id, bool sticky, bool dp_static)
4037{
4038 struct zebra_evpn_es *es;
4039 struct interface *acc_ifp;
4040
df6c1982 4041 /* If netlink message is with vid, it will have no nexthop.
4042 * So skip it.
4043 */
4044 if (vid) {
4045 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4046 zlog_debug("dpAdd MAC %pEA VID %u - ignore as no nhid",
4047 macaddr, vid);
4048 return 0;
4049 }
4050
4051 /* Get vxlan's vid for netlink message has no it. */
4052 vid = ((struct zebra_if *)ifp->info)->l2info.vxl.access_vlan;
4053
15400f95
AK
4054 /* if remote mac delete the local entry */
4055 if (!nhg_id || !zebra_evpn_nhg_is_local_es(nhg_id, &es)
4056 || !zebra_evpn_es_local_mac_via_network_port(es)) {
4057 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4058 zlog_debug("dpAdd remote MAC %pEA VID %u", macaddr,
4059 vid);
4060 return zebra_vxlan_check_del_local_mac(ifp, br_if, macaddr,
4061 vid);
4062 }
4063
4064 /* If local MAC on a down local ES translate the network-mac-add
209813e9 4065 * to a local-active-mac-add
15400f95
AK
4066 */
4067 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4068 zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr, vid);
4069 acc_ifp = es->zif->ifp;
4070 return zebra_vxlan_local_mac_add_update(
4071 acc_ifp, br_if, macaddr, vid, sticky,
4072 false /* local_inactive */, dp_static);
4073}
4074
13d60d35 4075/*
15400f95
AK
4076 * Handle network MAC delete by kernel -
4077 * 1. readd the remote MAC if we have it
4078 * 2. local MAC with does ES may also need to be re-installed
13d60d35 4079 */
15400f95
AK
4080int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
4081 struct interface *br_if,
4082 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 4083{
a9a76262
MK
4084 struct zebra_if *zif = NULL;
4085 struct zebra_l2info_vxlan *vxl = NULL;
d62a17ae 4086 vni_t vni;
f6371c34 4087 struct zebra_evpn *zevpn = NULL;
05843a27 4088 struct zebra_l3vni *zl3vni = NULL;
3198b2b3 4089 struct zebra_mac *mac = NULL;
2232a77c 4090
d62a17ae 4091 zif = ifp->info;
4092 assert(zif);
4093 vxl = &zif->l2info.vxl;
4094 vni = vxl->vni;
2232a77c 4095
2853fed6 4096 /* Check if EVPN is enabled. */
4097 if (!is_evpn_enabled())
d62a17ae 4098 return 0;
2232a77c 4099
a9a76262
MK
4100 /* check if this is a remote RMAC and readd simillar to remote macs */
4101 zl3vni = zl3vni_lookup(vni);
4102 if (zl3vni)
4103 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
4104
d62a17ae 4105 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4106 zevpn = zebra_evpn_lookup(vni);
87d76d54 4107 if (!zevpn)
d62a17ae 4108 return 0;
13d60d35 4109
d62a17ae 4110 /* If entry doesn't exist, nothing to do. */
b2998086 4111 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
d62a17ae 4112 if (!mac)
4113 return 0;
2232a77c 4114
15400f95
AK
4115 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
4116 /* If remote entry simply re-install */
4117 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4118 zlog_debug(
4119 "dpDel remote MAC %pEA intf %s(%u) VNI %u - readd",
4120 macaddr, ifp->name, ifp->ifindex, vni);
4121 zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */);
4122 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && mac->es
4123 && zebra_evpn_es_local_mac_via_network_port(mac->es)) {
4124 /* If local entry via nw-port call local-del which will
4125 * re-install entry in the dataplane is needed
4126 */
4127 if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
4128 zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr,
4129 vni);
00a7710c
AK
4130
4131 zebra_evpn_del_local_mac(zevpn, mac, false);
15400f95 4132 }
13d60d35 4133
d62a17ae 4134 return 0;
13d60d35 4135}
4136
4137/*
2232a77c 4138 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
13d60d35 4139 */
d62a17ae 4140int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
4141 struct ethaddr *macaddr, vlanid_t vid)
13d60d35 4142{
f6371c34 4143 struct zebra_evpn *zevpn;
3198b2b3 4144 struct zebra_mac *mac;
13d60d35 4145
d62a17ae 4146 /* We are interested in MACs only on ports or (port, VLAN) that
4147 * map to a VNI.
4148 */
8b5fdf2e 4149 zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
87d76d54 4150 if (!zevpn)
d62a17ae 4151 return 0;
87d76d54 4152 if (!zevpn->vxlan_if) {
9df414fe
QY
4153 zlog_debug(
4154 "VNI %u hash %p doesn't have intf upon local MAC DEL",
87d76d54 4155 zevpn->vni, zevpn);
d62a17ae 4156 return -1;
4157 }
13d60d35 4158
15400f95
AK
4159 /* If entry doesn't exist, nothing to do. */
4160 mac = zebra_evpn_mac_lookup(zevpn, macaddr);
4161 if (!mac)
4162 return 0;
4163
4164 /* Is it a local entry? */
4165 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
4166 return 0;
4167
00a7710c 4168 return zebra_evpn_del_local_mac(zevpn, mac, false);
13d60d35 4169}
4170
4171/*
2232a77c 4172 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
13d60d35 4173 */
d62a17ae 4174int zebra_vxlan_local_mac_add_update(struct interface *ifp,
4175 struct interface *br_if,
4176 struct ethaddr *macaddr, vlanid_t vid,
b169fd6f
AK
4177 bool sticky, bool local_inactive,
4178 bool dp_static)
d62a17ae 4179{
f6371c34 4180 struct zebra_evpn *zevpn;
e22a946a 4181 struct zebra_vrf *zvrf;
d62a17ae 4182
2bdd4461 4183 assert(ifp);
b7895aad 4184
d62a17ae 4185 /* We are interested in MACs only on ports or (port, VLAN) that
87d76d54 4186 * map to an EVPN.
d62a17ae 4187 */
8b5fdf2e 4188 zevpn = zebra_evpn_map_vlan(ifp, br_if, vid);
87d76d54 4189 if (!zevpn) {
d62a17ae 4190 if (IS_ZEBRA_DEBUG_VXLAN)
4191 zlog_debug(
ef7b8be4
DL
4192 " Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
4193 sticky ? "sticky " : "", macaddr,
d62a17ae 4194 ifp->name, ifp->ifindex, vid);
4195 return 0;
4196 }
4197
87d76d54 4198 if (!zevpn->vxlan_if) {
28bd0652
DS
4199 if (IS_ZEBRA_DEBUG_VXLAN)
4200 zlog_debug(
d6951e5e 4201 " VNI %u hash %p doesn't have intf upon local MAC ADD",
87d76d54 4202 zevpn->vni, zevpn);
d62a17ae 4203 return -1;
4204 }
4205
d6bf8f13 4206 zvrf = zebra_vrf_get_evpn();
d9d3455e
PR
4207 return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid,
4208 sticky, local_inactive,
00a7710c 4209 dp_static, NULL);
2232a77c 4210}
13d60d35 4211
4212/*
87d76d54 4213 * Handle message from client to delete a remote VTEP for an EVPN.
13d60d35 4214 */
7e5b0b2b 4215void zebra_vxlan_remote_vtep_del_zapi(ZAPI_HANDLER_ARGS)
d62a17ae 4216{
4217 struct stream *s;
d7c0a89a 4218 unsigned short l = 0;
d62a17ae 4219 vni_t vni;
4220 struct in_addr vtep_ip;
d62a17ae 4221
ec93aa12 4222 if (!is_evpn_enabled()) {
9df414fe 4223 zlog_debug(
7e5b0b2b 4224 "%s: EVPN is not enabled yet we have received a VTEP DEL msg",
15569c58 4225 __func__);
8068a649 4226 return;
ec93aa12
DS
4227 }
4228
986512a3 4229 if (!EVPN_ENABLED(zvrf)) {
7e5b0b2b
MS
4230 zlog_debug("Recv VTEP DEL zapi for non-EVPN VRF %u",
4231 zvrf_id(zvrf));
8068a649 4232 return;
2853fed6 4233 }
4234
1002497a 4235 s = msg;
d62a17ae 4236
89f4e507 4237 while (l < hdr->length) {
694bd4ce 4238 int flood_control __attribute__((unused));
8a64de72 4239
d62a17ae 4240 /* Obtain each remote VTEP and process. */
ec93aa12 4241 STREAM_GETL(s, vni);
d62a17ae 4242 l += 4;
ec93aa12 4243 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
d62a17ae 4244 l += IPV4_MAX_BYTELEN;
4245
8a64de72
DS
4246 /* Flood control is intentionally ignored right now */
4247 STREAM_GETL(s, flood_control);
4248 l += 4;
4249
d62a17ae 4250 if (IS_ZEBRA_DEBUG_VXLAN)
7e5b0b2b 4251 zlog_debug("Recv VTEP DEL %pI4 VNI %u from %s",
9bcef951 4252 &vtep_ip, vni,
d62a17ae 4253 zebra_route_string(client->proto));
4254
7e5b0b2b
MS
4255 /* Enqueue for processing */
4256 zebra_rib_queue_evpn_rem_vtep_del(zvrf_id(zvrf), vni, vtep_ip);
4257 }
4258
4259stream_failure:
4260 return;
4261}
4262
4263/*
4264 * Handle message from client to delete a remote VTEP for an EVPN.
4265 */
4266void zebra_vxlan_remote_vtep_del(vrf_id_t vrf_id, vni_t vni,
4267 struct in_addr vtep_ip)
4268{
f6371c34 4269 struct zebra_evpn *zevpn;
c172c032 4270 struct zebra_vtep *zvtep;
7e5b0b2b
MS
4271 struct interface *ifp;
4272 struct zebra_if *zif;
4273 struct zebra_vrf *zvrf;
4274
4275 if (!is_evpn_enabled()) {
4276 zlog_debug("%s: Can't process vtep del: EVPN is not enabled",
4277 __func__);
4278 return;
4279 }
4280
4281 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4282 if (!zvrf)
4283 return;
d62a17ae 4284
7e5b0b2b
MS
4285 if (!EVPN_ENABLED(zvrf)) {
4286 zlog_debug("Can't process VTEP DEL for non-EVPN VRF %u",
4287 zvrf_id(zvrf));
4288 return;
4289 }
4290
4291 /* Locate VNI hash entry - expected to exist. */
4292 zevpn = zebra_evpn_lookup(vni);
4293 if (!zevpn) {
4294 if (IS_ZEBRA_DEBUG_VXLAN)
9df414fe 4295 zlog_debug(
7e5b0b2b
MS
4296 "Failed to locate VNI hash for remote VTEP DEL, VNI %u",
4297 vni);
4298 return;
4299 }
b5ebdc9b 4300
7e5b0b2b
MS
4301 ifp = zevpn->vxlan_if;
4302 if (!ifp) {
4303 zlog_debug(
4304 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
4305 zevpn->vni, zevpn);
4306 return;
4307 }
4308 zif = ifp->info;
b5ebdc9b 4309
7e5b0b2b
MS
4310 /* If down or not mapped to a bridge, we're done. */
4311 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4312 return;
4313
4314 /* If the remote VTEP does not exist, there's nothing more to
4315 * do.
4316 * Otherwise, uninstall any remote MACs pointing to this VTEP
4317 * and then, the VTEP entry itself and remove it.
4318 */
4319 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4320 if (!zvtep)
4321 return;
4322
4323 zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
4324 zebra_evpn_vtep_del(zevpn, zvtep);
4325}
4326
4327/*
4328 * Handle message from client to add a remote VTEP for an EVPN.
4329 */
4330void zebra_vxlan_remote_vtep_add(vrf_id_t vrf_id, vni_t vni,
4331 struct in_addr vtep_ip, int flood_control)
4332{
f6371c34 4333 struct zebra_evpn *zevpn;
7e5b0b2b
MS
4334 struct interface *ifp;
4335 struct zebra_if *zif;
c172c032 4336 struct zebra_vtep *zvtep;
7e5b0b2b 4337 struct zebra_vrf *zvrf;
d62a17ae 4338
7e5b0b2b
MS
4339 if (!is_evpn_enabled()) {
4340 zlog_debug("%s: EVPN not enabled: can't process a VTEP ADD",
4341 __func__);
4342 return;
d62a17ae 4343 }
4344
7e5b0b2b
MS
4345 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4346 if (!zvrf)
4347 return;
4348
4349 if (!EVPN_ENABLED(zvrf)) {
4350 zlog_debug("Can't process VTEP ADD for non-EVPN VRF %u",
4351 zvrf_id(zvrf));
4352 return;
4353 }
4354
4355 /* Locate VNI hash entry - expected to exist. */
4356 zevpn = zebra_evpn_lookup(vni);
4357 if (!zevpn) {
4358 flog_err(
4359 EC_ZEBRA_VTEP_ADD_FAILED,
4360 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
4361 vni);
4362 return;
4363 }
4364
4365 ifp = zevpn->vxlan_if;
4366 if (!ifp) {
4367 flog_err(
4368 EC_ZEBRA_VTEP_ADD_FAILED,
4369 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
4370 zevpn->vni, zevpn);
4371 return;
4372 }
4373
4374 zif = ifp->info;
4375
4376 /* If down or not mapped to a bridge, we're done. */
4377 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
4378 return;
4379
4380 zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
4381 if (zvtep) {
4382 /* If the remote VTEP already exists check if
4383 * the flood mode has changed
4384 */
4385 if (zvtep->flood_control != flood_control) {
4386 if (zvtep->flood_control == VXLAN_FLOOD_DISABLED)
4387 /* old mode was head-end-replication but
4388 * is no longer; get rid of the HER fdb
4389 * entry installed before
4390 */
4391 zebra_evpn_vtep_uninstall(zevpn, &vtep_ip);
4392 zvtep->flood_control = flood_control;
4393 zebra_evpn_vtep_install(zevpn, zvtep);
4394 }
4395 } else {
4396 zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, flood_control);
4397 if (zvtep)
4398 zebra_evpn_vtep_install(zevpn, zvtep);
4399 else
4400 flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
4401 "Failed to add remote VTEP, VNI %u zevpn %p",
4402 vni, zevpn);
4403 }
13d60d35 4404}
4405
4406/*
87d76d54 4407 * Handle message from client to add a remote VTEP for an EVPN.
13d60d35 4408 */
7e5b0b2b 4409void zebra_vxlan_remote_vtep_add_zapi(ZAPI_HANDLER_ARGS)
d62a17ae 4410{
4411 struct stream *s;
d7c0a89a 4412 unsigned short l = 0;
d62a17ae 4413 vni_t vni;
4414 struct in_addr vtep_ip;
9718c54e 4415 int flood_control;
d62a17ae 4416
ec93aa12 4417 if (!is_evpn_enabled()) {
9df414fe 4418 zlog_debug(
7e5b0b2b 4419 "%s: EVPN not enabled yet we received a VTEP ADD zapi msg",
15569c58 4420 __func__);
8068a649 4421 return;
ec93aa12
DS
4422 }
4423
986512a3 4424 if (!EVPN_ENABLED(zvrf)) {
7e5b0b2b
MS
4425 zlog_debug("Recv VTEP ADD zapi for non-EVPN VRF %u",
4426 zvrf_id(zvrf));
8068a649 4427 return;
2853fed6 4428 }
d62a17ae 4429
1002497a 4430 s = msg;
d62a17ae 4431
89f4e507 4432 while (l < hdr->length) {
d62a17ae 4433 /* Obtain each remote VTEP and process. */
ec93aa12 4434 STREAM_GETL(s, vni);
d62a17ae 4435 l += 4;
ec93aa12 4436 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
9718c54e 4437 STREAM_GETL(s, flood_control);
8a64de72 4438 l += IPV4_MAX_BYTELEN + 4;
d62a17ae 4439
4440 if (IS_ZEBRA_DEBUG_VXLAN)
7e5b0b2b
MS
4441 zlog_debug("Recv VTEP ADD %pI4 VNI %u flood %d from %s",
4442 &vtep_ip, vni, flood_control,
4443 zebra_route_string(client->proto));
d62a17ae 4444
7e5b0b2b
MS
4445 /* Enqueue for processing */
4446 zebra_rib_queue_evpn_rem_vtep_add(zvrf_id(zvrf), vni, vtep_ip,
4447 flood_control);
d62a17ae 4448 }
4449
ec93aa12 4450stream_failure:
8068a649 4451 return;
13d60d35 4452}
4453
1a98c087
MK
4454/*
4455 * Add/Del gateway macip to evpn
4456 * g/w can be:
4457 * 1. SVI interface on a vlan aware bridge
4458 * 2. SVI interface on a vlan unaware bridge
4459 * 3. vrr interface (MACVLAN) associated to a SVI
4460 * We advertise macip routes for an interface if it is associated to VxLan vlan
4461 */
7e5b0b2b 4462int zebra_vxlan_add_del_gw_macip(struct interface *ifp, const struct prefix *p,
1a98c087
MK
4463 int add)
4464{
4465 struct ipaddr ip;
4466 struct ethaddr macaddr;
f6371c34 4467 struct zebra_evpn *zevpn = NULL;
1a98c087 4468
6006b807
DA
4469 memset(&ip, 0, sizeof(ip));
4470 memset(&macaddr, 0, sizeof(macaddr));
1a98c087 4471
2853fed6 4472 /* Check if EVPN is enabled. */
4473 if (!is_evpn_enabled())
297a21b6
MK
4474 return 0;
4475
1a98c087
MK
4476 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
4477 struct interface *svi_if =
4478 NULL; /* SVI corresponding to the MACVLAN */
4479 struct zebra_if *ifp_zif =
4480 NULL; /* Zebra daemon specific info for MACVLAN */
4481 struct zebra_if *svi_if_zif =
4482 NULL; /* Zebra daemon specific info for SVI*/
4483
4484 ifp_zif = ifp->info;
4485 if (!ifp_zif)
4486 return -1;
4487
71349e03
MK
4488 /*
4489 * for a MACVLAN interface the link represents the svi_if
4490 */
4491 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4492 ifp_zif->link_ifindex);
1a98c087 4493 if (!svi_if) {
9df414fe
QY
4494 zlog_debug("MACVLAN %s(%u) without link information",
4495 ifp->name, ifp->ifindex);
1a98c087
MK
4496 return -1;
4497 }
4498
4499 if (IS_ZEBRA_IF_VLAN(svi_if)) {
71349e03
MK
4500 /*
4501 * If it is a vlan aware bridge then the link gives the
4502 * bridge information
4503 */
4504 struct interface *svi_if_link = NULL;
4505
1a98c087 4506 svi_if_zif = svi_if->info;
71349e03
MK
4507 if (svi_if_zif) {
4508 svi_if_link = if_lookup_by_index_per_ns(
60466a63
QY
4509 zebra_ns_lookup(NS_DEFAULT),
4510 svi_if_zif->link_ifindex);
8b5fdf2e
PR
4511 zevpn = zebra_evpn_from_svi(svi_if,
4512 svi_if_link);
71349e03 4513 }
1a98c087 4514 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
71349e03
MK
4515 /*
4516 * If it is a vlan unaware bridge then svi is the bridge
4517 * itself
4518 */
8b5fdf2e 4519 zevpn = zebra_evpn_from_svi(svi_if, svi_if);
1a98c087
MK
4520 }
4521 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
4522 struct zebra_if *svi_if_zif =
71349e03
MK
4523 NULL; /* Zebra daemon specific info for SVI */
4524 struct interface *svi_if_link =
4525 NULL; /* link info for the SVI = bridge info */
1a98c087
MK
4526
4527 svi_if_zif = ifp->info;
e3bb770c
IS
4528 if (svi_if_zif) {
4529 svi_if_link = if_lookup_by_index_per_ns(
cef91a18
QY
4530 zebra_ns_lookup(NS_DEFAULT),
4531 svi_if_zif->link_ifindex);
e3bb770c 4532 if (svi_if_link)
8b5fdf2e 4533 zevpn = zebra_evpn_from_svi(ifp, svi_if_link);
e3bb770c 4534 }
1a98c087 4535 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
8b5fdf2e 4536 zevpn = zebra_evpn_from_svi(ifp, ifp);
1a98c087
MK
4537 }
4538
87d76d54 4539 if (!zevpn)
1a98c087
MK
4540 return 0;
4541
87d76d54 4542 if (!zevpn->vxlan_if) {
9df414fe 4543 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
87d76d54 4544 zevpn->vni, zevpn);
1a98c087
MK
4545 return -1;
4546 }
4547
c0c7707d
AK
4548 /* VRR IP is advertised only if gw-macip-adv-enabled */
4549 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
4550 if (!advertise_gw_macip_enabled(zevpn))
4551 return 0;
4552 } else {
4553 /* SVI IP is advertised if gw or svi macip-adv-enabled */
4554 if (!advertise_svi_macip_enabled(zevpn)
4555 && !advertise_gw_macip_enabled(zevpn))
4556 return 0;
4557 }
1a98c087 4558
1a98c087
MK
4559 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
4560
4561 if (p->family == AF_INET) {
4562 ip.ipa_type = IPADDR_V4;
4563 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
4564 sizeof(struct in_addr));
4565 } else if (p->family == AF_INET6) {
4566 ip.ipa_type = IPADDR_V6;
4567 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
4568 sizeof(struct in6_addr));
4569 }
4570
4571
4572 if (add)
8b5fdf2e 4573 zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip);
1a98c087 4574 else
8b5fdf2e 4575 zebra_evpn_gw_macip_del(ifp, zevpn, &ip);
1a98c087
MK
4576
4577 return 0;
4578}
4579
2232a77c 4580/*
b7cfce93
MK
4581 * Handle SVI interface going down.
4582 * SVI can be associated to either L3-VNI or L2-VNI.
4583 * For L2-VNI: At this point, this is a NOP since
4584 * the kernel deletes the neighbor entries on this SVI (if any).
87d76d54 4585 * We only need to update the vrf corresponding to zevpn.
b7cfce93
MK
4586 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
4587 * from bgp
2232a77c 4588 */
d62a17ae 4589int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
2232a77c 4590{
05843a27 4591 struct zebra_l3vni *zl3vni = NULL;
b7cfce93
MK
4592
4593 zl3vni = zl3vni_from_svi(ifp, link_if);
4594 if (zl3vni) {
4595
4596 /* process l3-vni down */
4597 zebra_vxlan_process_l3vni_oper_down(zl3vni);
4598
4599 /* remove association with svi-if */
4600 zl3vni->svi_if = NULL;
4601 } else {
f6371c34 4602 struct zebra_evpn *zevpn = NULL;
b7cfce93 4603
243b74ed
AK
4604 /* Unlink the SVI from the access VLAN */
4605 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, false);
4606
87d76d54 4607 /* since we dont have svi corresponding to zevpn, we associate it
b7cfce93
MK
4608 * to default vrf. Note: the corresponding neigh entries on the
4609 * SVI would have already been deleted */
8b5fdf2e 4610 zevpn = zebra_evpn_from_svi(ifp, link_if);
243b74ed 4611
87d76d54 4612 if (zevpn) {
b0b77855
QY
4613 /* remove from l3-vni list */
4614 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
4615 if (zl3vni)
4616 listnode_delete(zl3vni->l2vnis, zevpn);
b13f35ec 4617
9daa5d47 4618 zevpn->svi_if = NULL;
87d76d54 4619 zevpn->vrf_id = VRF_DEFAULT;
b7cfce93
MK
4620
4621 /* update the tenant vrf in BGP */
196d7a86
CS
4622 if (if_is_operative(zevpn->vxlan_if))
4623 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
4624 }
4625 }
d62a17ae 4626 return 0;
2232a77c 4627}
4628
4629/*
b7cfce93
MK
4630 * Handle SVI interface coming up.
4631 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
4632 * vxlan intf).
4633 * For L2-VNI: we need to install any remote neighbors entried (used for
b816de62 4634 * arp-suppression)
b7cfce93 4635 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
2232a77c 4636 */
d62a17ae 4637int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
2232a77c 4638{
f6371c34 4639 struct zebra_evpn *zevpn = NULL;
05843a27 4640 struct zebra_l3vni *zl3vni = NULL;
2232a77c 4641
b7cfce93
MK
4642 zl3vni = zl3vni_from_svi(ifp, link_if);
4643 if (zl3vni) {
2232a77c 4644
b7cfce93
MK
4645 /* associate with svi */
4646 zl3vni->svi_if = ifp;
2232a77c 4647
b7cfce93
MK
4648 /* process oper-up */
4649 if (is_l3vni_oper_up(zl3vni))
4650 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4651 } else {
4652
4653 /* process SVI up for l2-vni */
4654 struct neigh_walk_ctx n_wctx;
4655
8b5fdf2e 4656 zevpn = zebra_evpn_from_svi(ifp, link_if);
87d76d54 4657 if (!zevpn)
b7cfce93
MK
4658 return 0;
4659
87d76d54 4660 if (!zevpn->vxlan_if) {
9df414fe 4661 zlog_debug(
43e52561 4662 "VNI %u hash %p doesn't have intf upon SVI up",
87d76d54 4663 zevpn->vni, zevpn);
b7cfce93
MK
4664 return -1;
4665 }
4666
4667 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4668 zlog_debug(
4669 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
87d76d54 4670 ifp->name, ifp->ifindex, zevpn->vni,
096f7609 4671 ifp->vrf->name);
2232a77c 4672
b7cfce93 4673 /* update the vrf information for l2-vni and inform bgp */
9daa5d47 4674 zevpn->svi_if = ifp;
096f7609 4675 zevpn->vrf_id = ifp->vrf->vrf_id;
196d7a86 4676
b0b77855
QY
4677 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
4678 if (zl3vni)
4679 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
b13f35ec 4680
196d7a86
CS
4681 if (if_is_operative(zevpn->vxlan_if))
4682 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
4683
4684 /* Install any remote neighbors for this VNI. */
6006b807 4685 memset(&n_wctx, 0, sizeof(n_wctx));
87d76d54 4686 n_wctx.zevpn = zevpn;
7cbae20a 4687 hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash,
b7cfce93 4688 &n_wctx);
243b74ed
AK
4689
4690 /* Link the SVI from the access VLAN */
4691 zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, true);
56599dd9
TA
4692
4693 /* Update MACIP routes created by advertise-svi-ip */
4694 if (advertise_svi_macip_enabled(zevpn)) {
4695 zebra_evpn_del_macip_for_intf(ifp, zevpn);
4696 zebra_evpn_add_macip_for_intf(ifp, zevpn);
4697 }
b7cfce93 4698 }
2232a77c 4699
d62a17ae 4700 return 0;
2232a77c 4701}
4702
0056f687
CS
4703/*
4704 * Handle MAC-VLAN interface going down.
4705 * L3VNI: When MAC-VLAN interface goes down,
4706 * find its associated SVI and update type2/type-5 routes
4707 * with SVI as RMAC
4708 */
4709void zebra_vxlan_macvlan_down(struct interface *ifp)
4710{
05843a27 4711 struct zebra_l3vni *zl3vni = NULL;
0056f687
CS
4712 struct zebra_if *zif, *link_zif;
4713 struct interface *link_ifp, *link_if;
4714
4715 zif = ifp->info;
4716 assert(zif);
4717 link_ifp = zif->link;
59260d4a 4718 if (!link_ifp) {
a2df495f
IR
4719 if (IS_ZEBRA_DEBUG_VXLAN)
4720 zlog_debug(
4721 "macvlan parent link is not found. Parent index %d ifp %s",
4722 zif->link_ifindex,
096f7609
IR
4723 ifindex2ifname(zif->link_ifindex,
4724 ifp->vrf->vrf_id));
59260d4a
CS
4725 return;
4726 }
0056f687
CS
4727 link_zif = link_ifp->info;
4728 assert(link_zif);
4729
4730 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4731 link_zif->link_ifindex);
4732
4733 zl3vni = zl3vni_from_svi(link_ifp, link_if);
4734 if (zl3vni) {
4735 zl3vni->mac_vlan_if = NULL;
4736 if (is_l3vni_oper_up(zl3vni))
4737 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4738 }
4739}
4740
4741/*
4742 * Handle MAC-VLAN interface going up.
4743 * L3VNI: When MAC-VLAN interface comes up,
4744 * find its associated SVI and update type-2 routes
4745 * with MAC-VLAN's MAC as RMAC and for type-5 routes
4746 * use SVI's MAC as RMAC.
4747 */
4748void zebra_vxlan_macvlan_up(struct interface *ifp)
4749{
05843a27 4750 struct zebra_l3vni *zl3vni = NULL;
0056f687
CS
4751 struct zebra_if *zif, *link_zif;
4752 struct interface *link_ifp, *link_if;
4753
4754 zif = ifp->info;
4755 assert(zif);
4756 link_ifp = zif->link;
4757 link_zif = link_ifp->info;
4758 assert(link_zif);
4759
4760 link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
4761 link_zif->link_ifindex);
4762 zl3vni = zl3vni_from_svi(link_ifp, link_if);
4763 if (zl3vni) {
4764 /* associate with macvlan (VRR) interface */
4765 zl3vni->mac_vlan_if = ifp;
4766
4767 /* process oper-up */
4768 if (is_l3vni_oper_up(zl3vni))
4769 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4770 }
4771}
4772
13d60d35 4773/*
b7cfce93 4774 * Handle VxLAN interface down
13d60d35 4775 */
d62a17ae 4776int zebra_vxlan_if_down(struct interface *ifp)
13d60d35 4777{
d62a17ae 4778 vni_t vni;
b7cfce93
MK
4779 struct zebra_if *zif = NULL;
4780 struct zebra_l2info_vxlan *vxl = NULL;
05843a27 4781 struct zebra_l3vni *zl3vni = NULL;
f6371c34 4782 struct zebra_evpn *zevpn;
13d60d35 4783
2853fed6 4784 /* Check if EVPN is enabled. */
4785 if (!is_evpn_enabled())
d62a17ae 4786 return 0;
13d60d35 4787
d62a17ae 4788 zif = ifp->info;
4789 assert(zif);
4790 vxl = &zif->l2info.vxl;
4791 vni = vxl->vni;
13d60d35 4792
643215ce 4793 zl3vni = zl3vni_lookup(vni);
4794 if (zl3vni) {
b7cfce93 4795 /* process-if-down for l3-vni */
b7cfce93 4796 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4797 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
4798 ifp->ifindex, vni);
b7cfce93 4799
b7cfce93 4800 zebra_vxlan_process_l3vni_oper_down(zl3vni);
b7cfce93
MK
4801 } else {
4802 /* process if-down for l2-vni */
b7cfce93 4803 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4804 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
4805 ifp->ifindex, vni);
13d60d35 4806
b7cfce93 4807 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4808 zevpn = zebra_evpn_lookup(vni);
87d76d54 4809 if (!zevpn) {
9df414fe 4810 zlog_debug(
b7cfce93
MK
4811 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
4812 ifp->name, ifp->ifindex, vni);
4813 return -1;
4814 }
13d60d35 4815
87d76d54 4816 assert(zevpn->vxlan_if == ifp);
13d60d35 4817
c7e83a4e
CS
4818 /* remove from l3-vni list */
4819 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
4820 if (zl3vni)
4821 listnode_delete(zl3vni->l2vnis, zevpn);
4822
b7cfce93 4823 /* Delete this VNI from BGP. */
8b5fdf2e 4824 zebra_evpn_send_del_to_client(zevpn);
2232a77c 4825
b7cfce93 4826 /* Free up all neighbors and MACs, if any. */
7cbae20a 4827 zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
b2998086 4828 zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
13d60d35 4829
b7cfce93 4830 /* Free up all remote VTEPs, if any. */
8b5fdf2e 4831 zebra_evpn_vtep_del_all(zevpn, 1);
b7cfce93 4832 }
d62a17ae 4833 return 0;
13d60d35 4834}
4835
4836/*
4837 * Handle VxLAN interface up - update BGP if required.
4838 */
d62a17ae 4839int zebra_vxlan_if_up(struct interface *ifp)
13d60d35 4840{
d62a17ae 4841 vni_t vni;
b7cfce93
MK
4842 struct zebra_if *zif = NULL;
4843 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 4844 struct zebra_evpn *zevpn = NULL;
05843a27 4845 struct zebra_l3vni *zl3vni = NULL;
13d60d35 4846
2853fed6 4847 /* Check if EVPN is enabled. */
4848 if (!is_evpn_enabled())
d62a17ae 4849 return 0;
13d60d35 4850
d62a17ae 4851 zif = ifp->info;
4852 assert(zif);
4853 vxl = &zif->l2info.vxl;
4854 vni = vxl->vni;
13d60d35 4855
643215ce 4856 zl3vni = zl3vni_lookup(vni);
4857 if (zl3vni) {
b7cfce93 4858 /* we need to associate with SVI, if any, we can associate with
523cafc4 4859 * svi-if only after association with vxlan-intf is complete
4860 */
b7cfce93 4861 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
06d9cde5
CS
4862 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
4863
4864 if (IS_ZEBRA_DEBUG_VXLAN)
4865 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
4866 , ifp->name, ifp->ifindex, vni,
4867 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
4868 zl3vni->mac_vlan_if ?
4869 zl3vni->mac_vlan_if->name : "NIL");
b7cfce93
MK
4870
4871 if (is_l3vni_oper_up(zl3vni))
4872 zebra_vxlan_process_l3vni_oper_up(zl3vni);
4873 } else {
4874 /* Handle L2-VNI add */
b7cfce93
MK
4875 struct interface *vlan_if = NULL;
4876
4877 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4878 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
4879 ifp->ifindex, vni);
b7cfce93
MK
4880
4881 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4882 zevpn = zebra_evpn_lookup(vni);
87d76d54 4883 if (!zevpn) {
9df414fe 4884 zlog_debug(
87d76d54 4885 "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
b7cfce93
MK
4886 ifp->name, ifp->ifindex, vni);
4887 return -1;
4888 }
4889
87d76d54 4890 assert(zevpn->vxlan_if == ifp);
7cbae20a 4891 vlan_if = zvni_map_to_svi(vxl->access_vlan,
b7cfce93
MK
4892 zif->brslave_info.br_if);
4893 if (vlan_if) {
9daa5d47 4894 zevpn->svi_if = vlan_if;
096f7609
IR
4895 zevpn->vrf_id = vlan_if->vrf->vrf_id;
4896 zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
b7cfce93 4897 if (zl3vni)
c7e83a4e 4898 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
b7cfce93
MK
4899 }
4900
4901 /* If part of a bridge, inform BGP about this VNI. */
4902 /* Also, read and populate local MACs and neighbors. */
4903 if (zif->brslave_info.br_if) {
8b5fdf2e
PR
4904 zebra_evpn_send_add_to_client(zevpn);
4905 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93 4906 }
d62a17ae 4907 }
13d60d35 4908
d62a17ae 4909 return 0;
13d60d35 4910}
4911
4912/*
4913 * Handle VxLAN interface delete. Locate and remove entry in hash table
4914 * and update BGP, if required.
4915 */
d62a17ae 4916int zebra_vxlan_if_del(struct interface *ifp)
13d60d35 4917{
d62a17ae 4918 vni_t vni;
b7cfce93
MK
4919 struct zebra_if *zif = NULL;
4920 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 4921 struct zebra_evpn *zevpn = NULL;
05843a27 4922 struct zebra_l3vni *zl3vni = NULL;
13d60d35 4923
2853fed6 4924 /* Check if EVPN is enabled. */
4925 if (!is_evpn_enabled())
d62a17ae 4926 return 0;
13d60d35 4927
d62a17ae 4928 zif = ifp->info;
4929 assert(zif);
4930 vxl = &zif->l2info.vxl;
4931 vni = vxl->vni;
13d60d35 4932
643215ce 4933 zl3vni = zl3vni_lookup(vni);
4934 if (zl3vni) {
b7cfce93
MK
4935
4936 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4937 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
4938 ifp->ifindex);
13d60d35 4939
b7cfce93
MK
4940 /* process oper-down for l3-vni */
4941 zebra_vxlan_process_l3vni_oper_down(zl3vni);
2232a77c 4942
b7cfce93 4943 /* remove the association with vxlan_if */
b67a60d2 4944 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
b7cfce93
MK
4945 zl3vni->vxlan_if = NULL;
4946 } else {
13d60d35 4947
b7cfce93 4948 /* process if-del for l2-vni*/
b7cfce93 4949 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
4950 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
4951 ifp->ifindex);
b7cfce93
MK
4952
4953 /* Locate hash entry; it is expected to exist. */
8b5fdf2e 4954 zevpn = zebra_evpn_lookup(vni);
87d76d54 4955 if (!zevpn) {
9df414fe 4956 zlog_debug(
b7cfce93
MK
4957 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
4958 ifp->name, ifp->ifindex, vni);
4959 return 0;
4960 }
4961
4962 /* remove from l3-vni list */
87d76d54 4963 zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
b7cfce93 4964 if (zl3vni)
87d76d54 4965 listnode_delete(zl3vni->l2vnis, zevpn);
b7cfce93 4966 /* Delete VNI from BGP. */
8b5fdf2e 4967 zebra_evpn_send_del_to_client(zevpn);
b7cfce93
MK
4968
4969 /* Free up all neighbors and MAC, if any. */
7cbae20a 4970 zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH);
b2998086 4971 zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC);
b7cfce93
MK
4972
4973 /* Free up all remote VTEPs, if any. */
8b5fdf2e 4974 zebra_evpn_vtep_del_all(zevpn, 0);
b7cfce93
MK
4975
4976 /* Delete the hash entry. */
8b5fdf2e 4977 if (zebra_evpn_vxlan_del(zevpn)) {
e914ccbe 4978 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
87d76d54
PR
4979 "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
4980 zevpn, ifp->name, ifp->ifindex, zevpn->vni);
b7cfce93
MK
4981 return -1;
4982 }
d62a17ae 4983 }
d62a17ae 4984 return 0;
13d60d35 4985}
4986
4987/*
4988 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
4989 */
d7c0a89a 4990int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
d62a17ae 4991{
d62a17ae 4992 vni_t vni;
b7cfce93
MK
4993 struct zebra_if *zif = NULL;
4994 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 4995 struct zebra_evpn *zevpn = NULL;
05843a27 4996 struct zebra_l3vni *zl3vni = NULL;
9daa5d47 4997 struct interface *vlan_if = NULL;
d62a17ae 4998
2853fed6 4999 /* Check if EVPN is enabled. */
5000 if (!is_evpn_enabled())
d62a17ae 5001 return 0;
5002
5003 zif = ifp->info;
5004 assert(zif);
5005 vxl = &zif->l2info.vxl;
5006 vni = vxl->vni;
5007
643215ce 5008 zl3vni = zl3vni_lookup(vni);
5009 if (zl3vni) {
af026ae4 5010
b7cfce93
MK
5011 if (IS_ZEBRA_DEBUG_VXLAN)
5012 zlog_debug(
9bcef951 5013 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
996c9314 5014 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5015 &vxl->vtep_ip,
b7cfce93
MK
5016 zif->brslave_info.bridge_ifindex, chgflags);
5017
5018 /* Removed from bridge? Cleanup and return */
5019 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
5020 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
5021 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5022 return 0;
5023 }
5024
c7620108
PG
5025 if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
5026 && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
5027 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5028 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5029 return 0;
5030 }
5031
b7cfce93 5032 /* access-vlan change - process oper down, associate with new
523cafc4 5033 * svi_if and then process oper up again
5034 */
b7cfce93
MK
5035 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5036 if (if_is_operative(ifp)) {
5037 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5038 zl3vni->svi_if = NULL;
5039 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
06d9cde5
CS
5040 zl3vni->mac_vlan_if =
5041 zl3vni_map_to_mac_vlan_if(zl3vni);
bca63dc8 5042 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
5043 if (is_l3vni_oper_up(zl3vni))
5044 zebra_vxlan_process_l3vni_oper_up(
996c9314 5045 zl3vni);
b7cfce93
MK
5046 }
5047 }
d62a17ae 5048
12eeac84
MK
5049 /*
5050 * local-ip change - process oper down, associate with new
5051 * local-ip and then process oper up again
5052 */
5053 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
5054 if (if_is_operative(ifp)) {
5055 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5056 zl3vni->local_vtep_ip = vxl->vtep_ip;
5057 if (is_l3vni_oper_up(zl3vni))
5058 zebra_vxlan_process_l3vni_oper_up(
996c9314 5059 zl3vni);
12eeac84
MK
5060 }
5061 }
5062
bca63dc8
MK
5063 /* Update local tunnel IP. */
5064 zl3vni->local_vtep_ip = vxl->vtep_ip;
5065
12eeac84
MK
5066 /* if we have a valid new master, process l3-vni oper up */
5067 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
5068 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
b7cfce93
MK
5069 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5070 }
5071 } else {
d62a17ae 5072
b7cfce93 5073 /* Update VNI hash. */
8b5fdf2e 5074 zevpn = zebra_evpn_lookup(vni);
87d76d54 5075 if (!zevpn) {
9df414fe 5076 zlog_debug(
87d76d54 5077 "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
b7cfce93
MK
5078 ifp->name, ifp->ifindex, vni);
5079 return -1;
5080 }
d62a17ae 5081
b7cfce93
MK
5082 if (IS_ZEBRA_DEBUG_VXLAN)
5083 zlog_debug(
9bcef951 5084 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
996c9314 5085 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5086 &vxl->vtep_ip,
b7cfce93
MK
5087 zif->brslave_info.bridge_ifindex, chgflags);
5088
5089 /* Removed from bridge? Cleanup and return */
5090 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
5091 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
5092 /* Delete from client, remove all remote VTEPs */
5093 /* Also, free up all MACs and neighbors. */
9daa5d47 5094 zevpn->svi_if = NULL;
8b5fdf2e 5095 zebra_evpn_send_del_to_client(zevpn);
7cbae20a 5096 zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
b2998086 5097 zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
8b5fdf2e 5098 zebra_evpn_vtep_del_all(zevpn, 1);
b7cfce93
MK
5099 return 0;
5100 }
d62a17ae 5101
b7cfce93
MK
5102 /* Handle other changes. */
5103 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5104 /* Remove all existing local neigh and MACs for this VNI
5105 * (including from BGP)
5106 */
7cbae20a 5107 zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
b2998086 5108 zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC);
b7cfce93 5109 }
d62a17ae 5110
87d76d54
PR
5111 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
5112 zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
5113 zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
5114 zevpn->mcast_grp);
abfa0a96 5115 zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
87d76d54
PR
5116 zevpn->local_vtep_ip = vxl->vtep_ip;
5117 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
5118 /* on local vtep-ip check if ES orig-ip
5119 * needs to be updated
5120 */
87d76d54 5121 zebra_evpn_es_set_base_evpn(zevpn);
abfa0a96 5122 }
87d76d54 5123 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
9daa5d47
AD
5124 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5125 zif->brslave_info.br_if);
c4992a2f 5126 if (vlan_if) {
9daa5d47 5127 zevpn->svi_if = vlan_if;
c4992a2f 5128 zevpn->vrf_id = vlan_if->vrf->vrf_id;
5129 zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
5130 if (zl3vni)
5131 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
5132 }
9daa5d47 5133
b7cfce93
MK
5134 /* Take further actions needed.
5135 * Note that if we are here, there is a change of interest.
5136 */
5137 /* If down or not mapped to a bridge, we're done. */
5138 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5139 return 0;
d62a17ae 5140
b7cfce93
MK
5141 /* Inform BGP, if there is a change of interest. */
5142 if (chgflags
39c46ff1
AK
5143 & (ZEBRA_VXLIF_MASTER_CHANGE |
5144 ZEBRA_VXLIF_LOCAL_IP_CHANGE |
5145 ZEBRA_VXLIF_MCAST_GRP_CHANGE))
8b5fdf2e 5146 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
5147
5148 /* If there is a valid new master or a VLAN mapping change,
5149 * read and populate local MACs and neighbors.
5150 * Also, reinstall any remote MACs and neighbors
5151 * for this VNI (based on new VLAN).
5152 */
5153 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8b5fdf2e 5154 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93
MK
5155 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
5156 struct mac_walk_ctx m_wctx;
5157 struct neigh_walk_ctx n_wctx;
5158
8b5fdf2e 5159 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93 5160
6006b807 5161 memset(&m_wctx, 0, sizeof(m_wctx));
87d76d54 5162 m_wctx.zevpn = zevpn;
8b5fdf2e
PR
5163 hash_iterate(zevpn->mac_table,
5164 zebra_evpn_install_mac_hash, &m_wctx);
b7cfce93 5165
6006b807 5166 memset(&n_wctx, 0, sizeof(n_wctx));
87d76d54 5167 n_wctx.zevpn = zevpn;
7cbae20a
PR
5168 hash_iterate(zevpn->neigh_table,
5169 zebra_evpn_install_neigh_hash, &n_wctx);
b7cfce93 5170 }
d62a17ae 5171 }
5172
5173 return 0;
13d60d35 5174}
5175
5176/*
5177 * Handle VxLAN interface add.
5178 */
d62a17ae 5179int zebra_vxlan_if_add(struct interface *ifp)
13d60d35 5180{
d62a17ae 5181 vni_t vni;
b7cfce93
MK
5182 struct zebra_if *zif = NULL;
5183 struct zebra_l2info_vxlan *vxl = NULL;
f6371c34 5184 struct zebra_evpn *zevpn = NULL;
05843a27 5185 struct zebra_l3vni *zl3vni = NULL;
13d60d35 5186
2853fed6 5187 /* Check if EVPN is enabled. */
5188 if (!is_evpn_enabled())
d62a17ae 5189 return 0;
13d60d35 5190
d62a17ae 5191 zif = ifp->info;
5192 assert(zif);
5193 vxl = &zif->l2info.vxl;
5194 vni = vxl->vni;
13d60d35 5195
643215ce 5196 zl3vni = zl3vni_lookup(vni);
5197 if (zl3vni) {
13d60d35 5198
b7cfce93 5199 /* process if-add for l3-vni*/
b7cfce93
MK
5200 if (IS_ZEBRA_DEBUG_VXLAN)
5201 zlog_debug(
9bcef951 5202 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
996c9314 5203 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
9bcef951 5204 &vxl->vtep_ip,
b7cfce93
MK
5205 zif->brslave_info.bridge_ifindex);
5206
b7cfce93 5207 /* associate with vxlan_if */
b67a60d2 5208 zl3vni->local_vtep_ip = vxl->vtep_ip;
b7cfce93
MK
5209 zl3vni->vxlan_if = ifp;
5210
5211 /* Associate with SVI, if any. We can associate with svi-if only
5212 * after association with vxlan_if is complete */
5213 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5214
06d9cde5
CS
5215 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
5216
b7cfce93
MK
5217 if (is_l3vni_oper_up(zl3vni))
5218 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5219 } else {
5220
5221 /* process if-add for l2-vni */
b7cfce93
MK
5222 struct interface *vlan_if = NULL;
5223
87d76d54 5224 /* Create or update EVPN hash. */
8b5fdf2e 5225 zevpn = zebra_evpn_lookup(vni);
97511d01 5226 if (!zevpn)
8b5fdf2e 5227 zevpn = zebra_evpn_add(vni);
b7cfce93 5228
87d76d54
PR
5229 if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
5230 zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
5231 zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
5232 zevpn->mcast_grp);
abfa0a96 5233 zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp);
87d76d54
PR
5234 zevpn->local_vtep_ip = vxl->vtep_ip;
5235 zevpn->mcast_grp = vxl->mcast_grp;
ce5160c0
AK
5236 /* on local vtep-ip check if ES orig-ip
5237 * needs to be updated
5238 */
87d76d54 5239 zebra_evpn_es_set_base_evpn(zevpn);
abfa0a96 5240 }
87d76d54 5241 zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
7cbae20a 5242 vlan_if = zvni_map_to_svi(vxl->access_vlan,
b7cfce93
MK
5243 zif->brslave_info.br_if);
5244 if (vlan_if) {
9daa5d47 5245 zevpn->svi_if = vlan_if;
096f7609
IR
5246 zevpn->vrf_id = vlan_if->vrf->vrf_id;
5247 zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
b7cfce93 5248 if (zl3vni)
c7e83a4e 5249 listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
b7cfce93
MK
5250 }
5251
f6371c34 5252 if (IS_ZEBRA_DEBUG_VXLAN)
b7cfce93 5253 zlog_debug(
f6371c34 5254 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %pI4 mcast_grp %pI4 master %u",
b7cfce93 5255 vni,
096f7609 5256 vlan_if ? vlan_if->vrf->name : VRF_DEFAULT_NAME,
996c9314 5257 ifp->name, ifp->ifindex, vxl->access_vlan,
f6371c34 5258 &vxl->vtep_ip, &vxl->mcast_grp,
b7cfce93
MK
5259 zif->brslave_info.bridge_ifindex);
5260
5261 /* If down or not mapped to a bridge, we're done. */
5262 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5263 return 0;
5264
5265 /* Inform BGP */
8b5fdf2e 5266 zebra_evpn_send_add_to_client(zevpn);
b7cfce93
MK
5267
5268 /* Read and populate local MACs and neighbors */
8b5fdf2e 5269 zebra_evpn_read_mac_neigh(zevpn, ifp);
b7cfce93
MK
5270 }
5271
5272 return 0;
5273}
5274
996c9314
LB
5275int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
5276 char *err, int err_str_sz, int filter,
5277 int add)
b7cfce93 5278{
05843a27 5279 struct zebra_l3vni *zl3vni = NULL;
5e53dce3 5280 struct zebra_vrf *zvrf_evpn = NULL;
b7cfce93 5281
5e53dce3 5282 zvrf_evpn = zebra_vrf_get_evpn();
b7cfce93
MK
5283
5284 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314 5285 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
b7cfce93
MK
5286 add ? "ADD" : "DEL");
5287
5288 if (add) {
b7cfce93
MK
5289 /* check if the vni is already present under zvrf */
5290 if (zvrf->l3vni) {
3f02fbab 5291 snprintf(err, err_str_sz,
b7cfce93
MK
5292 "VNI is already configured under the vrf");
5293 return -1;
5294 }
5295
5296 /* check if this VNI is already present in the system */
5297 zl3vni = zl3vni_lookup(vni);
5298 if (zl3vni) {
3f02fbab 5299 snprintf(err, err_str_sz,
b7cfce93
MK
5300 "VNI is already configured as L3-VNI");
5301 return -1;
5302 }
5303
41a8b88c 5304 /* Remove L2VNI if present */
5305 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
5306
b7cfce93
MK
5307 /* add the L3-VNI to the global table */
5308 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
b7cfce93
MK
5309
5310 /* associate the vrf with vni */
5311 zvrf->l3vni = vni;
5312
c48d9f5f
MK
5313 /* set the filter in l3vni to denote if we are using l3vni only
5314 * for prefix routes
5315 */
5316 if (filter)
5317 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
5318
b7cfce93 5319 /* associate with vxlan-intf;
523cafc4 5320 * we need to associate with the vxlan-intf first
5321 */
b7cfce93
MK
5322 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
5323
5324 /* associate with corresponding SVI interface, we can associate
5325 * with svi-if only after vxlan interface association is
523cafc4 5326 * complete
5327 */
b7cfce93
MK
5328 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
5329
06d9cde5
CS
5330 zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
5331
5332 if (IS_ZEBRA_DEBUG_VXLAN)
15569c58
DA
5333 zlog_debug(
5334 "%s: l3vni %u svi_if %s mac_vlan_if %s",
5335 __func__, vni,
5336 zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
5337 zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
5338 : "NIL");
06d9cde5 5339
b7cfce93 5340 /* formulate l2vni list */
87d76d54 5341 hash_iterate(zvrf_evpn->evpn_table, zevpn_add_to_l3vni_list,
996c9314 5342 zl3vni);
b7cfce93
MK
5343
5344 if (is_l3vni_oper_up(zl3vni))
5345 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5346
5347 } else {
5348 zl3vni = zl3vni_lookup(vni);
5349 if (!zl3vni) {
3f02fbab 5350 snprintf(err, err_str_sz, "VNI doesn't exist");
d62a17ae 5351 return -1;
5352 }
b7cfce93 5353
7a6ca8a6
KA
5354 if (zvrf->l3vni != vni) {
5355 snprintf(err, err_str_sz,
5356 "VNI %d doesn't exist in VRF: %s",
5357 vni, zvrf->vrf->name);
5358 return -1;
5359 }
5360
cf299714
MK
5361 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
5362 snprintf(err, ERR_STR_SZ,
5363 "prefix-routes-only is not set for the vni");
5364 return -1;
5365 }
5366
b7cfce93
MK
5367 zebra_vxlan_process_l3vni_oper_down(zl3vni);
5368
5e06422c 5369 /* delete and uninstall all rmacs */
996c9314 5370 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
5e06422c
MK
5371 zl3vni);
5372
5373 /* delete and uninstall all next-hops */
996c9314 5374 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
5e06422c
MK
5375 zl3vni);
5376
b7cfce93
MK
5377 zvrf->l3vni = 0;
5378 zl3vni_del(zl3vni);
5379
3b0a590b 5380 /* Add L2VNI for this VNI */
b7cfce93 5381 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
d62a17ae 5382 }
b7cfce93
MK
5383 return 0;
5384}
13d60d35 5385
84915b0a 5386int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
5387{
05843a27 5388 struct zebra_l3vni *zl3vni = NULL;
84915b0a 5389
5390 if (zvrf->l3vni)
5391 zl3vni = zl3vni_lookup(zvrf->l3vni);
5392 if (!zl3vni)
5393 return 0;
5394
5395 zl3vni->vrf_id = zvrf_id(zvrf);
5396 if (is_l3vni_oper_up(zl3vni))
5397 zebra_vxlan_process_l3vni_oper_up(zl3vni);
5398 return 0;
5399}
5400
5401int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
b7cfce93 5402{
05843a27 5403 struct zebra_l3vni *zl3vni = NULL;
13d60d35 5404
84915b0a 5405 if (zvrf->l3vni)
5406 zl3vni = zl3vni_lookup(zvrf->l3vni);
b7cfce93 5407 if (!zl3vni)
d62a17ae 5408 return 0;
13d60d35 5409
b7cfce93 5410 zebra_vxlan_process_l3vni_oper_down(zl3vni);
92475ca4
CS
5411
5412 /* delete and uninstall all rmacs */
5413 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, zl3vni);
5414 /* delete and uninstall all next-hops */
5415 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, zl3vni);
5416
5417 zl3vni->vrf_id = VRF_UNKNOWN;
5418
84915b0a 5419 return 0;
5420}
5421
5422int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
5423{
05843a27 5424 struct zebra_l3vni *zl3vni = NULL;
84915b0a 5425 vni_t vni;
5426
5427 if (zvrf->l3vni)
5428 zl3vni = zl3vni_lookup(zvrf->l3vni);
5429 if (!zl3vni)
5430 return 0;
5431
5432 vni = zl3vni->vni;
b7cfce93 5433 zl3vni_del(zl3vni);
84915b0a 5434 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
2232a77c 5435
d62a17ae 5436 return 0;
13d60d35 5437}
5438
fbac9605
DS
5439/*
5440 * Handle message from client to specify the flooding mechanism for
5441 * BUM packets. The default is to do head-end (ingress) replication
5442 * and the other supported option is to disable it. This applies to
5443 * all BUM traffic and disabling it applies to both the transmit and
5444 * receive direction.
5445 */
5446void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
5447{
5448 struct stream *s;
5449 enum vxlan_flood_control flood_ctrl;
5450
986512a3 5451 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8 5452 zlog_err("EVPN flood control for non-EVPN VRF %u",
fbac9605
DS
5453 zvrf_id(zvrf));
5454 return;
5455 }
5456
5457 s = msg;
5458 STREAM_GETC(s, flood_ctrl);
5459
5460 if (IS_ZEBRA_DEBUG_VXLAN)
5461 zlog_debug("EVPN flood control %u, currently %u",
5462 flood_ctrl, zvrf->vxlan_flood_ctrl);
5463
5464 if (zvrf->vxlan_flood_ctrl == flood_ctrl)
5465 return;
5466
5467 zvrf->vxlan_flood_ctrl = flood_ctrl;
5468
5469 /* Install or uninstall flood entries corresponding to
5470 * remote VTEPs.
5471 */
8b5fdf2e 5472 hash_iterate(zvrf->evpn_table, zebra_evpn_handle_flooding_remote_vteps,
fbac9605
DS
5473 zvrf);
5474
5475stream_failure:
5476 return;
5477}
5478
278e26de
CS
5479/*
5480 * Handle message from client to enable/disable advertisement of svi macip
5481 * routes
5482 */
5483void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
5484{
5485 struct stream *s;
5486 int advertise;
5487 vni_t vni = 0;
f6371c34 5488 struct zebra_evpn *zevpn = NULL;
278e26de
CS
5489 struct interface *ifp = NULL;
5490
986512a3 5491 if (!EVPN_ENABLED(zvrf)) {
27627f9a 5492 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
a0b0b5c8 5493 zvrf_id(zvrf));
278e26de
CS
5494 return;
5495 }
5496
5497 s = msg;
5498 STREAM_GETC(s, advertise);
5499 STREAM_GETL(s, vni);
5500
5501 if (!vni) {
5502 if (IS_ZEBRA_DEBUG_VXLAN)
27627f9a 5503 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
278e26de 5504 advertise ? "enabled" : "disabled",
838cef6d 5505 advertise_svi_macip_enabled(NULL)
278e26de
CS
5506 ? "enabled"
5507 : "disabled");
5508
5509 if (zvrf->advertise_svi_macip == advertise)
5510 return;
5511
5512
5513 if (advertise) {
5514 zvrf->advertise_svi_macip = advertise;
87d76d54 5515 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5516 zebra_evpn_gw_macip_add_for_evpn_hash,
5517 NULL);
278e26de 5518 } else {
87d76d54 5519 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5520 zebra_evpn_svi_macip_del_for_evpn_hash,
5521 NULL);
278e26de
CS
5522 zvrf->advertise_svi_macip = advertise;
5523 }
5524
5525 } else {
5526 struct zebra_if *zif = NULL;
5527 struct zebra_l2info_vxlan zl2_info;
5528 struct interface *vlan_if = NULL;
5529
8b5fdf2e 5530 zevpn = zebra_evpn_lookup(vni);
87d76d54 5531 if (!zevpn)
278e26de
CS
5532 return;
5533
5534 if (IS_ZEBRA_DEBUG_VXLAN)
5535 zlog_debug(
5536 "EVPN SVI macip Adv %s on VNI %d , currently %s",
5537 advertise ? "enabled" : "disabled", vni,
87d76d54 5538 advertise_svi_macip_enabled(zevpn)
278e26de
CS
5539 ? "enabled"
5540 : "disabled");
5541
87d76d54 5542 if (zevpn->advertise_svi_macip == advertise)
278e26de
CS
5543 return;
5544
3dacbb9d
CS
5545 /* Store flag even though SVI is not present.
5546 * Once SVI comes up triggers self MAC-IP route add.
5547 */
87d76d54 5548 zevpn->advertise_svi_macip = advertise;
3dacbb9d 5549
87d76d54 5550 ifp = zevpn->vxlan_if;
278e26de
CS
5551 if (!ifp)
5552 return;
5553
5554 zif = ifp->info;
5555
5556 /* If down or not mapped to a bridge, we're done. */
5557 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
5558 return;
5559
5560 zl2_info = zif->l2info.vxl;
7cbae20a 5561 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
278e26de
CS
5562 zif->brslave_info.br_if);
5563 if (!vlan_if)
5564 return;
5565
5566 if (advertise) {
278e26de 5567 /* Add primary SVI MAC-IP */
8b5fdf2e 5568 zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
278e26de 5569 } else {
3dacbb9d 5570 /* Del primary SVI MAC-IP */
8b5fdf2e 5571 zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
278e26de
CS
5572 }
5573 }
5574
5575stream_failure:
5576 return;
5577}
5578
31310b25
MK
5579/*
5580 * Handle message from client to enable/disable advertisement of g/w macip
5581 * routes
5582 */
89f4e507 5583void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
31310b25
MK
5584{
5585 struct stream *s;
5586 int advertise;
5587 vni_t vni = 0;
f6371c34 5588 struct zebra_evpn *zevpn = NULL;
31310b25
MK
5589 struct interface *ifp = NULL;
5590 struct zebra_if *zif = NULL;
5591 struct zebra_l2info_vxlan zl2_info;
5592 struct interface *vlan_if = NULL;
5593
986512a3 5594 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8
T
5595 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5596 zvrf_id(zvrf));
8068a649 5597 return;
31310b25
MK
5598 }
5599
1002497a 5600 s = msg;
2017b3ea 5601 STREAM_GETC(s, advertise);
7fb29f49 5602 STREAM_GET(&vni, s, 3);
31310b25 5603
8b5fdf2e 5604 zevpn = zebra_evpn_lookup(vni);
87d76d54 5605 if (!zevpn)
8068a649 5606 return;
31310b25 5607
87d76d54 5608 if (zevpn->advertise_subnet == advertise)
8068a649 5609 return;
31310b25
MK
5610
5611 if (IS_ZEBRA_DEBUG_VXLAN)
996c9314
LB
5612 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
5613 advertise ? "enabled" : "disabled", vni,
87d76d54 5614 zevpn->advertise_subnet ? "enabled" : "disabled");
31310b25
MK
5615
5616
87d76d54 5617 zevpn->advertise_subnet = advertise;
31310b25 5618
87d76d54 5619 ifp = zevpn->vxlan_if;
31310b25 5620 if (!ifp)
8068a649 5621 return;
31310b25
MK
5622
5623 zif = ifp->info;
5624
5625 /* If down or not mapped to a bridge, we're done. */
5626 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 5627 return;
31310b25
MK
5628
5629 zl2_info = zif->l2info.vxl;
5630
996c9314 5631 vlan_if =
7cbae20a 5632 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
31310b25 5633 if (!vlan_if)
8068a649 5634 return;
31310b25 5635
87d76d54 5636 if (zevpn->advertise_subnet)
8b5fdf2e 5637 zebra_evpn_advertise_subnet(zevpn, vlan_if, 1);
31310b25 5638 else
8b5fdf2e 5639 zebra_evpn_advertise_subnet(zevpn, vlan_if, 0);
2017b3ea
DS
5640
5641stream_failure:
5642 return;
31310b25
MK
5643}
5644
1a98c087
MK
5645/*
5646 * Handle message from client to enable/disable advertisement of g/w macip
5647 * routes
5648 */
89f4e507 5649void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
1a98c087
MK
5650{
5651 struct stream *s;
5652 int advertise;
5653 vni_t vni = 0;
f6371c34 5654 struct zebra_evpn *zevpn = NULL;
b5ebdc9b 5655 struct interface *ifp = NULL;
1a98c087 5656
986512a3 5657 if (!EVPN_ENABLED(zvrf)) {
a0b0b5c8 5658 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9df414fe 5659 zvrf_id(zvrf));
8068a649 5660 return;
2853fed6 5661 }
5662
1002497a 5663 s = msg;
ec93aa12 5664 STREAM_GETC(s, advertise);
cc6d5476 5665 STREAM_GETL(s, vni);
1a98c087
MK
5666
5667 if (!vni) {
5668 if (IS_ZEBRA_DEBUG_VXLAN)
2853fed6 5669 zlog_debug("EVPN gateway macip Adv %s, currently %s",
1a98c087 5670 advertise ? "enabled" : "disabled",
2853fed6 5671 advertise_gw_macip_enabled(NULL)
1a98c087
MK
5672 ? "enabled"
5673 : "disabled");
5674
5675 if (zvrf->advertise_gw_macip == advertise)
8068a649 5676 return;
1a98c087
MK
5677
5678 zvrf->advertise_gw_macip = advertise;
5679
87d76d54
PR
5680 if (advertise_gw_macip_enabled(zevpn))
5681 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5682 zebra_evpn_gw_macip_add_for_evpn_hash,
5683 NULL);
1a98c087 5684 else
87d76d54 5685 hash_iterate(zvrf->evpn_table,
8b5fdf2e
PR
5686 zebra_evpn_gw_macip_del_for_evpn_hash,
5687 NULL);
1a98c087
MK
5688
5689 } else {
5690 struct zebra_if *zif = NULL;
5691 struct zebra_l2info_vxlan zl2_info;
5692 struct interface *vlan_if = NULL;
5693 struct interface *vrr_if = NULL;
5694
8b5fdf2e 5695 zevpn = zebra_evpn_lookup(vni);
87d76d54 5696 if (!zevpn)
124ead27 5697 return;
01a6143b 5698
1a98c087
MK
5699 if (IS_ZEBRA_DEBUG_VXLAN)
5700 zlog_debug(
2853fed6 5701 "EVPN gateway macip Adv %s on VNI %d , currently %s",
1a98c087 5702 advertise ? "enabled" : "disabled", vni,
87d76d54 5703 advertise_gw_macip_enabled(zevpn) ? "enabled"
996c9314 5704 : "disabled");
1a98c087 5705
87d76d54 5706 if (zevpn->advertise_gw_macip == advertise)
8068a649 5707 return;
1a98c087 5708
87d76d54 5709 zevpn->advertise_gw_macip = advertise;
1a98c087 5710
87d76d54 5711 ifp = zevpn->vxlan_if;
b5ebdc9b 5712 if (!ifp)
8068a649 5713 return;
b5ebdc9b 5714
5715 zif = ifp->info;
5716
5717 /* If down or not mapped to a bridge, we're done. */
b682f6de 5718 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8068a649 5719 return;
b5ebdc9b 5720
1a98c087
MK
5721 zl2_info = zif->l2info.vxl;
5722
7cbae20a 5723 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
1a98c087
MK
5724 zif->brslave_info.br_if);
5725 if (!vlan_if)
8068a649 5726 return;
1a98c087 5727
87d76d54 5728 if (advertise_gw_macip_enabled(zevpn)) {
1a98c087 5729 /* Add primary SVI MAC-IP */
8b5fdf2e 5730 zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
1a98c087
MK
5731
5732 /* Add VRR MAC-IP - if any*/
5733 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
5734 if (vrr_if)
8b5fdf2e 5735 zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
1a98c087
MK
5736 } else {
5737 /* Del primary MAC-IP */
8b5fdf2e 5738 zebra_evpn_del_macip_for_intf(vlan_if, zevpn);
1a98c087
MK
5739
5740 /* Del VRR MAC-IP - if any*/
5741 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
5742 if (vrr_if)
8b5fdf2e 5743 zebra_evpn_del_macip_for_intf(vrr_if, zevpn);
1a98c087
MK
5744 }
5745 }
5746
ec93aa12 5747stream_failure:
8068a649 5748 return;
1a98c087
MK
5749}
5750
2961d060
PG
5751static int macfdb_read_ns(struct ns *ns,
5752 void *_in_param __attribute__((unused)),
5753 void **out_param __attribute__((unused)))
6265fbe5 5754{
2961d060
PG
5755 struct zebra_ns *zns = ns->info;
5756
6265fbe5 5757 macfdb_read(zns);
2961d060 5758 return NS_WALK_CONTINUE;
6265fbe5
PG
5759}
5760
2961d060
PG
5761static int neigh_read_ns(struct ns *ns,
5762 void *_in_param __attribute__((unused)),
5763 void **out_param __attribute__((unused)))
6265fbe5 5764{
2961d060
PG
5765 struct zebra_ns *zns = ns->info;
5766
6265fbe5 5767 neigh_read(zns);
2961d060 5768 return NS_WALK_CONTINUE;
6265fbe5 5769}
1a98c087 5770
13d60d35 5771/*
5772 * Handle message from client to learn (or stop learning) about VNIs and MACs.
5773 * When enabled, the VNI hash table will be built and MAC FDB table read;
5774 * when disabled, the entries should be deleted and remote VTEPs and MACs
5775 * uninstalled from the kernel.
fbac9605
DS
5776 * This also informs the setting for BUM handling at the time this change
5777 * occurs; it is relevant only when specifying "learn".
13d60d35 5778 */
89f4e507 5779void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
13d60d35 5780{
655b04d1
MK
5781 struct stream *s = NULL;
5782 int advertise = 0;
fbac9605 5783 enum vxlan_flood_control flood_ctrl;
13d60d35 5784
77b998fb
T
5785 /* Mismatch between EVPN VRF and current VRF (should be prevented by
5786 * bgpd's cli) */
f920dd6d 5787 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf))
8068a649 5788 return;
2853fed6 5789
1002497a 5790 s = msg;
ec93aa12 5791 STREAM_GETC(s, advertise);
fbac9605 5792 STREAM_GETC(s, flood_ctrl);
13d60d35 5793
d62a17ae 5794 if (IS_ZEBRA_DEBUG_VXLAN)
150971b5
T
5795 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
5796 zvrf_name(zvrf), zvrf_id(zvrf),
d62a17ae 5797 advertise ? "enabled" : "disabled",
fbac9605
DS
5798 is_evpn_enabled() ? "enabled" : "disabled",
5799 flood_ctrl);
13d60d35 5800
d62a17ae 5801 if (zvrf->advertise_all_vni == advertise)
8068a649 5802 return;
13d60d35 5803
d62a17ae 5804 zvrf->advertise_all_vni = advertise;
f920dd6d 5805 if (EVPN_ENABLED(zvrf)) {
0fb2ad05 5806 zrouter.evpn_vrf = zvrf;
150971b5 5807
fbac9605
DS
5808 /* Note BUM handling */
5809 zvrf->vxlan_flood_ctrl = flood_ctrl;
5810
ce5160c0
AK
5811 /* Replay all ESs */
5812 zebra_evpn_es_send_all_to_client(true /* add */);
5813
87d76d54
PR
5814 /* Build EVPN hash table and inform BGP. */
5815 zevpn_build_hash_table();
2232a77c 5816
1a98c087 5817 /* Add all SVI (L3 GW) MACs to BGP*/
8b5fdf2e
PR
5818 hash_iterate(zvrf->evpn_table,
5819 zebra_evpn_gw_macip_add_for_evpn_hash, NULL);
1a98c087 5820
d62a17ae 5821 /* Read the MAC FDB */
2961d060 5822 ns_walk_func(macfdb_read_ns, NULL, NULL);
2232a77c 5823
d62a17ae 5824 /* Read neighbors */
2961d060 5825 ns_walk_func(neigh_read_ns, NULL, NULL);
d62a17ae 5826 } else {
87d76d54 5827 /* Cleanup VTEPs for all EVPNs - uninstall from
d62a17ae 5828 * kernel and free entries.
5829 */
8b5fdf2e
PR
5830 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all,
5831 zvrf);
655b04d1 5832
ce5160c0
AK
5833 /* Delete all ESs in BGP */
5834 zebra_evpn_es_send_all_to_client(false /* add */);
5835
655b04d1 5836 /* cleanup all l3vnis */
89272910 5837 hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
150971b5 5838
0fb2ad05
T
5839 /* Mark as "no EVPN VRF" */
5840 zrouter.evpn_vrf = NULL;
d62a17ae 5841 }
13d60d35 5842
ec93aa12 5843stream_failure:
8068a649 5844 return;
13d60d35 5845}
5846
5847/*
87d76d54 5848 * Allocate EVPN hash table for this VRF and do other initialization.
13d60d35 5849 * NOTE: Currently supported only for default VRF.
5850 */
d62a17ae 5851void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
13d60d35 5852{
4a73887e
DS
5853 char buffer[80];
5854
d62a17ae 5855 if (!zvrf)
5856 return;
4a73887e
DS
5857
5858 snprintf(buffer, sizeof(buffer), "Zebra VRF EVPN Table: %s",
5859 zvrf->vrf->name);
5860 zvrf->evpn_table = hash_create_size(8, zebra_evpn_hash_keymake,
5861 zebra_evpn_hash_cmp, buffer);
5862
5863 snprintf(buffer, sizeof(buffer), "Zebra VxLAN SG Table: %s",
5864 zvrf->vrf->name);
5865 zvrf->vxlan_sg_table = hash_create_size(8, zebra_vxlan_sg_hash_key_make,
e2071325 5866 zebra_vxlan_sg_hash_eq, buffer);
13d60d35 5867}
5868
87d76d54 5869/* Cleanup EVPN info, but don't free the table. */
84915b0a 5870void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
5871{
ce5160c0
AK
5872 struct zebra_vrf *evpn_zvrf = zebra_vrf_get_evpn();
5873
8b5fdf2e 5874 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
0c16fb72 5875 zebra_vxlan_cleanup_sg_table(zvrf);
ce5160c0
AK
5876
5877 if (zvrf == evpn_zvrf)
5878 zebra_evpn_es_cleanup();
84915b0a 5879}
5880
87d76d54 5881/* Close all EVPN handling */
d62a17ae 5882void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
13d60d35 5883{
2853fed6 5884 if (!zvrf)
5885 return;
8b5fdf2e 5886 hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf);
87d76d54 5887 hash_free(zvrf->evpn_table);
0c16fb72
AK
5888 if (zvrf->vxlan_sg_table) {
5889 zebra_vxlan_cleanup_sg_table(zvrf);
5890 hash_free(zvrf->vxlan_sg_table);
5891 zvrf->vxlan_sg_table = NULL;
5892 }
13d60d35 5893}
b7cfce93
MK
5894
5895/* init the l3vni table */
6548050a 5896void zebra_vxlan_init(void)
b7cfce93 5897{
89272910
DS
5898 zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
5899 "Zebra VRF L3 VNI table");
0fb2ad05 5900 zrouter.evpn_vrf = NULL;
ce5160c0 5901 zebra_evpn_mh_init();
b7cfce93
MK
5902}
5903
5904/* free l3vni table */
6548050a 5905void zebra_vxlan_disable(void)
b7cfce93 5906{
89272910 5907 hash_free(zrouter.l3vni_table);
ce5160c0 5908 zebra_evpn_mh_terminate();
b7cfce93 5909}
d3135ba3 5910
5911/* get the l3vni svi ifindex */
5912ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
5913{
05843a27 5914 struct zebra_l3vni *zl3vni = NULL;
d3135ba3 5915
5916 zl3vni = zl3vni_from_vrf(vrf_id);
5917 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
5918 return 0;
5919
5920 return zl3vni->svi_if->ifindex;
5921}
c80a972c 5922
015d264c 5923/************************** vxlan SG cache management ************************/
4ab3321f 5924/* Inform PIM about the mcast group */
ecbbc3a7
AK
5925static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
5926 struct prefix_sg *sg,
5927 char *sg_str, uint16_t cmd)
4ab3321f
AK
5928{
5929 struct zserv *client = NULL;
5930 struct stream *s = NULL;
5931
5932 client = zserv_find_client(ZEBRA_ROUTE_PIM, 0);
5933 if (!client)
5934 return 0;
5935
ecbbc3a7
AK
5936 if (!CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG))
5937 return 0;
5938
4ab3321f
AK
5939 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
5940
5941 zclient_create_header(s, cmd, VRF_DEFAULT);
5942 stream_putl(s, IPV4_MAX_BYTELEN);
5943 stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
5944 stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);
5945
5946 /* Write packet size. */
5947 stream_putw_at(s, 0, stream_get_endp(s));
5948
5949 if (IS_ZEBRA_DEBUG_VXLAN)
5950 zlog_debug(
5951 "Send %s %s to %s",
5952 (cmd == ZEBRA_VXLAN_SG_ADD) ? "add" : "del", sg_str,
5953 zebra_route_string(client->proto));
5954
5955 if (cmd == ZEBRA_VXLAN_SG_ADD)
5956 client->vxlan_sg_add_cnt++;
5957 else
5958 client->vxlan_sg_del_cnt++;
5959
5960 return zserv_send_message(client, s);
5961}
5962
d8b87afe 5963static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
015d264c 5964{
847f168d 5965 const struct zebra_vxlan_sg *vxlan_sg = p;
015d264c
AK
5966
5967 return (jhash_2words(vxlan_sg->sg.src.s_addr,
5968 vxlan_sg->sg.grp.s_addr, 0));
5969}
5970
5971static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
5972{
847f168d
DS
5973 const struct zebra_vxlan_sg *sg1 = p1;
5974 const struct zebra_vxlan_sg *sg2 = p2;
015d264c
AK
5975
5976 return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
5977 && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
5978}
5979
847f168d
DS
5980static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
5981 struct prefix_sg *sg)
015d264c 5982{
847f168d 5983 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
5984
5985 vxlan_sg = XCALLOC(MTYPE_ZVXLAN_SG, sizeof(*vxlan_sg));
5986
5987 vxlan_sg->zvrf = zvrf;
5988 vxlan_sg->sg = *sg;
5989 prefix_sg2str(sg, vxlan_sg->sg_str);
5990
5991 vxlan_sg = hash_get(zvrf->vxlan_sg_table, vxlan_sg, hash_alloc_intern);
5992
5993 if (IS_ZEBRA_DEBUG_VXLAN)
5994 zlog_debug("vxlan SG %s created", vxlan_sg->sg_str);
5995
5996 return vxlan_sg;
5997}
5998
847f168d
DS
5999static struct zebra_vxlan_sg *zebra_vxlan_sg_find(struct zebra_vrf *zvrf,
6000 struct prefix_sg *sg)
015d264c 6001{
847f168d 6002 struct zebra_vxlan_sg lookup;
015d264c
AK
6003
6004 lookup.sg = *sg;
6005 return hash_lookup(zvrf->vxlan_sg_table, &lookup);
6006}
6007
847f168d
DS
6008static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
6009 struct prefix_sg *sg)
015d264c 6010{
847f168d
DS
6011 struct zebra_vxlan_sg *vxlan_sg;
6012 struct zebra_vxlan_sg *parent = NULL;
015d264c
AK
6013 struct in_addr sip;
6014
6015 vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
6016 if (vxlan_sg)
6017 return vxlan_sg;
6018
6019 /* create a *G entry for every BUM group implicitly -
6020 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
6021 * 2. the XG entry is used by pimd to setup the
6022 * vxlan-termination-mroute
6023 */
975a328e 6024 if (sg->src.s_addr != INADDR_ANY) {
015d264c
AK
6025 memset(&sip, 0, sizeof(sip));
6026 parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
6027 if (!parent)
6028 return NULL;
6029 }
6030
6031 vxlan_sg = zebra_vxlan_sg_new(zvrf, sg);
015d264c 6032
ecbbc3a7
AK
6033 zebra_vxlan_sg_send(zvrf, sg, vxlan_sg->sg_str,
6034 ZEBRA_VXLAN_SG_ADD);
4ab3321f 6035
015d264c
AK
6036 return vxlan_sg;
6037}
6038
847f168d 6039static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
015d264c
AK
6040{
6041 struct in_addr sip;
6042 struct zebra_vrf *zvrf;
6043
6044 zvrf = vrf_info_lookup(VRF_DEFAULT);
6045 if (!zvrf)
6046 return;
6047
6048 /* On SG entry deletion remove the reference to its parent XG
6049 * entry
6050 */
975a328e 6051 if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
015d264c
AK
6052 memset(&sip, 0, sizeof(sip));
6053 zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
6054 }
6055
ecbbc3a7
AK
6056 zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
6057 vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
4ab3321f 6058
015d264c
AK
6059 hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
6060
6061 if (IS_ZEBRA_DEBUG_VXLAN)
6062 zlog_debug("VXLAN SG %s deleted", vxlan_sg->sg_str);
6063
6064 XFREE(MTYPE_ZVXLAN_SG, vxlan_sg);
6065}
6066
6067static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
6068 struct in_addr sip, struct in_addr mcast_grp)
6069{
847f168d 6070 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
6071 struct prefix_sg sg;
6072
6073 sg.family = AF_INET;
6074 sg.prefixlen = IPV4_MAX_BYTELEN;
6075 sg.src = sip;
6076 sg.grp = mcast_grp;
6077 vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
6078 if (!vxlan_sg)
6079 return;
6080
6081 if (vxlan_sg->ref_cnt)
6082 --vxlan_sg->ref_cnt;
6083
6084 if (!vxlan_sg->ref_cnt)
6085 zebra_vxlan_sg_del(vxlan_sg);
6086}
6087
847f168d
DS
6088static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
6089 struct in_addr sip,
6090 struct in_addr mcast_grp)
015d264c 6091{
847f168d 6092 struct zebra_vxlan_sg *vxlan_sg;
015d264c
AK
6093 struct prefix_sg sg;
6094
6095 sg.family = AF_INET;
6096 sg.prefixlen = IPV4_MAX_BYTELEN;
6097 sg.src = sip;
6098 sg.grp = mcast_grp;
6099 vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
6100 if (vxlan_sg)
6101 ++vxlan_sg->ref_cnt;
6102
6103 return vxlan_sg;
6104}
abfa0a96
AK
6105
6106static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
6107 struct in_addr mcast_grp)
6108{
6109 struct zebra_vrf *zvrf;
6110
975a328e
DA
6111 if (local_vtep_ip.s_addr == INADDR_ANY
6112 || mcast_grp.s_addr == INADDR_ANY)
abfa0a96
AK
6113 return;
6114
6115 zvrf = vrf_info_lookup(VRF_DEFAULT);
6116 if (!zvrf)
6117 return;
6118
6119 zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
6120}
6121
6122static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
6123 struct in_addr mcast_grp)
6124{
6125 struct zebra_vrf *zvrf;
6126
975a328e
DA
6127 if (local_vtep_ip.s_addr == INADDR_ANY
6128 || mcast_grp.s_addr == INADDR_ANY)
abfa0a96
AK
6129 return;
6130
6131 zvrf = vrf_info_lookup(VRF_DEFAULT);
6132 if (!zvrf)
6133 return;
6134 zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
6135}
6136
1ac88792 6137static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
0c16fb72 6138{
847f168d 6139 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
0c16fb72
AK
6140
6141 /* increment the ref count against (*,G) to prevent them from being
6142 * deleted
6143 */
6144 if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
6145 ++vxlan_sg->ref_cnt;
6146}
6147
1ac88792 6148static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
0c16fb72 6149{
847f168d 6150 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
0c16fb72
AK
6151
6152 /* decrement the dummy ref count against (*,G) to delete them */
6153 if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
6154 if (vxlan_sg->ref_cnt)
6155 --vxlan_sg->ref_cnt;
6156 if (!vxlan_sg->ref_cnt)
6157 zebra_vxlan_sg_del(vxlan_sg);
6158 }
6159}
6160
1ac88792 6161static void zebra_vxlan_sg_cleanup(struct hash_bucket *bucket, void *arg)
abfa0a96 6162{
847f168d 6163 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
abfa0a96
AK
6164
6165 zebra_vxlan_sg_del(vxlan_sg);
6166}
27627f9a 6167
0c16fb72
AK
6168static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf)
6169{
6170 /* increment the ref count against (*,G) to prevent them from being
6171 * deleted
6172 */
6173 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_pre_cleanup, NULL);
6174
6175 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL);
6176
6177 /* decrement the dummy ref count against the XG entries */
6178 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_xg_post_cleanup, NULL);
6179}
6180
1ac88792 6181static void zebra_vxlan_sg_replay_send(struct hash_bucket *bucket, void *arg)
ecbbc3a7 6182{
847f168d 6183 struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
ecbbc3a7
AK
6184
6185 zebra_vxlan_sg_send(vxlan_sg->zvrf, &vxlan_sg->sg,
6186 vxlan_sg->sg_str, ZEBRA_VXLAN_SG_ADD);
6187}
6188
6189/* Handle message from client to replay vxlan SG entries */
6190void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS)
6191{
6192 if (IS_ZEBRA_DEBUG_VXLAN)
6193 zlog_debug("VxLAN SG updates to PIM, start");
6194
6195 SET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
6196
6197 if (!EVPN_ENABLED(zvrf)) {
8f86bb06
DS
6198 if (IS_ZEBRA_DEBUG_VXLAN)
6199 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
6200 zvrf->vrf->vrf_id);
ecbbc3a7
AK
6201 return;
6202 }
6203
6204 hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL);
6205}
6206
27627f9a
KA
6207
6208/* Cleanup EVPN configuration of a specific VRF */
6209static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
6210{
05843a27 6211 struct zebra_l3vni *zl3vni = NULL;
b6587fc2 6212
27627f9a
KA
6213 zvrf->advertise_all_vni = 0;
6214 zvrf->advertise_gw_macip = 0;
6215 zvrf->advertise_svi_macip = 0;
6216 zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
6217
8b5fdf2e 6218 hash_iterate(zvrf->evpn_table, zebra_evpn_cfg_cleanup, NULL);
b6587fc2
CS
6219
6220 if (zvrf->l3vni)
6221 zl3vni = zl3vni_lookup(zvrf->l3vni);
6222 if (zl3vni) {
6223 /* delete and uninstall all rmacs */
6224 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
6225 zl3vni);
6226 /* delete and uninstall all next-hops */
6227 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
6228 zl3vni);
6229 }
27627f9a
KA
6230}
6231
6232/* Cleanup BGP EVPN configuration upon client disconnect */
ecbbc3a7 6233static int zebra_evpn_bgp_cfg_clean_up(struct zserv *client)
27627f9a
KA
6234{
6235 struct vrf *vrf;
6236 struct zebra_vrf *zvrf;
6237
27627f9a
KA
6238 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
6239 zvrf = vrf->info;
6240 if (zvrf)
6241 zebra_evpn_vrf_cfg_cleanup(zvrf);
6242 }
6243
6244 return 0;
6245}
6246
ecbbc3a7
AK
6247static int zebra_evpn_pim_cfg_clean_up(struct zserv *client)
6248{
6249 struct zebra_vrf *zvrf = zebra_vrf_get_evpn();
6250
81157cbd 6251 if (CHECK_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG)) {
ecbbc3a7
AK
6252 if (IS_ZEBRA_DEBUG_VXLAN)
6253 zlog_debug("VxLAN SG updates to PIM, stop");
6254 UNSET_FLAG(zvrf->flags, ZEBRA_PIM_SEND_VXLAN_SG);
6255 }
6256
6257 return 0;
6258}
6259
6260static int zebra_evpn_cfg_clean_up(struct zserv *client)
6261{
6262 if (client->proto == ZEBRA_ROUTE_BGP)
6263 return zebra_evpn_bgp_cfg_clean_up(client);
6264
6265 if (client->proto == ZEBRA_ROUTE_PIM)
6266 return zebra_evpn_pim_cfg_clean_up(client);
6267
6268 return 0;
6269}
6270
036d93c0
MS
6271/*
6272 * Handle results for vxlan dataplane operations.
6273 */
6274extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
6275{
f00b37e7 6276 return;
036d93c0
MS
6277}
6278
27627f9a
KA
6279/* Cleanup BGP EVPN configuration upon client disconnect */
6280extern void zebra_evpn_init(void)
6281{
6282 hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
6283}