2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
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
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.
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
37 #include <linux/neighbour.h>
39 #include "lib/printfrr.h"
41 #include "zebra/zebra_router.h"
42 #include "zebra/debug.h"
43 #include "zebra/interface.h"
44 #include "zebra/rib.h"
46 #include "zebra/rt_netlink.h"
47 #include "zebra/zebra_errors.h"
48 #include "zebra/zebra_l2.h"
49 #include "zebra/zebra_memory.h"
50 #include "zebra/zebra_ns.h"
51 #include "zebra/zebra_vrf.h"
52 #include "zebra/zebra_vxlan.h"
53 #include "zebra/zebra_evpn.h"
54 #include "zebra/zebra_evpn_mac.h"
55 #include "zebra/zebra_evpn_neigh.h"
56 #include "zebra/zebra_vxlan_private.h"
57 #include "zebra/zebra_evpn_mh.h"
58 #include "zebra/zebra_evpn_vxlan.h"
59 #include "zebra/zebra_router.h"
61 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
62 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
63 DEFINE_MTYPE_STATIC(ZEBRA
, L3VNI_MAC
, "EVPN L3VNI MAC");
64 DEFINE_MTYPE_STATIC(ZEBRA
, L3NEIGH
, "EVPN Neighbor");
65 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
67 DEFINE_HOOK(zebra_rmac_update
, (zebra_mac_t
*rmac
, zebra_l3vni_t
*zl3vni
,
68 bool delete, const char *reason
), (rmac
, zl3vni
, delete, reason
))
70 /* static function declarations */
71 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
73 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
75 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
77 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
);
79 /* l3-vni next-hop neigh related APIs */
80 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
81 const struct ipaddr
*ip
);
82 static void *zl3vni_nh_alloc(void *p
);
83 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
84 const struct ipaddr
*vtep_ip
,
85 const struct ethaddr
*rmac
);
86 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
87 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
88 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
90 /* l3-vni rmac related APIs */
91 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
92 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
93 const struct ethaddr
*rmac
);
94 static void *zl3vni_rmac_alloc(void *p
);
95 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
96 const struct ethaddr
*rmac
);
97 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
98 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
99 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
101 /* l3-vni related APIs*/
102 static void *zl3vni_alloc(void *p
);
103 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
104 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
105 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
106 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
108 static void zevpn_build_hash_table(void);
109 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
110 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
111 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
112 struct in_addr sip
, struct in_addr mcast_grp
);
113 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
114 struct in_addr sip
, struct in_addr mcast_grp
);
115 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
116 struct in_addr mcast_grp
);
117 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
118 struct in_addr mcast_grp
);
119 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*bucket
, void *arg
);
121 /* Private functions */
122 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
123 const struct host_rb_entry
*hle2
)
125 if (hle1
->p
.family
< hle2
->p
.family
)
128 if (hle1
->p
.family
> hle2
->p
.family
)
131 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
134 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
137 if (hle1
->p
.family
== AF_INET
) {
138 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
141 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
145 } else if (hle1
->p
.family
== AF_INET6
) {
146 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
149 zlog_debug("%s: Unexpected family type: %d", __func__
,
154 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
156 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
158 struct host_rb_entry
*hle
;
161 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
168 * Print neighbors for all EVPN.
170 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
174 json_object
*json
= NULL
, *json_evpn
= NULL
;
177 struct neigh_walk_ctx wctx
;
178 char vni_str
[VNI_STR_LEN
];
181 vty
= (struct vty
*)args
[0];
182 json
= (json_object
*)args
[1];
183 print_dup
= (uint32_t)(uintptr_t)args
[2];
185 zevpn
= (zebra_evpn_t
*)bucket
->data
;
187 num_neigh
= hashcount(zevpn
->neigh_table
);
190 num_neigh
= num_dup_detected_neighs(zevpn
);
194 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
195 zevpn
->vni
, num_neigh
);
197 json_evpn
= json_object_new_object();
198 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
199 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
204 json_object_object_add(json
, vni_str
, json_evpn
);
208 /* Since we have IPv6 addresses to deal with which can vary widely in
209 * size, we try to be a bit more elegant in display by first computing
212 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
215 wctx
.addr_width
= 15;
216 wctx
.json
= json_evpn
;
217 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
221 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
224 hash_iterate(zevpn
->neigh_table
,
225 zebra_evpn_print_dad_neigh_hash
, &wctx
);
227 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
,
231 json_object_object_add(json
, vni_str
, json_evpn
);
235 * Print neighbors for all EVPNs in detail.
237 static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket
*bucket
,
241 json_object
*json
= NULL
, *json_evpn
= NULL
;
244 struct neigh_walk_ctx wctx
;
245 char vni_str
[VNI_STR_LEN
];
248 vty
= (struct vty
*)args
[0];
249 json
= (json_object
*)args
[1];
250 print_dup
= (uint32_t)(uintptr_t)args
[2];
252 zevpn
= (zebra_evpn_t
*)bucket
->data
;
255 vty_out(vty
, "{}\n");
258 num_neigh
= hashcount(zevpn
->neigh_table
);
260 if (print_dup
&& num_dup_detected_neighs(zevpn
) == 0)
265 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
266 zevpn
->vni
, num_neigh
);
268 json_evpn
= json_object_new_object();
269 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
270 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
274 json_object_object_add(json
, vni_str
, json_evpn
);
278 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
281 wctx
.addr_width
= 15;
282 wctx
.json
= json_evpn
;
285 hash_iterate(zevpn
->neigh_table
,
286 zebra_evpn_print_dad_neigh_hash_detail
, &wctx
);
288 hash_iterate(zevpn
->neigh_table
,
289 zebra_evpn_print_neigh_hash_detail
, &wctx
);
292 json_object_object_add(json
, vni_str
, json_evpn
);
295 /* print a specific next hop for an l3vni */
296 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
299 char buf1
[ETHER_ADDR_STRLEN
];
300 char buf2
[INET6_ADDRSTRLEN
];
301 json_object
*json_hosts
= NULL
;
302 struct host_rb_entry
*hle
;
305 vty_out(vty
, "Ip: %s\n",
306 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
307 vty_out(vty
, " RMAC: %s\n",
308 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
309 vty_out(vty
, " Refcount: %d\n",
310 rb_host_count(&n
->host_rb
));
311 vty_out(vty
, " Prefixes:\n");
312 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
313 vty_out(vty
, " %pFX\n", &hle
->p
);
315 json_hosts
= json_object_new_array();
316 json_object_string_add(
317 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
318 json_object_string_add(
320 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
321 json_object_int_add(json
, "refCount",
322 rb_host_count(&n
->host_rb
));
323 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
324 json_object_array_add(json_hosts
,
325 json_object_new_string(prefix2str(
326 &hle
->p
, buf2
, sizeof(buf2
))));
327 json_object_object_add(json
, "prefixList", json_hosts
);
331 /* Print a specific RMAC entry */
332 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
335 char buf1
[ETHER_ADDR_STRLEN
];
336 char buf2
[PREFIX_STRLEN
];
337 json_object
*json_hosts
= NULL
;
338 struct host_rb_entry
*hle
;
341 vty_out(vty
, "MAC: %s\n",
342 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
343 vty_out(vty
, " Remote VTEP: %pI4\n",
344 &zrmac
->fwd_info
.r_vtep_ip
);
345 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
346 vty_out(vty
, " Prefixes:\n");
347 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
348 vty_out(vty
, " %pFX\n", &hle
->p
);
350 json_hosts
= json_object_new_array();
351 json_object_string_add(
353 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
354 json_object_string_add(json
, "vtepIp",
356 &zrmac
->fwd_info
.r_vtep_ip
,
357 buf1
, sizeof(buf1
)));
358 json_object_int_add(json
, "refCount",
359 rb_host_count(&zrmac
->host_rb
));
360 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
361 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
362 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
363 json_object_array_add(
365 json_object_new_string(prefix2str(
366 &hle
->p
, buf2
, sizeof(buf2
))));
367 json_object_object_add(json
, "prefixList", json_hosts
);
372 * Print MACs for all EVPNs.
374 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
)
377 json_object
*json
= NULL
, *json_evpn
= NULL
;
378 json_object
*json_mac
= NULL
;
381 struct mac_walk_ctx
*wctx
= ctxt
;
382 char vni_str
[VNI_STR_LEN
];
387 zevpn
= (zebra_evpn_t
*)bucket
->data
;
390 /*We are iterating over a new VNI, set the count to 0*/
393 num_macs
= num_valid_macs(zevpn
);
398 num_macs
= num_dup_detected_macs(zevpn
);
401 json_evpn
= json_object_new_object();
402 json_mac
= json_object_new_object();
403 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
406 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
408 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
409 zevpn
->vni
, num_macs
);
411 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
412 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
413 "Type", "Flags", "Intf/Remote ES/VTEP",
416 json_object_int_add(json_evpn
, "numMacs", num_macs
);
421 json_object_int_add(json_evpn
, "numMacs", num_macs
);
422 json_object_object_add(json
, vni_str
, json_evpn
);
427 /* assign per-evpn to wctx->json object to fill macs
428 * under the evpn. Re-assign primary json object to fill
429 * next evpn information.
431 wctx
->json
= json_mac
;
433 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
,
436 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, wctx
);
440 json_object_object_add(json_evpn
, "macs", json_mac
);
441 json_object_object_add(json
, vni_str
, json_evpn
);
446 * Print MACs in detail for all EVPNs.
448 static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket
*bucket
,
452 json_object
*json
= NULL
, *json_evpn
= NULL
;
453 json_object
*json_mac
= NULL
;
456 struct mac_walk_ctx
*wctx
= ctxt
;
457 char vni_str
[VNI_STR_LEN
];
462 zevpn
= (zebra_evpn_t
*)bucket
->data
;
465 vty_out(vty
, "{}\n");
470 /*We are iterating over a new EVPN, set the count to 0*/
473 num_macs
= num_valid_macs(zevpn
);
477 if (wctx
->print_dup
&& (num_dup_detected_macs(zevpn
) == 0))
481 json_evpn
= json_object_new_object();
482 json_mac
= json_object_new_object();
483 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
486 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
488 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
489 zevpn
->vni
, num_macs
);
491 json_object_int_add(json_evpn
, "numMacs", num_macs
);
493 /* assign per-evpn to wctx->json object to fill macs
494 * under the evpn. Re-assign primary json object to fill
495 * next evpn information.
497 wctx
->json
= json_mac
;
499 hash_iterate(zevpn
->mac_table
,
500 zebra_evpn_print_dad_mac_hash_detail
, wctx
);
502 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash_detail
,
507 json_object_object_add(json_evpn
, "macs", json_mac
);
508 json_object_object_add(json
, vni_str
, json_evpn
);
512 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
514 struct nh_walk_ctx
*wctx
= NULL
;
515 struct vty
*vty
= NULL
;
516 struct json_object
*json_evpn
= NULL
;
517 struct json_object
*json_nh
= NULL
;
518 zebra_neigh_t
*n
= NULL
;
519 char buf1
[ETHER_ADDR_STRLEN
];
520 char buf2
[INET6_ADDRSTRLEN
];
522 wctx
= (struct nh_walk_ctx
*)ctx
;
524 json_evpn
= wctx
->json
;
526 json_nh
= json_object_new_object();
527 n
= (zebra_neigh_t
*)bucket
->data
;
530 vty_out(vty
, "%-15s %-17s\n",
531 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
532 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
534 json_object_string_add(json_nh
, "nexthopIp",
535 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
536 json_object_string_add(
537 json_nh
, "routerMac",
538 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
539 json_object_object_add(json_evpn
,
540 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
545 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
548 struct vty
*vty
= NULL
;
549 json_object
*json
= NULL
;
550 json_object
*json_evpn
= NULL
;
551 zebra_l3vni_t
*zl3vni
= NULL
;
553 struct nh_walk_ctx wctx
;
554 char vni_str
[VNI_STR_LEN
];
556 vty
= (struct vty
*)args
[0];
557 json
= (struct json_object
*)args
[1];
559 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
561 num_nh
= hashcount(zl3vni
->nh_table
);
566 json_evpn
= json_object_new_object();
567 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
571 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
572 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
574 json_object_int_add(json_evpn
, "numNextHops", num_nh
);
576 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
578 wctx
.json
= json_evpn
;
579 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
581 json_object_object_add(json
, vni_str
, json_evpn
);
584 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
587 struct vty
*vty
= NULL
;
588 json_object
*json
= NULL
;
589 json_object
*json_evpn
= NULL
;
590 zebra_l3vni_t
*zl3vni
= NULL
;
592 struct rmac_walk_ctx wctx
;
593 char vni_str
[VNI_STR_LEN
];
595 vty
= (struct vty
*)args
[0];
596 json
= (struct json_object
*)args
[1];
598 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
600 num_rmacs
= hashcount(zl3vni
->rmac_table
);
605 json_evpn
= json_object_new_object();
606 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
610 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
611 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
613 json_object_int_add(json_evpn
, "numRmacs", num_rmacs
);
615 /* assign per-vni to wctx->json object to fill macs
616 * under the vni. Re-assign primary json object to fill
617 * next vni information.
619 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
621 wctx
.json
= json_evpn
;
622 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
624 json_object_object_add(json
, vni_str
, json_evpn
);
627 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
629 zebra_mac_t
*zrmac
= NULL
;
630 struct rmac_walk_ctx
*wctx
= NULL
;
631 struct vty
*vty
= NULL
;
632 struct json_object
*json
= NULL
;
633 struct json_object
*json_rmac
= NULL
;
634 char buf
[PREFIX_STRLEN
];
636 wctx
= (struct rmac_walk_ctx
*)ctx
;
640 json_rmac
= json_object_new_object();
641 zrmac
= (zebra_mac_t
*)bucket
->data
;
644 vty_out(vty
, "%-17s %-21pI4\n",
645 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
646 &zrmac
->fwd_info
.r_vtep_ip
);
648 json_object_string_add(
649 json_rmac
, "routerMac",
650 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
651 json_object_string_add(json_rmac
, "vtepIp",
653 &zrmac
->fwd_info
.r_vtep_ip
,
655 json_object_object_add(
656 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
661 /* print a specific L3 VNI entry */
662 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
664 char buf
[PREFIX_STRLEN
];
665 struct vty
*vty
= NULL
;
666 json_object
*json
= NULL
;
667 zebra_evpn_t
*zevpn
= NULL
;
668 json_object
*json_evpn_list
= NULL
;
669 struct listnode
*node
= NULL
, *nnode
= NULL
;
675 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
676 vty_out(vty
, " Type: %s\n", "L3");
677 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
678 vty_out(vty
, " Local Vtep Ip: %pI4\n",
679 &zl3vni
->local_vtep_ip
);
680 vty_out(vty
, " Vxlan-Intf: %s\n",
681 zl3vni_vxlan_if_name(zl3vni
));
682 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
683 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
684 vty_out(vty
, " VNI Filter: %s\n",
685 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
686 ? "prefix-routes-only"
688 vty_out(vty
, " System MAC: %s\n",
689 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
690 vty_out(vty
, " Router MAC: %s\n",
691 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
692 vty_out(vty
, " L2 VNIs: ");
693 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
))
694 vty_out(vty
, "%u ", zevpn
->vni
);
697 json_evpn_list
= json_object_new_array();
698 json_object_int_add(json
, "vni", zl3vni
->vni
);
699 json_object_string_add(json
, "type", "L3");
700 json_object_string_add(
702 inet_ntop(AF_INET
, &zl3vni
->local_vtep_ip
, buf
,
704 json_object_string_add(json
, "vxlanIntf",
705 zl3vni_vxlan_if_name(zl3vni
));
706 json_object_string_add(json
, "sviIntf",
707 zl3vni_svi_if_name(zl3vni
));
708 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
709 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
710 json_object_string_add(
712 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
713 json_object_string_add(
715 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
716 json_object_string_add(
718 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
719 ? "prefix-routes-only"
721 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
)) {
722 json_object_array_add(json_evpn_list
,
723 json_object_new_int(zevpn
->vni
));
725 json_object_object_add(json
, "l2Vnis", json_evpn_list
);
729 /* print a L3 VNI hash entry */
730 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
732 struct vty
*vty
= NULL
;
733 json_object
*json
= NULL
;
734 json_object
*json_evpn
= NULL
;
735 zebra_l3vni_t
*zl3vni
= NULL
;
737 vty
= (struct vty
*)ctx
[0];
738 json
= (json_object
*)ctx
[1];
740 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
743 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
744 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
745 hashcount(zl3vni
->rmac_table
),
746 hashcount(zl3vni
->nh_table
), "n/a",
747 zl3vni_vrf_name(zl3vni
));
749 char vni_str
[VNI_STR_LEN
];
751 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
752 json_evpn
= json_object_new_object();
753 json_object_int_add(json_evpn
, "vni", zl3vni
->vni
);
754 json_object_string_add(json_evpn
, "vxlanIf",
755 zl3vni_vxlan_if_name(zl3vni
));
756 json_object_int_add(json_evpn
, "numMacs",
757 hashcount(zl3vni
->rmac_table
));
758 json_object_int_add(json_evpn
, "numArpNd",
759 hashcount(zl3vni
->nh_table
));
760 json_object_string_add(json_evpn
, "numRemoteVteps", "n/a");
761 json_object_string_add(json_evpn
, "type", "L3");
762 json_object_string_add(json_evpn
, "tenantVrf",
763 zl3vni_vrf_name(zl3vni
));
764 json_object_object_add(json
, vni_str
, json_evpn
);
768 /* print a L3 VNI hash entry in detail*/
769 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
771 struct vty
*vty
= NULL
;
772 zebra_l3vni_t
*zl3vni
= NULL
;
773 json_object
*json_array
= NULL
;
774 bool use_json
= false;
775 struct zebra_evpn_show
*zes
= data
;
778 json_array
= zes
->json
;
779 use_json
= zes
->use_json
;
781 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
783 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
,
784 use_json
, json_array
);
790 static int zvni_map_to_svi_ns(struct ns
*ns
,
794 struct zebra_ns
*zns
= ns
->info
;
795 struct route_node
*rn
;
796 struct zebra_from_svi_param
*in_param
=
797 (struct zebra_from_svi_param
*)_in_param
;
798 struct zebra_l2info_vlan
*vl
;
799 struct interface
*tmp_if
= NULL
;
800 struct interface
**p_ifp
= (struct interface
**)_p_ifp
;
801 struct zebra_if
*zif
;
806 /* TODO: Optimize with a hash. */
807 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
808 tmp_if
= (struct interface
*)rn
->info
;
809 /* Check oper status of the SVI. */
810 if (!tmp_if
|| !if_is_operative(tmp_if
))
813 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
814 || zif
->link
!= in_param
->br_if
)
816 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
818 if (vl
->vid
== in_param
->vid
) {
824 return NS_WALK_CONTINUE
;
827 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
829 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
830 * linked to the bridge
831 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
834 struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
836 struct interface
*tmp_if
= NULL
;
837 struct zebra_if
*zif
;
838 struct zebra_l2info_bridge
*br
;
839 struct zebra_from_svi_param in_param
;
840 struct interface
**p_ifp
;
841 /* Defensive check, caller expected to invoke only with valid bridge. */
845 /* Determine if bridge is VLAN-aware or not */
848 br
= &zif
->l2info
.br
;
849 in_param
.bridge_vlan_aware
= br
->vlan_aware
;
850 /* Check oper status of the SVI. */
851 if (!in_param
.bridge_vlan_aware
)
852 return if_is_operative(br_if
) ? br_if
: NULL
;
855 in_param
.br_if
= br_if
;
858 /* Identify corresponding VLAN interface. */
859 ns_walk_func(zvni_map_to_svi_ns
, (void *)&in_param
,
864 static int zebra_evpn_vxlan_del(zebra_evpn_t
*zevpn
)
866 zevpn_vxlan_if_set(zevpn
, zevpn
->vxlan_if
, false /* set */);
868 /* Remove references to the BUM mcast grp */
869 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
, zevpn
->mcast_grp
);
871 return zebra_evpn_del(zevpn
);
874 static int zevpn_build_hash_table_zns(struct ns
*ns
,
875 void *param_in
__attribute__((unused
)),
876 void **param_out
__attribute__((unused
)))
878 struct zebra_ns
*zns
= ns
->info
;
879 struct route_node
*rn
;
880 struct interface
*ifp
;
881 struct zebra_vrf
*zvrf
;
883 zvrf
= zebra_vrf_get_evpn();
888 /* Walk VxLAN interfaces and create EVPN hash. */
889 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
891 zebra_evpn_t
*zevpn
= NULL
;
892 zebra_l3vni_t
*zl3vni
= NULL
;
893 struct zebra_if
*zif
;
894 struct zebra_l2info_vxlan
*vxl
;
896 ifp
= (struct interface
*)rn
->info
;
900 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
903 vxl
= &zif
->l2info
.vxl
;
905 /* link of VXLAN interface should be in zebra_evpn_vrf */
906 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
907 if (IS_ZEBRA_DEBUG_VXLAN
)
909 "Intf %s(%u) VNI %u, link not in same "
910 "namespace than BGP EVPN core instance ",
911 ifp
->name
, ifp
->ifindex
, vni
);
914 /* L3-VNI and L2-VNI are handled seperately */
915 zl3vni
= zl3vni_lookup(vni
);
918 if (IS_ZEBRA_DEBUG_VXLAN
)
920 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
921 ifp
->name
, ifp
->ifindex
, vni
);
923 /* associate with vxlan_if */
924 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
925 zl3vni
->vxlan_if
= ifp
;
928 * we need to associate with SVI.
929 * we can associate with svi-if only after association
930 * with vxlan-intf is complete
932 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
934 /* Associate l3vni to mac-vlan and extract VRR MAC */
935 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
937 if (IS_ZEBRA_DEBUG_VXLAN
)
938 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
939 vni
, zl3vni
->svi_if
? zl3vni
->svi_if
->name
941 zl3vni
->mac_vlan_if
?
942 zl3vni
->mac_vlan_if
->name
: "NIL");
944 if (is_l3vni_oper_up(zl3vni
))
945 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
948 struct interface
*vlan_if
= NULL
;
950 if (IS_ZEBRA_DEBUG_VXLAN
)
952 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
953 ifp
->name
, ifp
->ifindex
, vni
,
956 /* EVPN hash entry is expected to exist, if the BGP process is killed */
957 zevpn
= zebra_evpn_lookup(vni
);
960 "EVPN hash already present for IF %s(%u) L2-VNI %u",
961 ifp
->name
, ifp
->ifindex
, vni
);
964 * Inform BGP if intf is up and mapped to
967 if (if_is_operative(ifp
) &&
968 zif
->brslave_info
.br_if
)
969 zebra_evpn_send_add_to_client(zevpn
);
971 /* Send Local MAC-entries to client */
972 zebra_evpn_send_mac_list_to_client(zevpn
);
974 /* Send Loval Neighbor entries to client */
975 zebra_evpn_send_neigh_to_client(zevpn
);
977 zevpn
= zebra_evpn_add(vni
);
980 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
981 ifp
->name
, ifp
->ifindex
, vni
);
982 return NS_WALK_CONTINUE
;
985 if (zevpn
->local_vtep_ip
.s_addr
!=
986 vxl
->vtep_ip
.s_addr
||
987 zevpn
->mcast_grp
.s_addr
!=
988 vxl
->mcast_grp
.s_addr
) {
989 zebra_vxlan_sg_deref(
990 zevpn
->local_vtep_ip
,
992 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
994 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
995 zevpn
->mcast_grp
= vxl
->mcast_grp
;
996 /* on local vtep-ip check if ES
997 * orig-ip needs to be updated
999 zebra_evpn_es_set_base_evpn(zevpn
);
1001 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
1002 vlan_if
= zvni_map_to_svi(
1004 zif
->brslave_info
.br_if
);
1006 zevpn
->vrf_id
= vlan_if
->vrf_id
;
1007 zl3vni
= zl3vni_from_vrf(
1011 zl3vni
->l2vnis
, zevpn
);
1015 * Inform BGP if intf is up and mapped to
1018 if (if_is_operative(ifp
) &&
1019 zif
->brslave_info
.br_if
)
1020 zebra_evpn_send_add_to_client(zevpn
);
1024 return NS_WALK_CONTINUE
;
1028 * Build the VNI hash table by going over the VxLAN interfaces. This
1029 * is called when EVPN (advertise-all-vni) is enabled.
1032 static void zevpn_build_hash_table(void)
1034 ns_walk_func(zevpn_build_hash_table_zns
,
1040 * Cleanup EVPN/VTEP and update kernel
1042 static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
1044 zebra_evpn_t
*zevpn
= NULL
;
1045 zebra_l3vni_t
*zl3vni
= NULL
;
1046 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
1048 zevpn
= (zebra_evpn_t
*)bucket
->data
;
1050 /* remove from l3-vni list */
1052 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
1054 listnode_delete(zl3vni
->l2vnis
, zevpn
);
1056 zebra_evpn_cleanup_all(bucket
, arg
);
1060 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
1062 zebra_l3vni_t
*zl3vni
= NULL
;
1064 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1066 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
1069 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
1070 const struct prefix
*host
)
1072 struct host_rb_entry lookup
;
1073 struct host_rb_entry
*hle
;
1075 memset(&lookup
, 0, sizeof(lookup
));
1076 memcpy(&lookup
.p
, host
, sizeof(*host
));
1078 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1082 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
1083 memcpy(hle
, &lookup
, sizeof(lookup
));
1085 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
1088 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
1090 struct host_rb_entry lookup
;
1091 struct host_rb_entry
*hle
;
1093 memset(&lookup
, 0, sizeof(lookup
));
1094 memcpy(&lookup
.p
, host
, sizeof(*host
));
1096 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
1098 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
1099 XFREE(MTYPE_HOST_PREFIX
, hle
);
1106 * Look up MAC hash entry.
1108 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
1109 const struct ethaddr
*rmac
)
1114 memset(&tmp
, 0, sizeof(tmp
));
1115 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
1116 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
1122 * Callback to allocate RMAC hash entry.
1124 static void *zl3vni_rmac_alloc(void *p
)
1126 const zebra_mac_t
*tmp_rmac
= p
;
1129 zrmac
= XCALLOC(MTYPE_L3VNI_MAC
, sizeof(zebra_mac_t
));
1132 return ((void *)zrmac
);
1136 * Add RMAC entry to l3-vni
1138 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
1139 const struct ethaddr
*rmac
)
1141 zebra_mac_t tmp_rmac
;
1142 zebra_mac_t
*zrmac
= NULL
;
1144 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
1145 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
1146 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
1149 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
1151 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
1152 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
1160 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
1162 zebra_mac_t
*tmp_rmac
;
1163 struct host_rb_entry
*hle
;
1165 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
1166 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
1168 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
1169 XFREE(MTYPE_HOST_PREFIX
, hle
);
1172 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
1173 XFREE(MTYPE_L3VNI_MAC
, tmp_rmac
);
1179 * Install remote RMAC into the forwarding plane.
1181 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
1183 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
1184 const struct zebra_l2info_vxlan
*vxl
= NULL
;
1185 const struct interface
*br_ifp
;
1186 enum zebra_dplane_result res
;
1189 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1190 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1193 zif
= zl3vni
->vxlan_if
->info
;
1197 br_ifp
= zif
->brslave_info
.br_if
;
1201 vxl
= &zif
->l2info
.vxl
;
1203 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1205 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1206 vid
= vxl
->access_vlan
;
1210 res
= dplane_rem_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
,
1211 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0, 0,
1212 false /*was_static*/);
1213 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1220 * Uninstall remote RMAC from the forwarding plane.
1222 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
1224 char buf
[ETHER_ADDR_STRLEN
];
1225 const struct zebra_if
*zif
= NULL
, *br_zif
;
1226 const struct zebra_l2info_vxlan
*vxl
= NULL
;
1227 const struct interface
*br_ifp
;
1229 enum zebra_dplane_result res
;
1231 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
1232 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
1235 if (!zl3vni
->vxlan_if
) {
1236 if (IS_ZEBRA_DEBUG_VXLAN
)
1238 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
1239 prefix_mac2str(&zrmac
->macaddr
,
1241 zl3vni
->vni
, zl3vni
);
1245 zif
= zl3vni
->vxlan_if
->info
;
1249 br_ifp
= zif
->brslave_info
.br_if
;
1253 vxl
= &zif
->l2info
.vxl
;
1255 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
1256 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
1257 vid
= vxl
->access_vlan
;
1261 res
= dplane_rem_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
,
1262 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
1263 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
1269 /* handle rmac add */
1270 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
,
1271 const struct ethaddr
*rmac
,
1272 const struct ipaddr
*vtep_ip
,
1273 const struct prefix
*host_prefix
)
1275 char buf
[ETHER_ADDR_STRLEN
];
1276 char buf1
[INET6_ADDRSTRLEN
];
1277 zebra_mac_t
*zrmac
= NULL
;
1279 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
1282 /* Create the RMAC entry, or update its vtep, if necessary. */
1283 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
1286 "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %pFX",
1287 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
1289 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
1293 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
1294 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1296 /* Send RMAC for FPM processing */
1297 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
1300 /* install rmac in kernel */
1301 zl3vni_rmac_install(zl3vni
, zrmac
);
1302 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
1303 &vtep_ip
->ipaddr_v4
)) {
1304 if (IS_ZEBRA_DEBUG_VXLAN
)
1306 "L3VNI %u Remote VTEP change(%pI4 -> %s) for RMAC %s, prefix %pFX",
1308 &zrmac
->fwd_info
.r_vtep_ip
,
1309 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
1310 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
1313 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
1315 /* install rmac in kernel */
1316 zl3vni_rmac_install(zl3vni
, zrmac
);
1319 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
1325 /* handle rmac delete */
1326 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
1327 struct prefix
*host_prefix
)
1329 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
1331 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
1332 /* uninstall from kernel */
1333 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
1335 /* Send RMAC for FPM processing */
1336 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
1339 /* del the rmac entry */
1340 zl3vni_rmac_del(zl3vni
, zrmac
);
1345 * Look up nh hash entry on a l3-vni.
1347 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
1348 const struct ipaddr
*ip
)
1353 memset(&tmp
, 0, sizeof(tmp
));
1354 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
1355 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
1362 * Callback to allocate NH hash entry on L3-VNI.
1364 static void *zl3vni_nh_alloc(void *p
)
1366 const zebra_neigh_t
*tmp_n
= p
;
1369 n
= XCALLOC(MTYPE_L3NEIGH
, sizeof(zebra_neigh_t
));
1376 * Add neighbor entry.
1378 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
1379 const struct ipaddr
*ip
,
1380 const struct ethaddr
*mac
)
1382 zebra_neigh_t tmp_n
;
1383 zebra_neigh_t
*n
= NULL
;
1385 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1386 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1387 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
1390 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
1392 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1393 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
1394 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
1400 * Delete neighbor entry.
1402 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
1404 zebra_neigh_t
*tmp_n
;
1405 struct host_rb_entry
*hle
;
1407 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
1408 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
1410 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
1411 XFREE(MTYPE_HOST_PREFIX
, hle
);
1414 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
1415 XFREE(MTYPE_L3NEIGH
, tmp_n
);
1421 * Install remote nh as neigh into the kernel.
1423 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
1428 if (!is_l3vni_oper_up(zl3vni
))
1431 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1432 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1435 flags
= DPLANE_NTF_EXT_LEARNED
;
1436 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
1437 flags
|= DPLANE_NTF_ROUTER
;
1439 dplane_rem_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
,
1440 false /*was_static*/);
1446 * Uninstall remote nh from the kernel.
1448 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
1450 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
1451 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
1454 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
1457 dplane_rem_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
1462 /* add remote vtep as a neigh entry */
1463 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
,
1464 const struct ipaddr
*vtep_ip
,
1465 const struct ethaddr
*rmac
,
1466 const struct prefix
*host_prefix
)
1468 char buf
[ETHER_ADDR_STRLEN
];
1469 char buf1
[ETHER_ADDR_STRLEN
];
1470 char buf2
[INET6_ADDRSTRLEN
];
1471 zebra_neigh_t
*nh
= NULL
;
1473 /* Create the next hop entry, or update its mac, if necessary. */
1474 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
1476 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
1479 "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %pFX)",
1480 ipaddr2str(vtep_ip
, buf1
, sizeof(buf2
)),
1481 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
1482 zl3vni
->vni
, host_prefix
);
1486 /* install the nh neigh in kernel */
1487 zl3vni_nh_install(zl3vni
, nh
);
1488 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
1489 if (IS_ZEBRA_DEBUG_VXLAN
)
1491 "L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %pFX",
1493 prefix_mac2str(&nh
->emac
, buf
, sizeof(buf
)),
1494 prefix_mac2str(rmac
, buf1
, sizeof(buf1
)),
1495 ipaddr2str(vtep_ip
, buf2
, sizeof(buf2
)),
1498 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
1499 /* install (update) the nh neigh in kernel */
1500 zl3vni_nh_install(zl3vni
, nh
);
1503 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
1508 /* handle nh neigh delete */
1509 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
1510 struct prefix
*host_prefix
)
1512 rb_delete_host(&nh
->host_rb
, host_prefix
);
1514 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
1515 /* uninstall from kernel */
1516 zl3vni_nh_uninstall(zl3vni
, nh
);
1518 /* delete the nh entry */
1519 zl3vni_nh_del(zl3vni
, nh
);
1523 /* handle neigh update from kernel - the only thing of interest is to
1524 * readd stale entries.
1526 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
1530 zebra_neigh_t
*n
= NULL
;
1532 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1536 /* all next hop neigh are remote and installed by frr.
1537 * If the kernel has aged this entry, re-install.
1539 if (state
& NUD_STALE
)
1540 zl3vni_nh_install(zl3vni
, n
);
1545 /* handle neigh delete from kernel */
1546 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
1548 zebra_neigh_t
*n
= NULL
;
1550 n
= zl3vni_nh_lookup(zl3vni
, ip
);
1554 /* all next hop neigh are remote and installed by frr.
1555 * If we get an age out notification for these neigh entries, we have to
1558 zl3vni_nh_install(zl3vni
, n
);
1564 * Hash function for L3 VNI.
1566 static unsigned int l3vni_hash_keymake(const void *p
)
1568 const zebra_l3vni_t
*zl3vni
= p
;
1570 return jhash_1word(zl3vni
->vni
, 0);
1574 * Compare 2 L3 VNI hash entries.
1576 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
1578 const zebra_l3vni_t
*zl3vni1
= p1
;
1579 const zebra_l3vni_t
*zl3vni2
= p2
;
1581 return (zl3vni1
->vni
== zl3vni2
->vni
);
1585 * Callback to allocate L3 VNI hash entry.
1587 static void *zl3vni_alloc(void *p
)
1589 zebra_l3vni_t
*zl3vni
= NULL
;
1590 const zebra_l3vni_t
*tmp_l3vni
= p
;
1592 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
1593 zl3vni
->vni
= tmp_l3vni
->vni
;
1594 return ((void *)zl3vni
);
1598 * Look up L3 VNI hash entry.
1600 zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
1602 zebra_l3vni_t tmp_l3vni
;
1603 zebra_l3vni_t
*zl3vni
= NULL
;
1605 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
1606 tmp_l3vni
.vni
= vni
;
1607 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
1613 * Add L3 VNI hash entry.
1615 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
1617 zebra_l3vni_t tmp_zl3vni
;
1618 zebra_l3vni_t
*zl3vni
= NULL
;
1620 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
1621 tmp_zl3vni
.vni
= vni
;
1623 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
1626 zl3vni
->vrf_id
= vrf_id
;
1627 zl3vni
->svi_if
= NULL
;
1628 zl3vni
->vxlan_if
= NULL
;
1629 zl3vni
->l2vnis
= list_new();
1630 zl3vni
->l2vnis
->cmp
= zebra_evpn_list_cmp
;
1632 /* Create hash table for remote RMAC */
1633 zl3vni
->rmac_table
= zebra_mac_db_create("Zebra L3-VNI RMAC-Table");
1635 /* Create hash table for neighbors */
1636 zl3vni
->nh_table
= zebra_neigh_db_create("Zebra L3-VNI next-hop table");
1642 * Delete L3 VNI hash entry.
1644 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
1646 zebra_l3vni_t
*tmp_zl3vni
;
1648 /* free the list of l2vnis */
1649 list_delete(&zl3vni
->l2vnis
);
1650 zl3vni
->l2vnis
= NULL
;
1652 /* Free the rmac table */
1653 hash_free(zl3vni
->rmac_table
);
1654 zl3vni
->rmac_table
= NULL
;
1656 /* Free the nh table */
1657 hash_free(zl3vni
->nh_table
);
1658 zl3vni
->nh_table
= NULL
;
1660 /* Free the VNI hash entry and allocated memory. */
1661 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
1662 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
1667 static int zl3vni_map_to_vxlan_if_ns(struct ns
*ns
,
1671 struct zebra_ns
*zns
= ns
->info
;
1672 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)_zl3vni
;
1673 struct route_node
*rn
= NULL
;
1674 struct interface
*ifp
= NULL
;
1675 struct zebra_vrf
*zvrf
;
1677 zvrf
= zebra_vrf_get_evpn();
1680 return NS_WALK_STOP
;
1682 /* loop through all vxlan-interface */
1683 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1685 struct zebra_if
*zif
= NULL
;
1686 struct zebra_l2info_vxlan
*vxl
= NULL
;
1688 ifp
= (struct interface
*)rn
->info
;
1693 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1696 vxl
= &zif
->l2info
.vxl
;
1697 if (vxl
->vni
!= zl3vni
->vni
)
1700 /* link of VXLAN interface should be in zebra_evpn_vrf */
1701 if (zvrf
->zns
->ns_id
!= vxl
->link_nsid
) {
1702 if (IS_ZEBRA_DEBUG_VXLAN
)
1704 "Intf %s(%u) VNI %u, link not in same "
1705 "namespace than BGP EVPN core instance ",
1706 ifp
->name
, ifp
->ifindex
, vxl
->vni
);
1711 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
1713 *_pifp
= (void *)ifp
;
1714 return NS_WALK_STOP
;
1717 return NS_WALK_CONTINUE
;
1720 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
1722 struct interface
**p_ifp
;
1723 struct interface
*ifp
= NULL
;
1727 ns_walk_func(zl3vni_map_to_vxlan_if_ns
,
1728 (void *)zl3vni
, (void **)p_ifp
);
1732 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
1734 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
1735 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
1740 if (!zl3vni
->vxlan_if
)
1743 zif
= zl3vni
->vxlan_if
->info
;
1747 vxl
= &zif
->l2info
.vxl
;
1749 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
1752 struct interface
*zl3vni_map_to_mac_vlan_if(zebra_l3vni_t
*zl3vni
)
1754 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
1759 if (!zl3vni
->vxlan_if
)
1762 zif
= zl3vni
->vxlan_if
->info
;
1766 return zebra_evpn_map_to_macvlan(zif
->brslave_info
.br_if
,
1771 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
1773 struct zebra_vrf
*zvrf
= NULL
;
1775 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
1779 return zl3vni_lookup(zvrf
->l3vni
);
1783 * Map SVI and associated bridge to a VNI. This is invoked upon getting
1784 * neighbor notifications, to see if they are of interest.
1786 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
1787 struct interface
*br_if
)
1791 uint8_t bridge_vlan_aware
= 0;
1792 zebra_l3vni_t
*zl3vni
= NULL
;
1793 struct zebra_ns
*zns
= NULL
;
1794 struct route_node
*rn
= NULL
;
1795 struct zebra_if
*zif
= NULL
;
1796 struct interface
*tmp_if
= NULL
;
1797 struct zebra_l2info_bridge
*br
= NULL
;
1798 struct zebra_l2info_vxlan
*vxl
= NULL
;
1803 /* Make sure the linked interface is a bridge. */
1804 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
1807 /* Determine if bridge is VLAN-aware or not */
1810 br
= &zif
->l2info
.br
;
1811 bridge_vlan_aware
= br
->vlan_aware
;
1812 if (bridge_vlan_aware
) {
1813 struct zebra_l2info_vlan
*vl
;
1815 if (!IS_ZEBRA_IF_VLAN(ifp
))
1820 vl
= &zif
->l2info
.vl
;
1824 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
1825 /* TODO: Optimize with a hash. */
1826 zns
= zebra_ns_lookup(NS_DEFAULT
);
1827 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
1828 tmp_if
= (struct interface
*)rn
->info
;
1832 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
1834 if (!if_is_operative(tmp_if
))
1836 vxl
= &zif
->l2info
.vxl
;
1838 if (zif
->brslave_info
.br_if
!= br_if
)
1841 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
1850 zl3vni
= zl3vni_lookup(vxl
->vni
);
1854 static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t
*zl3vni
,
1855 struct ethaddr
*rmac
)
1860 if (!is_l3vni_oper_up(zl3vni
))
1863 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
1864 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
1868 * Inform BGP about l3-vni.
1870 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
1872 struct stream
*s
= NULL
;
1873 struct zserv
*client
= NULL
;
1874 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
1875 struct zebra_vrf
*zvrf
;
1876 char buf
[ETHER_ADDR_STRLEN
];
1877 char buf1
[ETHER_ADDR_STRLEN
];
1878 bool is_anycast_mac
= true;
1880 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1881 /* BGP may not be running. */
1885 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
1888 /* get the svi and vrr rmac values */
1889 memset(&svi_rmac
, 0, sizeof(struct ethaddr
));
1890 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
1891 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
1893 /* In absence of vrr mac use svi mac as anycast MAC value */
1894 if (is_zero_mac(&vrr_rmac
)) {
1895 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
1896 is_anycast_mac
= false;
1899 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1901 /* The message is used for both vni add and/or update like
1902 * vrr mac is added for l3vni SVI.
1904 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
1905 stream_putl(s
, zl3vni
->vni
);
1906 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
1907 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
1908 stream_put(s
, &zl3vni
->filter
, sizeof(int));
1909 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
1910 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
1911 stream_putl(s
, is_anycast_mac
);
1913 /* Write packet size. */
1914 stream_putw_at(s
, 0, stream_get_endp(s
));
1916 if (IS_ZEBRA_DEBUG_VXLAN
)
1918 "Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %pI4 filter %s to %s",
1919 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
1920 prefix_mac2str(&svi_rmac
, buf
, sizeof(buf
)),
1921 prefix_mac2str(&vrr_rmac
, buf1
, sizeof(buf1
)),
1922 &zl3vni
->local_vtep_ip
,
1923 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1924 ? "prefix-routes-only"
1926 zebra_route_string(client
->proto
));
1928 client
->l3vniadd_cnt
++;
1929 return zserv_send_message(client
, s
);
1933 * Inform BGP about local l3-VNI deletion.
1935 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
1937 struct stream
*s
= NULL
;
1938 struct zserv
*client
= NULL
;
1940 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1941 /* BGP may not be running. */
1945 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1947 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
1948 stream_putl(s
, zl3vni
->vni
);
1950 /* Write packet size. */
1951 stream_putw_at(s
, 0, stream_get_endp(s
));
1953 if (IS_ZEBRA_DEBUG_VXLAN
)
1954 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
1955 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
1956 zebra_route_string(client
->proto
));
1958 client
->l3vnidel_cnt
++;
1959 return zserv_send_message(client
, s
);
1962 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
1967 /* send l3vni add to BGP */
1968 zl3vni_send_add_to_client(zl3vni
);
1971 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
1976 /* send l3-vni del to BGP*/
1977 zl3vni_send_del_to_client(zl3vni
);
1980 static void zevpn_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
1982 zebra_evpn_t
*zevpn
= (zebra_evpn_t
*)bucket
->data
;
1983 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
1985 if (zevpn
->vrf_id
== zl3vni_vrf_id(zl3vni
))
1986 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
1990 * handle transition of vni from l2 to l3 and vice versa
1992 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
1995 zebra_evpn_t
*zevpn
= NULL
;
1997 /* There is a possibility that VNI notification was already received
1998 * from kernel and we programmed it as L2-VNI
1999 * In such a case we need to delete this L2-VNI first, so
2000 * that it can be reprogrammed as L3-VNI in the system. It is also
2001 * possible that the vrf-vni mapping is removed from FRR while the vxlan
2002 * interface is still present in kernel. In this case to keep it
2003 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
2006 /* Locate hash entry */
2007 zevpn
= zebra_evpn_lookup(vni
);
2011 if (IS_ZEBRA_DEBUG_VXLAN
)
2012 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
2014 /* Delete EVPN from BGP. */
2015 zebra_evpn_send_del_to_client(zevpn
);
2017 zebra_evpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
2018 zebra_evpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
2020 /* Free up all remote VTEPs, if any. */
2021 zebra_evpn_vtep_del_all(zevpn
, 0);
2023 /* Delete the hash entry. */
2024 if (zebra_evpn_vxlan_del(zevpn
)) {
2025 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
2026 "Failed to del EVPN hash %p, VNI %u", zevpn
,
2031 /* TODO_MITESH: This needs to be thought through. We don't have
2032 * enough information at this point to reprogram the vni as
2033 * l2-vni. One way is to store the required info in l3-vni and
2034 * used it solely for this purpose
2041 /* delete and uninstall rmac hash entry */
2042 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2044 zebra_mac_t
*zrmac
= NULL
;
2045 zebra_l3vni_t
*zl3vni
= NULL
;
2047 zrmac
= (zebra_mac_t
*)bucket
->data
;
2048 zl3vni
= (zebra_l3vni_t
*)ctx
;
2049 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
2051 /* Send RMAC for FPM processing */
2052 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
2054 zl3vni_rmac_del(zl3vni
, zrmac
);
2057 /* delete and uninstall nh hash entry */
2058 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
2060 zebra_neigh_t
*n
= NULL
;
2061 zebra_l3vni_t
*zl3vni
= NULL
;
2063 n
= (zebra_neigh_t
*)bucket
->data
;
2064 zl3vni
= (zebra_l3vni_t
*)ctx
;
2065 zl3vni_nh_uninstall(zl3vni
, n
);
2066 zl3vni_nh_del(zl3vni
, n
);
2069 /* re-add remote rmac if needed */
2070 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
2071 struct ethaddr
*rmac
)
2073 char buf
[ETHER_ADDR_STRLEN
];
2074 zebra_mac_t
*zrmac
= NULL
;
2076 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2080 if (IS_ZEBRA_DEBUG_VXLAN
)
2081 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
2082 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
2084 zl3vni_rmac_install(zl3vni
, zrmac
);
2088 /* Public functions */
2090 int is_l3vni_for_prefix_routes_only(vni_t vni
)
2092 zebra_l3vni_t
*zl3vni
= NULL
;
2094 zl3vni
= zl3vni_lookup(vni
);
2098 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
2101 /* handle evpn route in vrf table */
2102 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, const struct ethaddr
*rmac
,
2103 const struct ipaddr
*vtep_ip
,
2104 const struct prefix
*host_prefix
)
2106 zebra_l3vni_t
*zl3vni
= NULL
;
2107 struct ipaddr ipv4_vtep
;
2109 zl3vni
= zl3vni_from_vrf(vrf_id
);
2110 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
2114 * add the next hop neighbor -
2115 * neigh to be installed is the ipv6 nexthop neigh
2117 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
2120 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
2121 * address. Rmac is programmed against the ipv4 vtep because we only
2122 * support ipv4 tunnels in the h/w right now
2124 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
2125 ipv4_vtep
.ipa_type
= IPADDR_V4
;
2126 if (vtep_ip
->ipa_type
== IPADDR_V6
)
2127 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
2128 &(ipv4_vtep
.ipaddr_v4
));
2130 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
2131 sizeof(struct in_addr
));
2134 * add the rmac - remote rmac to be installed is against the ipv4
2137 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
2140 /* handle evpn vrf route delete */
2141 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
2142 struct ipaddr
*vtep_ip
,
2143 struct prefix
*host_prefix
)
2145 zebra_l3vni_t
*zl3vni
= NULL
;
2146 zebra_neigh_t
*nh
= NULL
;
2147 zebra_mac_t
*zrmac
= NULL
;
2149 zl3vni
= zl3vni_from_vrf(vrf_id
);
2153 /* find the next hop entry and rmac entry */
2154 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
2157 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
2159 /* delete the next hop entry */
2160 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
2162 /* delete the rmac entry */
2164 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
2168 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
2169 struct ethaddr
*rmac
, bool use_json
)
2171 zebra_l3vni_t
*zl3vni
= NULL
;
2172 zebra_mac_t
*zrmac
= NULL
;
2173 json_object
*json
= NULL
;
2175 if (!is_evpn_enabled()) {
2177 vty_out(vty
, "{}\n");
2182 json
= json_object_new_object();
2184 zl3vni
= zl3vni_lookup(l3vni
);
2187 vty_out(vty
, "{}\n");
2189 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
2193 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
2196 vty_out(vty
, "{}\n");
2199 "%% Requested RMAC doesn't exist in L3-VNI %u",
2204 zl3vni_print_rmac(zrmac
, vty
, json
);
2207 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2208 json
, JSON_C_TO_STRING_PRETTY
));
2209 json_object_free(json
);
2213 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2215 zebra_l3vni_t
*zl3vni
;
2217 struct rmac_walk_ctx wctx
;
2218 json_object
*json
= NULL
;
2220 if (!is_evpn_enabled())
2223 zl3vni
= zl3vni_lookup(l3vni
);
2226 vty_out(vty
, "{}\n");
2228 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2231 num_rmacs
= hashcount(zl3vni
->rmac_table
);
2236 json
= json_object_new_object();
2238 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
2242 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
2244 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
2246 json_object_int_add(json
, "numRmacs", num_rmacs
);
2248 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
2251 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2252 json
, JSON_C_TO_STRING_PRETTY
));
2253 json_object_free(json
);
2257 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
2259 json_object
*json
= NULL
;
2262 if (!is_evpn_enabled()) {
2264 vty_out(vty
, "{}\n");
2269 json
= json_object_new_object();
2273 hash_iterate(zrouter
.l3vni_table
,
2274 (void (*)(struct hash_bucket
*,
2275 void *))zl3vni_print_rmac_hash_all_vni
,
2279 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2280 json
, JSON_C_TO_STRING_PRETTY
));
2281 json_object_free(json
);
2285 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
2286 struct ipaddr
*ip
, bool use_json
)
2288 zebra_l3vni_t
*zl3vni
= NULL
;
2289 zebra_neigh_t
*n
= NULL
;
2290 json_object
*json
= NULL
;
2292 if (!is_evpn_enabled()) {
2294 vty_out(vty
, "{}\n");
2299 json
= json_object_new_object();
2301 zl3vni
= zl3vni_lookup(l3vni
);
2304 vty_out(vty
, "{}\n");
2306 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2310 n
= zl3vni_nh_lookup(zl3vni
, ip
);
2313 vty_out(vty
, "{}\n");
2316 "%% Requested next-hop not present for L3-VNI %u",
2321 zl3vni_print_nh(n
, vty
, json
);
2324 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2325 json
, JSON_C_TO_STRING_PRETTY
));
2326 json_object_free(json
);
2330 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
2333 struct nh_walk_ctx wctx
;
2334 json_object
*json
= NULL
;
2335 zebra_l3vni_t
*zl3vni
= NULL
;
2337 if (!is_evpn_enabled())
2340 zl3vni
= zl3vni_lookup(l3vni
);
2343 vty_out(vty
, "{}\n");
2345 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
2349 num_nh
= hashcount(zl3vni
->nh_table
);
2354 json
= json_object_new_object();
2359 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
2361 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
2363 json_object_int_add(json
, "numNextHops", num_nh
);
2365 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
2368 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2369 json
, JSON_C_TO_STRING_PRETTY
));
2370 json_object_free(json
);
2374 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
2376 json_object
*json
= NULL
;
2379 if (!is_evpn_enabled()) {
2381 vty_out(vty
, "{}\n");
2386 json
= json_object_new_object();
2390 hash_iterate(zrouter
.l3vni_table
,
2391 (void (*)(struct hash_bucket
*,
2392 void *))zl3vni_print_nh_hash_all_vni
,
2396 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2397 json
, JSON_C_TO_STRING_PRETTY
));
2398 json_object_free(json
);
2403 * Display L3 VNI information (VTY command handler).
2405 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
2408 json_object
*json
= NULL
;
2409 zebra_l3vni_t
*zl3vni
= NULL
;
2411 if (!is_evpn_enabled()) {
2413 vty_out(vty
, "{}\n");
2417 zl3vni
= zl3vni_lookup(vni
);
2420 vty_out(vty
, "{}\n");
2422 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2427 json
= json_object_new_object();
2431 zl3vni_print(zl3vni
, (void *)args
);
2434 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2435 json
, JSON_C_TO_STRING_PRETTY
));
2436 json_object_free(json
);
2440 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2441 json_object
*json_vrfs
)
2443 char buf
[ETHER_ADDR_STRLEN
];
2444 zebra_l3vni_t
*zl3vni
= NULL
;
2446 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
2451 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
2452 zvrf_name(zvrf
), zl3vni
->vni
,
2453 zl3vni_vxlan_if_name(zl3vni
),
2454 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
2455 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2457 json_object
*json_vrf
= NULL
;
2459 json_vrf
= json_object_new_object();
2460 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
2461 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
2462 json_object_string_add(json_vrf
, "vxlanIntf",
2463 zl3vni_vxlan_if_name(zl3vni
));
2464 json_object_string_add(json_vrf
, "sviIntf",
2465 zl3vni_svi_if_name(zl3vni
));
2466 json_object_string_add(json_vrf
, "state",
2467 zl3vni_state2str(zl3vni
));
2468 json_object_string_add(
2469 json_vrf
, "routerMac",
2470 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2471 json_object_array_add(json_vrfs
, json_vrf
);
2476 * Display Neighbors for a VNI (VTY command handler).
2478 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2479 vni_t vni
, bool use_json
)
2481 zebra_evpn_t
*zevpn
;
2483 struct neigh_walk_ctx wctx
;
2484 json_object
*json
= NULL
;
2486 if (!is_evpn_enabled())
2488 zevpn
= zebra_evpn_lookup(vni
);
2491 vty_out(vty
, "{}\n");
2493 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2496 num_neigh
= hashcount(zevpn
->neigh_table
);
2501 json
= json_object_new_object();
2503 /* Since we have IPv6 addresses to deal with which can vary widely in
2504 * size, we try to be a bit more elegant in display by first computing
2505 * the maximum width.
2507 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2510 wctx
.addr_width
= 15;
2512 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2517 "Number of ARPs (local and remote) known for this VNI: %u\n",
2519 zebra_evpn_print_neigh_hdr(vty
, &wctx
);
2521 json_object_int_add(json
, "numArpNd", num_neigh
);
2523 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
2525 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2526 json
, JSON_C_TO_STRING_PRETTY
));
2527 json_object_free(json
);
2532 * Display neighbors across all VNIs (VTY command handler).
2534 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2535 bool print_dup
, bool use_json
)
2537 json_object
*json
= NULL
;
2540 if (!is_evpn_enabled())
2544 json
= json_object_new_object();
2548 args
[2] = (void *)(ptrdiff_t)print_dup
;
2550 hash_iterate(zvrf
->evpn_table
,
2551 (void (*)(struct hash_bucket
*,
2552 void *))zevpn_print_neigh_hash_all_evpn
,
2555 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2556 json
, JSON_C_TO_STRING_PRETTY
));
2557 json_object_free(json
);
2562 * Display neighbors across all VNIs in detail(VTY command handler).
2564 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
2565 struct zebra_vrf
*zvrf
,
2566 bool print_dup
, bool use_json
)
2568 json_object
*json
= NULL
;
2571 if (!is_evpn_enabled())
2575 json
= json_object_new_object();
2579 args
[2] = (void *)(ptrdiff_t)print_dup
;
2581 hash_iterate(zvrf
->evpn_table
,
2582 (void (*)(struct hash_bucket
*,
2583 void *))zevpn_print_neigh_hash_all_evpn_detail
,
2586 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2587 json
, JSON_C_TO_STRING_PRETTY
));
2588 json_object_free(json
);
2593 * Display specific neighbor for a VNI, if present (VTY command handler).
2595 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
2596 struct zebra_vrf
*zvrf
, vni_t vni
,
2597 struct ipaddr
*ip
, bool use_json
)
2599 zebra_evpn_t
*zevpn
;
2601 json_object
*json
= NULL
;
2603 if (!is_evpn_enabled())
2605 zevpn
= zebra_evpn_lookup(vni
);
2608 vty_out(vty
, "{}\n");
2610 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2613 n
= zebra_evpn_neigh_lookup(zevpn
, ip
);
2617 "%% Requested neighbor does not exist in VNI %u\n",
2622 json
= json_object_new_object();
2624 zebra_evpn_print_neigh(n
, vty
, json
);
2627 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2628 json
, JSON_C_TO_STRING_PRETTY
));
2629 json_object_free(json
);
2634 * Display neighbors for a VNI from specific VTEP (VTY command handler).
2635 * By definition, these are remote neighbors.
2637 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2638 vni_t vni
, struct in_addr vtep_ip
,
2641 zebra_evpn_t
*zevpn
;
2643 struct neigh_walk_ctx wctx
;
2644 json_object
*json
= NULL
;
2646 if (!is_evpn_enabled())
2648 zevpn
= zebra_evpn_lookup(vni
);
2651 vty_out(vty
, "{}\n");
2653 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2656 num_neigh
= hashcount(zevpn
->neigh_table
);
2661 json
= json_object_new_object();
2663 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2666 wctx
.addr_width
= 15;
2667 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
2668 wctx
.r_vtep_ip
= vtep_ip
;
2670 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2672 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_neigh_hash
, &wctx
);
2675 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2676 json
, JSON_C_TO_STRING_PRETTY
));
2677 json_object_free(json
);
2682 * Display Duplicate detected Neighbors for a VNI
2683 * (VTY command handler).
2685 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
2686 struct zebra_vrf
*zvrf
,
2690 zebra_evpn_t
*zevpn
;
2692 struct neigh_walk_ctx wctx
;
2693 json_object
*json
= NULL
;
2695 if (!is_evpn_enabled())
2698 zevpn
= zebra_evpn_lookup(vni
);
2700 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2704 num_neigh
= hashcount(zevpn
->neigh_table
);
2708 num_neigh
= num_dup_detected_neighs(zevpn
);
2713 json
= json_object_new_object();
2715 /* Since we have IPv6 addresses to deal with which can vary widely in
2716 * size, we try to be a bit more elegant in display by first computing
2717 * the maximum width.
2719 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2722 wctx
.addr_width
= 15;
2724 hash_iterate(zevpn
->neigh_table
, zebra_evpn_find_neigh_addr_width
,
2729 "Number of ARPs (local and remote) known for this VNI: %u\n",
2731 vty_out(vty
, "%*s %-6s %-8s %-17s %-30s\n",
2732 -wctx
.addr_width
, "IP", "Type",
2733 "State", "MAC", "Remote ES/VTEP");
2735 json_object_int_add(json
, "numArpNd", num_neigh
);
2737 hash_iterate(zevpn
->neigh_table
, zebra_evpn_print_dad_neigh_hash
,
2741 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2742 json
, JSON_C_TO_STRING_PRETTY
));
2743 json_object_free(json
);
2748 * Display MACs for a VNI (VTY command handler).
2750 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2751 vni_t vni
, bool use_json
)
2753 zebra_evpn_t
*zevpn
;
2755 struct mac_walk_ctx wctx
;
2756 json_object
*json
= NULL
;
2757 json_object
*json_mac
= NULL
;
2759 if (!is_evpn_enabled())
2761 zevpn
= zebra_evpn_lookup(vni
);
2764 vty_out(vty
, "{}\n");
2766 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2769 num_macs
= num_valid_macs(zevpn
);
2774 json
= json_object_new_object();
2775 json_mac
= json_object_new_object();
2778 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2781 wctx
.json
= json_mac
;
2785 "Number of MACs (local and remote) known for this VNI: %u\n",
2788 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
2789 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
2790 "Type", "Flags", "Intf/Remote ES/VTEP",
2793 json_object_int_add(json
, "numMacs", num_macs
);
2795 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, &wctx
);
2798 json_object_object_add(json
, "macs", json_mac
);
2799 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2800 json
, JSON_C_TO_STRING_PRETTY
));
2801 json_object_free(json
);
2806 * Display MACs for all VNIs (VTY command handler).
2808 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2809 bool print_dup
, bool use_json
)
2811 struct mac_walk_ctx wctx
;
2812 json_object
*json
= NULL
;
2814 if (!is_evpn_enabled()) {
2816 vty_out(vty
, "{}\n");
2820 json
= json_object_new_object();
2822 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2825 wctx
.print_dup
= print_dup
;
2826 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
2829 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2830 json
, JSON_C_TO_STRING_PRETTY
));
2831 json_object_free(json
);
2836 * Display MACs in detail for all VNIs (VTY command handler).
2838 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
2839 struct zebra_vrf
*zvrf
,
2840 bool print_dup
, bool use_json
)
2842 struct mac_walk_ctx wctx
;
2843 json_object
*json
= NULL
;
2845 if (!is_evpn_enabled()) {
2847 vty_out(vty
, "{}\n");
2851 json
= json_object_new_object();
2853 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2856 wctx
.print_dup
= print_dup
;
2857 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn_detail
,
2861 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2862 json
, JSON_C_TO_STRING_PRETTY
));
2863 json_object_free(json
);
2868 * Display MACs for all VNIs (VTY command handler).
2870 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
2871 struct zebra_vrf
*zvrf
,
2872 struct in_addr vtep_ip
, bool use_json
)
2874 struct mac_walk_ctx wctx
;
2875 json_object
*json
= NULL
;
2877 if (!is_evpn_enabled())
2881 json
= json_object_new_object();
2883 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2885 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
2886 wctx
.r_vtep_ip
= vtep_ip
;
2888 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
2891 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2892 json
, JSON_C_TO_STRING_PRETTY
));
2893 json_object_free(json
);
2898 * Display specific MAC for a VNI, if present (VTY command handler).
2900 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
2901 vni_t vni
, struct ethaddr
*macaddr
,
2904 zebra_evpn_t
*zevpn
;
2906 json_object
*json
= NULL
;
2908 if (!is_evpn_enabled())
2911 zevpn
= zebra_evpn_lookup(vni
);
2914 vty_out(vty
, "{}\n");
2916 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2919 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
2922 vty_out(vty
, "{}\n");
2925 "%% Requested MAC does not exist in VNI %u\n",
2931 json
= json_object_new_object();
2933 zebra_evpn_print_mac(mac
, vty
, json
);
2935 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2936 json
, JSON_C_TO_STRING_PRETTY
));
2937 json_object_free(json
);
2941 /* Print Duplicate MACs per VNI */
2942 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
2943 struct zebra_vrf
*zvrf
,
2944 vni_t vni
, bool use_json
)
2946 zebra_evpn_t
*zevpn
;
2947 struct mac_walk_ctx wctx
;
2949 json_object
*json
= NULL
;
2950 json_object
*json_mac
= NULL
;
2952 if (!is_evpn_enabled())
2955 zevpn
= zebra_evpn_lookup(vni
);
2957 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
2961 num_macs
= num_valid_macs(zevpn
);
2965 num_macs
= num_dup_detected_macs(zevpn
);
2970 json
= json_object_new_object();
2971 json_mac
= json_object_new_object();
2974 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
2977 wctx
.json
= json_mac
;
2981 "Number of MACs (local and remote) known for this VNI: %u\n",
2983 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
2984 "Flags", "Intf/Remote ES/VTEP", "VLAN");
2986 json_object_int_add(json
, "numMacs", num_macs
);
2988 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_dad_mac_hash
, &wctx
);
2991 json_object_object_add(json
, "macs", json_mac
);
2992 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2993 json
, JSON_C_TO_STRING_PRETTY
));
2994 json_object_free(json
);
2999 int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf
*zvrf
, vni_t vni
,
3000 struct ethaddr
*macaddr
, char *errmsg
,
3003 zebra_evpn_t
*zevpn
;
3005 struct listnode
*node
= NULL
;
3006 zebra_neigh_t
*nbr
= NULL
;
3008 if (!is_evpn_enabled())
3011 zevpn
= zebra_evpn_lookup(vni
);
3013 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist", vni
);
3017 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3019 snprintf(errmsg
, errmsg_len
,
3020 "Requested MAC does not exist in VNI %u\n", vni
);
3024 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3025 snprintfrr(errmsg
, errmsg_len
,
3026 "Requested MAC is not duplicate detected\n");
3030 /* Remove all IPs as duplicate associcated with this MAC */
3031 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3032 /* For local neigh mark inactive so MACIP update is generated
3033 * to BGP. This is a scenario where MAC update received
3034 * and detected as duplicate which marked neigh as duplicate.
3035 * Later local neigh update did not get a chance to relay
3036 * to BGP. Similarly remote macip update, neigh needs to be
3037 * installed locally.
3039 if (zvrf
->dad_freeze
&&
3040 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3041 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
3042 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3043 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
3044 zebra_evpn_rem_neigh_install(
3045 zevpn
, nbr
, false /*was_static*/);
3048 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3050 nbr
->detect_start_time
.tv_sec
= 0;
3051 nbr
->dad_dup_detect_time
= 0;
3054 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3056 mac
->detect_start_time
.tv_sec
= 0;
3057 mac
->detect_start_time
.tv_usec
= 0;
3058 mac
->dad_dup_detect_time
= 0;
3059 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3061 /* warn-only action return */
3062 if (!zvrf
->dad_freeze
)
3065 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3066 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3068 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3069 mac
->flags
, mac
->loc_seq
,
3073 /* Process all neighbors associated with this MAC. */
3074 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3077 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3078 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3080 /* Install the entry. */
3081 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3087 int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf
*zvrf
, vni_t vni
,
3088 struct ipaddr
*ip
, char *errmsg
,
3091 zebra_evpn_t
*zevpn
;
3094 char buf
[INET6_ADDRSTRLEN
];
3095 char buf2
[ETHER_ADDR_STRLEN
];
3097 if (!is_evpn_enabled())
3100 zevpn
= zebra_evpn_lookup(vni
);
3102 snprintfrr(errmsg
, errmsg_len
, "VNI %u does not exist\n", vni
);
3106 nbr
= zebra_evpn_neigh_lookup(zevpn
, ip
);
3108 snprintfrr(errmsg
, errmsg_len
,
3109 "Requested host IP does not exist in VNI %u\n", vni
);
3113 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
3115 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
3116 snprintfrr(errmsg
, errmsg_len
,
3117 "Requested host IP %s is not duplicate detected\n",
3122 mac
= zebra_evpn_mac_lookup(zevpn
, &nbr
->emac
);
3124 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
3127 "Requested IP's associated MAC %s is still in duplicate state\n",
3128 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
3132 if (IS_ZEBRA_DEBUG_VXLAN
)
3133 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
3134 __func__
, buf
, nbr
->flags
, nbr
->loc_seq
);
3136 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3138 nbr
->detect_start_time
.tv_sec
= 0;
3139 nbr
->detect_start_time
.tv_usec
= 0;
3140 nbr
->dad_dup_detect_time
= 0;
3141 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
3143 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3144 zebra_evpn_neigh_send_add_to_client(zevpn
->vni
, ip
, &nbr
->emac
,
3145 nbr
->mac
, nbr
->flags
,
3147 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3148 zebra_evpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
3154 static void zevpn_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3156 struct mac_walk_ctx
*wctx
= ctxt
;
3158 zebra_evpn_t
*zevpn
;
3159 struct listnode
*node
= NULL
;
3160 zebra_neigh_t
*nbr
= NULL
;
3162 mac
= (zebra_mac_t
*)bucket
->data
;
3166 zevpn
= wctx
->zevpn
;
3168 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
3171 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
3173 mac
->detect_start_time
.tv_sec
= 0;
3174 mac
->detect_start_time
.tv_usec
= 0;
3175 mac
->dad_dup_detect_time
= 0;
3176 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3178 /* Remove all IPs as duplicate associcated with this MAC */
3179 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
3180 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
3182 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
3184 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
3186 nbr
->detect_start_time
.tv_sec
= 0;
3187 nbr
->dad_dup_detect_time
= 0;
3190 /* Local: Notify Peer VTEPs, Remote: Install the entry */
3191 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
3193 if (zebra_evpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
3194 mac
->flags
, mac
->loc_seq
,
3198 /* Process all neighbors associated with this MAC. */
3199 zebra_evpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
3202 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
3203 zebra_evpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
3205 /* Install the entry. */
3206 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
3210 static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
3213 zebra_evpn_t
*zevpn
;
3214 struct zebra_vrf
*zvrf
;
3215 struct mac_walk_ctx m_wctx
;
3216 struct neigh_walk_ctx n_wctx
;
3218 zevpn
= (zebra_evpn_t
*)bucket
->data
;
3222 zvrf
= (struct zebra_vrf
*)args
[0];
3224 if (hashcount(zevpn
->neigh_table
)) {
3225 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
3226 n_wctx
.zevpn
= zevpn
;
3228 hash_iterate(zevpn
->neigh_table
,
3229 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3232 if (num_valid_macs(zevpn
)) {
3233 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
3234 m_wctx
.zevpn
= zevpn
;
3236 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3241 int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf
*zvrf
)
3245 if (!is_evpn_enabled())
3250 hash_iterate(zvrf
->evpn_table
,
3251 (void (*)(struct hash_bucket
*, void *))
3252 zevpn_clear_dup_detect_hash_vni_all
, args
);
3257 int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf
*zvrf
, vni_t vni
)
3259 zebra_evpn_t
*zevpn
;
3260 struct mac_walk_ctx m_wctx
;
3261 struct neigh_walk_ctx n_wctx
;
3263 if (!is_evpn_enabled())
3266 zevpn
= zebra_evpn_lookup(vni
);
3268 zlog_warn("VNI %u does not exist\n", vni
);
3272 if (hashcount(zevpn
->neigh_table
)) {
3273 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
3274 n_wctx
.zevpn
= zevpn
;
3276 hash_iterate(zevpn
->neigh_table
,
3277 zebra_evpn_clear_dup_neigh_hash
, &n_wctx
);
3280 if (num_valid_macs(zevpn
)) {
3281 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
3282 m_wctx
.zevpn
= zevpn
;
3284 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
3291 * Display MACs for a VNI from specific VTEP (VTY command handler).
3293 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3294 vni_t vni
, struct in_addr vtep_ip
,
3297 zebra_evpn_t
*zevpn
;
3299 struct mac_walk_ctx wctx
;
3300 json_object
*json
= NULL
;
3301 json_object
*json_mac
= NULL
;
3303 if (!is_evpn_enabled())
3305 zevpn
= zebra_evpn_lookup(vni
);
3308 vty_out(vty
, "{}\n");
3310 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3313 num_macs
= num_valid_macs(zevpn
);
3318 json
= json_object_new_object();
3319 json_mac
= json_object_new_object();
3322 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3325 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
3326 wctx
.r_vtep_ip
= vtep_ip
;
3327 wctx
.json
= json_mac
;
3328 hash_iterate(zevpn
->mac_table
, zebra_evpn_print_mac_hash
, &wctx
);
3331 json_object_int_add(json
, "numMacs", wctx
.count
);
3333 json_object_object_add(json
, "macs", json_mac
);
3334 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3335 json
, JSON_C_TO_STRING_PRETTY
));
3336 json_object_free(json
);
3342 * Display VNI information (VTY command handler).
3344 * use_json flag indicates that output should be in JSON format.
3345 * json_array is non NULL when JSON output needs to be aggregated (by the
3346 * caller) and then printed, otherwise, JSON evpn vni info is printed
3349 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
3350 bool use_json
, json_object
*json_array
)
3352 json_object
*json
= NULL
;
3354 zebra_l3vni_t
*zl3vni
= NULL
;
3355 zebra_evpn_t
*zevpn
= NULL
;
3357 if (!is_evpn_enabled())
3361 json
= json_object_new_object();
3366 zl3vni
= zl3vni_lookup(vni
);
3368 zl3vni_print(zl3vni
, (void *)args
);
3370 zevpn
= zebra_evpn_lookup(vni
);
3372 zebra_evpn_print(zevpn
, (void *)args
);
3374 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
3379 * Each "json" object contains info about 1 VNI.
3380 * When "json_array" is non-null, we aggreggate the json output
3381 * into json_array and print it as a JSON array.
3384 json_object_array_add(json_array
, json
);
3386 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3387 json
, JSON_C_TO_STRING_PRETTY
));
3388 json_object_free(json
);
3393 /* Display all global details for EVPN */
3394 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
3399 json_object
*json
= NULL
;
3400 struct zebra_vrf
*zvrf
= NULL
;
3402 if (!is_evpn_enabled())
3405 zvrf
= zebra_vrf_get_evpn();
3409 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
3410 num_l2vnis
= hashcount(zvrf
->evpn_table
);
3411 num_vnis
= num_l2vnis
+ num_l3vnis
;
3414 json
= json_object_new_object();
3415 json_object_string_add(json
, "advertiseGatewayMacip",
3416 zvrf
->advertise_gw_macip
? "Yes" : "No");
3417 json_object_int_add(json
, "numVnis", num_vnis
);
3418 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3419 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3420 if (zvrf
->dup_addr_detect
)
3421 json_object_boolean_true_add(json
,
3422 "isDuplicateAddrDetection");
3424 json_object_boolean_false_add(json
,
3425 "isDuplicateAddrDetection");
3426 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
3427 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
3428 json_object_int_add(json
, "detectionFreezeTime",
3429 zvrf
->dad_freeze_time
);
3432 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
3433 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
3434 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
3435 zvrf
->advertise_gw_macip
? "Yes" : "No");
3436 vty_out(vty
, "Advertise svi mac-ip: %s\n",
3437 zvrf
->advertise_svi_macip
? "Yes" : "No");
3438 vty_out(vty
, "Duplicate address detection: %s\n",
3439 zvrf
->dup_addr_detect
? "Enable" : "Disable");
3440 vty_out(vty
, " Detection max-moves %u, time %d\n",
3441 zvrf
->dad_max_moves
, zvrf
->dad_time
);
3442 if (zvrf
->dad_freeze
) {
3443 if (zvrf
->dad_freeze_time
)
3444 vty_out(vty
, " Detection freeze %u\n",
3445 zvrf
->dad_freeze_time
);
3447 vty_out(vty
, " Detection freeze %s\n",
3453 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3454 json
, JSON_C_TO_STRING_PRETTY
));
3455 json_object_free(json
);
3460 * Display VNI hash table (VTY command handler).
3462 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3465 json_object
*json
= NULL
;
3468 if (!is_evpn_enabled())
3472 json
= json_object_new_object();
3474 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
3475 "Type", "VxLAN IF", "# MACs", "# ARPs",
3476 "# Remote VTEPs", "Tenant VRF");
3481 /* Display all L2-VNIs */
3484 (void (*)(struct hash_bucket
*, void *))zebra_evpn_print_hash
,
3487 /* Display all L3-VNIs */
3488 hash_iterate(zrouter
.l3vni_table
,
3489 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
3493 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3494 json
, JSON_C_TO_STRING_PRETTY
));
3495 json_object_free(json
);
3499 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
3503 uint32_t max_moves
= 0;
3504 uint32_t freeze_time
= 0;
3505 bool dup_addr_detect
= false;
3506 bool freeze
= false;
3509 STREAM_GETL(s
, dup_addr_detect
);
3510 STREAM_GETL(s
, time
);
3511 STREAM_GETL(s
, max_moves
);
3512 STREAM_GETL(s
, freeze
);
3513 STREAM_GETL(s
, freeze_time
);
3515 /* DAD previous state was enabled, and new state is disable,
3516 * clear all duplicate detected addresses.
3518 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
3519 zebra_vxlan_clear_dup_detect_vni_all(zvrf
);
3521 zvrf
->dup_addr_detect
= dup_addr_detect
;
3522 zvrf
->dad_time
= time
;
3523 zvrf
->dad_max_moves
= max_moves
;
3524 zvrf
->dad_freeze
= freeze
;
3525 zvrf
->dad_freeze_time
= freeze_time
;
3527 if (IS_ZEBRA_DEBUG_VXLAN
)
3529 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
3530 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
3531 zvrf
->dup_addr_detect
? "enable" : "disable",
3532 zvrf
->dad_max_moves
,
3534 zvrf
->dad_freeze
? "enable" : "disable",
3535 zvrf
->dad_freeze_time
);
3542 * Display VNI hash table in detail(VTY command handler).
3544 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
3547 json_object
*json_array
= NULL
;
3548 struct zebra_ns
*zns
= NULL
;
3549 struct zebra_evpn_show zes
;
3551 if (!is_evpn_enabled())
3554 zns
= zebra_ns_lookup(NS_DEFAULT
);
3559 json_array
= json_object_new_array();
3562 zes
.json
= json_array
;
3564 zes
.use_json
= use_json
;
3566 /* Display all L2-VNIs */
3567 hash_iterate(zvrf
->evpn_table
,
3568 (void (*)(struct hash_bucket
*,
3569 void *))zebra_evpn_print_hash_detail
,
3572 /* Display all L3-VNIs */
3573 hash_iterate(zrouter
.l3vni_table
,
3574 (void (*)(struct hash_bucket
*,
3575 void *))zl3vni_print_hash_detail
,
3579 vty_out(vty
, "%s\n",
3580 json_object_to_json_string_ext(
3581 json_array
, JSON_C_TO_STRING_PRETTY
));
3582 json_object_free(json_array
);
3587 * Handle neighbor delete notification from the kernel (on a VLAN device
3588 * / L3 interface). This may result in either the neighbor getting deleted
3589 * from our database or being re-added to the kernel (if it is a valid
3592 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
3593 struct interface
*link_if
,
3596 char buf
[INET6_ADDRSTRLEN
];
3597 zebra_evpn_t
*zevpn
= NULL
;
3598 zebra_l3vni_t
*zl3vni
= NULL
;
3600 /* check if this is a remote neigh entry corresponding to remote
3603 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
3605 return zl3vni_local_nh_del(zl3vni
, ip
);
3607 /* We are only interested in neighbors on an SVI that resides on top
3608 * of a VxLAN bridge.
3610 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
3612 if (IS_ZEBRA_DEBUG_VXLAN
)
3614 "%s: Del neighbor %s EVPN is not present for interface %s",
3615 __func__
, ipaddr2str(ip
, buf
, sizeof(buf
)),
3620 if (!zevpn
->vxlan_if
) {
3622 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
3627 if (IS_ZEBRA_DEBUG_VXLAN
)
3628 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
3629 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
3630 ifp
->ifindex
, zevpn
->vni
);
3632 return zebra_evpn_neigh_del_ip(zevpn
, ip
);
3636 * Handle neighbor add or update notification from the kernel (on a VLAN
3637 * device / L3 interface). This is typically for a local neighbor but can
3638 * also be for a remote neighbor (e.g., ageout notification). It could
3639 * also be a "move" scenario.
3641 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
3642 struct interface
*link_if
,
3644 struct ethaddr
*macaddr
,
3648 bool local_inactive
, bool dp_static
)
3650 char buf
[ETHER_ADDR_STRLEN
];
3651 char buf2
[INET6_ADDRSTRLEN
];
3652 zebra_evpn_t
*zevpn
= NULL
;
3653 zebra_l3vni_t
*zl3vni
= NULL
;
3655 /* check if this is a remote neigh entry corresponding to remote
3658 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
3660 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
3662 /* We are only interested in neighbors on an SVI that resides on top
3663 * of a VxLAN bridge.
3665 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
3669 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
3671 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s%s%s-> L2-VNI %u",
3672 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3673 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
3674 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
3675 is_router
? "router " : "",
3676 local_inactive
? "local_inactive " : "",
3679 /* Is this about a local neighbor or a remote one? */
3681 return zebra_evpn_local_neigh_update(zevpn
, ifp
, ip
, macaddr
,
3682 is_router
, local_inactive
,
3685 return zebra_evpn_remote_neigh_update(zevpn
, ifp
, ip
, macaddr
, state
);
3689 zebra_vxlan_remote_macip_helper(bool add
, struct stream
*s
, vni_t
*vni
,
3690 struct ethaddr
*macaddr
, uint16_t *ipa_len
,
3691 struct ipaddr
*ip
, struct in_addr
*vtep_ip
,
3692 uint8_t *flags
, uint32_t *seq
, esi_t
*esi
)
3697 * Obtain each remote MACIP and process.
3698 * Message contains VNI, followed by MAC followed by IP (if any)
3699 * followed by remote VTEP IP.
3701 memset(ip
, 0, sizeof(*ip
));
3702 STREAM_GETL(s
, *vni
);
3703 STREAM_GET(macaddr
->octet
, s
, ETH_ALEN
);
3704 STREAM_GETL(s
, *ipa_len
);
3707 if (*ipa_len
== IPV4_MAX_BYTELEN
)
3708 ip
->ipa_type
= IPADDR_V4
;
3709 else if (*ipa_len
== IPV6_MAX_BYTELEN
)
3710 ip
->ipa_type
= IPADDR_V6
;
3712 if (IS_ZEBRA_DEBUG_VXLAN
)
3714 "ipa_len *must* be %d or %d bytes in length not %d",
3715 IPV4_MAX_BYTELEN
, IPV6_MAX_BYTELEN
,
3717 goto stream_failure
;
3720 STREAM_GET(&ip
->ip
.addr
, s
, *ipa_len
);
3722 l
+= 4 + ETH_ALEN
+ 4 + *ipa_len
;
3723 STREAM_GET(&vtep_ip
->s_addr
, s
, IPV4_MAX_BYTELEN
);
3724 l
+= IPV4_MAX_BYTELEN
;
3727 STREAM_GETC(s
, *flags
);
3728 STREAM_GETL(s
, *seq
);
3730 STREAM_GET(esi
, s
, sizeof(esi_t
));
3741 * Handle message from client to delete a remote MACIP for a VNI.
3743 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
3747 struct ethaddr macaddr
;
3749 struct in_addr vtep_ip
;
3750 uint16_t l
= 0, ipa_len
;
3751 char buf
[ETHER_ADDR_STRLEN
];
3752 char buf1
[INET6_ADDRSTRLEN
];
3754 memset(&macaddr
, 0, sizeof(struct ethaddr
));
3755 memset(&ip
, 0, sizeof(struct ipaddr
));
3756 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
3760 while (l
< hdr
->length
) {
3761 int res_length
= zebra_vxlan_remote_macip_helper(
3762 false, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
, NULL
,
3765 if (res_length
== -1)
3766 goto stream_failure
;
3769 if (IS_ZEBRA_DEBUG_VXLAN
)
3771 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %pI4 from %s",
3773 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
3774 ipa_len
? " IP " : "",
3776 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
3777 &vtep_ip
, zebra_route_string(client
->proto
));
3779 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
3787 * Handle message from client to add a remote MACIP for a VNI. This
3788 * could be just the add of a MAC address or the add of a neighbor
3791 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
3795 struct ethaddr macaddr
;
3797 struct in_addr vtep_ip
;
3798 uint16_t l
= 0, ipa_len
;
3801 char buf
[ETHER_ADDR_STRLEN
];
3802 char buf1
[INET6_ADDRSTRLEN
];
3804 char esi_buf
[ESI_STR_LEN
];
3806 memset(&macaddr
, 0, sizeof(struct ethaddr
));
3807 memset(&ip
, 0, sizeof(struct ipaddr
));
3808 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
3810 if (!EVPN_ENABLED(zvrf
)) {
3811 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
3817 while (l
< hdr
->length
) {
3818 int res_length
= zebra_vxlan_remote_macip_helper(
3819 true, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
,
3820 &flags
, &seq
, &esi
);
3822 if (res_length
== -1)
3823 goto stream_failure
;
3826 if (IS_ZEBRA_DEBUG_VXLAN
) {
3827 if (memcmp(&esi
, zero_esi
, sizeof(esi_t
)))
3828 esi_to_str(&esi
, esi_buf
, sizeof(esi_buf
));
3830 strlcpy(esi_buf
, "-", ESI_STR_LEN
);
3832 "Recv %sMACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
3833 (flags
& ZEBRA_MACIP_TYPE_SYNC_PATH
) ?
3836 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
3837 ipa_len
? " IP " : "",
3839 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
3840 flags
, seq
, &vtep_ip
, esi_buf
,
3841 zebra_route_string(client
->proto
));
3844 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
3845 flags
, seq
, vtep_ip
, &esi
);
3853 * Handle remote vtep delete by kernel; re-add the vtep if we have it
3855 int zebra_vxlan_check_readd_vtep(struct interface
*ifp
,
3856 struct in_addr vtep_ip
)
3858 struct zebra_if
*zif
;
3859 struct zebra_vrf
*zvrf
= NULL
;
3860 struct zebra_l2info_vxlan
*vxl
;
3862 zebra_evpn_t
*zevpn
= NULL
;
3863 zebra_vtep_t
*zvtep
= NULL
;
3867 vxl
= &zif
->l2info
.vxl
;
3870 /* If EVPN is not enabled, nothing to do. */
3871 if (!is_evpn_enabled())
3874 /* Locate VRF corresponding to interface. */
3875 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
3879 /* Locate hash entry; it is expected to exist. */
3880 zevpn
= zebra_evpn_lookup(vni
);
3884 /* If the remote vtep entry doesn't exists nothing to do */
3885 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
3889 if (IS_ZEBRA_DEBUG_VXLAN
)
3891 "Del MAC for remote VTEP %pI4 intf %s(%u) VNI %u - readd",
3892 &vtep_ip
, ifp
->name
, ifp
->ifindex
, vni
);
3894 zebra_evpn_vtep_install(zevpn
, zvtep
);
3899 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
3900 * us, this must involve a multihoming scenario. Treat this as implicit delete
3901 * of any prior local MAC.
3903 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
3904 struct interface
*br_if
,
3905 struct ethaddr
*macaddr
, vlanid_t vid
)
3907 struct zebra_if
*zif
;
3908 struct zebra_l2info_vxlan
*vxl
;
3910 zebra_evpn_t
*zevpn
;
3912 char buf
[ETHER_ADDR_STRLEN
];
3916 vxl
= &zif
->l2info
.vxl
;
3919 /* Check if EVPN is enabled. */
3920 if (!is_evpn_enabled())
3923 /* Locate hash entry; it is expected to exist. */
3924 zevpn
= zebra_evpn_lookup(vni
);
3928 /* If entry doesn't exist, nothing to do. */
3929 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
3933 /* Is it a local entry? */
3934 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
3937 if (IS_ZEBRA_DEBUG_VXLAN
)
3939 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
3940 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
3941 ifp
->ifindex
, vni
, mac
->flags
);
3943 /* Remove MAC from BGP. */
3944 zebra_evpn_mac_send_del_to_client(zevpn
->vni
, macaddr
, mac
->flags
,
3948 * If there are no neigh associated with the mac delete the mac
3949 * else mark it as AUTO for forward reference
3951 if (!listcount(mac
->neigh_list
)) {
3952 zebra_evpn_mac_del(zevpn
, mac
);
3954 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
3955 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
3956 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
3963 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
3964 * This can happen because the remote MAC entries are also added as "dynamic",
3965 * so the kernel can ageout the entry.
3967 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
3968 struct interface
*br_if
,
3969 struct ethaddr
*macaddr
, vlanid_t vid
)
3971 struct zebra_if
*zif
= NULL
;
3972 struct zebra_l2info_vxlan
*vxl
= NULL
;
3974 zebra_evpn_t
*zevpn
= NULL
;
3975 zebra_l3vni_t
*zl3vni
= NULL
;
3976 zebra_mac_t
*mac
= NULL
;
3977 char buf
[ETHER_ADDR_STRLEN
];
3981 vxl
= &zif
->l2info
.vxl
;
3984 /* Check if EVPN is enabled. */
3985 if (!is_evpn_enabled())
3988 /* check if this is a remote RMAC and readd simillar to remote macs */
3989 zl3vni
= zl3vni_lookup(vni
);
3991 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
3993 /* Locate hash entry; it is expected to exist. */
3994 zevpn
= zebra_evpn_lookup(vni
);
3998 /* If entry doesn't exist, nothing to do. */
3999 mac
= zebra_evpn_mac_lookup(zevpn
, macaddr
);
4003 /* Is it a remote entry? */
4004 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
4007 if (IS_ZEBRA_DEBUG_VXLAN
)
4008 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
4009 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
4012 zebra_evpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
4017 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
4019 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
4020 struct ethaddr
*macaddr
, vlanid_t vid
)
4022 zebra_evpn_t
*zevpn
;
4024 /* We are interested in MACs only on ports or (port, VLAN) that
4027 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4030 if (!zevpn
->vxlan_if
) {
4032 "VNI %u hash %p doesn't have intf upon local MAC DEL",
4037 return zebra_evpn_del_local_mac(zevpn
, macaddr
, ifp
);
4041 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
4043 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
4044 struct interface
*br_if
,
4045 struct ethaddr
*macaddr
, vlanid_t vid
,
4046 bool sticky
, bool local_inactive
,
4049 zebra_evpn_t
*zevpn
;
4050 struct zebra_vrf
*zvrf
;
4051 char buf
[ETHER_ADDR_STRLEN
];
4055 /* We are interested in MACs only on ports or (port, VLAN) that
4058 zevpn
= zebra_evpn_map_vlan(ifp
, br_if
, vid
);
4060 if (IS_ZEBRA_DEBUG_VXLAN
)
4062 " Add/Update %sMAC %s intf %s(%u) VID %u, could not find EVPN",
4063 sticky
? "sticky " : "",
4064 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4065 ifp
->name
, ifp
->ifindex
, vid
);
4069 if (!zevpn
->vxlan_if
) {
4070 if (IS_ZEBRA_DEBUG_VXLAN
)
4072 " VNI %u hash %p doesn't have intf upon local MAC ADD",
4077 zvrf
= zebra_vrf_get_evpn();
4079 if (IS_ZEBRA_DEBUG_VXLAN
)
4080 zlog_debug(" No Evpn Global Vrf found");
4084 return zebra_evpn_add_update_local_mac(zvrf
, zevpn
, ifp
, macaddr
, vid
,
4085 sticky
, local_inactive
,
4090 * Handle message from client to delete a remote VTEP for an EVPN.
4092 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
4095 unsigned short l
= 0;
4097 struct in_addr vtep_ip
;
4098 zebra_evpn_t
*zevpn
;
4099 zebra_vtep_t
*zvtep
;
4100 struct interface
*ifp
;
4101 struct zebra_if
*zif
;
4103 if (!is_evpn_enabled()) {
4105 "%s: EVPN is not enabled yet we have received a vtep del command",
4110 if (!EVPN_ENABLED(zvrf
)) {
4111 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
4118 while (l
< hdr
->length
) {
4119 int flood_control
__attribute__((unused
));
4121 /* Obtain each remote VTEP and process. */
4122 STREAM_GETL(s
, vni
);
4124 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4125 l
+= IPV4_MAX_BYTELEN
;
4127 /* Flood control is intentionally ignored right now */
4128 STREAM_GETL(s
, flood_control
);
4131 if (IS_ZEBRA_DEBUG_VXLAN
)
4132 zlog_debug("Recv VTEP_DEL %pI4 VNI %u from %s",
4134 zebra_route_string(client
->proto
));
4136 /* Locate VNI hash entry - expected to exist. */
4137 zevpn
= zebra_evpn_lookup(vni
);
4139 if (IS_ZEBRA_DEBUG_VXLAN
)
4141 "Failed to locate VNI hash upon remote VTEP DEL, VNI %u",
4146 ifp
= zevpn
->vxlan_if
;
4149 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
4155 /* If down or not mapped to a bridge, we're done. */
4156 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4159 /* If the remote VTEP does not exist, there's nothing more to
4161 * Otherwise, uninstall any remote MACs pointing to this VTEP
4163 * then, the VTEP entry itself and remove it.
4165 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4169 zebra_evpn_vtep_uninstall(zevpn
, &vtep_ip
);
4170 zebra_evpn_vtep_del(zevpn
, zvtep
);
4178 * Handle message from client to add a remote VTEP for an EVPN.
4180 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
4183 unsigned short l
= 0;
4185 struct in_addr vtep_ip
;
4186 zebra_evpn_t
*zevpn
;
4187 struct interface
*ifp
;
4188 struct zebra_if
*zif
;
4190 zebra_vtep_t
*zvtep
;
4192 if (!is_evpn_enabled()) {
4194 "%s: EVPN not enabled yet we received a vtep_add zapi call",
4199 if (!EVPN_ENABLED(zvrf
)) {
4200 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
4207 while (l
< hdr
->length
) {
4208 /* Obtain each remote VTEP and process. */
4209 STREAM_GETL(s
, vni
);
4211 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
4212 STREAM_GETL(s
, flood_control
);
4213 l
+= IPV4_MAX_BYTELEN
+ 4;
4215 if (IS_ZEBRA_DEBUG_VXLAN
)
4216 zlog_debug("Recv VTEP_ADD %pI4 VNI %u flood %d from %s",
4217 &vtep_ip
, vni
, flood_control
,
4218 zebra_route_string(client
->proto
));
4220 /* Locate VNI hash entry - expected to exist. */
4221 zevpn
= zebra_evpn_lookup(vni
);
4224 EC_ZEBRA_VTEP_ADD_FAILED
,
4225 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
4230 ifp
= zevpn
->vxlan_if
;
4233 EC_ZEBRA_VTEP_ADD_FAILED
,
4234 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
4241 /* If down or not mapped to a bridge, we're done. */
4242 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4245 zvtep
= zebra_evpn_vtep_find(zevpn
, &vtep_ip
);
4247 /* If the remote VTEP already exists check if
4248 * the flood mode has changed
4250 if (zvtep
->flood_control
!= flood_control
) {
4251 if (zvtep
->flood_control
4252 == VXLAN_FLOOD_DISABLED
)
4253 /* old mode was head-end-replication but
4254 * is no longer; get rid of the HER fdb
4255 * entry installed before
4257 zebra_evpn_vtep_uninstall(zevpn
,
4259 zvtep
->flood_control
= flood_control
;
4260 zebra_evpn_vtep_install(zevpn
, zvtep
);
4263 zvtep
= zebra_evpn_vtep_add(zevpn
, &vtep_ip
,
4266 zebra_evpn_vtep_install(zevpn
, zvtep
);
4268 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
4269 "Failed to add remote VTEP, VNI %u zevpn %p",
4279 * Add/Del gateway macip to evpn
4281 * 1. SVI interface on a vlan aware bridge
4282 * 2. SVI interface on a vlan unaware bridge
4283 * 3. vrr interface (MACVLAN) associated to a SVI
4284 * We advertise macip routes for an interface if it is associated to VxLan vlan
4286 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
4290 struct ethaddr macaddr
;
4291 zebra_evpn_t
*zevpn
= NULL
;
4293 memset(&ip
, 0, sizeof(struct ipaddr
));
4294 memset(&macaddr
, 0, sizeof(struct ethaddr
));
4296 /* Check if EVPN is enabled. */
4297 if (!is_evpn_enabled())
4300 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
4301 struct interface
*svi_if
=
4302 NULL
; /* SVI corresponding to the MACVLAN */
4303 struct zebra_if
*ifp_zif
=
4304 NULL
; /* Zebra daemon specific info for MACVLAN */
4305 struct zebra_if
*svi_if_zif
=
4306 NULL
; /* Zebra daemon specific info for SVI*/
4308 ifp_zif
= ifp
->info
;
4313 * for a MACVLAN interface the link represents the svi_if
4315 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4316 ifp_zif
->link_ifindex
);
4318 zlog_debug("MACVLAN %s(%u) without link information",
4319 ifp
->name
, ifp
->ifindex
);
4323 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
4325 * If it is a vlan aware bridge then the link gives the
4326 * bridge information
4328 struct interface
*svi_if_link
= NULL
;
4330 svi_if_zif
= svi_if
->info
;
4332 svi_if_link
= if_lookup_by_index_per_ns(
4333 zebra_ns_lookup(NS_DEFAULT
),
4334 svi_if_zif
->link_ifindex
);
4335 zevpn
= zebra_evpn_from_svi(svi_if
,
4338 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
4340 * If it is a vlan unaware bridge then svi is the bridge
4343 zevpn
= zebra_evpn_from_svi(svi_if
, svi_if
);
4345 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
4346 struct zebra_if
*svi_if_zif
=
4347 NULL
; /* Zebra daemon specific info for SVI */
4348 struct interface
*svi_if_link
=
4349 NULL
; /* link info for the SVI = bridge info */
4351 svi_if_zif
= ifp
->info
;
4353 svi_if_link
= if_lookup_by_index_per_ns(
4354 zebra_ns_lookup(NS_DEFAULT
),
4355 svi_if_zif
->link_ifindex
);
4357 zevpn
= zebra_evpn_from_svi(ifp
, svi_if_link
);
4359 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
4360 zevpn
= zebra_evpn_from_svi(ifp
, ifp
);
4366 if (!zevpn
->vxlan_if
) {
4367 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
4373 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
4375 if (p
->family
== AF_INET
) {
4376 ip
.ipa_type
= IPADDR_V4
;
4377 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
4378 sizeof(struct in_addr
));
4379 } else if (p
->family
== AF_INET6
) {
4380 ip
.ipa_type
= IPADDR_V6
;
4381 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
4382 sizeof(struct in6_addr
));
4387 zebra_evpn_gw_macip_add(ifp
, zevpn
, &macaddr
, &ip
);
4389 zebra_evpn_gw_macip_del(ifp
, zevpn
, &ip
);
4395 * Handle SVI interface going down.
4396 * SVI can be associated to either L3-VNI or L2-VNI.
4397 * For L2-VNI: At this point, this is a NOP since
4398 * the kernel deletes the neighbor entries on this SVI (if any).
4399 * We only need to update the vrf corresponding to zevpn.
4400 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
4403 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
4405 zebra_l3vni_t
*zl3vni
= NULL
;
4407 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4410 /* process l3-vni down */
4411 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4413 /* remove association with svi-if */
4414 zl3vni
->svi_if
= NULL
;
4416 zebra_evpn_t
*zevpn
= NULL
;
4418 /* since we dont have svi corresponding to zevpn, we associate it
4419 * to default vrf. Note: the corresponding neigh entries on the
4420 * SVI would have already been deleted */
4421 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4423 zevpn
->vrf_id
= VRF_DEFAULT
;
4425 /* update the tenant vrf in BGP */
4426 zebra_evpn_send_add_to_client(zevpn
);
4433 * Handle SVI interface coming up.
4434 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
4436 * For L2-VNI: we need to install any remote neighbors entried (used for
4438 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
4440 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
4442 zebra_evpn_t
*zevpn
= NULL
;
4443 zebra_l3vni_t
*zl3vni
= NULL
;
4445 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
4448 /* associate with svi */
4449 zl3vni
->svi_if
= ifp
;
4451 /* process oper-up */
4452 if (is_l3vni_oper_up(zl3vni
))
4453 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4456 /* process SVI up for l2-vni */
4457 struct neigh_walk_ctx n_wctx
;
4459 zevpn
= zebra_evpn_from_svi(ifp
, link_if
);
4463 if (!zevpn
->vxlan_if
) {
4465 "VNI %u hash %p doesn't have intf upon SVI up",
4470 if (IS_ZEBRA_DEBUG_VXLAN
)
4472 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
4473 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
4474 vrf_id_to_name(ifp
->vrf_id
));
4476 /* update the vrf information for l2-vni and inform bgp */
4477 zevpn
->vrf_id
= ifp
->vrf_id
;
4478 zebra_evpn_send_add_to_client(zevpn
);
4480 /* Install any remote neighbors for this VNI. */
4481 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
4482 n_wctx
.zevpn
= zevpn
;
4483 hash_iterate(zevpn
->neigh_table
, zebra_evpn_install_neigh_hash
,
4491 * Handle MAC-VLAN interface going down.
4492 * L3VNI: When MAC-VLAN interface goes down,
4493 * find its associated SVI and update type2/type-5 routes
4496 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
4498 zebra_l3vni_t
*zl3vni
= NULL
;
4499 struct zebra_if
*zif
, *link_zif
;
4500 struct interface
*link_ifp
, *link_if
;
4504 link_ifp
= zif
->link
;
4506 if (IS_ZEBRA_DEBUG_VXLAN
) {
4507 struct interface
*ifp
;
4509 ifp
= if_lookup_by_index_all_vrf(zif
->link_ifindex
);
4510 zlog_debug("macvlan parent link is not found. Parent index %d ifp %s",
4511 zif
->link_ifindex
, ifp
? ifp
->name
: " ");
4515 link_zif
= link_ifp
->info
;
4518 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4519 link_zif
->link_ifindex
);
4521 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
4523 zl3vni
->mac_vlan_if
= NULL
;
4524 if (is_l3vni_oper_up(zl3vni
))
4525 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4530 * Handle MAC-VLAN interface going up.
4531 * L3VNI: When MAC-VLAN interface comes up,
4532 * find its associated SVI and update type-2 routes
4533 * with MAC-VLAN's MAC as RMAC and for type-5 routes
4534 * use SVI's MAC as RMAC.
4536 void zebra_vxlan_macvlan_up(struct interface
*ifp
)
4538 zebra_l3vni_t
*zl3vni
= NULL
;
4539 struct zebra_if
*zif
, *link_zif
;
4540 struct interface
*link_ifp
, *link_if
;
4544 link_ifp
= zif
->link
;
4545 link_zif
= link_ifp
->info
;
4548 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
4549 link_zif
->link_ifindex
);
4550 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
4552 /* associate with macvlan (VRR) interface */
4553 zl3vni
->mac_vlan_if
= ifp
;
4555 /* process oper-up */
4556 if (is_l3vni_oper_up(zl3vni
))
4557 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4562 * Handle VxLAN interface down
4564 int zebra_vxlan_if_down(struct interface
*ifp
)
4567 struct zebra_if
*zif
= NULL
;
4568 struct zebra_l2info_vxlan
*vxl
= NULL
;
4569 zebra_l3vni_t
*zl3vni
= NULL
;
4570 zebra_evpn_t
*zevpn
;
4572 /* Check if EVPN is enabled. */
4573 if (!is_evpn_enabled())
4578 vxl
= &zif
->l2info
.vxl
;
4581 zl3vni
= zl3vni_lookup(vni
);
4583 /* process-if-down for l3-vni */
4584 if (IS_ZEBRA_DEBUG_VXLAN
)
4585 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
4588 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4590 /* process if-down for l2-vni */
4591 if (IS_ZEBRA_DEBUG_VXLAN
)
4592 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
4595 /* Locate hash entry; it is expected to exist. */
4596 zevpn
= zebra_evpn_lookup(vni
);
4599 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
4600 ifp
->name
, ifp
->ifindex
, vni
);
4604 assert(zevpn
->vxlan_if
== ifp
);
4606 /* remove from l3-vni list */
4607 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4609 listnode_delete(zl3vni
->l2vnis
, zevpn
);
4611 /* Delete this VNI from BGP. */
4612 zebra_evpn_send_del_to_client(zevpn
);
4614 /* Free up all neighbors and MACs, if any. */
4615 zebra_evpn_neigh_del_all(zevpn
, 1, 0, DEL_ALL_NEIGH
);
4616 zebra_evpn_mac_del_all(zevpn
, 1, 0, DEL_ALL_MAC
);
4618 /* Free up all remote VTEPs, if any. */
4619 zebra_evpn_vtep_del_all(zevpn
, 1);
4625 * Handle VxLAN interface up - update BGP if required.
4627 int zebra_vxlan_if_up(struct interface
*ifp
)
4630 struct zebra_if
*zif
= NULL
;
4631 struct zebra_l2info_vxlan
*vxl
= NULL
;
4632 zebra_evpn_t
*zevpn
= NULL
;
4633 zebra_l3vni_t
*zl3vni
= NULL
;
4635 /* Check if EVPN is enabled. */
4636 if (!is_evpn_enabled())
4641 vxl
= &zif
->l2info
.vxl
;
4644 zl3vni
= zl3vni_lookup(vni
);
4646 /* we need to associate with SVI, if any, we can associate with
4647 * svi-if only after association with vxlan-intf is complete
4649 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4650 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4652 if (IS_ZEBRA_DEBUG_VXLAN
)
4653 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
4654 , ifp
->name
, ifp
->ifindex
, vni
,
4655 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
4656 zl3vni
->mac_vlan_if
?
4657 zl3vni
->mac_vlan_if
->name
: "NIL");
4659 if (is_l3vni_oper_up(zl3vni
))
4660 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4662 /* Handle L2-VNI add */
4663 struct interface
*vlan_if
= NULL
;
4665 if (IS_ZEBRA_DEBUG_VXLAN
)
4666 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
4669 /* Locate hash entry; it is expected to exist. */
4670 zevpn
= zebra_evpn_lookup(vni
);
4673 "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
4674 ifp
->name
, ifp
->ifindex
, vni
);
4678 assert(zevpn
->vxlan_if
== ifp
);
4679 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4680 zif
->brslave_info
.br_if
);
4682 zevpn
->vrf_id
= vlan_if
->vrf_id
;
4683 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4685 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
4688 /* If part of a bridge, inform BGP about this VNI. */
4689 /* Also, read and populate local MACs and neighbors. */
4690 if (zif
->brslave_info
.br_if
) {
4691 zebra_evpn_send_add_to_client(zevpn
);
4692 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
4700 * Handle VxLAN interface delete. Locate and remove entry in hash table
4701 * and update BGP, if required.
4703 int zebra_vxlan_if_del(struct interface
*ifp
)
4706 struct zebra_if
*zif
= NULL
;
4707 struct zebra_l2info_vxlan
*vxl
= NULL
;
4708 zebra_evpn_t
*zevpn
= NULL
;
4709 zebra_l3vni_t
*zl3vni
= NULL
;
4711 /* Check if EVPN is enabled. */
4712 if (!is_evpn_enabled())
4717 vxl
= &zif
->l2info
.vxl
;
4720 zl3vni
= zl3vni_lookup(vni
);
4723 if (IS_ZEBRA_DEBUG_VXLAN
)
4724 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
4727 /* process oper-down for l3-vni */
4728 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4730 /* remove the association with vxlan_if */
4731 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
4732 zl3vni
->vxlan_if
= NULL
;
4735 /* process if-del for l2-vni*/
4736 if (IS_ZEBRA_DEBUG_VXLAN
)
4737 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
4740 /* Locate hash entry; it is expected to exist. */
4741 zevpn
= zebra_evpn_lookup(vni
);
4744 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
4745 ifp
->name
, ifp
->ifindex
, vni
);
4749 /* remove from l3-vni list */
4750 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
4752 listnode_delete(zl3vni
->l2vnis
, zevpn
);
4753 /* Delete VNI from BGP. */
4754 zebra_evpn_send_del_to_client(zevpn
);
4756 /* Free up all neighbors and MAC, if any. */
4757 zebra_evpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
4758 zebra_evpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
4760 /* Free up all remote VTEPs, if any. */
4761 zebra_evpn_vtep_del_all(zevpn
, 0);
4763 /* Delete the hash entry. */
4764 if (zebra_evpn_vxlan_del(zevpn
)) {
4765 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4766 "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
4767 zevpn
, ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
4775 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
4777 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
4780 struct zebra_if
*zif
= NULL
;
4781 struct zebra_l2info_vxlan
*vxl
= NULL
;
4782 zebra_evpn_t
*zevpn
= NULL
;
4783 zebra_l3vni_t
*zl3vni
= NULL
;
4785 /* Check if EVPN is enabled. */
4786 if (!is_evpn_enabled())
4791 vxl
= &zif
->l2info
.vxl
;
4794 zl3vni
= zl3vni_lookup(vni
);
4797 if (IS_ZEBRA_DEBUG_VXLAN
)
4799 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
4800 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
4802 zif
->brslave_info
.bridge_ifindex
, chgflags
);
4804 /* Removed from bridge? Cleanup and return */
4805 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
4806 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
4807 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4811 /* access-vlan change - process oper down, associate with new
4812 * svi_if and then process oper up again
4814 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
4815 if (if_is_operative(ifp
)) {
4816 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4817 zl3vni
->svi_if
= NULL
;
4818 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4819 zl3vni
->mac_vlan_if
=
4820 zl3vni_map_to_mac_vlan_if(zl3vni
);
4821 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4822 if (is_l3vni_oper_up(zl3vni
))
4823 zebra_vxlan_process_l3vni_oper_up(
4829 * local-ip change - process oper down, associate with new
4830 * local-ip and then process oper up again
4832 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
4833 if (if_is_operative(ifp
)) {
4834 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4835 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4836 if (is_l3vni_oper_up(zl3vni
))
4837 zebra_vxlan_process_l3vni_oper_up(
4842 /* Update local tunnel IP. */
4843 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4845 /* if we have a valid new master, process l3-vni oper up */
4846 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
4847 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
4848 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4852 /* Update VNI hash. */
4853 zevpn
= zebra_evpn_lookup(vni
);
4856 "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
4857 ifp
->name
, ifp
->ifindex
, vni
);
4861 if (IS_ZEBRA_DEBUG_VXLAN
)
4863 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u chg 0x%x",
4864 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
4866 zif
->brslave_info
.bridge_ifindex
, chgflags
);
4868 /* Removed from bridge? Cleanup and return */
4869 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
4870 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
4871 /* Delete from client, remove all remote VTEPs */
4872 /* Also, free up all MACs and neighbors. */
4873 zebra_evpn_send_del_to_client(zevpn
);
4874 zebra_evpn_neigh_del_all(zevpn
, 1, 0, DEL_ALL_NEIGH
);
4875 zebra_evpn_mac_del_all(zevpn
, 1, 0, DEL_ALL_MAC
);
4876 zebra_evpn_vtep_del_all(zevpn
, 1);
4880 /* Handle other changes. */
4881 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
4882 /* Remove all existing local neigh and MACs for this VNI
4883 * (including from BGP)
4885 zebra_evpn_neigh_del_all(zevpn
, 0, 1, DEL_LOCAL_MAC
);
4886 zebra_evpn_mac_del_all(zevpn
, 0, 1, DEL_LOCAL_MAC
);
4889 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
4890 zevpn
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
4891 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
4893 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
4894 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
4895 zevpn
->mcast_grp
= vxl
->mcast_grp
;
4896 /* on local vtep-ip check if ES orig-ip
4897 * needs to be updated
4899 zebra_evpn_es_set_base_evpn(zevpn
);
4901 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
4902 /* Take further actions needed.
4903 * Note that if we are here, there is a change of interest.
4905 /* If down or not mapped to a bridge, we're done. */
4906 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
4909 /* Inform BGP, if there is a change of interest. */
4911 & (ZEBRA_VXLIF_MASTER_CHANGE
|
4912 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
4913 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
4914 zebra_evpn_send_add_to_client(zevpn
);
4916 /* If there is a valid new master or a VLAN mapping change,
4917 * read and populate local MACs and neighbors.
4918 * Also, reinstall any remote MACs and neighbors
4919 * for this VNI (based on new VLAN).
4921 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
4922 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
4923 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
4924 struct mac_walk_ctx m_wctx
;
4925 struct neigh_walk_ctx n_wctx
;
4927 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
4929 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
4930 m_wctx
.zevpn
= zevpn
;
4931 hash_iterate(zevpn
->mac_table
,
4932 zebra_evpn_install_mac_hash
, &m_wctx
);
4934 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
4935 n_wctx
.zevpn
= zevpn
;
4936 hash_iterate(zevpn
->neigh_table
,
4937 zebra_evpn_install_neigh_hash
, &n_wctx
);
4945 * Handle VxLAN interface add.
4947 int zebra_vxlan_if_add(struct interface
*ifp
)
4950 struct zebra_if
*zif
= NULL
;
4951 struct zebra_l2info_vxlan
*vxl
= NULL
;
4952 zebra_evpn_t
*zevpn
= NULL
;
4953 zebra_l3vni_t
*zl3vni
= NULL
;
4955 /* Check if EVPN is enabled. */
4956 if (!is_evpn_enabled())
4961 vxl
= &zif
->l2info
.vxl
;
4964 zl3vni
= zl3vni_lookup(vni
);
4967 /* process if-add for l3-vni*/
4968 if (IS_ZEBRA_DEBUG_VXLAN
)
4970 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %pI4 master %u",
4971 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
4973 zif
->brslave_info
.bridge_ifindex
);
4975 /* associate with vxlan_if */
4976 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4977 zl3vni
->vxlan_if
= ifp
;
4979 /* Associate with SVI, if any. We can associate with svi-if only
4980 * after association with vxlan_if is complete */
4981 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4983 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4985 if (is_l3vni_oper_up(zl3vni
))
4986 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4989 /* process if-add for l2-vni */
4990 struct interface
*vlan_if
= NULL
;
4992 /* Create or update EVPN hash. */
4993 zevpn
= zebra_evpn_lookup(vni
);
4995 zevpn
= zebra_evpn_add(vni
);
4998 EC_ZEBRA_VNI_ADD_FAILED
,
4999 "Failed to add EVPN hash, IF %s(%u) VNI %u",
5000 ifp
->name
, ifp
->ifindex
, vni
);
5005 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
5006 zevpn
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
5007 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
5009 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
5010 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
5011 zevpn
->mcast_grp
= vxl
->mcast_grp
;
5012 /* on local vtep-ip check if ES orig-ip
5013 * needs to be updated
5015 zebra_evpn_es_set_base_evpn(zevpn
);
5017 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
5018 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5019 zif
->brslave_info
.br_if
);
5021 zevpn
->vrf_id
= vlan_if
->vrf_id
;
5022 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
5024 listnode_add_sort_nodup(zl3vni
->l2vnis
, zevpn
);
5027 if (IS_ZEBRA_DEBUG_VXLAN
) {
5028 char addr_buf1
[INET_ADDRSTRLEN
];
5029 char addr_buf2
[INET_ADDRSTRLEN
];
5031 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
5032 addr_buf1
, INET_ADDRSTRLEN
);
5033 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
5034 addr_buf2
, INET_ADDRSTRLEN
);
5037 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
5039 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
5041 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
5042 addr_buf1
, addr_buf2
,
5043 zif
->brslave_info
.bridge_ifindex
);
5046 /* If down or not mapped to a bridge, we're done. */
5047 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5051 zebra_evpn_send_add_to_client(zevpn
);
5053 /* Read and populate local MACs and neighbors */
5054 zebra_evpn_read_mac_neigh(zevpn
, ifp
);
5060 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
5061 char *err
, int err_str_sz
, int filter
,
5064 zebra_l3vni_t
*zl3vni
= NULL
;
5065 struct zebra_vrf
*zvrf_evpn
= NULL
;
5067 zvrf_evpn
= zebra_vrf_get_evpn();
5071 if (IS_ZEBRA_DEBUG_VXLAN
)
5072 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
5073 add
? "ADD" : "DEL");
5077 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
5079 /* check if the vni is already present under zvrf */
5081 snprintf(err
, err_str_sz
,
5082 "VNI is already configured under the vrf");
5086 /* check if this VNI is already present in the system */
5087 zl3vni
= zl3vni_lookup(vni
);
5089 snprintf(err
, err_str_sz
,
5090 "VNI is already configured as L3-VNI");
5094 /* add the L3-VNI to the global table */
5095 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
5097 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
5101 /* associate the vrf with vni */
5104 /* set the filter in l3vni to denote if we are using l3vni only
5108 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
5110 /* associate with vxlan-intf;
5111 * we need to associate with the vxlan-intf first
5113 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
5115 /* associate with corresponding SVI interface, we can associate
5116 * with svi-if only after vxlan interface association is
5119 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
5121 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
5123 if (IS_ZEBRA_DEBUG_VXLAN
)
5125 "%s: l3vni %u svi_if %s mac_vlan_if %s",
5127 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
5128 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
5131 /* formulate l2vni list */
5132 hash_iterate(zvrf_evpn
->evpn_table
, zevpn_add_to_l3vni_list
,
5135 if (is_l3vni_oper_up(zl3vni
))
5136 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5139 zl3vni
= zl3vni_lookup(vni
);
5141 snprintf(err
, err_str_sz
, "VNI doesn't exist");
5145 if (zvrf
->l3vni
!= vni
) {
5146 snprintf(err
, err_str_sz
,
5147 "VNI %d doesn't exist in VRF: %s",
5148 vni
, zvrf
->vrf
->name
);
5152 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
5153 snprintf(err
, ERR_STR_SZ
,
5154 "prefix-routes-only is not set for the vni");
5158 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5160 /* delete and uninstall all rmacs */
5161 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
5164 /* delete and uninstall all next-hops */
5165 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
5171 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
5176 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
5178 zebra_l3vni_t
*zl3vni
= NULL
;
5181 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5185 zl3vni
->vrf_id
= zvrf_id(zvrf
);
5186 if (is_l3vni_oper_up(zl3vni
))
5187 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
5191 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
5193 zebra_l3vni_t
*zl3vni
= NULL
;
5196 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5200 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
5202 /* delete and uninstall all rmacs */
5203 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
, zl3vni
);
5204 /* delete and uninstall all next-hops */
5205 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
, zl3vni
);
5207 zl3vni
->vrf_id
= VRF_UNKNOWN
;
5212 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
5214 zebra_l3vni_t
*zl3vni
= NULL
;
5218 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5224 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
5230 * Handle message from client to specify the flooding mechanism for
5231 * BUM packets. The default is to do head-end (ingress) replication
5232 * and the other supported option is to disable it. This applies to
5233 * all BUM traffic and disabling it applies to both the transmit and
5234 * receive direction.
5236 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
5239 enum vxlan_flood_control flood_ctrl
;
5241 if (!EVPN_ENABLED(zvrf
)) {
5242 zlog_err("EVPN flood control for non-EVPN VRF %u",
5248 STREAM_GETC(s
, flood_ctrl
);
5250 if (IS_ZEBRA_DEBUG_VXLAN
)
5251 zlog_debug("EVPN flood control %u, currently %u",
5252 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
5254 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
5257 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5259 /* Install or uninstall flood entries corresponding to
5262 hash_iterate(zvrf
->evpn_table
, zebra_evpn_handle_flooding_remote_vteps
,
5270 * Handle message from client to enable/disable advertisement of svi macip
5273 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
5278 zebra_evpn_t
*zevpn
= NULL
;
5279 struct interface
*ifp
= NULL
;
5281 if (!EVPN_ENABLED(zvrf
)) {
5282 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
5288 STREAM_GETC(s
, advertise
);
5289 STREAM_GETL(s
, vni
);
5292 if (IS_ZEBRA_DEBUG_VXLAN
)
5293 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
5294 advertise
? "enabled" : "disabled",
5295 advertise_svi_macip_enabled(NULL
)
5299 if (zvrf
->advertise_svi_macip
== advertise
)
5304 zvrf
->advertise_svi_macip
= advertise
;
5305 hash_iterate(zvrf
->evpn_table
,
5306 zebra_evpn_gw_macip_add_for_evpn_hash
,
5309 hash_iterate(zvrf
->evpn_table
,
5310 zebra_evpn_svi_macip_del_for_evpn_hash
,
5312 zvrf
->advertise_svi_macip
= advertise
;
5316 struct zebra_if
*zif
= NULL
;
5317 struct zebra_l2info_vxlan zl2_info
;
5318 struct interface
*vlan_if
= NULL
;
5320 zevpn
= zebra_evpn_lookup(vni
);
5324 if (IS_ZEBRA_DEBUG_VXLAN
)
5326 "EVPN SVI macip Adv %s on VNI %d , currently %s",
5327 advertise
? "enabled" : "disabled", vni
,
5328 advertise_svi_macip_enabled(zevpn
)
5332 if (zevpn
->advertise_svi_macip
== advertise
)
5335 /* Store flag even though SVI is not present.
5336 * Once SVI comes up triggers self MAC-IP route add.
5338 zevpn
->advertise_svi_macip
= advertise
;
5340 ifp
= zevpn
->vxlan_if
;
5346 /* If down or not mapped to a bridge, we're done. */
5347 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5350 zl2_info
= zif
->l2info
.vxl
;
5351 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
5352 zif
->brslave_info
.br_if
);
5357 /* Add primary SVI MAC-IP */
5358 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5360 /* Del primary SVI MAC-IP */
5361 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5370 * Handle message from client to enable/disable advertisement of g/w macip
5373 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
5378 zebra_evpn_t
*zevpn
= NULL
;
5379 struct interface
*ifp
= NULL
;
5380 struct zebra_if
*zif
= NULL
;
5381 struct zebra_l2info_vxlan zl2_info
;
5382 struct interface
*vlan_if
= NULL
;
5384 if (!EVPN_ENABLED(zvrf
)) {
5385 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5391 STREAM_GETC(s
, advertise
);
5392 STREAM_GET(&vni
, s
, 3);
5394 zevpn
= zebra_evpn_lookup(vni
);
5398 if (zevpn
->advertise_subnet
== advertise
)
5401 if (IS_ZEBRA_DEBUG_VXLAN
)
5402 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
5403 advertise
? "enabled" : "disabled", vni
,
5404 zevpn
->advertise_subnet
? "enabled" : "disabled");
5407 zevpn
->advertise_subnet
= advertise
;
5409 ifp
= zevpn
->vxlan_if
;
5415 /* If down or not mapped to a bridge, we're done. */
5416 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5419 zl2_info
= zif
->l2info
.vxl
;
5422 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
5426 if (zevpn
->advertise_subnet
)
5427 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 1);
5429 zebra_evpn_advertise_subnet(zevpn
, vlan_if
, 0);
5436 * Handle message from client to enable/disable advertisement of g/w macip
5439 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
5444 zebra_evpn_t
*zevpn
= NULL
;
5445 struct interface
*ifp
= NULL
;
5447 if (!EVPN_ENABLED(zvrf
)) {
5448 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
5454 STREAM_GETC(s
, advertise
);
5455 STREAM_GETL(s
, vni
);
5458 if (IS_ZEBRA_DEBUG_VXLAN
)
5459 zlog_debug("EVPN gateway macip Adv %s, currently %s",
5460 advertise
? "enabled" : "disabled",
5461 advertise_gw_macip_enabled(NULL
)
5465 if (zvrf
->advertise_gw_macip
== advertise
)
5468 zvrf
->advertise_gw_macip
= advertise
;
5470 if (advertise_gw_macip_enabled(zevpn
))
5471 hash_iterate(zvrf
->evpn_table
,
5472 zebra_evpn_gw_macip_add_for_evpn_hash
,
5475 hash_iterate(zvrf
->evpn_table
,
5476 zebra_evpn_gw_macip_del_for_evpn_hash
,
5480 struct zebra_if
*zif
= NULL
;
5481 struct zebra_l2info_vxlan zl2_info
;
5482 struct interface
*vlan_if
= NULL
;
5483 struct interface
*vrr_if
= NULL
;
5485 zevpn
= zebra_evpn_lookup(vni
);
5489 if (IS_ZEBRA_DEBUG_VXLAN
)
5491 "EVPN gateway macip Adv %s on VNI %d , currently %s",
5492 advertise
? "enabled" : "disabled", vni
,
5493 advertise_gw_macip_enabled(zevpn
) ? "enabled"
5496 if (zevpn
->advertise_gw_macip
== advertise
)
5499 zevpn
->advertise_gw_macip
= advertise
;
5501 ifp
= zevpn
->vxlan_if
;
5507 /* If down or not mapped to a bridge, we're done. */
5508 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
5511 zl2_info
= zif
->l2info
.vxl
;
5513 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
5514 zif
->brslave_info
.br_if
);
5518 if (advertise_gw_macip_enabled(zevpn
)) {
5519 /* Add primary SVI MAC-IP */
5520 zebra_evpn_add_macip_for_intf(vlan_if
, zevpn
);
5522 /* Add VRR MAC-IP - if any*/
5523 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5525 zebra_evpn_add_macip_for_intf(vrr_if
, zevpn
);
5527 /* Del primary MAC-IP */
5528 zebra_evpn_del_macip_for_intf(vlan_if
, zevpn
);
5530 /* Del VRR MAC-IP - if any*/
5531 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
5533 zebra_evpn_del_macip_for_intf(vrr_if
, zevpn
);
5541 static int macfdb_read_ns(struct ns
*ns
,
5542 void *_in_param
__attribute__((unused
)),
5543 void **out_param
__attribute__((unused
)))
5545 struct zebra_ns
*zns
= ns
->info
;
5548 return NS_WALK_CONTINUE
;
5551 static int neigh_read_ns(struct ns
*ns
,
5552 void *_in_param
__attribute__((unused
)),
5553 void **out_param
__attribute__((unused
)))
5555 struct zebra_ns
*zns
= ns
->info
;
5558 return NS_WALK_CONTINUE
;
5562 * Handle message from client to learn (or stop learning) about VNIs and MACs.
5563 * When enabled, the VNI hash table will be built and MAC FDB table read;
5564 * when disabled, the entries should be deleted and remote VTEPs and MACs
5565 * uninstalled from the kernel.
5566 * This also informs the setting for BUM handling at the time this change
5567 * occurs; it is relevant only when specifying "learn".
5569 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
5571 struct stream
*s
= NULL
;
5573 enum vxlan_flood_control flood_ctrl
;
5575 /* Mismatch between EVPN VRF and current VRF (should be prevented by
5577 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
5581 STREAM_GETC(s
, advertise
);
5582 STREAM_GETC(s
, flood_ctrl
);
5584 if (IS_ZEBRA_DEBUG_VXLAN
)
5585 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
5586 zvrf_name(zvrf
), zvrf_id(zvrf
),
5587 advertise
? "enabled" : "disabled",
5588 is_evpn_enabled() ? "enabled" : "disabled",
5591 if (zvrf
->advertise_all_vni
== advertise
)
5594 zvrf
->advertise_all_vni
= advertise
;
5595 if (EVPN_ENABLED(zvrf
)) {
5596 zrouter
.evpn_vrf
= zvrf
;
5598 /* Note BUM handling */
5599 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
5601 /* Replay all ESs */
5602 zebra_evpn_es_send_all_to_client(true /* add */);
5604 /* Build EVPN hash table and inform BGP. */
5605 zevpn_build_hash_table();
5607 /* Add all SVI (L3 GW) MACs to BGP*/
5608 hash_iterate(zvrf
->evpn_table
,
5609 zebra_evpn_gw_macip_add_for_evpn_hash
, NULL
);
5611 /* Read the MAC FDB */
5612 ns_walk_func(macfdb_read_ns
, NULL
, NULL
);
5614 /* Read neighbors */
5615 ns_walk_func(neigh_read_ns
, NULL
, NULL
);
5617 /* Cleanup VTEPs for all EVPNs - uninstall from
5618 * kernel and free entries.
5620 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
,
5623 /* Delete all ESs in BGP */
5624 zebra_evpn_es_send_all_to_client(false /* add */);
5626 /* cleanup all l3vnis */
5627 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
5629 /* Mark as "no EVPN VRF" */
5630 zrouter
.evpn_vrf
= NULL
;
5638 * Allocate EVPN hash table for this VRF and do other initialization.
5639 * NOTE: Currently supported only for default VRF.
5641 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
5646 hash_create(zebra_evpn_hash_keymake
, zebra_evpn_hash_cmp
,
5647 "Zebra VRF EVPN Table");
5648 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
5649 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
5652 /* Cleanup EVPN info, but don't free the table. */
5653 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
5655 struct zebra_vrf
*evpn_zvrf
= zebra_vrf_get_evpn();
5659 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5660 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
5662 if (zvrf
== evpn_zvrf
)
5663 zebra_evpn_es_cleanup();
5666 /* Close all EVPN handling */
5667 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
5671 hash_iterate(zvrf
->evpn_table
, zebra_evpn_vxlan_cleanup_all
, zvrf
);
5672 hash_free(zvrf
->evpn_table
);
5675 /* init the l3vni table */
5676 void zebra_vxlan_init(void)
5678 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
5679 "Zebra VRF L3 VNI table");
5680 zrouter
.evpn_vrf
= NULL
;
5681 zebra_evpn_mh_init();
5684 /* free l3vni table */
5685 void zebra_vxlan_disable(void)
5687 hash_free(zrouter
.l3vni_table
);
5688 zebra_evpn_mh_terminate();
5691 /* get the l3vni svi ifindex */
5692 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
5694 zebra_l3vni_t
*zl3vni
= NULL
;
5696 zl3vni
= zl3vni_from_vrf(vrf_id
);
5697 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5700 return zl3vni
->svi_if
->ifindex
;
5703 /************************** vxlan SG cache management ************************/
5704 /* Inform PIM about the mcast group */
5705 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
5706 struct prefix_sg
*sg
,
5707 char *sg_str
, uint16_t cmd
)
5709 struct zserv
*client
= NULL
;
5710 struct stream
*s
= NULL
;
5712 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
5716 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
5719 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5721 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
5722 stream_putl(s
, IPV4_MAX_BYTELEN
);
5723 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
5724 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
5726 /* Write packet size. */
5727 stream_putw_at(s
, 0, stream_get_endp(s
));
5729 if (IS_ZEBRA_DEBUG_VXLAN
)
5732 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
5733 zebra_route_string(client
->proto
));
5735 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
5736 client
->vxlan_sg_add_cnt
++;
5738 client
->vxlan_sg_del_cnt
++;
5740 return zserv_send_message(client
, s
);
5743 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
5745 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
5747 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
5748 vxlan_sg
->sg
.grp
.s_addr
, 0));
5751 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
5753 const zebra_vxlan_sg_t
*sg1
= p1
;
5754 const zebra_vxlan_sg_t
*sg2
= p2
;
5756 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
5757 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
5760 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
5761 struct prefix_sg
*sg
)
5763 zebra_vxlan_sg_t
*vxlan_sg
;
5765 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
5767 vxlan_sg
->zvrf
= zvrf
;
5769 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
5771 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
5773 if (IS_ZEBRA_DEBUG_VXLAN
)
5774 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
5779 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
5780 struct prefix_sg
*sg
)
5782 zebra_vxlan_sg_t lookup
;
5785 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
5788 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
5789 struct prefix_sg
*sg
)
5791 zebra_vxlan_sg_t
*vxlan_sg
;
5792 zebra_vxlan_sg_t
*parent
= NULL
;
5795 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
5799 /* create a *G entry for every BUM group implicitly -
5800 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
5801 * 2. the XG entry is used by pimd to setup the
5802 * vxlan-termination-mroute
5804 if (sg
->src
.s_addr
!= INADDR_ANY
) {
5805 memset(&sip
, 0, sizeof(sip
));
5806 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
5811 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
5814 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
5818 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
5819 ZEBRA_VXLAN_SG_ADD
);
5824 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
5827 struct zebra_vrf
*zvrf
;
5829 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5833 /* On SG entry deletion remove the reference to its parent XG
5836 if (vxlan_sg
->sg
.src
.s_addr
!= INADDR_ANY
) {
5837 memset(&sip
, 0, sizeof(sip
));
5838 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
5841 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
5842 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
5844 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
5846 if (IS_ZEBRA_DEBUG_VXLAN
)
5847 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
5849 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
5852 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
5853 struct in_addr sip
, struct in_addr mcast_grp
)
5855 zebra_vxlan_sg_t
*vxlan_sg
;
5856 struct prefix_sg sg
;
5858 sg
.family
= AF_INET
;
5859 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5862 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
5866 if (vxlan_sg
->ref_cnt
)
5867 --vxlan_sg
->ref_cnt
;
5869 if (!vxlan_sg
->ref_cnt
)
5870 zebra_vxlan_sg_del(vxlan_sg
);
5873 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
5874 struct in_addr sip
, struct in_addr mcast_grp
)
5876 zebra_vxlan_sg_t
*vxlan_sg
;
5877 struct prefix_sg sg
;
5879 sg
.family
= AF_INET
;
5880 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
5883 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
5885 ++vxlan_sg
->ref_cnt
;
5890 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
5891 struct in_addr mcast_grp
)
5893 struct zebra_vrf
*zvrf
;
5895 if (local_vtep_ip
.s_addr
== INADDR_ANY
5896 || mcast_grp
.s_addr
== INADDR_ANY
)
5899 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5903 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
5906 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
5907 struct in_addr mcast_grp
)
5909 struct zebra_vrf
*zvrf
;
5911 if (local_vtep_ip
.s_addr
== INADDR_ANY
5912 || mcast_grp
.s_addr
== INADDR_ANY
)
5915 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
5918 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
5921 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*backet
, void *arg
)
5923 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
5925 zebra_vxlan_sg_del(vxlan_sg
);
5928 static void zebra_vxlan_sg_replay_send(struct hash_bucket
*backet
, void *arg
)
5930 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
5932 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
5933 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
5936 /* Handle message from client to replay vxlan SG entries */
5937 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
5939 if (IS_ZEBRA_DEBUG_VXLAN
)
5940 zlog_debug("VxLAN SG updates to PIM, start");
5942 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
5944 if (!EVPN_ENABLED(zvrf
)) {
5945 if (IS_ZEBRA_DEBUG_VXLAN
)
5946 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
5951 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
5955 /* Cleanup EVPN configuration of a specific VRF */
5956 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
5958 zebra_l3vni_t
*zl3vni
= NULL
;
5960 zvrf
->advertise_all_vni
= 0;
5961 zvrf
->advertise_gw_macip
= 0;
5962 zvrf
->advertise_svi_macip
= 0;
5963 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
5965 hash_iterate(zvrf
->evpn_table
, zebra_evpn_cfg_cleanup
, NULL
);
5968 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5970 /* delete and uninstall all rmacs */
5971 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
5973 /* delete and uninstall all next-hops */
5974 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
5979 /* Cleanup BGP EVPN configuration upon client disconnect */
5980 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
5983 struct zebra_vrf
*zvrf
;
5985 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
5988 zebra_evpn_vrf_cfg_cleanup(zvrf
);
5994 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
5996 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
5998 if (zvrf
&& CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
5999 if (IS_ZEBRA_DEBUG_VXLAN
)
6000 zlog_debug("VxLAN SG updates to PIM, stop");
6001 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
6007 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
6009 if (client
->proto
== ZEBRA_ROUTE_BGP
)
6010 return zebra_evpn_bgp_cfg_clean_up(client
);
6012 if (client
->proto
== ZEBRA_ROUTE_PIM
)
6013 return zebra_evpn_pim_cfg_clean_up(client
);
6019 * Handle results for vxlan dataplane operations.
6021 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
6023 /* TODO -- anything other than freeing the context? */
6024 dplane_ctx_fini(&ctx
);
6027 /* Cleanup BGP EVPN configuration upon client disconnect */
6028 extern void zebra_evpn_init(void)
6030 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);