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>
40 #include "zebra/zebra_router.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/rib.h"
45 #include "zebra/rt_netlink.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_l2.h"
48 #include "zebra/zebra_memory.h"
49 #include "zebra/zebra_ns.h"
50 #include "zebra/zebra_vrf.h"
51 #include "zebra/zebra_vxlan.h"
52 #include "zebra/zebra_vxlan_private.h"
53 #include "zebra/zebra_router.h"
55 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
58 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
59 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
60 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
61 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
63 DEFINE_HOOK(zebra_rmac_update
, (zebra_mac_t
*rmac
, zebra_l3vni_t
*zl3vni
,
64 bool delete, const char *reason
), (rmac
, zl3vni
, delete, reason
))
68 #define VXLAN_FLOOD_STR_NO_INFO "-"
69 #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO
70 static const struct message zvtep_flood_str
[] = {
71 {VXLAN_FLOOD_DISABLED
, VXLAN_FLOOD_STR_NO_INFO
},
72 {VXLAN_FLOOD_PIM_SM
, "PIM-SM"},
73 {VXLAN_FLOOD_HEAD_END_REPL
, "HER"},
78 /* static function declarations */
79 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
81 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
82 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
83 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
84 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
86 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
88 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
90 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
91 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
92 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
);
93 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
94 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
96 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
97 struct ipaddr
*ip
, uint8_t flags
,
98 uint32_t seq
, int state
, uint16_t cmd
);
99 static unsigned int neigh_hash_keymake(const void *p
);
100 static void *zvni_neigh_alloc(void *p
);
101 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
102 struct ethaddr
*mac
);
103 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
104 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
105 struct in_addr
*r_vtep_ip
);
106 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
108 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
109 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
110 struct ethaddr
*macaddr
,
111 uint8_t flags
, uint32_t seq
);
112 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
113 struct ethaddr
*macaddr
,
114 uint8_t flags
, int state
);
115 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
116 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
117 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
118 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
119 struct interface
*br_if
);
120 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
122 /* l3-vni next-hop neigh related APIs */
123 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
125 static void *zl3vni_nh_alloc(void *p
);
126 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
127 struct ipaddr
*vtep_ip
,
128 struct ethaddr
*rmac
);
129 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
130 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
131 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
133 /* l3-vni rmac related APIs */
134 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
135 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
136 struct ethaddr
*rmac
);
137 static void *zl3vni_rmac_alloc(void *p
);
138 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
139 struct ethaddr
*rmac
);
140 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
141 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
142 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
144 /* l3-vni related APIs*/
145 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
146 static void *zl3vni_alloc(void *p
);
147 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
148 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
149 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
150 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
152 static unsigned int mac_hash_keymake(const void *p
);
153 static bool mac_cmp(const void *p1
, const void *p2
);
154 static void *zvni_mac_alloc(void *p
);
155 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
156 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
157 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
158 struct in_addr
*r_vtep_ip
);
159 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
161 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
162 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
163 uint8_t flags
, uint32_t seq
);
164 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
165 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
166 struct interface
*br_if
, vlanid_t vid
);
167 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
168 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
169 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
171 static unsigned int vni_hash_keymake(const void *p
);
172 static void *zvni_alloc(void *p
);
173 static zebra_vni_t
*zvni_lookup(vni_t vni
);
174 static zebra_vni_t
*zvni_add(vni_t vni
);
175 static int zvni_del(zebra_vni_t
*zvni
);
176 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
177 static int zvni_send_del_to_client(vni_t vni
);
178 static void zvni_build_hash_table(void);
179 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
180 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
181 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
183 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
184 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
185 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
186 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
187 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
188 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
189 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
190 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
191 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
193 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
194 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
195 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
196 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
197 zebra_mac_t
*old_zmac
,
198 zebra_mac_t
*new_zmac
,
200 static int remote_neigh_count(zebra_mac_t
*zmac
);
201 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
202 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
203 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
204 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
206 struct in_addr vtep_ip
,
210 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
212 struct in_addr vtep_ip
,
216 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
217 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
218 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
219 struct in_addr sip
, struct in_addr mcast_grp
);
220 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
221 struct in_addr sip
, struct in_addr mcast_grp
);
222 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
223 struct in_addr mcast_grp
);
224 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
225 struct in_addr mcast_grp
);
226 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
);
228 static void zvni_send_mac_to_client(zebra_vni_t
*zvn
);
229 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
);
231 /* Private functions */
232 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
233 const struct host_rb_entry
*hle2
)
235 if (hle1
->p
.family
< hle2
->p
.family
)
238 if (hle1
->p
.family
> hle2
->p
.family
)
241 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
244 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
247 if (hle1
->p
.family
== AF_INET
) {
248 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
251 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
255 } else if (hle1
->p
.family
== AF_INET6
) {
256 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
259 zlog_debug("%s: Unexpected family type: %d",
260 __PRETTY_FUNCTION__
, hle1
->p
.family
);
264 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
266 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
268 struct host_rb_entry
*hle
;
271 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
278 * Return number of valid MACs in a VNI's MAC hash table - all
279 * remote MACs and non-internal (auto) local MACs count.
281 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
284 uint32_t num_macs
= 0;
286 struct hash_bucket
*hb
;
289 hash
= zvni
->mac_table
;
292 for (i
= 0; i
< hash
->size
; i
++) {
293 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
294 mac
= (zebra_mac_t
*)hb
->data
;
295 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
296 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
297 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
305 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
308 uint32_t num_macs
= 0;
310 struct hash_bucket
*hb
;
313 hash
= zvni
->mac_table
;
316 for (i
= 0; i
< hash
->size
; i
++) {
317 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
318 mac
= (zebra_mac_t
*)hb
->data
;
319 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
327 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
330 uint32_t num_neighs
= 0;
332 struct hash_bucket
*hb
;
335 hash
= zvni
->neigh_table
;
338 for (i
= 0; i
< hash
->size
; i
++) {
339 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
340 nbr
= (zebra_neigh_t
*)hb
->data
;
341 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
349 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
351 struct zebra_vrf
*zvrf
;
353 zvrf
= zebra_vrf_get_evpn();
354 if (zvrf
&& zvrf
->advertise_gw_macip
)
357 if (zvni
&& zvni
->advertise_gw_macip
)
363 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
365 struct zebra_vrf
*zvrf
;
367 zvrf
= zebra_vrf_get_evpn();
368 if (zvrf
&& zvrf
->advertise_svi_macip
)
371 if (zvni
&& zvni
->advertise_svi_macip
)
377 /* As part Duplicate Address Detection (DAD) for IP mobility
378 * MAC binding changes, ensure to inherit duplicate flag
381 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
382 zebra_mac_t
*old_zmac
,
383 zebra_mac_t
*new_zmac
,
386 bool is_old_mac_dup
= false;
387 bool is_new_mac_dup
= false;
389 if (!zvrf
->dup_addr_detect
)
391 /* Check old or new MAC is detected as duplicate
392 * mark this neigh as duplicate
395 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
396 ZEBRA_MAC_DUPLICATE
);
398 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
399 ZEBRA_MAC_DUPLICATE
);
400 /* Old and/or new MAC can be in duplicate state,
401 * based on that IP/Neigh Inherits the flag.
402 * If New MAC is marked duplicate, inherit to the IP.
403 * If old MAC is duplicate but new MAC is not, clear
404 * duplicate flag for IP and reset detection params
405 * and let IP DAD retrigger.
407 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
408 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
409 /* Capture Duplicate detection time */
410 nbr
->dad_dup_detect_time
= monotime(NULL
);
411 /* Mark neigh inactive */
412 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
415 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
416 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
418 nbr
->detect_start_time
.tv_sec
= 0;
419 nbr
->detect_start_time
.tv_usec
= 0;
424 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
426 struct in_addr vtep_ip
,
432 struct listnode
*node
= NULL
;
433 struct timeval elapsed
= {0, 0};
434 char buf
[ETHER_ADDR_STRLEN
];
435 char buf1
[INET6_ADDRSTRLEN
];
436 bool reset_params
= false;
438 if (!(zvrf
->dup_addr_detect
&& do_dad
))
441 /* MAC is detected as duplicate,
442 * Local MAC event -> hold on advertising to BGP.
443 * Remote MAC event -> hold on installing it.
445 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
446 if (IS_ZEBRA_DEBUG_VXLAN
)
448 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
450 prefix_mac2str(&mac
->macaddr
, buf
,
452 mac
->flags
, mac
->dad_count
,
453 zvrf
->dad_freeze_time
);
455 /* For duplicate MAC do not update
456 * client but update neigh due to
459 if (zvrf
->dad_freeze
)
460 *is_dup_detect
= true;
465 /* Check if detection time (M-secs) expired.
466 * Reset learn count and detection start time.
468 monotime_since(&mac
->detect_start_time
, &elapsed
);
469 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
470 if (is_local
&& !reset_params
) {
471 /* RFC-7432: A PE/VTEP that detects a MAC mobility
472 * event via LOCAL learning starts an M-second timer.
474 * NOTE: This is the START of the probe with count is
475 * 0 during LOCAL learn event.
476 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
478 reset_params
= !mac
->dad_count
;
482 if (IS_ZEBRA_DEBUG_VXLAN
)
484 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
485 , __PRETTY_FUNCTION__
,
486 prefix_mac2str(&mac
->macaddr
, buf
,
488 mac
->flags
, mac
->dad_count
);
491 /* Start dup. addr detection (DAD) start time,
492 * ONLY during LOCAL learn.
495 monotime(&mac
->detect_start_time
);
497 } else if (!is_local
) {
498 /* For REMOTE MAC, increment detection count
499 * ONLY while in probe window, once window passed,
500 * next local learn event should trigger DAD.
505 /* For LOCAL MAC learn event, once count is reset above via either
506 * initial/start detection time or passed the probe time, the count
507 * needs to be incremented.
512 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
513 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
514 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
516 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
517 is_local
? "local update, last" :
518 "remote update, from", inet_ntoa(vtep_ip
));
520 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
522 /* Capture Duplicate detection time */
523 mac
->dad_dup_detect_time
= monotime(NULL
);
525 /* Mark all IPs/Neighs as duplicate
526 * associcated with this MAC
528 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
530 /* Ony Mark IPs which are Local */
531 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
534 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
536 nbr
->dad_dup_detect_time
= monotime(NULL
);
538 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
539 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
541 prefix_mac2str(&mac
->macaddr
,
543 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
544 is_local
? "local" : "remote");
547 /* Start auto recovery timer for this MAC */
548 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
549 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
550 if (IS_ZEBRA_DEBUG_VXLAN
)
552 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
553 , __PRETTY_FUNCTION__
,
554 prefix_mac2str(&mac
->macaddr
, buf
,
556 mac
->flags
, zvrf
->dad_freeze_time
);
558 thread_add_timer(zrouter
.master
,
559 zebra_vxlan_dad_mac_auto_recovery_exp
,
560 mac
, zvrf
->dad_freeze_time
,
561 &mac
->dad_mac_auto_recovery_timer
);
564 /* In case of local update, do not inform to client (BGPd),
565 * upd_neigh for neigh sequence change.
567 if (zvrf
->dad_freeze
)
568 *is_dup_detect
= true;
572 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
574 struct in_addr vtep_ip
,
580 struct timeval elapsed
= {0, 0};
581 char buf
[ETHER_ADDR_STRLEN
];
582 char buf1
[INET6_ADDRSTRLEN
];
583 bool reset_params
= false;
585 if (!zvrf
->dup_addr_detect
)
588 /* IP is detected as duplicate or inherit dup
589 * state, hold on to install as remote entry
590 * only if freeze is enabled.
592 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
593 if (IS_ZEBRA_DEBUG_VXLAN
)
595 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
597 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
598 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
599 nbr
->flags
, nbr
->dad_count
,
600 zvrf
->dad_freeze_time
);
602 if (zvrf
->dad_freeze
)
603 *is_dup_detect
= true;
605 /* warn-only action, neigh will be installed.
606 * freeze action, it wil not be installed.
614 /* Check if detection time (M-secs) expired.
615 * Reset learn count and detection start time.
616 * During remote mac add, count should already be 1
617 * via local learning.
619 monotime_since(&nbr
->detect_start_time
, &elapsed
);
620 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
622 if (is_local
&& !reset_params
) {
623 /* RFC-7432: A PE/VTEP that detects a MAC mobility
624 * event via LOCAL learning starts an M-second timer.
626 * NOTE: This is the START of the probe with count is
627 * 0 during LOCAL learn event.
629 reset_params
= !nbr
->dad_count
;
633 if (IS_ZEBRA_DEBUG_VXLAN
)
635 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
637 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
638 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
639 nbr
->flags
, nbr
->dad_count
);
640 /* Reset learn count but do not start detection
641 * during REMOTE learn event.
644 /* Start dup. addr detection (DAD) start time,
645 * ONLY during LOCAL learn.
648 monotime(&nbr
->detect_start_time
);
650 } else if (!is_local
) {
651 /* For REMOTE IP/Neigh, increment detection count
652 * ONLY while in probe window, once window passed,
653 * next local learn event should trigger DAD.
658 /* For LOCAL IP/Neigh learn event, once count is reset above via either
659 * initial/start detection time or passed the probe time, the count
660 * needs to be incremented.
665 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
666 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
667 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
669 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
670 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
671 is_local
? "local update, last" :
672 "remote update, from",
675 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
677 /* Capture Duplicate detection time */
678 nbr
->dad_dup_detect_time
= monotime(NULL
);
680 /* Start auto recovery timer for this IP */
681 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
682 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
683 if (IS_ZEBRA_DEBUG_VXLAN
)
685 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
687 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
688 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
689 nbr
->flags
, zvrf
->dad_freeze_time
);
691 thread_add_timer(zrouter
.master
,
692 zebra_vxlan_dad_ip_auto_recovery_exp
,
693 nbr
, zvrf
->dad_freeze_time
,
694 &nbr
->dad_ip_auto_recovery_timer
);
696 if (zvrf
->dad_freeze
)
697 *is_dup_detect
= true;
702 * Helper function to determine maximum width of neighbor IP address for
703 * display - just because we're dealing with IPv6 addresses that can
706 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
709 char buf
[INET6_ADDRSTRLEN
];
710 struct neigh_walk_ctx
*wctx
= ctxt
;
713 n
= (zebra_neigh_t
*)bucket
->data
;
715 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
717 if (width
> wctx
->addr_width
)
718 wctx
->addr_width
= width
;
723 * Print a specific neighbor entry.
725 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
728 char buf1
[ETHER_ADDR_STRLEN
];
729 char buf2
[INET6_ADDRSTRLEN
];
730 const char *type_str
;
731 const char *state_str
;
732 bool flags_present
= false;
733 struct zebra_vrf
*zvrf
= NULL
;
734 struct timeval detect_start_time
= {0, 0};
735 char timebuf
[MONOTIME_STRLEN
];
737 zvrf
= zebra_vrf_get_evpn();
741 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
742 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
743 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
745 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
746 vty
= (struct vty
*)ctxt
;
748 vty_out(vty
, "IP: %s\n",
749 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
750 vty_out(vty
, " Type: %s\n", type_str
);
751 vty_out(vty
, " State: %s\n", state_str
);
752 vty_out(vty
, " MAC: %s\n",
753 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
755 json_object_string_add(json
, "ip", buf2
);
756 json_object_string_add(json
, "type", type_str
);
757 json_object_string_add(json
, "state", state_str
);
758 json_object_string_add(json
, "mac", buf1
);
760 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
762 vty_out(vty
, " Remote VTEP: %s\n",
763 inet_ntoa(n
->r_vtep_ip
));
765 json_object_string_add(json
, "remoteVtep",
766 inet_ntoa(n
->r_vtep_ip
));
768 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
770 vty_out(vty
, " Flags: Default-gateway");
771 flags_present
= true;
773 json_object_boolean_true_add(json
, "defaultGateway");
775 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
778 flags_present
? " ,Router" : " Flags: Router");
779 flags_present
= true;
785 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
786 n
->loc_seq
, n
->rem_seq
);
788 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
789 vty_out(vty
, " Duplicate, detected at %s",
790 time_to_string(n
->dad_dup_detect_time
,
792 } else if (n
->dad_count
) {
793 monotime_since(&n
->detect_start_time
,
795 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
796 time_to_string(n
->detect_start_time
.tv_sec
,
799 " Duplicate detection started at %s, detection count %u\n",
800 timebuf
, n
->dad_count
);
804 json_object_int_add(json
, "localSequence", n
->loc_seq
);
805 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
806 json_object_int_add(json
, "detectionCount",
808 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
809 json_object_boolean_true_add(json
, "isDuplicate");
811 json_object_boolean_false_add(json
, "isDuplicate");
818 * Print neighbor hash entry - called for display of all neighbors.
820 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
823 json_object
*json_vni
= NULL
, *json_row
= NULL
;
825 char buf1
[ETHER_ADDR_STRLEN
];
826 char buf2
[INET6_ADDRSTRLEN
];
827 struct neigh_walk_ctx
*wctx
= ctxt
;
828 const char *state_str
;
831 json_vni
= wctx
->json
;
832 n
= (zebra_neigh_t
*)bucket
->data
;
835 json_row
= json_object_new_object();
837 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
838 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
839 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
840 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
841 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
844 if (json_vni
== NULL
) {
845 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
846 -wctx
->addr_width
, buf2
, "local",
847 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
849 json_object_string_add(json_row
, "type", "local");
850 json_object_string_add(json_row
, "state", state_str
);
851 json_object_string_add(json_row
, "mac", buf1
);
852 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
853 json_object_boolean_true_add(
854 json_row
, "defaultGateway");
855 json_object_int_add(json_row
, "localSequence",
857 json_object_int_add(json_row
, "remoteSequence",
859 json_object_int_add(json_row
, "detectionCount",
861 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
862 json_object_boolean_true_add(json_row
,
865 json_object_boolean_false_add(json_row
,
869 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
870 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
871 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
874 if (json_vni
== NULL
) {
875 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
877 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
878 -wctx
->addr_width
, "Neighbor", "Type",
879 "State", "MAC", "Remote VTEP",
881 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
882 -wctx
->addr_width
, buf2
, "remote", state_str
,
883 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
885 json_object_string_add(json_row
, "type", "remote");
886 json_object_string_add(json_row
, "state", state_str
);
887 json_object_string_add(json_row
, "mac", buf1
);
888 json_object_string_add(json_row
, "remoteVtep",
889 inet_ntoa(n
->r_vtep_ip
));
890 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
891 json_object_boolean_true_add(json_row
,
893 json_object_int_add(json_row
, "localSequence",
895 json_object_int_add(json_row
, "remoteSequence",
897 json_object_int_add(json_row
, "detectionCount",
899 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
900 json_object_boolean_true_add(json_row
,
903 json_object_boolean_false_add(json_row
,
910 json_object_object_add(json_vni
, buf2
, json_row
);
914 * Print neighbor hash entry in detail - called for display of all neighbors.
916 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
919 json_object
*json_vni
= NULL
, *json_row
= NULL
;
921 char buf
[INET6_ADDRSTRLEN
];
922 struct neigh_walk_ctx
*wctx
= ctxt
;
925 json_vni
= wctx
->json
;
926 n
= (zebra_neigh_t
*)bucket
->data
;
930 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
932 json_row
= json_object_new_object();
934 zvni_print_neigh(n
, vty
, json_row
);
937 json_object_object_add(json_vni
, buf
, json_row
);
941 * Print neighbors for all VNI.
943 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
947 json_object
*json
= NULL
, *json_vni
= NULL
;
950 struct neigh_walk_ctx wctx
;
951 char vni_str
[VNI_STR_LEN
];
954 vty
= (struct vty
*)args
[0];
955 json
= (json_object
*)args
[1];
956 print_dup
= (uint32_t)(uintptr_t)args
[2];
958 zvni
= (zebra_vni_t
*)bucket
->data
;
960 num_neigh
= hashcount(zvni
->neigh_table
);
963 num_neigh
= num_dup_detected_neighs(zvni
);
967 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
968 zvni
->vni
, num_neigh
);
970 json_vni
= json_object_new_object();
971 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
972 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
977 json_object_object_add(json
, vni_str
, json_vni
);
981 /* Since we have IPv6 addresses to deal with which can vary widely in
982 * size, we try to be a bit more elegant in display by first computing
985 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
988 wctx
.addr_width
= 15;
989 wctx
.json
= json_vni
;
990 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
993 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
994 -wctx
.addr_width
, "IP", "Type",
995 "State", "MAC", "Remote VTEP", "Seq #'s");
998 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
1001 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1004 json_object_object_add(json
, vni_str
, json_vni
);
1007 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1011 nbr
= (zebra_neigh_t
*)bucket
->data
;
1015 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1016 zvni_print_neigh_hash(bucket
, ctxt
);
1019 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1024 nbr
= (zebra_neigh_t
*)bucket
->data
;
1028 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1029 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1033 * Print neighbors for all VNIs in detail.
1035 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1039 json_object
*json
= NULL
, *json_vni
= NULL
;
1042 struct neigh_walk_ctx wctx
;
1043 char vni_str
[VNI_STR_LEN
];
1046 vty
= (struct vty
*)args
[0];
1047 json
= (json_object
*)args
[1];
1048 print_dup
= (uint32_t)(uintptr_t)args
[2];
1050 zvni
= (zebra_vni_t
*)bucket
->data
;
1053 vty_out(vty
, "{}\n");
1056 num_neigh
= hashcount(zvni
->neigh_table
);
1058 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1063 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1064 zvni
->vni
, num_neigh
);
1066 json_vni
= json_object_new_object();
1067 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1068 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1072 json_object_object_add(json
, vni_str
, json_vni
);
1076 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1079 wctx
.addr_width
= 15;
1080 wctx
.json
= json_vni
;
1083 hash_iterate(zvni
->neigh_table
,
1084 zvni_print_dad_neigh_hash_detail
, &wctx
);
1086 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1090 json_object_object_add(json
, vni_str
, json_vni
);
1093 /* print a specific next hop for an l3vni */
1094 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1097 char buf1
[ETHER_ADDR_STRLEN
];
1098 char buf2
[INET6_ADDRSTRLEN
];
1099 json_object
*json_hosts
= NULL
;
1100 struct host_rb_entry
*hle
;
1103 vty_out(vty
, "Ip: %s\n",
1104 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1105 vty_out(vty
, " RMAC: %s\n",
1106 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1107 vty_out(vty
, " Refcount: %d\n",
1108 rb_host_count(&n
->host_rb
));
1109 vty_out(vty
, " Prefixes:\n");
1110 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1111 vty_out(vty
, " %s\n",
1112 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1114 json_hosts
= json_object_new_array();
1115 json_object_string_add(
1116 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1117 json_object_string_add(
1119 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1120 json_object_int_add(json
, "refCount",
1121 rb_host_count(&n
->host_rb
));
1122 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1123 json_object_array_add(json_hosts
,
1124 json_object_new_string(prefix2str(
1125 &hle
->p
, buf2
, sizeof(buf2
))));
1126 json_object_object_add(json
, "prefixList", json_hosts
);
1130 /* Print a specific RMAC entry */
1131 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1134 char buf1
[ETHER_ADDR_STRLEN
];
1135 char buf2
[PREFIX_STRLEN
];
1136 json_object
*json_hosts
= NULL
;
1137 struct host_rb_entry
*hle
;
1140 vty_out(vty
, "MAC: %s\n",
1141 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1142 vty_out(vty
, " Remote VTEP: %s\n",
1143 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1144 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1145 vty_out(vty
, " Prefixes:\n");
1146 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1147 vty_out(vty
, " %s\n",
1148 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1150 json_hosts
= json_object_new_array();
1151 json_object_string_add(
1153 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1154 json_object_string_add(json
, "vtepIp",
1155 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1156 json_object_int_add(json
, "refCount",
1157 rb_host_count(&zrmac
->host_rb
));
1158 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1159 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1160 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1161 json_object_array_add(
1163 json_object_new_string(prefix2str(
1164 &hle
->p
, buf2
, sizeof(buf2
))));
1165 json_object_object_add(json
, "prefixList", json_hosts
);
1170 * Print a specific MAC entry.
1172 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1175 zebra_neigh_t
*n
= NULL
;
1176 struct listnode
*node
= NULL
;
1177 char buf1
[ETHER_ADDR_STRLEN
];
1178 char buf2
[INET6_ADDRSTRLEN
];
1179 struct zebra_vrf
*zvrf
;
1180 struct timeval detect_start_time
= {0, 0};
1181 char timebuf
[MONOTIME_STRLEN
];
1183 zvrf
= zebra_vrf_get_evpn();
1187 vty
= (struct vty
*)ctxt
;
1188 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1191 json_object
*json_mac
= json_object_new_object();
1193 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1194 struct zebra_ns
*zns
;
1195 struct interface
*ifp
;
1198 ifindex
= mac
->fwd_info
.local
.ifindex
;
1199 zns
= zebra_ns_lookup(NS_DEFAULT
);
1200 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1203 json_object_string_add(json_mac
, "type", "local");
1204 json_object_string_add(json_mac
, "intf", ifp
->name
);
1205 json_object_int_add(json_mac
, "ifindex", ifindex
);
1206 if (mac
->fwd_info
.local
.vid
)
1207 json_object_int_add(json_mac
, "vlan",
1208 mac
->fwd_info
.local
.vid
);
1209 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1210 json_object_string_add(json_mac
, "type", "remote");
1211 json_object_string_add(
1212 json_mac
, "remoteVtep",
1213 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1214 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1215 json_object_string_add(json_mac
, "type", "auto");
1217 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1218 json_object_boolean_true_add(json_mac
, "stickyMac");
1220 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1221 json_object_boolean_true_add(json_mac
,
1224 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1225 json_object_boolean_true_add(json_mac
,
1226 "remoteGatewayMac");
1228 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1229 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1231 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1232 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1233 json_object_boolean_true_add(json_mac
, "isDuplicate");
1235 json_object_boolean_false_add(json_mac
, "isDuplicate");
1237 /* print all the associated neigh */
1238 if (!listcount(mac
->neigh_list
))
1239 json_object_string_add(json_mac
, "neighbors", "none");
1241 json_object
*json_active_nbrs
= json_object_new_array();
1242 json_object
*json_inactive_nbrs
=
1243 json_object_new_array();
1244 json_object
*json_nbrs
= json_object_new_object();
1246 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1247 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1248 json_object_array_add(
1250 json_object_new_string(
1255 json_object_array_add(
1257 json_object_new_string(
1263 json_object_object_add(json_nbrs
, "active",
1265 json_object_object_add(json_nbrs
, "inactive",
1266 json_inactive_nbrs
);
1267 json_object_object_add(json_mac
, "neighbors",
1271 json_object_object_add(json
, buf1
, json_mac
);
1273 vty_out(vty
, "MAC: %s\n", buf1
);
1275 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1276 struct zebra_ns
*zns
;
1277 struct interface
*ifp
;
1280 ifindex
= mac
->fwd_info
.local
.ifindex
;
1281 zns
= zebra_ns_lookup(NS_DEFAULT
);
1282 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1285 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1286 if (mac
->fwd_info
.local
.vid
)
1287 vty_out(vty
, " VLAN: %u",
1288 mac
->fwd_info
.local
.vid
);
1289 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1290 vty_out(vty
, " Remote VTEP: %s",
1291 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1292 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1293 vty_out(vty
, " Auto Mac ");
1296 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1297 vty_out(vty
, " Sticky Mac ");
1299 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1300 vty_out(vty
, " Default-gateway Mac ");
1302 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1303 vty_out(vty
, " Remote-gateway Mac ");
1306 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1310 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1311 vty_out(vty
, " Duplicate, detected at %s",
1312 time_to_string(mac
->dad_dup_detect_time
,
1314 } else if (mac
->dad_count
) {
1315 monotime_since(&mac
->detect_start_time
,
1316 &detect_start_time
);
1317 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1318 time_to_string(mac
->detect_start_time
.tv_sec
,
1321 " Duplicate detection started at %s, detection count %u\n",
1322 timebuf
, mac
->dad_count
);
1326 /* print all the associated neigh */
1327 vty_out(vty
, " Neighbors:\n");
1328 if (!listcount(mac
->neigh_list
))
1329 vty_out(vty
, " No Neighbors\n");
1331 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1332 vty_out(vty
, " %s %s\n",
1333 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1334 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1345 * Print MAC hash entry - called for display of all MACs.
1347 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1350 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1352 char buf1
[ETHER_ADDR_STRLEN
];
1353 struct mac_walk_ctx
*wctx
= ctxt
;
1356 json_mac_hdr
= wctx
->json
;
1357 mac
= (zebra_mac_t
*)bucket
->data
;
1359 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1362 json_mac
= json_object_new_object();
1364 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1365 struct zebra_ns
*zns
;
1367 struct interface
*ifp
;
1370 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1373 zns
= zebra_ns_lookup(NS_DEFAULT
);
1374 ifindex
= mac
->fwd_info
.local
.ifindex
;
1375 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1376 if (!ifp
) // unexpected
1378 vid
= mac
->fwd_info
.local
.vid
;
1379 if (json_mac_hdr
== NULL
)
1380 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1383 json_object_string_add(json_mac
, "type", "local");
1384 json_object_string_add(json_mac
, "intf", ifp
->name
);
1387 if (json_mac_hdr
== NULL
)
1388 vty_out(vty
, " %-5u", vid
);
1390 json_object_int_add(json_mac
, "vlan", vid
);
1391 } else /* No vid? fill out the space */
1392 if (json_mac_hdr
== NULL
)
1393 vty_out(vty
, " %-5s", "");
1394 if (json_mac_hdr
== NULL
) {
1395 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1398 json_object_int_add(json_mac
, "localSequence",
1400 json_object_int_add(json_mac
, "remoteSequence",
1402 json_object_int_add(json_mac
, "detectionCount",
1404 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1405 json_object_boolean_true_add(json_mac
,
1408 json_object_boolean_false_add(json_mac
,
1410 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1415 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1417 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1418 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1422 if (json_mac_hdr
== NULL
) {
1423 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1424 (wctx
->count
== 0)) {
1425 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1426 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n",
1427 "MAC", "Type", "Intf/Remote VTEP",
1430 vty_out(vty
, "%-17s %-6s %-21s %-5s %u/%u\n", buf1
,
1431 "remote", inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1432 "", mac
->loc_seq
, mac
->rem_seq
);
1434 json_object_string_add(json_mac
, "type", "remote");
1435 json_object_string_add(json_mac
, "remoteVtep",
1436 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1437 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1438 json_object_int_add(json_mac
, "localSequence",
1440 json_object_int_add(json_mac
, "remoteSequence",
1442 json_object_int_add(json_mac
, "detectionCount",
1444 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1445 json_object_boolean_true_add(json_mac
,
1448 json_object_boolean_false_add(json_mac
,
1457 /* Print Duplicate MAC */
1458 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1462 mac
= (zebra_mac_t
*)bucket
->data
;
1466 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1467 zvni_print_mac_hash(bucket
, ctxt
);
1471 * Print MAC hash entry in detail - called for display of all MACs.
1473 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1476 json_object
*json_mac_hdr
= NULL
;
1478 struct mac_walk_ctx
*wctx
= ctxt
;
1479 char buf1
[ETHER_ADDR_STRLEN
];
1482 json_mac_hdr
= wctx
->json
;
1483 mac
= (zebra_mac_t
*)bucket
->data
;
1488 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1490 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1493 /* Print Duplicate MAC in detail */
1494 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1499 mac
= (zebra_mac_t
*)bucket
->data
;
1503 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1504 zvni_print_mac_hash_detail(bucket
, ctxt
);
1508 * Print MACs for all VNI.
1510 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1513 json_object
*json
= NULL
, *json_vni
= NULL
;
1514 json_object
*json_mac
= NULL
;
1517 struct mac_walk_ctx
*wctx
= ctxt
;
1518 char vni_str
[VNI_STR_LEN
];
1520 vty
= (struct vty
*)wctx
->vty
;
1521 json
= (struct json_object
*)wctx
->json
;
1523 zvni
= (zebra_vni_t
*)bucket
->data
;
1526 /*We are iterating over a new VNI, set the count to 0*/
1529 num_macs
= num_valid_macs(zvni
);
1533 if (wctx
->print_dup
)
1534 num_macs
= num_dup_detected_macs(zvni
);
1537 json_vni
= json_object_new_object();
1538 json_mac
= json_object_new_object();
1539 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1542 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1544 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1545 zvni
->vni
, num_macs
);
1546 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC",
1547 "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
1549 json_object_int_add(json_vni
, "numMacs", num_macs
);
1554 json_object_int_add(json_vni
, "numMacs", num_macs
);
1555 json_object_object_add(json
, vni_str
, json_vni
);
1560 /* assign per-vni to wctx->json object to fill macs
1561 * under the vni. Re-assign primary json object to fill
1562 * next vni information.
1564 wctx
->json
= json_mac
;
1565 if (wctx
->print_dup
)
1566 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1568 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1572 json_object_object_add(json_vni
, "macs", json_mac
);
1573 json_object_object_add(json
, vni_str
, json_vni
);
1578 * Print MACs in detail for all VNI.
1580 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1584 json_object
*json
= NULL
, *json_vni
= NULL
;
1585 json_object
*json_mac
= NULL
;
1588 struct mac_walk_ctx
*wctx
= ctxt
;
1589 char vni_str
[VNI_STR_LEN
];
1591 vty
= (struct vty
*)wctx
->vty
;
1592 json
= (struct json_object
*)wctx
->json
;
1594 zvni
= (zebra_vni_t
*)bucket
->data
;
1597 vty_out(vty
, "{}\n");
1602 /*We are iterating over a new VNI, set the count to 0*/
1605 num_macs
= num_valid_macs(zvni
);
1609 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1613 json_vni
= json_object_new_object();
1614 json_mac
= json_object_new_object();
1615 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1618 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1620 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1621 zvni
->vni
, num_macs
);
1623 json_object_int_add(json_vni
, "numMacs", num_macs
);
1625 /* assign per-vni to wctx->json object to fill macs
1626 * under the vni. Re-assign primary json object to fill
1627 * next vni information.
1629 wctx
->json
= json_mac
;
1630 if (wctx
->print_dup
)
1631 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1634 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1638 json_object_object_add(json_vni
, "macs", json_mac
);
1639 json_object_object_add(json
, vni_str
, json_vni
);
1643 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1645 struct nh_walk_ctx
*wctx
= NULL
;
1646 struct vty
*vty
= NULL
;
1647 struct json_object
*json_vni
= NULL
;
1648 struct json_object
*json_nh
= NULL
;
1649 zebra_neigh_t
*n
= NULL
;
1650 char buf1
[ETHER_ADDR_STRLEN
];
1651 char buf2
[INET6_ADDRSTRLEN
];
1653 wctx
= (struct nh_walk_ctx
*)ctx
;
1655 json_vni
= wctx
->json
;
1657 json_nh
= json_object_new_object();
1658 n
= (zebra_neigh_t
*)bucket
->data
;
1661 vty_out(vty
, "%-15s %-17s\n",
1662 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1663 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1665 json_object_string_add(json_nh
, "nexthopIp",
1666 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1667 json_object_string_add(
1668 json_nh
, "routerMac",
1669 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1670 json_object_object_add(json_vni
,
1671 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1676 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1679 struct vty
*vty
= NULL
;
1680 json_object
*json
= NULL
;
1681 json_object
*json_vni
= NULL
;
1682 zebra_l3vni_t
*zl3vni
= NULL
;
1683 uint32_t num_nh
= 0;
1684 struct nh_walk_ctx wctx
;
1685 char vni_str
[VNI_STR_LEN
];
1687 vty
= (struct vty
*)args
[0];
1688 json
= (struct json_object
*)args
[1];
1690 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1692 num_nh
= hashcount(zl3vni
->nh_table
);
1697 json_vni
= json_object_new_object();
1698 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1702 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1703 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1705 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1707 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1709 wctx
.json
= json_vni
;
1710 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1712 json_object_object_add(json
, vni_str
, json_vni
);
1715 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1718 struct vty
*vty
= NULL
;
1719 json_object
*json
= NULL
;
1720 json_object
*json_vni
= NULL
;
1721 zebra_l3vni_t
*zl3vni
= NULL
;
1723 struct rmac_walk_ctx wctx
;
1724 char vni_str
[VNI_STR_LEN
];
1726 vty
= (struct vty
*)args
[0];
1727 json
= (struct json_object
*)args
[1];
1729 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1731 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1736 json_vni
= json_object_new_object();
1737 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1741 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1742 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1744 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1746 /* assign per-vni to wctx->json object to fill macs
1747 * under the vni. Re-assign primary json object to fill
1748 * next vni information.
1750 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1752 wctx
.json
= json_vni
;
1753 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1755 json_object_object_add(json
, vni_str
, json_vni
);
1758 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1760 zebra_mac_t
*zrmac
= NULL
;
1761 struct rmac_walk_ctx
*wctx
= NULL
;
1762 struct vty
*vty
= NULL
;
1763 struct json_object
*json
= NULL
;
1764 struct json_object
*json_rmac
= NULL
;
1765 char buf
[ETHER_ADDR_STRLEN
];
1767 wctx
= (struct rmac_walk_ctx
*)ctx
;
1771 json_rmac
= json_object_new_object();
1772 zrmac
= (zebra_mac_t
*)bucket
->data
;
1775 vty_out(vty
, "%-17s %-21s\n",
1776 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1777 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1779 json_object_string_add(
1780 json_rmac
, "routerMac",
1781 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1782 json_object_string_add(json_rmac
, "vtepIp",
1783 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1784 json_object_object_add(
1785 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1790 /* print a specific L3 VNI entry */
1791 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1793 char buf
[ETHER_ADDR_STRLEN
];
1794 struct vty
*vty
= NULL
;
1795 json_object
*json
= NULL
;
1796 zebra_vni_t
*zvni
= NULL
;
1797 json_object
*json_vni_list
= NULL
;
1798 struct listnode
*node
= NULL
, *nnode
= NULL
;
1804 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1805 vty_out(vty
, " Type: %s\n", "L3");
1806 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1807 vty_out(vty
, " Local Vtep Ip: %s\n",
1808 inet_ntoa(zl3vni
->local_vtep_ip
));
1809 vty_out(vty
, " Vxlan-Intf: %s\n",
1810 zl3vni_vxlan_if_name(zl3vni
));
1811 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1812 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1813 vty_out(vty
, " VNI Filter: %s\n",
1814 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1815 ? "prefix-routes-only"
1817 vty_out(vty
, " Router MAC: %s\n",
1818 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1819 vty_out(vty
, " L2 VNIs: ");
1820 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1821 vty_out(vty
, "%u ", zvni
->vni
);
1824 json_vni_list
= json_object_new_array();
1825 json_object_int_add(json
, "vni", zl3vni
->vni
);
1826 json_object_string_add(json
, "type", "L3");
1827 json_object_string_add(json
, "localVtepIp",
1828 inet_ntoa(zl3vni
->local_vtep_ip
));
1829 json_object_string_add(json
, "vxlanIntf",
1830 zl3vni_vxlan_if_name(zl3vni
));
1831 json_object_string_add(json
, "sviIntf",
1832 zl3vni_svi_if_name(zl3vni
));
1833 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1834 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1835 json_object_string_add(
1837 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1838 json_object_string_add(
1840 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1841 ? "prefix-routes-only"
1843 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1844 json_object_array_add(json_vni_list
,
1845 json_object_new_int(zvni
->vni
));
1847 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1852 * Print a specific VNI entry.
1854 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1857 zebra_vtep_t
*zvtep
;
1860 json_object
*json
= NULL
;
1861 json_object
*json_vtep_list
= NULL
;
1862 json_object
*json_ip_str
= NULL
;
1868 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1869 vty_out(vty
, " Type: %s\n", "L2");
1870 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1872 json_object_int_add(json
, "vni", zvni
->vni
);
1873 json_object_string_add(json
, "type", "L2");
1874 json_object_string_add(json
, "vrf",
1875 vrf_id_to_name(zvni
->vrf_id
));
1878 if (!zvni
->vxlan_if
) { // unexpected
1880 vty_out(vty
, " VxLAN interface: unknown\n");
1883 num_macs
= num_valid_macs(zvni
);
1884 num_neigh
= hashcount(zvni
->neigh_table
);
1886 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1887 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1888 vty_out(vty
, " Local VTEP IP: %s\n",
1889 inet_ntoa(zvni
->local_vtep_ip
));
1890 vty_out(vty
, " Mcast group: %s\n",
1891 inet_ntoa(zvni
->mcast_grp
));
1893 json_object_string_add(json
, "vxlanInterface",
1894 zvni
->vxlan_if
->name
);
1895 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1896 json_object_string_add(json
, "vtepIp",
1897 inet_ntoa(zvni
->local_vtep_ip
));
1898 json_object_string_add(json
, "mcastGroup",
1899 inet_ntoa(zvni
->mcast_grp
));
1900 json_object_string_add(json
, "advertiseGatewayMacip",
1901 zvni
->advertise_gw_macip
? "Yes" : "No");
1902 json_object_int_add(json
, "numMacs", num_macs
);
1903 json_object_int_add(json
, "numArpNd", num_neigh
);
1907 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1910 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1912 json_vtep_list
= json_object_new_array();
1913 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1914 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1915 zvtep
->flood_control
,
1916 VXLAN_FLOOD_STR_DEFAULT
);
1919 vty_out(vty
, " %s flood: %s\n",
1920 inet_ntoa(zvtep
->vtep_ip
),
1923 json_ip_str
= json_object_new_string(
1924 inet_ntoa(zvtep
->vtep_ip
));
1925 json_object_array_add(json_vtep_list
,
1930 json_object_object_add(json
, "numRemoteVteps",
1935 " Number of MACs (local and remote) known for this VNI: %u\n",
1938 " Number of ARPs (IPv4 and IPv6, local and remote) "
1939 "known for this VNI: %u\n",
1941 vty_out(vty
, " Advertise-gw-macip: %s\n",
1942 zvni
->advertise_gw_macip
? "Yes" : "No");
1946 /* print a L3 VNI hash entry */
1947 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1949 struct vty
*vty
= NULL
;
1950 json_object
*json
= NULL
;
1951 json_object
*json_vni
= NULL
;
1952 zebra_l3vni_t
*zl3vni
= NULL
;
1954 vty
= (struct vty
*)ctx
[0];
1955 json
= (json_object
*)ctx
[1];
1957 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1960 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1961 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1962 hashcount(zl3vni
->rmac_table
),
1963 hashcount(zl3vni
->nh_table
), "n/a",
1964 zl3vni_vrf_name(zl3vni
));
1966 char vni_str
[VNI_STR_LEN
];
1968 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1969 json_vni
= json_object_new_object();
1970 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1971 json_object_string_add(json_vni
, "vxlanIf",
1972 zl3vni_vxlan_if_name(zl3vni
));
1973 json_object_int_add(json_vni
, "numMacs",
1974 hashcount(zl3vni
->rmac_table
));
1975 json_object_int_add(json_vni
, "numArpNd",
1976 hashcount(zl3vni
->nh_table
));
1977 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1978 json_object_string_add(json_vni
, "type", "L3");
1979 json_object_string_add(json_vni
, "tenantVrf",
1980 zl3vni_vrf_name(zl3vni
));
1981 json_object_object_add(json
, vni_str
, json_vni
);
1985 /* Private Structure to pass callback data for hash iterator */
1986 struct zvni_evpn_show
{
1989 struct zebra_vrf
*zvrf
;
1992 /* print a L3 VNI hash entry in detail*/
1993 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1995 struct vty
*vty
= NULL
;
1996 zebra_l3vni_t
*zl3vni
= NULL
;
1997 json_object
*json
= NULL
;
1998 bool use_json
= false;
1999 struct zvni_evpn_show
*zes
= data
;
2007 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2009 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2015 * Print a VNI hash entry - called for display of all VNIs.
2017 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2021 zebra_vtep_t
*zvtep
;
2022 uint32_t num_vteps
= 0;
2023 uint32_t num_macs
= 0;
2024 uint32_t num_neigh
= 0;
2025 json_object
*json
= NULL
;
2026 json_object
*json_vni
= NULL
;
2027 json_object
*json_ip_str
= NULL
;
2028 json_object
*json_vtep_list
= NULL
;
2033 zvni
= (zebra_vni_t
*)bucket
->data
;
2035 zvtep
= zvni
->vteps
;
2038 zvtep
= zvtep
->next
;
2041 num_macs
= num_valid_macs(zvni
);
2042 num_neigh
= hashcount(zvni
->neigh_table
);
2044 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2046 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2047 num_macs
, num_neigh
, num_vteps
,
2048 vrf_id_to_name(zvni
->vrf_id
));
2050 char vni_str
[VNI_STR_LEN
];
2051 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2052 json_vni
= json_object_new_object();
2053 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2054 json_object_string_add(json_vni
, "type", "L2");
2055 json_object_string_add(json_vni
, "vxlanIf",
2056 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2058 json_object_int_add(json_vni
, "numMacs", num_macs
);
2059 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2060 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2061 json_object_string_add(json_vni
, "tenantVrf",
2062 vrf_id_to_name(zvni
->vrf_id
));
2064 json_vtep_list
= json_object_new_array();
2065 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2066 json_ip_str
= json_object_new_string(
2067 inet_ntoa(zvtep
->vtep_ip
));
2068 json_object_array_add(json_vtep_list
,
2071 json_object_object_add(json_vni
, "remoteVteps",
2074 json_object_object_add(json
, vni_str
, json_vni
);
2079 * Print a VNI hash entry in detail - called for display of all VNIs.
2081 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2085 json_object
*json
= NULL
;
2086 bool use_json
= false;
2087 struct zvni_evpn_show
*zes
= data
;
2095 zvni
= (zebra_vni_t
*)bucket
->data
;
2097 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2102 * Inform BGP about local MACIP.
2104 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2105 struct ipaddr
*ip
, uint8_t flags
,
2106 uint32_t seq
, int state
, uint16_t cmd
)
2108 char buf
[ETHER_ADDR_STRLEN
];
2109 char buf2
[INET6_ADDRSTRLEN
];
2111 struct zserv
*client
= NULL
;
2112 struct stream
*s
= NULL
;
2114 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2115 /* BGP may not be running. */
2119 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2121 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2122 stream_putl(s
, vni
);
2123 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2126 if (IS_IPADDR_V4(ip
))
2127 ipa_len
= IPV4_MAX_BYTELEN
;
2128 else if (IS_IPADDR_V6(ip
))
2129 ipa_len
= IPV6_MAX_BYTELEN
;
2131 stream_putl(s
, ipa_len
); /* IP address length */
2133 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2135 stream_putl(s
, 0); /* Just MAC. */
2137 if (cmd
== ZEBRA_MACIP_ADD
) {
2138 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2139 stream_putl(s
, seq
); /* sequence number */
2141 stream_putl(s
, state
); /* state - active/inactive */
2145 /* Write packet size. */
2146 stream_putw_at(s
, 0, stream_get_endp(s
));
2148 if (IS_ZEBRA_DEBUG_VXLAN
)
2150 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2151 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2152 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2153 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2154 zebra_route_string(client
->proto
));
2156 if (cmd
== ZEBRA_MACIP_ADD
)
2157 client
->macipadd_cnt
++;
2159 client
->macipdel_cnt
++;
2161 return zserv_send_message(client
, s
);
2165 * Make hash key for neighbors.
2167 static unsigned int neigh_hash_keymake(const void *p
)
2169 const zebra_neigh_t
*n
= p
;
2170 const struct ipaddr
*ip
= &n
->ip
;
2172 if (IS_IPADDR_V4(ip
))
2173 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2175 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2176 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2180 * Compare two neighbor hash structures.
2182 static bool neigh_cmp(const void *p1
, const void *p2
)
2184 const zebra_neigh_t
*n1
= p1
;
2185 const zebra_neigh_t
*n2
= p2
;
2187 if (n1
== NULL
&& n2
== NULL
)
2190 if (n1
== NULL
|| n2
== NULL
)
2193 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2196 static int neigh_list_cmp(void *p1
, void *p2
)
2198 const zebra_neigh_t
*n1
= p1
;
2199 const zebra_neigh_t
*n2
= p2
;
2201 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2205 * Callback to allocate neighbor hash entry.
2207 static void *zvni_neigh_alloc(void *p
)
2209 const zebra_neigh_t
*tmp_n
= p
;
2212 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2219 * Add neighbor entry.
2221 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2222 struct ethaddr
*mac
)
2224 zebra_neigh_t tmp_n
;
2225 zebra_neigh_t
*n
= NULL
;
2226 zebra_mac_t
*zmac
= NULL
;
2228 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2229 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2230 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2233 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2234 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2236 n
->dad_ip_auto_recovery_timer
= NULL
;
2238 /* Associate the neigh to mac */
2239 zmac
= zvni_mac_lookup(zvni
, mac
);
2241 listnode_add_sort(zmac
->neigh_list
, n
);
2247 * Delete neighbor entry.
2249 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2251 zebra_neigh_t
*tmp_n
;
2252 zebra_mac_t
*zmac
= NULL
;
2254 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2256 listnode_delete(zmac
->neigh_list
, n
);
2258 /* Cancel auto recovery */
2259 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2261 /* Free the VNI hash entry and allocated memory. */
2262 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2263 XFREE(MTYPE_NEIGH
, tmp_n
);
2269 * Free neighbor hash entry (callback)
2271 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2273 struct neigh_walk_ctx
*wctx
= arg
;
2274 zebra_neigh_t
*n
= bucket
->data
;
2276 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2277 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2278 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2279 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2280 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2281 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2282 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2283 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2284 &n
->emac
, 0, n
->state
);
2286 if (wctx
->uninstall
)
2287 zvni_neigh_uninstall(wctx
->zvni
, n
);
2289 zvni_neigh_del(wctx
->zvni
, n
);
2296 * Delete all neighbor entries from specific VTEP for a particular VNI.
2298 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2299 struct in_addr
*r_vtep_ip
)
2301 struct neigh_walk_ctx wctx
;
2303 if (!zvni
->neigh_table
)
2306 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2308 wctx
.uninstall
= uninstall
;
2309 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2310 wctx
.r_vtep_ip
= *r_vtep_ip
;
2312 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2316 * Delete all neighbor entries for this VNI.
2318 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2321 struct neigh_walk_ctx wctx
;
2323 if (!zvni
->neigh_table
)
2326 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2328 wctx
.uninstall
= uninstall
;
2329 wctx
.upd_client
= upd_client
;
2332 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2336 * Look up neighbor hash entry.
2338 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2343 memset(&tmp
, 0, sizeof(tmp
));
2344 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2345 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2351 * Process all neighbors associated with a MAC upon the MAC being learnt
2352 * locally or undergoing any other change (such as sequence number).
2354 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2358 zebra_neigh_t
*n
= NULL
;
2359 struct listnode
*node
= NULL
;
2360 struct zebra_vrf
*zvrf
= NULL
;
2361 char buf
[ETHER_ADDR_STRLEN
];
2363 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2365 if (IS_ZEBRA_DEBUG_VXLAN
)
2366 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2367 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2368 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2370 /* Walk all neighbors and mark any inactive local neighbors as
2371 * active and/or update sequence number upon a move, and inform BGP.
2372 * The action for remote neighbors is TBD.
2373 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2374 * accidentally end up deleting a just-learnt local neighbor.
2376 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2377 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2378 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2379 ZEBRA_NEIGH_SET_ACTIVE(n
);
2380 n
->loc_seq
= zmac
->loc_seq
;
2381 if (!(zvrf
->dup_addr_detect
&&
2382 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2383 ZEBRA_NEIGH_DUPLICATE
)))
2384 zvni_neigh_send_add_to_client(
2385 zvni
->vni
, &n
->ip
, &n
->emac
,
2386 n
->flags
, n
->loc_seq
);
2393 * Process all neighbors associated with a local MAC upon the MAC being
2396 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2399 zebra_neigh_t
*n
= NULL
;
2400 struct listnode
*node
= NULL
;
2401 char buf
[ETHER_ADDR_STRLEN
];
2403 if (IS_ZEBRA_DEBUG_VXLAN
)
2404 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2405 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2408 /* Walk all local neighbors and mark as inactive and inform
2410 * TBD: There is currently no handling for remote neighbors. We
2411 * don't expect them to exist, if they do, do we install the MAC
2412 * as a remote MAC and the neighbor as remote?
2414 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2415 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2416 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2417 ZEBRA_NEIGH_SET_INACTIVE(n
);
2419 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2420 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2427 * Process all neighbors associated with a MAC upon the MAC being remotely
2430 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2433 zebra_neigh_t
*n
= NULL
;
2434 struct listnode
*node
= NULL
;
2435 char buf
[ETHER_ADDR_STRLEN
];
2437 if (IS_ZEBRA_DEBUG_VXLAN
)
2438 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2439 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2442 /* Walk all local neighbors and mark as inactive and inform
2445 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2446 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2447 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2448 ZEBRA_NEIGH_SET_INACTIVE(n
);
2450 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2451 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2458 * Process all neighbors associated with a remote MAC upon the MAC being
2461 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2464 /* NOTE: Currently a NO-OP. */
2467 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2469 zebra_neigh_t
*nbr
= NULL
;
2470 struct listnode
*node
= NULL
;
2472 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2473 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2474 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2475 zvni_neigh_probe(zvni
, nbr
);
2480 * Inform BGP about local neighbor addition.
2482 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2483 struct ethaddr
*macaddr
,
2484 uint8_t neigh_flags
,
2489 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2490 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2491 /* Set router flag (R-bit) based on local neigh entry add */
2492 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2493 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2495 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2496 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2500 * Inform BGP about local neighbor deletion.
2502 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2503 struct ethaddr
*macaddr
, uint8_t flags
,
2506 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2507 0, state
, ZEBRA_MACIP_DEL
);
2511 * Install remote neighbor into the kernel.
2513 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2515 struct zebra_if
*zif
;
2516 struct zebra_l2info_vxlan
*vxl
;
2517 struct interface
*vlan_if
;
2521 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2524 zif
= zvni
->vxlan_if
->info
;
2527 vxl
= &zif
->l2info
.vxl
;
2529 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2533 flags
= DPLANE_NTF_EXT_LEARNED
;
2534 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2535 flags
|= DPLANE_NTF_ROUTER
;
2536 ZEBRA_NEIGH_SET_ACTIVE(n
);
2538 dplane_neigh_add(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2544 * Uninstall remote neighbor from the kernel.
2546 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2548 struct zebra_if
*zif
;
2549 struct zebra_l2info_vxlan
*vxl
;
2550 struct interface
*vlan_if
;
2552 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2555 if (!zvni
->vxlan_if
) {
2556 if (IS_ZEBRA_DEBUG_VXLAN
)
2557 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2562 zif
= zvni
->vxlan_if
->info
;
2565 vxl
= &zif
->l2info
.vxl
;
2566 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2570 ZEBRA_NEIGH_SET_INACTIVE(n
);
2573 dplane_neigh_delete(vlan_if
, &n
->ip
);
2579 * Probe neighbor from the kernel.
2581 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2583 struct zebra_if
*zif
;
2584 struct zebra_l2info_vxlan
*vxl
;
2585 struct interface
*vlan_if
;
2587 zif
= zvni
->vxlan_if
->info
;
2590 vxl
= &zif
->l2info
.vxl
;
2592 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2596 dplane_neigh_update(vlan_if
, &n
->ip
, &n
->emac
);
2602 * Install neighbor hash entry - called upon access VLAN change.
2604 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2607 struct neigh_walk_ctx
*wctx
= ctxt
;
2609 n
= (zebra_neigh_t
*)bucket
->data
;
2611 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2612 zvni_neigh_install(wctx
->zvni
, n
);
2615 /* Get the VRR interface for SVI if any */
2616 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2618 struct zebra_vrf
*zvrf
= NULL
;
2619 struct interface
*tmp_if
= NULL
;
2620 struct zebra_if
*zif
= NULL
;
2622 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2625 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2630 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2633 if (zif
->link
== ifp
)
2640 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2642 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2643 struct connected
*c
= NULL
;
2644 struct ethaddr macaddr
;
2646 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2648 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2651 memset(&ip
, 0, sizeof(struct ipaddr
));
2652 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2655 if (c
->address
->family
== AF_INET
) {
2656 ip
.ipa_type
= IPADDR_V4
;
2657 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2658 sizeof(struct in_addr
));
2659 } else if (c
->address
->family
== AF_INET6
) {
2660 ip
.ipa_type
= IPADDR_V6
;
2661 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2662 sizeof(struct in6_addr
));
2667 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2673 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2675 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2676 struct connected
*c
= NULL
;
2677 struct ethaddr macaddr
;
2679 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2681 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2684 memset(&ip
, 0, sizeof(struct ipaddr
));
2685 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2688 if (c
->address
->family
== AF_INET
) {
2689 ip
.ipa_type
= IPADDR_V4
;
2690 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2691 sizeof(struct in_addr
));
2692 } else if (c
->address
->family
== AF_INET6
) {
2693 ip
.ipa_type
= IPADDR_V6
;
2694 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2695 sizeof(struct in6_addr
));
2700 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2706 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2709 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2710 struct connected
*c
= NULL
;
2711 struct ethaddr macaddr
;
2713 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2715 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2718 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2720 /* skip link local address */
2721 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2726 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2727 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2729 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2730 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2736 * zvni_gw_macip_add_to_client
2738 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2739 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2741 char buf
[ETHER_ADDR_STRLEN
];
2742 char buf2
[INET6_ADDRSTRLEN
];
2743 zebra_neigh_t
*n
= NULL
;
2744 zebra_mac_t
*mac
= NULL
;
2745 struct zebra_if
*zif
= NULL
;
2746 struct zebra_l2info_vxlan
*vxl
= NULL
;
2748 zif
= zvni
->vxlan_if
->info
;
2752 vxl
= &zif
->l2info
.vxl
;
2754 mac
= zvni_mac_lookup(zvni
, macaddr
);
2756 mac
= zvni_mac_add(zvni
, macaddr
);
2758 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2759 "Failed to add MAC %s intf %s(%u) VID %u",
2760 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2761 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2766 /* Set "local" forwarding info. */
2767 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2768 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2769 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2770 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2771 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2772 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2774 n
= zvni_neigh_lookup(zvni
, ip
);
2776 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2779 EC_ZEBRA_MAC_ADD_FAILED
,
2780 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2781 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2782 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2783 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2788 /* Set "local" forwarding info. */
2789 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2790 ZEBRA_NEIGH_SET_ACTIVE(n
);
2791 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2792 n
->ifindex
= ifp
->ifindex
;
2794 /* Only advertise in BGP if the knob is enabled */
2795 if (advertise_gw_macip_enabled(zvni
)) {
2797 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2798 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2799 /* Set Router flag (R-bit) */
2800 if (ip
->ipa_type
== IPADDR_V6
)
2801 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2803 if (IS_ZEBRA_DEBUG_VXLAN
)
2805 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2806 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2807 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2808 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2810 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2811 n
->flags
, n
->loc_seq
);
2812 } else if (advertise_svi_macip_enabled(zvni
)) {
2814 if (IS_ZEBRA_DEBUG_VXLAN
)
2816 "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
2817 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2818 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2819 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2821 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2822 n
->flags
, n
->loc_seq
);
2829 * zvni_gw_macip_del_from_client
2831 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2834 char buf1
[ETHER_ADDR_STRLEN
];
2835 char buf2
[INET6_ADDRSTRLEN
];
2836 zebra_neigh_t
*n
= NULL
;
2837 zebra_mac_t
*mac
= NULL
;
2839 /* If the neigh entry is not present nothing to do*/
2840 n
= zvni_neigh_lookup(zvni
, ip
);
2844 /* mac entry should be present */
2845 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2847 if (IS_ZEBRA_DEBUG_VXLAN
)
2848 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2849 prefix_mac2str(&n
->emac
,
2850 buf1
, sizeof(buf1
)),
2851 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2856 /* If the entry is not local nothing to do*/
2857 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2860 /* only need to delete the entry from bgp if we sent it before */
2861 if (IS_ZEBRA_DEBUG_VXLAN
)
2863 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2864 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2865 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2866 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2868 /* Remove neighbor from BGP. */
2869 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2870 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2872 /* Delete this neighbor entry. */
2873 zvni_neigh_del(zvni
, n
);
2875 /* see if the mac needs to be deleted as well*/
2877 zvni_deref_ip2mac(zvni
, mac
);
2882 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2885 zebra_vni_t
*zvni
= NULL
;
2886 struct zebra_if
*zif
= NULL
;
2887 struct zebra_l2info_vxlan zl2_info
;
2888 struct interface
*vlan_if
= NULL
;
2889 struct interface
*vrr_if
= NULL
;
2890 struct interface
*ifp
;
2892 /* Add primary SVI MAC*/
2893 zvni
= (zebra_vni_t
*)bucket
->data
;
2895 /* Global (Zvrf) advertise-default-gw is disabled,
2896 * but zvni advertise-default-gw is enabled
2898 if (zvni
->advertise_gw_macip
) {
2899 if (IS_ZEBRA_DEBUG_VXLAN
)
2900 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
2905 ifp
= zvni
->vxlan_if
;
2910 /* If down or not mapped to a bridge, we're done. */
2911 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2914 zl2_info
= zif
->l2info
.vxl
;
2917 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2921 /* Del primary MAC-IP */
2922 zvni_del_macip_for_intf(vlan_if
, zvni
);
2924 /* Del VRR MAC-IP - if any*/
2925 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2927 zvni_del_macip_for_intf(vrr_if
, zvni
);
2932 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2935 zebra_vni_t
*zvni
= NULL
;
2936 struct zebra_if
*zif
= NULL
;
2937 struct zebra_l2info_vxlan zl2_info
;
2938 struct interface
*vlan_if
= NULL
;
2939 struct interface
*vrr_if
= NULL
;
2940 struct interface
*ifp
= NULL
;
2942 zvni
= (zebra_vni_t
*)bucket
->data
;
2944 ifp
= zvni
->vxlan_if
;
2949 /* If down or not mapped to a bridge, we're done. */
2950 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2952 zl2_info
= zif
->l2info
.vxl
;
2955 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2959 /* Add primary SVI MAC-IP */
2960 zvni_add_macip_for_intf(vlan_if
, zvni
);
2962 if (advertise_gw_macip_enabled(zvni
)) {
2963 /* Add VRR MAC-IP - if any*/
2964 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2966 zvni_add_macip_for_intf(vrr_if
, zvni
);
2972 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2975 zebra_vni_t
*zvni
= NULL
;
2976 struct zebra_if
*zif
= NULL
;
2977 struct zebra_l2info_vxlan zl2_info
;
2978 struct interface
*vlan_if
= NULL
;
2979 struct interface
*ifp
;
2981 /* Add primary SVI MAC*/
2982 zvni
= (zebra_vni_t
*)bucket
->data
;
2986 /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
2989 if (zvni
->advertise_svi_macip
) {
2990 if (IS_ZEBRA_DEBUG_VXLAN
)
2991 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
2996 ifp
= zvni
->vxlan_if
;
3001 /* If down or not mapped to a bridge, we're done. */
3002 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3005 zl2_info
= zif
->l2info
.vxl
;
3007 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
3008 zif
->brslave_info
.br_if
);
3012 /* Del primary MAC-IP */
3013 zvni_del_macip_for_intf(vlan_if
, zvni
);
3018 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
3019 struct interface
*ifp
,
3021 struct ethaddr
*macaddr
,
3024 char buf
[ETHER_ADDR_STRLEN
];
3025 char buf2
[INET6_ADDRSTRLEN
];
3026 struct zebra_vrf
*zvrf
;
3027 zebra_neigh_t
*n
= NULL
;
3028 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3029 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3030 bool upd_mac_seq
= false;
3031 bool neigh_mac_change
= false;
3032 bool neigh_on_hold
= false;
3033 bool neigh_was_remote
= false;
3034 bool do_dad
= false;
3035 struct in_addr vtep_ip
= {.s_addr
= 0};
3037 /* Check if the MAC exists. */
3038 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3040 /* create a dummy MAC if the MAC is not already present */
3041 if (IS_ZEBRA_DEBUG_VXLAN
)
3043 "AUTO MAC %s created for neigh %s on VNI %u",
3044 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3045 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3047 zmac
= zvni_mac_add(zvni
, macaddr
);
3049 zlog_debug("Failed to add MAC %s VNI %u",
3050 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3055 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3056 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3057 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3059 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3061 * We don't change the MAC to local upon a neighbor
3062 * learn event, we wait for the explicit local MAC
3063 * learn. However, we have to compute its sequence
3064 * number in preparation for when it actually turns
3071 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3073 if (IS_ZEBRA_DEBUG_VXLAN
)
3074 zlog_debug("\tUnable to find vrf for: %d",
3075 zvni
->vxlan_if
->vrf_id
);
3079 /* Check if the neighbor exists. */
3080 n
= zvni_neigh_lookup(zvni
, ip
);
3082 /* New neighbor - create */
3083 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3086 EC_ZEBRA_MAC_ADD_FAILED
,
3087 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3088 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3089 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3090 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3093 /* Set "local" forwarding info. */
3094 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3095 n
->ifindex
= ifp
->ifindex
;
3097 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3101 /* Note any changes and see if of interest to BGP. */
3102 mac_different
= (memcmp(n
->emac
.octet
,
3103 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3104 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3105 ZEBRA_NEIGH_ROUTER_FLAG
);
3106 if (!mac_different
&& is_router
== cur_is_router
) {
3107 if (IS_ZEBRA_DEBUG_VXLAN
)
3109 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3110 n
->ifindex
= ifp
->ifindex
;
3114 if (!mac_different
) {
3115 bool is_neigh_freezed
= false;
3117 /* Only the router flag has changed. */
3120 ZEBRA_NEIGH_ROUTER_FLAG
);
3122 UNSET_FLAG(n
->flags
,
3123 ZEBRA_NEIGH_ROUTER_FLAG
);
3125 /* Neigh is in freeze state and freeze action
3126 * is enabled, do not send update to client.
3128 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3130 CHECK_FLAG(n
->flags
,
3131 ZEBRA_NEIGH_DUPLICATE
));
3133 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3135 return zvni_neigh_send_add_to_client(
3136 zvni
->vni
, ip
, macaddr
,
3137 n
->flags
, n
->loc_seq
);
3139 if (IS_ZEBRA_DEBUG_VXLAN
)
3141 "\tNeighbor active and frozen");
3146 /* The MAC has changed, need to issue a delete
3147 * first as this means a different MACIP route.
3148 * Also, need to do some unlinking/relinking.
3149 * We also need to update the MAC's sequence number
3150 * in different situations.
3152 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3153 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3154 &n
->emac
, 0, n
->state
);
3155 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3157 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3159 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3160 neigh_mac_change
= upd_mac_seq
= true;
3161 listnode_delete(old_zmac
->neigh_list
, n
);
3162 zvni_deref_ip2mac(zvni
, old_zmac
);
3165 /* Update the forwarding info. */
3166 n
->ifindex
= ifp
->ifindex
;
3167 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3169 /* Link to new MAC */
3170 listnode_add_sort(zmac
->neigh_list
, n
);
3171 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3173 * Neighbor has moved from remote to local. Its
3174 * MAC could have also changed as part of the move.
3176 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3178 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3180 old_mac_seq
= CHECK_FLAG(
3185 neigh_mac_change
= upd_mac_seq
= true;
3186 listnode_delete(old_zmac
->neigh_list
,
3188 zvni_deref_ip2mac(zvni
, old_zmac
);
3191 /* Link to new MAC */
3192 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3193 listnode_add_sort(zmac
->neigh_list
, n
);
3195 /* Based on Mobility event Scenario-B from the
3196 * draft, neigh's previous state was remote treat this
3199 neigh_was_remote
= true;
3200 vtep_ip
= n
->r_vtep_ip
;
3201 /* Mark appropriately */
3202 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3203 n
->r_vtep_ip
.s_addr
= 0;
3204 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3205 n
->ifindex
= ifp
->ifindex
;
3209 /* If MAC was previously remote, or the neighbor had a different
3210 * MAC earlier, recompute the sequence number.
3213 uint32_t seq1
, seq2
;
3215 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3216 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3217 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3218 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3219 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3222 /* Mark Router flag (R-bit) */
3224 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3226 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3228 /* Check old and/or new MAC detected as duplicate mark
3229 * the neigh as duplicate
3231 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3232 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3233 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3235 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3236 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3239 /* For IP Duplicate Address Detection (DAD) is trigger,
3240 * when the event is extended mobility based on scenario-B
3241 * from the draft, IP/Neigh's MAC binding changed and
3242 * neigh's previous state was remote.
3244 if (neigh_mac_change
&& neigh_was_remote
)
3247 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3248 &neigh_on_hold
, true);
3250 /* Before we program this in BGP, we need to check if MAC is locally
3251 * learnt. If not, force neighbor to be inactive and reset its seq.
3253 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3254 ZEBRA_NEIGH_SET_INACTIVE(n
);
3256 zmac
->loc_seq
= mac_new_seq
;
3260 /* If the MAC's sequence number has changed, inform the MAC and all
3261 * neighbors associated with the MAC to BGP, else just inform this
3264 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3265 if (IS_ZEBRA_DEBUG_VXLAN
)
3266 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3267 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3268 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3269 zmac
->loc_seq
= mac_new_seq
;
3270 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3271 zmac
->flags
, zmac
->loc_seq
))
3273 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3277 n
->loc_seq
= zmac
->loc_seq
;
3279 if (!neigh_on_hold
) {
3280 ZEBRA_NEIGH_SET_ACTIVE(n
);
3282 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3283 n
->flags
, n
->loc_seq
);
3285 if (IS_ZEBRA_DEBUG_VXLAN
)
3286 zlog_debug("\tNeighbor on hold not sending");
3291 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3292 struct interface
*ifp
,
3294 struct ethaddr
*macaddr
,
3297 char buf
[ETHER_ADDR_STRLEN
];
3298 char buf2
[INET6_ADDRSTRLEN
];
3299 zebra_neigh_t
*n
= NULL
;
3300 zebra_mac_t
*zmac
= NULL
;
3302 /* If the neighbor is unknown, there is no further action. */
3303 n
= zvni_neigh_lookup(zvni
, ip
);
3307 /* If a remote entry, see if it needs to be refreshed */
3308 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3310 if (state
& NUD_STALE
)
3311 zvni_neigh_install(zvni
, n
);
3314 /* We got a "remote" neighbor notification for an entry
3315 * we think is local. This can happen in a multihoming
3316 * scenario - but only if the MAC is already "remote".
3317 * Just mark our entry as "remote".
3319 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3320 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3322 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3323 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3324 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3329 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3330 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3331 ZEBRA_NEIGH_SET_ACTIVE(n
);
3332 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3339 * Make hash key for MAC.
3341 static unsigned int mac_hash_keymake(const void *p
)
3343 const zebra_mac_t
*pmac
= p
;
3344 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3346 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3350 * Compare two MAC addresses.
3352 static bool mac_cmp(const void *p1
, const void *p2
)
3354 const zebra_mac_t
*pmac1
= p1
;
3355 const zebra_mac_t
*pmac2
= p2
;
3357 if (pmac1
== NULL
&& pmac2
== NULL
)
3360 if (pmac1
== NULL
|| pmac2
== NULL
)
3363 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3368 * Callback to allocate MAC hash entry.
3370 static void *zvni_mac_alloc(void *p
)
3372 const zebra_mac_t
*tmp_mac
= p
;
3375 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3378 return ((void *)mac
);
3384 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3386 zebra_mac_t tmp_mac
;
3387 zebra_mac_t
*mac
= NULL
;
3389 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3390 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3391 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3395 mac
->dad_mac_auto_recovery_timer
= NULL
;
3397 mac
->neigh_list
= list_new();
3398 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3406 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3408 zebra_mac_t
*tmp_mac
;
3410 /* Cancel auto recovery */
3411 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3413 list_delete(&mac
->neigh_list
);
3415 /* Free the VNI hash entry and allocated memory. */
3416 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3417 XFREE(MTYPE_MAC
, tmp_mac
);
3422 static bool zvni_check_mac_del_from_db(struct mac_walk_ctx
*wctx
,
3425 if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3426 (mac
->flags
& ZEBRA_MAC_LOCAL
))
3428 else if ((wctx
->flags
& DEL_REMOTE_MAC
) &&
3429 (mac
->flags
& ZEBRA_MAC_REMOTE
))
3431 else if ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
) &&
3432 (mac
->flags
& ZEBRA_MAC_REMOTE
) &&
3433 IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &wctx
->r_vtep_ip
))
3435 else if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3436 (mac
->flags
& ZEBRA_MAC_AUTO
) &&
3437 !listcount(mac
->neigh_list
)) {
3438 if (IS_ZEBRA_DEBUG_VXLAN
) {
3439 char buf
[ETHER_ADDR_STRLEN
];
3441 zlog_debug("%s: Del MAC %s flags 0x%x",
3442 __PRETTY_FUNCTION__
,
3443 prefix_mac2str(&mac
->macaddr
,
3447 wctx
->uninstall
= 0;
3456 * Free MAC hash entry (callback)
3458 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3460 struct mac_walk_ctx
*wctx
= arg
;
3461 zebra_mac_t
*mac
= bucket
->data
;
3463 if (zvni_check_mac_del_from_db(wctx
, mac
)) {
3464 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3465 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3468 if (wctx
->uninstall
)
3469 zvni_mac_uninstall(wctx
->zvni
, mac
);
3471 zvni_mac_del(wctx
->zvni
, mac
);
3478 * Delete all MAC entries from specific VTEP for a particular VNI.
3480 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3481 struct in_addr
*r_vtep_ip
)
3483 struct mac_walk_ctx wctx
;
3485 if (!zvni
->mac_table
)
3488 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3490 wctx
.uninstall
= uninstall
;
3491 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3492 wctx
.r_vtep_ip
= *r_vtep_ip
;
3494 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3498 * Delete all MAC entries for this VNI.
3500 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3503 struct mac_walk_ctx wctx
;
3505 if (!zvni
->mac_table
)
3508 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3510 wctx
.uninstall
= uninstall
;
3511 wctx
.upd_client
= upd_client
;
3514 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3518 * Look up MAC hash entry.
3520 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3525 memset(&tmp
, 0, sizeof(tmp
));
3526 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3527 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3533 * Inform BGP about local MAC addition.
3535 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3536 uint8_t mac_flags
, uint32_t seq
)
3540 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3541 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3542 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3543 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3545 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3546 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3550 * Inform BGP about local MAC deletion.
3552 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3554 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3555 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3559 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3560 * notifications, to see if they are of interest.
3562 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3563 struct interface
*br_if
, vlanid_t vid
)
3565 struct zebra_ns
*zns
;
3566 struct route_node
*rn
;
3567 struct interface
*tmp_if
= NULL
;
3568 struct zebra_if
*zif
;
3569 struct zebra_l2info_bridge
*br
;
3570 struct zebra_l2info_vxlan
*vxl
= NULL
;
3571 uint8_t bridge_vlan_aware
;
3575 /* Determine if bridge is VLAN-aware or not */
3578 br
= &zif
->l2info
.br
;
3579 bridge_vlan_aware
= br
->vlan_aware
;
3581 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3582 /* TODO: Optimize with a hash. */
3583 zns
= zebra_ns_lookup(NS_DEFAULT
);
3584 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3585 tmp_if
= (struct interface
*)rn
->info
;
3589 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3591 if (!if_is_operative(tmp_if
))
3593 vxl
= &zif
->l2info
.vxl
;
3595 if (zif
->brslave_info
.br_if
!= br_if
)
3598 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3607 zvni
= zvni_lookup(vxl
->vni
);
3612 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3613 * neighbor notifications, to see if they are of interest.
3615 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3616 struct interface
*br_if
)
3618 struct zebra_ns
*zns
;
3619 struct route_node
*rn
;
3620 struct interface
*tmp_if
= NULL
;
3621 struct zebra_if
*zif
;
3622 struct zebra_l2info_bridge
*br
;
3623 struct zebra_l2info_vxlan
*vxl
= NULL
;
3624 uint8_t bridge_vlan_aware
;
3632 /* Make sure the linked interface is a bridge. */
3633 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3636 /* Determine if bridge is VLAN-aware or not */
3639 br
= &zif
->l2info
.br
;
3640 bridge_vlan_aware
= br
->vlan_aware
;
3641 if (bridge_vlan_aware
) {
3642 struct zebra_l2info_vlan
*vl
;
3644 if (!IS_ZEBRA_IF_VLAN(ifp
))
3649 vl
= &zif
->l2info
.vl
;
3653 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3654 /* TODO: Optimize with a hash. */
3655 zns
= zebra_ns_lookup(NS_DEFAULT
);
3656 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3657 tmp_if
= (struct interface
*)rn
->info
;
3661 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3663 if (!if_is_operative(tmp_if
))
3665 vxl
= &zif
->l2info
.vxl
;
3667 if (zif
->brslave_info
.br_if
!= br_if
)
3670 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3679 zvni
= zvni_lookup(vxl
->vni
);
3683 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3685 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3686 * linked to the bridge
3687 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3690 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3692 struct zebra_ns
*zns
;
3693 struct route_node
*rn
;
3694 struct interface
*tmp_if
= NULL
;
3695 struct zebra_if
*zif
;
3696 struct zebra_l2info_bridge
*br
;
3697 struct zebra_l2info_vlan
*vl
;
3698 uint8_t bridge_vlan_aware
;
3701 /* Defensive check, caller expected to invoke only with valid bridge. */
3705 /* Determine if bridge is VLAN-aware or not */
3708 br
= &zif
->l2info
.br
;
3709 bridge_vlan_aware
= br
->vlan_aware
;
3711 /* Check oper status of the SVI. */
3712 if (!bridge_vlan_aware
)
3713 return if_is_operative(br_if
) ? br_if
: NULL
;
3715 /* Identify corresponding VLAN interface. */
3716 /* TODO: Optimize with a hash. */
3717 zns
= zebra_ns_lookup(NS_DEFAULT
);
3718 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3719 tmp_if
= (struct interface
*)rn
->info
;
3720 /* Check oper status of the SVI. */
3721 if (!tmp_if
|| !if_is_operative(tmp_if
))
3724 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3725 || zif
->link
!= br_if
)
3727 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3729 if (vl
->vid
== vid
) {
3735 return found
? tmp_if
: NULL
;
3739 * Install remote MAC into the forwarding plane.
3741 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3743 const struct zebra_if
*zif
, *br_zif
;
3744 const struct zebra_l2info_vxlan
*vxl
;
3746 enum zebra_dplane_result res
;
3747 const struct interface
*br_ifp
;
3750 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3753 zif
= zvni
->vxlan_if
->info
;
3757 br_ifp
= zif
->brslave_info
.br_if
;
3761 vxl
= &zif
->l2info
.vxl
;
3763 sticky
= !!CHECK_FLAG(mac
->flags
,
3764 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3766 br_zif
= (const struct zebra_if
*)(br_ifp
->info
);
3768 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3769 vid
= vxl
->access_vlan
;
3773 res
= dplane_mac_add(zvni
->vxlan_if
, br_ifp
, vid
,
3774 &mac
->macaddr
, mac
->fwd_info
.r_vtep_ip
, sticky
);
3775 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3782 * Uninstall remote MAC from the forwarding plane.
3784 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3786 const struct zebra_if
*zif
, *br_zif
;
3787 const struct zebra_l2info_vxlan
*vxl
;
3788 struct in_addr vtep_ip
;
3789 const struct interface
*ifp
, *br_ifp
;
3791 enum zebra_dplane_result res
;
3793 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3796 if (!zvni
->vxlan_if
) {
3797 if (IS_ZEBRA_DEBUG_VXLAN
)
3798 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3803 zif
= zvni
->vxlan_if
->info
;
3807 br_ifp
= zif
->brslave_info
.br_if
;
3811 vxl
= &zif
->l2info
.vxl
;
3813 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
3815 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3816 vid
= vxl
->access_vlan
;
3820 ifp
= zvni
->vxlan_if
;
3821 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3823 res
= dplane_mac_del(ifp
, br_ifp
, vid
, &mac
->macaddr
, vtep_ip
);
3824 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3831 * Install MAC hash entry - called upon access VLAN change.
3833 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3836 struct mac_walk_ctx
*wctx
= ctxt
;
3838 mac
= (zebra_mac_t
*)bucket
->data
;
3840 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3841 zvni_mac_install(wctx
->zvni
, mac
);
3845 * Count of remote neighbors referencing this MAC.
3847 static int remote_neigh_count(zebra_mac_t
*zmac
)
3849 zebra_neigh_t
*n
= NULL
;
3850 struct listnode
*node
= NULL
;
3853 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3854 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3862 * Decrement neighbor refcount of MAC; uninstall and free it if
3865 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3867 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3870 /* If all remote neighbors referencing a remote MAC go away,
3871 * we need to uninstall the MAC.
3873 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3874 remote_neigh_count(mac
) == 0) {
3875 zvni_mac_uninstall(zvni
, mac
);
3876 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3879 /* If no neighbors, delete the MAC. */
3880 if (list_isempty(mac
->neigh_list
))
3881 zvni_mac_del(zvni
, mac
);
3885 * Read and populate local MACs and neighbors corresponding to this VNI.
3887 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3889 struct zebra_ns
*zns
;
3890 struct zebra_if
*zif
;
3891 struct interface
*vlan_if
;
3892 struct zebra_l2info_vxlan
*vxl
;
3893 struct interface
*vrr_if
;
3896 vxl
= &zif
->l2info
.vxl
;
3897 zns
= zebra_ns_lookup(NS_DEFAULT
);
3899 if (IS_ZEBRA_DEBUG_VXLAN
)
3901 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3902 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3903 zif
->brslave_info
.bridge_ifindex
);
3905 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3906 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3909 /* Add SVI MAC-IP */
3910 zvni_add_macip_for_intf(vlan_if
, zvni
);
3912 /* Add VRR MAC-IP - if any*/
3913 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3915 zvni_add_macip_for_intf(vrr_if
, zvni
);
3917 neigh_read_for_vlan(zns
, vlan_if
);
3922 * Hash function for VNI.
3924 static unsigned int vni_hash_keymake(const void *p
)
3926 const zebra_vni_t
*zvni
= p
;
3928 return (jhash_1word(zvni
->vni
, 0));
3932 * Compare 2 VNI hash entries.
3934 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3936 const zebra_vni_t
*zvni1
= p1
;
3937 const zebra_vni_t
*zvni2
= p2
;
3939 return (zvni1
->vni
== zvni2
->vni
);
3942 static int vni_list_cmp(void *p1
, void *p2
)
3944 const zebra_vni_t
*zvni1
= p1
;
3945 const zebra_vni_t
*zvni2
= p2
;
3947 if (zvni1
->vni
== zvni2
->vni
)
3949 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3953 * Callback to allocate VNI hash entry.
3955 static void *zvni_alloc(void *p
)
3957 const zebra_vni_t
*tmp_vni
= p
;
3960 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3961 zvni
->vni
= tmp_vni
->vni
;
3962 return ((void *)zvni
);
3966 * Look up VNI hash entry.
3968 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3970 struct zebra_vrf
*zvrf
;
3971 zebra_vni_t tmp_vni
;
3972 zebra_vni_t
*zvni
= NULL
;
3974 zvrf
= zebra_vrf_get_evpn();
3976 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3978 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3984 * Add VNI hash entry.
3986 static zebra_vni_t
*zvni_add(vni_t vni
)
3988 struct zebra_vrf
*zvrf
;
3989 zebra_vni_t tmp_zvni
;
3990 zebra_vni_t
*zvni
= NULL
;
3992 zvrf
= zebra_vrf_get_evpn();
3994 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3996 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3999 /* Create hash table for MAC */
4001 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
4003 /* Create hash table for neighbors */
4004 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4005 "Zebra VNI Neighbor Table");
4011 * Delete VNI hash entry.
4013 static int zvni_del(zebra_vni_t
*zvni
)
4015 struct zebra_vrf
*zvrf
;
4016 zebra_vni_t
*tmp_zvni
;
4018 zvrf
= zebra_vrf_get_evpn();
4021 zvni
->vxlan_if
= NULL
;
4023 /* Remove references to the BUM mcast grp */
4024 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
4026 /* Free the neighbor hash table. */
4027 hash_free(zvni
->neigh_table
);
4028 zvni
->neigh_table
= NULL
;
4030 /* Free the MAC hash table. */
4031 hash_free(zvni
->mac_table
);
4032 zvni
->mac_table
= NULL
;
4034 /* Free the VNI hash entry and allocated memory. */
4035 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
4036 XFREE(MTYPE_ZVNI
, tmp_zvni
);
4042 * Inform BGP about local VNI addition.
4044 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
4046 struct zserv
*client
;
4049 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4050 /* BGP may not be running. */
4054 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4056 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
4057 stream_putl(s
, zvni
->vni
);
4058 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
4059 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
4060 stream_put_in_addr(s
, &zvni
->mcast_grp
);
4062 /* Write packet size. */
4063 stream_putw_at(s
, 0, stream_get_endp(s
));
4065 if (IS_ZEBRA_DEBUG_VXLAN
)
4066 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
4067 inet_ntoa(zvni
->local_vtep_ip
),
4068 vrf_id_to_name(zvni
->vrf_id
),
4069 zebra_route_string(client
->proto
));
4071 client
->vniadd_cnt
++;
4072 return zserv_send_message(client
, s
);
4076 * Inform BGP about local VNI deletion.
4078 static int zvni_send_del_to_client(vni_t vni
)
4080 struct zserv
*client
;
4083 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4084 /* BGP may not be running. */
4088 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4091 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4092 stream_putl(s
, vni
);
4094 /* Write packet size. */
4095 stream_putw_at(s
, 0, stream_get_endp(s
));
4097 if (IS_ZEBRA_DEBUG_VXLAN
)
4098 zlog_debug("Send VNI_DEL %u to %s", vni
,
4099 zebra_route_string(client
->proto
));
4101 client
->vnidel_cnt
++;
4102 return zserv_send_message(client
, s
);
4106 * Build the VNI hash table by going over the VxLAN interfaces. This
4107 * is called when EVPN (advertise-all-vni) is enabled.
4109 static void zvni_build_hash_table(void)
4111 struct zebra_ns
*zns
;
4112 struct route_node
*rn
;
4113 struct interface
*ifp
;
4115 /* Walk VxLAN interfaces and create VNI hash. */
4116 zns
= zebra_ns_lookup(NS_DEFAULT
);
4117 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4119 zebra_vni_t
*zvni
= NULL
;
4120 zebra_l3vni_t
*zl3vni
= NULL
;
4121 struct zebra_if
*zif
;
4122 struct zebra_l2info_vxlan
*vxl
;
4124 ifp
= (struct interface
*)rn
->info
;
4128 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4131 vxl
= &zif
->l2info
.vxl
;
4134 /* L3-VNI and L2-VNI are handled seperately */
4135 zl3vni
= zl3vni_lookup(vni
);
4138 if (IS_ZEBRA_DEBUG_VXLAN
)
4140 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4141 ifp
->name
, ifp
->ifindex
, vni
);
4143 /* associate with vxlan_if */
4144 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4145 zl3vni
->vxlan_if
= ifp
;
4148 * we need to associate with SVI.
4149 * we can associate with svi-if only after association
4150 * with vxlan-intf is complete
4152 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4154 if (is_l3vni_oper_up(zl3vni
))
4155 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4158 struct interface
*vlan_if
= NULL
;
4160 if (IS_ZEBRA_DEBUG_VXLAN
)
4162 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4163 ifp
->name
, ifp
->ifindex
, vni
,
4164 inet_ntoa(vxl
->vtep_ip
));
4166 /* VNI hash entry is expected to exist, if the BGP process is killed */
4167 zvni
= zvni_lookup(vni
);
4170 "VNI hash already present for IF %s(%u) L2-VNI %u",
4171 ifp
->name
, ifp
->ifindex
, vni
);
4174 * Inform BGP if intf is up and mapped to
4177 if (if_is_operative(ifp
) &&
4178 zif
->brslave_info
.br_if
)
4179 zvni_send_add_to_client(zvni
);
4181 /* Send Local MAC-entries to client */
4182 zvni_send_mac_to_client(zvni
);
4184 /* Send Loval Neighbor entries to client */
4185 zvni_send_neigh_to_client(zvni
);
4187 zvni
= zvni_add(vni
);
4190 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4191 ifp
->name
, ifp
->ifindex
, vni
);
4195 if (zvni
->local_vtep_ip
.s_addr
!=
4196 vxl
->vtep_ip
.s_addr
||
4197 zvni
->mcast_grp
.s_addr
!=
4198 vxl
->mcast_grp
.s_addr
) {
4199 zebra_vxlan_sg_deref(
4200 zvni
->local_vtep_ip
,
4202 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4204 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4205 zvni
->mcast_grp
= vxl
->mcast_grp
;
4207 zvni
->vxlan_if
= ifp
;
4208 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4209 zif
->brslave_info
.br_if
);
4211 zvni
->vrf_id
= vlan_if
->vrf_id
;
4212 zl3vni
= zl3vni_from_vrf(
4216 zl3vni
->l2vnis
, zvni
);
4220 * Inform BGP if intf is up and mapped to
4223 if (if_is_operative(ifp
) &&
4224 zif
->brslave_info
.br_if
)
4225 zvni_send_add_to_client(zvni
);
4232 * See if remote VTEP matches with prefix.
4234 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4236 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4240 * Locate remote VTEP in VNI hash table.
4242 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4244 zebra_vtep_t
*zvtep
;
4249 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4250 if (zvni_vtep_match(vtep_ip
, zvtep
))
4258 * Add remote VTEP to VNI hash table.
4260 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4264 zebra_vtep_t
*zvtep
;
4266 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4268 zvtep
->vtep_ip
= *vtep_ip
;
4269 zvtep
->flood_control
= flood_control
;
4272 zvni
->vteps
->prev
= zvtep
;
4273 zvtep
->next
= zvni
->vteps
;
4274 zvni
->vteps
= zvtep
;
4280 * Remove remote VTEP from VNI hash table.
4282 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4285 zvtep
->next
->prev
= zvtep
->prev
;
4287 zvtep
->prev
->next
= zvtep
->next
;
4289 zvni
->vteps
= zvtep
->next
;
4291 zvtep
->prev
= zvtep
->next
= NULL
;
4292 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4298 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4299 * uninstall from kernel if asked to.
4301 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4303 zebra_vtep_t
*zvtep
, *zvtep_next
;
4308 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4309 zvtep_next
= zvtep
->next
;
4311 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4312 zvni_vtep_del(zvni
, zvtep
);
4319 * Install remote VTEP into the kernel if the remote VTEP has asked
4320 * for head-end-replication.
4322 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4324 if (is_vxlan_flooding_head_end() &&
4325 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
)) {
4326 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4327 dplane_vtep_add(zvni
->vxlan_if
,
4328 &zvtep
->vtep_ip
, zvni
->vni
))
4336 * Uninstall remote VTEP from the kernel.
4338 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4340 if (!zvni
->vxlan_if
) {
4341 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4346 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4347 dplane_vtep_delete(zvni
->vxlan_if
, vtep_ip
, zvni
->vni
))
4354 * Install or uninstall flood entries in the kernel corresponding to
4355 * remote VTEPs. This is invoked upon change to BUM handling.
4357 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4361 zebra_vtep_t
*zvtep
;
4363 zvni
= (zebra_vni_t
*)bucket
->data
;
4367 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4368 if (is_vxlan_flooding_head_end())
4369 zvni_vtep_install(zvni
, zvtep
);
4371 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4376 * Cleanup VNI/VTEP and update kernel
4378 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4380 zebra_vni_t
*zvni
= NULL
;
4381 zebra_l3vni_t
*zl3vni
= NULL
;
4382 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4384 zvni
= (zebra_vni_t
*)bucket
->data
;
4386 /* remove from l3-vni list */
4388 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4390 listnode_delete(zl3vni
->l2vnis
, zvni
);
4392 /* Free up all neighbors and MACs, if any. */
4393 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4394 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4396 /* Free up all remote VTEPs, if any. */
4397 zvni_vtep_del_all(zvni
, 1);
4399 /* Delete the hash entry. */
4404 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4406 zebra_l3vni_t
*zl3vni
= NULL
;
4408 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4410 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4413 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4414 struct prefix
*host
)
4416 struct host_rb_entry lookup
;
4417 struct host_rb_entry
*hle
;
4419 memset(&lookup
, 0, sizeof(lookup
));
4420 memcpy(&lookup
.p
, host
, sizeof(*host
));
4422 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4426 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4427 memcpy(hle
, &lookup
, sizeof(lookup
));
4429 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4432 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4434 struct host_rb_entry lookup
;
4435 struct host_rb_entry
*hle
;
4437 memset(&lookup
, 0, sizeof(lookup
));
4438 memcpy(&lookup
.p
, host
, sizeof(*host
));
4440 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4442 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4443 XFREE(MTYPE_HOST_PREFIX
, hle
);
4450 * Look up MAC hash entry.
4452 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4453 struct ethaddr
*rmac
)
4458 memset(&tmp
, 0, sizeof(tmp
));
4459 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4460 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4466 * Callback to allocate RMAC hash entry.
4468 static void *zl3vni_rmac_alloc(void *p
)
4470 const zebra_mac_t
*tmp_rmac
= p
;
4473 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4476 return ((void *)zrmac
);
4480 * Add RMAC entry to l3-vni
4482 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4484 zebra_mac_t tmp_rmac
;
4485 zebra_mac_t
*zrmac
= NULL
;
4487 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4488 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4489 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4492 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4494 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4495 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4503 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4505 zebra_mac_t
*tmp_rmac
;
4506 struct host_rb_entry
*hle
;
4508 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4509 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4511 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4512 XFREE(MTYPE_HOST_PREFIX
, hle
);
4515 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4516 XFREE(MTYPE_MAC
, tmp_rmac
);
4522 * Install remote RMAC into the forwarding plane.
4524 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4526 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
4527 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4528 const struct interface
*br_ifp
;
4529 enum zebra_dplane_result res
;
4532 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4533 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4536 zif
= zl3vni
->vxlan_if
->info
;
4540 br_ifp
= zif
->brslave_info
.br_if
;
4544 vxl
= &zif
->l2info
.vxl
;
4546 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4548 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4549 vid
= vxl
->access_vlan
;
4553 res
= dplane_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
,
4554 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4555 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4562 * Uninstall remote RMAC from the forwarding plane.
4564 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4566 char buf
[ETHER_ADDR_STRLEN
];
4567 const struct zebra_if
*zif
= NULL
, *br_zif
;
4568 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4569 const struct interface
*br_ifp
;
4571 enum zebra_dplane_result res
;
4573 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4574 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4577 if (!zl3vni
->vxlan_if
) {
4578 if (IS_ZEBRA_DEBUG_VXLAN
)
4580 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4581 prefix_mac2str(&zrmac
->macaddr
,
4583 zl3vni
->vni
, zl3vni
);
4587 zif
= zl3vni
->vxlan_if
->info
;
4591 br_ifp
= zif
->brslave_info
.br_if
;
4595 vxl
= &zif
->l2info
.vxl
;
4597 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4598 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4599 vid
= vxl
->access_vlan
;
4603 res
= dplane_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
,
4604 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4605 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4611 /* handle rmac add */
4612 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4613 struct ipaddr
*vtep_ip
,
4614 struct prefix
*host_prefix
)
4616 char buf
[ETHER_ADDR_STRLEN
];
4617 char buf1
[INET6_ADDRSTRLEN
];
4618 char buf2
[PREFIX_STRLEN
];
4619 zebra_mac_t
*zrmac
= NULL
;
4621 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4624 /* Create the RMAC entry, or update its vtep, if necessary. */
4625 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4628 "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s",
4629 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4631 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4632 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4635 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4636 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4638 /* Send RMAC for FPM processing */
4639 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
4642 /* install rmac in kernel */
4643 zl3vni_rmac_install(zl3vni
, zrmac
);
4644 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
4645 &vtep_ip
->ipaddr_v4
)) {
4646 if (IS_ZEBRA_DEBUG_VXLAN
)
4648 "L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s",
4650 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
),
4651 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4652 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4653 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4655 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4657 /* install rmac in kernel */
4658 zl3vni_rmac_install(zl3vni
, zrmac
);
4661 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4667 /* handle rmac delete */
4668 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4669 struct prefix
*host_prefix
)
4671 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4673 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4674 /* uninstall from kernel */
4675 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4677 /* Send RMAC for FPM processing */
4678 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
4681 /* del the rmac entry */
4682 zl3vni_rmac_del(zl3vni
, zrmac
);
4687 * Look up nh hash entry on a l3-vni.
4689 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4694 memset(&tmp
, 0, sizeof(tmp
));
4695 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4696 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4703 * Callback to allocate NH hash entry on L3-VNI.
4705 static void *zl3vni_nh_alloc(void *p
)
4707 const zebra_neigh_t
*tmp_n
= p
;
4710 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4717 * Add neighbor entry.
4719 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4720 struct ethaddr
*mac
)
4722 zebra_neigh_t tmp_n
;
4723 zebra_neigh_t
*n
= NULL
;
4725 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4726 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4727 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4730 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4732 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4733 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4734 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4740 * Delete neighbor entry.
4742 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4744 zebra_neigh_t
*tmp_n
;
4745 struct host_rb_entry
*hle
;
4747 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4748 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4750 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4751 XFREE(MTYPE_HOST_PREFIX
, hle
);
4754 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4755 XFREE(MTYPE_NEIGH
, tmp_n
);
4761 * Install remote nh as neigh into the kernel.
4763 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4768 if (!is_l3vni_oper_up(zl3vni
))
4771 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4772 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4775 flags
= DPLANE_NTF_EXT_LEARNED
;
4776 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4777 flags
|= DPLANE_NTF_ROUTER
;
4779 dplane_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4785 * Uninstall remote nh from the kernel.
4787 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4789 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4790 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4793 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4796 dplane_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
4801 /* add remote vtep as a neigh entry */
4802 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4803 struct ethaddr
*rmac
,
4804 struct prefix
*host_prefix
)
4806 char buf
[ETHER_ADDR_STRLEN
];
4807 char buf1
[ETHER_ADDR_STRLEN
];
4808 char buf2
[INET6_ADDRSTRLEN
];
4809 char buf3
[PREFIX_STRLEN
];
4810 zebra_neigh_t
*nh
= NULL
;
4812 /* Create the next hop entry, or update its mac, if necessary. */
4813 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4815 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4818 "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)",
4819 ipaddr2str(vtep_ip
, buf1
, sizeof(buf2
)),
4820 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4822 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4826 /* install the nh neigh in kernel */
4827 zl3vni_nh_install(zl3vni
, nh
);
4828 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
4829 if (IS_ZEBRA_DEBUG_VXLAN
)
4830 zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s",
4832 prefix_mac2str(&nh
->emac
, buf
, sizeof(buf
)),
4833 prefix_mac2str(rmac
, buf1
, sizeof(buf1
)),
4834 ipaddr2str(vtep_ip
, buf2
, sizeof(buf2
)),
4835 prefix2str(host_prefix
, buf3
, sizeof(buf3
)));
4837 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
4838 /* install (update) the nh neigh in kernel */
4839 zl3vni_nh_install(zl3vni
, nh
);
4842 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4847 /* handle nh neigh delete */
4848 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4849 struct prefix
*host_prefix
)
4851 rb_delete_host(&nh
->host_rb
, host_prefix
);
4853 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4854 /* uninstall from kernel */
4855 zl3vni_nh_uninstall(zl3vni
, nh
);
4857 /* delete the nh entry */
4858 zl3vni_nh_del(zl3vni
, nh
);
4862 /* handle neigh update from kernel - the only thing of interest is to
4863 * readd stale entries.
4865 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4869 zebra_neigh_t
*n
= NULL
;
4871 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4875 /* all next hop neigh are remote and installed by frr.
4876 * If the kernel has aged this entry, re-install.
4878 if (state
& NUD_STALE
)
4879 zl3vni_nh_install(zl3vni
, n
);
4884 /* handle neigh delete from kernel */
4885 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4887 zebra_neigh_t
*n
= NULL
;
4889 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4893 /* all next hop neigh are remote and installed by frr.
4894 * If we get an age out notification for these neigh entries, we have to
4897 zl3vni_nh_install(zl3vni
, n
);
4903 * Hash function for L3 VNI.
4905 static unsigned int l3vni_hash_keymake(const void *p
)
4907 const zebra_l3vni_t
*zl3vni
= p
;
4909 return jhash_1word(zl3vni
->vni
, 0);
4913 * Compare 2 L3 VNI hash entries.
4915 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4917 const zebra_l3vni_t
*zl3vni1
= p1
;
4918 const zebra_l3vni_t
*zl3vni2
= p2
;
4920 return (zl3vni1
->vni
== zl3vni2
->vni
);
4924 * Callback to allocate L3 VNI hash entry.
4926 static void *zl3vni_alloc(void *p
)
4928 zebra_l3vni_t
*zl3vni
= NULL
;
4929 const zebra_l3vni_t
*tmp_l3vni
= p
;
4931 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4932 zl3vni
->vni
= tmp_l3vni
->vni
;
4933 return ((void *)zl3vni
);
4937 * Look up L3 VNI hash entry.
4939 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4941 zebra_l3vni_t tmp_l3vni
;
4942 zebra_l3vni_t
*zl3vni
= NULL
;
4944 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4945 tmp_l3vni
.vni
= vni
;
4946 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4952 * Add L3 VNI hash entry.
4954 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4956 zebra_l3vni_t tmp_zl3vni
;
4957 zebra_l3vni_t
*zl3vni
= NULL
;
4959 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4960 tmp_zl3vni
.vni
= vni
;
4962 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4965 zl3vni
->vrf_id
= vrf_id
;
4966 zl3vni
->svi_if
= NULL
;
4967 zl3vni
->vxlan_if
= NULL
;
4968 zl3vni
->l2vnis
= list_new();
4969 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4971 /* Create hash table for remote RMAC */
4972 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4973 "Zebra L3-VNI RMAC-Table");
4975 /* Create hash table for neighbors */
4976 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4977 "Zebra L3-VNI next-hop table");
4983 * Delete L3 VNI hash entry.
4985 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4987 zebra_l3vni_t
*tmp_zl3vni
;
4989 /* free the list of l2vnis */
4990 list_delete(&zl3vni
->l2vnis
);
4991 zl3vni
->l2vnis
= NULL
;
4993 /* Free the rmac table */
4994 hash_free(zl3vni
->rmac_table
);
4995 zl3vni
->rmac_table
= NULL
;
4997 /* Free the nh table */
4998 hash_free(zl3vni
->nh_table
);
4999 zl3vni
->nh_table
= NULL
;
5001 /* Free the VNI hash entry and allocated memory. */
5002 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
5003 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
5008 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
5010 struct zebra_ns
*zns
= NULL
;
5011 struct route_node
*rn
= NULL
;
5012 struct interface
*ifp
= NULL
;
5014 /* loop through all vxlan-interface */
5015 zns
= zebra_ns_lookup(NS_DEFAULT
);
5016 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5018 struct zebra_if
*zif
= NULL
;
5019 struct zebra_l2info_vxlan
*vxl
= NULL
;
5021 ifp
= (struct interface
*)rn
->info
;
5026 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5029 vxl
= &zif
->l2info
.vxl
;
5030 if (vxl
->vni
== zl3vni
->vni
) {
5031 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
5039 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
5041 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5042 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
5047 if (!zl3vni
->vxlan_if
)
5050 zif
= zl3vni
->vxlan_if
->info
;
5054 vxl
= &zif
->l2info
.vxl
;
5056 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
5059 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
5061 struct zebra_vrf
*zvrf
= NULL
;
5063 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
5067 return zl3vni_lookup(zvrf
->l3vni
);
5071 * Map SVI and associated bridge to a VNI. This is invoked upon getting
5072 * neighbor notifications, to see if they are of interest.
5074 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
5075 struct interface
*br_if
)
5079 uint8_t bridge_vlan_aware
= 0;
5080 zebra_l3vni_t
*zl3vni
= NULL
;
5081 struct zebra_ns
*zns
= NULL
;
5082 struct route_node
*rn
= NULL
;
5083 struct zebra_if
*zif
= NULL
;
5084 struct interface
*tmp_if
= NULL
;
5085 struct zebra_l2info_bridge
*br
= NULL
;
5086 struct zebra_l2info_vxlan
*vxl
= NULL
;
5091 /* Make sure the linked interface is a bridge. */
5092 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
5095 /* Determine if bridge is VLAN-aware or not */
5098 br
= &zif
->l2info
.br
;
5099 bridge_vlan_aware
= br
->vlan_aware
;
5100 if (bridge_vlan_aware
) {
5101 struct zebra_l2info_vlan
*vl
;
5103 if (!IS_ZEBRA_IF_VLAN(ifp
))
5108 vl
= &zif
->l2info
.vl
;
5112 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
5113 /* TODO: Optimize with a hash. */
5114 zns
= zebra_ns_lookup(NS_DEFAULT
);
5115 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5116 tmp_if
= (struct interface
*)rn
->info
;
5120 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5122 if (!if_is_operative(tmp_if
))
5124 vxl
= &zif
->l2info
.vxl
;
5126 if (zif
->brslave_info
.br_if
!= br_if
)
5129 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
5138 zl3vni
= zl3vni_lookup(vxl
->vni
);
5143 * Inform BGP about l3-vni.
5145 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
5147 struct stream
*s
= NULL
;
5148 struct zserv
*client
= NULL
;
5149 struct ethaddr rmac
;
5150 char buf
[ETHER_ADDR_STRLEN
];
5152 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5153 /* BGP may not be running. */
5158 memset(&rmac
, 0, sizeof(struct ethaddr
));
5159 zl3vni_get_rmac(zl3vni
, &rmac
);
5161 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5163 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
5164 stream_putl(s
, zl3vni
->vni
);
5165 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
5166 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
5167 stream_put(s
, &zl3vni
->filter
, sizeof(int));
5168 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
5170 /* Write packet size. */
5171 stream_putw_at(s
, 0, stream_get_endp(s
));
5173 if (IS_ZEBRA_DEBUG_VXLAN
)
5175 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
5176 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5177 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
5178 inet_ntoa(zl3vni
->local_vtep_ip
),
5179 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5180 ? "prefix-routes-only"
5182 zebra_route_string(client
->proto
));
5184 client
->l3vniadd_cnt
++;
5185 return zserv_send_message(client
, s
);
5189 * Inform BGP about local l3-VNI deletion.
5191 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5193 struct stream
*s
= NULL
;
5194 struct zserv
*client
= NULL
;
5196 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5197 /* BGP may not be running. */
5201 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5203 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5204 stream_putl(s
, zl3vni
->vni
);
5206 /* Write packet size. */
5207 stream_putw_at(s
, 0, stream_get_endp(s
));
5209 if (IS_ZEBRA_DEBUG_VXLAN
)
5210 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5211 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5212 zebra_route_string(client
->proto
));
5214 client
->l3vnidel_cnt
++;
5215 return zserv_send_message(client
, s
);
5218 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5223 /* send l3vni add to BGP */
5224 zl3vni_send_add_to_client(zl3vni
);
5227 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5232 /* send l3-vni del to BGP*/
5233 zl3vni_send_del_to_client(zl3vni
);
5236 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5238 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5239 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5241 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5242 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5246 * handle transition of vni from l2 to l3 and vice versa
5248 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5251 zebra_vni_t
*zvni
= NULL
;
5253 /* There is a possibility that VNI notification was already received
5254 * from kernel and we programmed it as L2-VNI
5255 * In such a case we need to delete this L2-VNI first, so
5256 * that it can be reprogrammed as L3-VNI in the system. It is also
5257 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5258 * interface is still present in kernel. In this case to keep it
5259 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5262 /* Locate hash entry */
5263 zvni
= zvni_lookup(vni
);
5267 if (IS_ZEBRA_DEBUG_VXLAN
)
5268 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5270 /* Delete VNI from BGP. */
5271 zvni_send_del_to_client(zvni
->vni
);
5273 /* Free up all neighbors and MAC, if any. */
5274 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5275 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5277 /* Free up all remote VTEPs, if any. */
5278 zvni_vtep_del_all(zvni
, 0);
5280 /* Delete the hash entry. */
5281 if (zvni_del(zvni
)) {
5282 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5283 "Failed to del VNI hash %p, VNI %u", zvni
,
5288 /* TODO_MITESH: This needs to be thought through. We don't have
5289 * enough information at this point to reprogram the vni as
5290 * l2-vni. One way is to store the required info in l3-vni and
5291 * used it solely for this purpose
5298 /* delete and uninstall rmac hash entry */
5299 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5301 zebra_mac_t
*zrmac
= NULL
;
5302 zebra_l3vni_t
*zl3vni
= NULL
;
5304 zrmac
= (zebra_mac_t
*)bucket
->data
;
5305 zl3vni
= (zebra_l3vni_t
*)ctx
;
5306 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5308 /* Send RMAC for FPM processing */
5309 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5311 zl3vni_rmac_del(zl3vni
, zrmac
);
5314 /* delete and uninstall nh hash entry */
5315 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5317 zebra_neigh_t
*n
= NULL
;
5318 zebra_l3vni_t
*zl3vni
= NULL
;
5320 n
= (zebra_neigh_t
*)bucket
->data
;
5321 zl3vni
= (zebra_l3vni_t
*)ctx
;
5322 zl3vni_nh_uninstall(zl3vni
, n
);
5323 zl3vni_nh_del(zl3vni
, n
);
5326 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5329 struct zserv
*client
= NULL
;
5330 struct stream
*s
= NULL
;
5331 char buf
[PREFIX_STRLEN
];
5333 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5334 /* BGP may not be running. */
5338 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5340 zclient_create_header(s
, cmd
, vrf_id
);
5341 stream_put(s
, p
, sizeof(struct prefix
));
5343 /* Write packet size. */
5344 stream_putw_at(s
, 0, stream_get_endp(s
));
5346 if (IS_ZEBRA_DEBUG_VXLAN
)
5347 zlog_debug("Send ip prefix %s %s on vrf %s",
5348 prefix2str(p
, buf
, sizeof(buf
)),
5349 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5350 vrf_id_to_name(vrf_id
));
5352 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5353 client
->prefixadd_cnt
++;
5355 client
->prefixdel_cnt
++;
5357 return zserv_send_message(client
, s
);
5360 /* re-add remote rmac if needed */
5361 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5362 struct ethaddr
*rmac
)
5364 char buf
[ETHER_ADDR_STRLEN
];
5365 zebra_mac_t
*zrmac
= NULL
;
5367 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5371 if (IS_ZEBRA_DEBUG_VXLAN
)
5372 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5373 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5375 zl3vni_rmac_install(zl3vni
, zrmac
);
5379 /* Process a remote MACIP add from BGP. */
5380 static void process_remote_macip_add(vni_t vni
,
5381 struct ethaddr
*macaddr
,
5383 struct ipaddr
*ipaddr
,
5386 struct in_addr vtep_ip
)
5389 zebra_vtep_t
*zvtep
;
5390 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5391 zebra_neigh_t
*n
= NULL
;
5392 int update_mac
= 0, update_neigh
= 0;
5393 char buf
[ETHER_ADDR_STRLEN
];
5394 char buf1
[INET6_ADDRSTRLEN
];
5395 struct interface
*ifp
= NULL
;
5396 struct zebra_if
*zif
= NULL
;
5397 struct zebra_vrf
*zvrf
;
5402 bool do_dad
= false;
5403 bool is_dup_detect
= false;
5405 /* Locate VNI hash entry - expected to exist. */
5406 zvni
= zvni_lookup(vni
);
5408 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5412 ifp
= zvni
->vxlan_if
;
5416 !if_is_operative(ifp
) ||
5418 !zif
->brslave_info
.br_if
) {
5419 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5424 /* The remote VTEP specified should normally exist, but it is
5425 * possible that when peering comes up, peer may advertise MACIP
5426 * routes before advertising type-3 routes.
5428 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5430 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5433 EC_ZEBRA_VTEP_ADD_FAILED
,
5434 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5439 zvni_vtep_install(zvni
, zvtep
);
5442 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5443 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5444 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5446 mac
= zvni_mac_lookup(zvni
, macaddr
);
5448 /* Ignore if the mac is already present as a gateway mac */
5450 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5451 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5452 if (IS_ZEBRA_DEBUG_VXLAN
)
5453 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5455 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5456 ipa_len
? " IP " : "",
5458 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5462 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5466 /* check if the remote MAC is unknown or has a change.
5467 * If so, that needs to be updated first. Note that client could
5468 * install MAC and MACIP separately or just install the latter.
5471 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5472 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5473 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5474 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5475 || seq
!= mac
->rem_seq
)
5480 mac
= zvni_mac_add(zvni
, macaddr
);
5483 "Failed to add MAC %s VNI %u Remote VTEP %s",
5484 prefix_mac2str(macaddr
, buf
,
5486 vni
, inet_ntoa(vtep_ip
));
5490 /* Is this MAC created for a MACIP? */
5492 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5494 /* When host moves but changes its (MAC,IP)
5495 * binding, BGP may install a MACIP entry that
5496 * corresponds to "older" location of the host
5497 * in transient situations (because {IP1,M1}
5498 * is a different route from {IP1,M2}). Check
5499 * the sequence number and ignore this update
5502 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5503 tmp_seq
= mac
->loc_seq
;
5505 tmp_seq
= mac
->rem_seq
;
5507 if (seq
< tmp_seq
) {
5508 if (IS_ZEBRA_DEBUG_VXLAN
)
5509 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
5511 prefix_mac2str(macaddr
,
5513 ipa_len
? " IP " : "",
5516 buf1
, sizeof(buf1
)) : "",
5517 tmp_seq
, mac
->flags
);
5522 /* Check MAC's curent state is local (this is the case
5523 * where MAC has moved from L->R) and check previous
5524 * detection started via local learning.
5525 * RFC-7432: A PE/VTEP that detects a MAC mobility
5526 * event via local learning starts an M-second timer.
5528 * VTEP-IP or seq. change alone is not considered
5529 * for dup. detection.
5531 * MAC is already marked duplicate set dad, then
5532 * is_dup_detect will be set to not install the entry.
5534 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5536 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5539 /* Remove local MAC from BGP. */
5540 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5541 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5543 /* Set "auto" and "remote" forwarding info. */
5544 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5545 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5546 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5547 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5550 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5552 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5555 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5557 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5559 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5560 mac
->fwd_info
.r_vtep_ip
,
5561 do_dad
, &is_dup_detect
,
5564 if (!is_dup_detect
) {
5565 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5566 /* Install the entry. */
5567 zvni_mac_install(zvni
, mac
);
5571 /* Update seq number. */
5574 /* If there is no IP, return after clearing AUTO flag of MAC. */
5576 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5583 /* Check if the remote neighbor itself is unknown or has a
5584 * change. If so, create or update and then install the entry.
5586 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5588 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5589 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5590 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5591 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5592 || seq
!= n
->rem_seq
)
5597 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5600 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5601 ipaddr2str(ipaddr
, buf1
,
5603 prefix_mac2str(macaddr
, buf
,
5605 vni
, inet_ntoa(vtep_ip
));
5612 /* When host moves but changes its (MAC,IP)
5613 * binding, BGP may install a MACIP entry that
5614 * corresponds to "older" location of the host
5615 * in transient situations (because {IP1,M1}
5616 * is a different route from {IP1,M2}). Check
5617 * the sequence number and ignore this update
5620 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5621 tmp_seq
= n
->loc_seq
;
5624 tmp_seq
= n
->rem_seq
;
5627 if (seq
< tmp_seq
) {
5628 if (IS_ZEBRA_DEBUG_VXLAN
)
5629 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5631 prefix_mac2str(macaddr
,
5634 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5639 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5640 /* MAC change, send a delete for old
5641 * neigh if learnt locally.
5643 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5644 IS_ZEBRA_NEIGH_ACTIVE(n
))
5645 zvni_neigh_send_del_to_client(
5647 &n
->emac
, 0, n
->state
);
5649 /* update neigh list for macs */
5650 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5652 listnode_delete(old_mac
->neigh_list
, n
);
5653 zvni_deref_ip2mac(zvni
, old_mac
);
5655 listnode_add_sort(mac
->neigh_list
, n
);
5656 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5658 /* Check Neigh's curent state is local
5659 * (this is the case where neigh/host has moved
5660 * from L->R) and check previous detction
5661 * started via local learning.
5663 * RFC-7432: A PE/VTEP that detects a MAC
5664 * mobilit event via local learning starts
5665 * an M-second timer.
5666 * VTEP-IP or seq. change along is not
5667 * considered for dup. detection.
5669 * Mobilty event scenario-B IP-MAC binding
5672 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5679 /* Set "remote" forwarding info. */
5680 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5681 n
->r_vtep_ip
= vtep_ip
;
5682 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5684 /* Set router flag (R-bit) to this Neighbor entry */
5685 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5686 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5688 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5690 /* Check old or new MAC detected as duplicate,
5691 * inherit duplicate flag to this neigh.
5693 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5695 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5696 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5698 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5699 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5702 /* Check duplicate address detection for IP */
5703 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5708 /* Install the entry. */
5710 zvni_neigh_install(zvni
, n
);
5713 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5715 /* Update seq number. */
5719 /* Process a remote MACIP delete from BGP. */
5720 static void process_remote_macip_del(vni_t vni
,
5721 struct ethaddr
*macaddr
,
5723 struct ipaddr
*ipaddr
,
5724 struct in_addr vtep_ip
)
5727 zebra_mac_t
*mac
= NULL
;
5728 zebra_neigh_t
*n
= NULL
;
5729 struct interface
*ifp
= NULL
;
5730 struct zebra_if
*zif
= NULL
;
5731 struct zebra_ns
*zns
;
5732 struct zebra_l2info_vxlan
*vxl
;
5733 struct zebra_vrf
*zvrf
;
5734 char buf
[ETHER_ADDR_STRLEN
];
5735 char buf1
[INET6_ADDRSTRLEN
];
5737 /* Locate VNI hash entry - expected to exist. */
5738 zvni
= zvni_lookup(vni
);
5740 if (IS_ZEBRA_DEBUG_VXLAN
)
5741 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5745 ifp
= zvni
->vxlan_if
;
5749 !if_is_operative(ifp
) ||
5751 !zif
->brslave_info
.br_if
) {
5752 if (IS_ZEBRA_DEBUG_VXLAN
)
5753 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5757 zns
= zebra_ns_lookup(NS_DEFAULT
);
5758 vxl
= &zif
->l2info
.vxl
;
5760 /* The remote VTEP specified is normally expected to exist, but
5761 * it is possible that the peer may delete the VTEP before deleting
5762 * any MACs referring to the VTEP, in which case the handler (see
5763 * remote_vtep_del) would have already deleted the MACs.
5765 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5768 mac
= zvni_mac_lookup(zvni
, macaddr
);
5770 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5773 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5774 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5775 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5779 /* If the remote mac or neighbor doesn't exist there is nothing
5780 * more to do. Otherwise, uninstall the entry and then remove it.
5785 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5787 /* Ignore the delete if this mac is a gateway mac-ip */
5788 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5789 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5791 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5793 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5794 ipa_len
? " IP " : "",
5796 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5800 /* Uninstall remote neighbor or MAC. */
5802 if (zvrf
->dad_freeze
&&
5803 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5804 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5805 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5806 struct interface
*vlan_if
;
5808 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5809 zif
->brslave_info
.br_if
);
5810 if (IS_ZEBRA_DEBUG_VXLAN
)
5812 "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5813 __PRETTY_FUNCTION__
,
5814 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5816 vlan_if
? vlan_if
->name
: "Unknown");
5818 neigh_read_specific_ip(ipaddr
, vlan_if
);
5821 /* When the MAC changes for an IP, it is possible the
5822 * client may update the new MAC before trying to delete the
5823 * "old" neighbor (as these are two different MACIP routes).
5824 * Do the delete only if the MAC matches.
5826 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5827 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5828 zvni_neigh_uninstall(zvni
, n
);
5829 zvni_neigh_del(zvni
, n
);
5830 zvni_deref_ip2mac(zvni
, mac
);
5833 /* DAD: when MAC is freeze state as remote learn event,
5834 * remote mac-ip delete event is received will result in freeze
5835 * entry removal, first fetch kernel for the same entry present
5836 * as LOCAL and reachable, avoid deleting this entry instead
5837 * use kerenel local entry to update during unfreeze time.
5839 if (zvrf
->dad_freeze
&&
5840 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5841 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5842 if (IS_ZEBRA_DEBUG_VXLAN
)
5843 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5844 __PRETTY_FUNCTION__
,
5845 prefix_mac2str(macaddr
, buf
,
5848 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5849 macaddr
, vxl
->access_vlan
);
5852 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5853 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5855 * the remote sequence number in the auto mac entry
5856 * needs to be reset to 0 as the mac entry may have
5857 * been removed on all VTEPs (including
5858 * the originating one)
5862 /* If all remote neighbors referencing a remote MAC
5863 * go away, we need to uninstall the MAC.
5865 if (remote_neigh_count(mac
) == 0) {
5866 zvni_mac_uninstall(zvni
, mac
);
5867 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5869 if (list_isempty(mac
->neigh_list
))
5870 zvni_mac_del(zvni
, mac
);
5872 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5878 /* Public functions */
5880 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5882 zebra_l3vni_t
*zl3vni
= NULL
;
5884 zl3vni
= zl3vni_lookup(vni
);
5888 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5891 /* handle evpn route in vrf table */
5892 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5893 struct ipaddr
*vtep_ip
,
5894 struct prefix
*host_prefix
)
5896 zebra_l3vni_t
*zl3vni
= NULL
;
5897 struct ipaddr ipv4_vtep
;
5899 zl3vni
= zl3vni_from_vrf(vrf_id
);
5900 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5904 * add the next hop neighbor -
5905 * neigh to be installed is the ipv6 nexthop neigh
5907 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5910 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5911 * address. Rmac is programmed against the ipv4 vtep because we only
5912 * support ipv4 tunnels in the h/w right now
5914 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5915 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5916 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5917 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5918 &(ipv4_vtep
.ipaddr_v4
));
5920 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5921 sizeof(struct in_addr
));
5924 * add the rmac - remote rmac to be installed is against the ipv4
5927 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5930 /* handle evpn vrf route delete */
5931 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5932 struct ipaddr
*vtep_ip
,
5933 struct prefix
*host_prefix
)
5935 zebra_l3vni_t
*zl3vni
= NULL
;
5936 zebra_neigh_t
*nh
= NULL
;
5937 zebra_mac_t
*zrmac
= NULL
;
5939 zl3vni
= zl3vni_from_vrf(vrf_id
);
5943 /* find the next hop entry and rmac entry */
5944 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5947 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5949 /* delete the next hop entry */
5950 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5952 /* delete the rmac entry */
5954 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5958 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5959 struct ethaddr
*rmac
, bool use_json
)
5961 zebra_l3vni_t
*zl3vni
= NULL
;
5962 zebra_mac_t
*zrmac
= NULL
;
5963 json_object
*json
= NULL
;
5965 if (!is_evpn_enabled()) {
5967 vty_out(vty
, "{}\n");
5972 json
= json_object_new_object();
5974 zl3vni
= zl3vni_lookup(l3vni
);
5977 vty_out(vty
, "{}\n");
5979 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5983 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5986 vty_out(vty
, "{}\n");
5989 "%% Requested RMAC doesn't exist in L3-VNI %u",
5994 zl3vni_print_rmac(zrmac
, vty
, json
);
5997 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5998 json
, JSON_C_TO_STRING_PRETTY
));
5999 json_object_free(json
);
6003 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6005 zebra_l3vni_t
*zl3vni
;
6007 struct rmac_walk_ctx wctx
;
6008 json_object
*json
= NULL
;
6010 if (!is_evpn_enabled())
6013 zl3vni
= zl3vni_lookup(l3vni
);
6016 vty_out(vty
, "{}\n");
6018 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6021 num_rmacs
= hashcount(zl3vni
->rmac_table
);
6026 json
= json_object_new_object();
6028 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
6032 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
6034 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
6036 json_object_int_add(json
, "numRmacs", num_rmacs
);
6038 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
6041 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6042 json
, JSON_C_TO_STRING_PRETTY
));
6043 json_object_free(json
);
6047 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
6049 json_object
*json
= NULL
;
6052 if (!is_evpn_enabled()) {
6054 vty_out(vty
, "{}\n");
6059 json
= json_object_new_object();
6063 hash_iterate(zrouter
.l3vni_table
,
6064 (void (*)(struct hash_bucket
*,
6065 void *))zl3vni_print_rmac_hash_all_vni
,
6069 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6070 json
, JSON_C_TO_STRING_PRETTY
));
6071 json_object_free(json
);
6075 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
6076 struct ipaddr
*ip
, bool use_json
)
6078 zebra_l3vni_t
*zl3vni
= NULL
;
6079 zebra_neigh_t
*n
= NULL
;
6080 json_object
*json
= NULL
;
6082 if (!is_evpn_enabled()) {
6084 vty_out(vty
, "{}\n");
6089 json
= json_object_new_object();
6091 zl3vni
= zl3vni_lookup(l3vni
);
6094 vty_out(vty
, "{}\n");
6096 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6100 n
= zl3vni_nh_lookup(zl3vni
, ip
);
6103 vty_out(vty
, "{}\n");
6106 "%% Requested next-hop not present for L3-VNI %u",
6111 zl3vni_print_nh(n
, vty
, json
);
6114 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6115 json
, JSON_C_TO_STRING_PRETTY
));
6116 json_object_free(json
);
6120 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6123 struct nh_walk_ctx wctx
;
6124 json_object
*json
= NULL
;
6125 zebra_l3vni_t
*zl3vni
= NULL
;
6127 if (!is_evpn_enabled())
6130 zl3vni
= zl3vni_lookup(l3vni
);
6133 vty_out(vty
, "{}\n");
6135 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6139 num_nh
= hashcount(zl3vni
->nh_table
);
6144 json
= json_object_new_object();
6149 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
6151 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
6153 json_object_int_add(json
, "numNextHops", num_nh
);
6155 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
6158 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6159 json
, JSON_C_TO_STRING_PRETTY
));
6160 json_object_free(json
);
6164 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
6166 json_object
*json
= NULL
;
6169 if (!is_evpn_enabled()) {
6171 vty_out(vty
, "{}\n");
6176 json
= json_object_new_object();
6180 hash_iterate(zrouter
.l3vni_table
,
6181 (void (*)(struct hash_bucket
*,
6182 void *))zl3vni_print_nh_hash_all_vni
,
6186 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6187 json
, JSON_C_TO_STRING_PRETTY
));
6188 json_object_free(json
);
6193 * Display L3 VNI information (VTY command handler).
6195 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
6198 json_object
*json
= NULL
;
6199 zebra_l3vni_t
*zl3vni
= NULL
;
6201 if (!is_evpn_enabled()) {
6203 vty_out(vty
, "{}\n");
6207 zl3vni
= zl3vni_lookup(vni
);
6210 vty_out(vty
, "{}\n");
6212 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6217 json
= json_object_new_object();
6221 zl3vni_print(zl3vni
, (void *)args
);
6224 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6225 json
, JSON_C_TO_STRING_PRETTY
));
6226 json_object_free(json
);
6230 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6231 json_object
*json_vrfs
)
6233 char buf
[ETHER_ADDR_STRLEN
];
6234 zebra_l3vni_t
*zl3vni
= NULL
;
6236 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6241 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6242 zvrf_name(zvrf
), zl3vni
->vni
,
6243 zl3vni_vxlan_if_name(zl3vni
),
6244 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6245 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6247 json_object
*json_vrf
= NULL
;
6249 json_vrf
= json_object_new_object();
6250 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6251 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6252 json_object_string_add(json_vrf
, "vxlanIntf",
6253 zl3vni_vxlan_if_name(zl3vni
));
6254 json_object_string_add(json_vrf
, "sviIntf",
6255 zl3vni_svi_if_name(zl3vni
));
6256 json_object_string_add(json_vrf
, "state",
6257 zl3vni_state2str(zl3vni
));
6258 json_object_string_add(
6259 json_vrf
, "routerMac",
6260 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6261 json_object_array_add(json_vrfs
, json_vrf
);
6266 * Display Neighbors for a VNI (VTY command handler).
6268 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6269 vni_t vni
, bool use_json
)
6273 struct neigh_walk_ctx wctx
;
6274 json_object
*json
= NULL
;
6276 if (!is_evpn_enabled())
6278 zvni
= zvni_lookup(vni
);
6281 vty_out(vty
, "{}\n");
6283 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6286 num_neigh
= hashcount(zvni
->neigh_table
);
6291 json
= json_object_new_object();
6293 /* Since we have IPv6 addresses to deal with which can vary widely in
6294 * size, we try to be a bit more elegant in display by first computing
6295 * the maximum width.
6297 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6300 wctx
.addr_width
= 15;
6302 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6306 "Number of ARPs (local and remote) known for this VNI: %u\n",
6308 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx
.addr_width
,
6309 "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s");
6311 json_object_int_add(json
, "numArpNd", num_neigh
);
6313 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6315 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6316 json
, JSON_C_TO_STRING_PRETTY
));
6317 json_object_free(json
);
6322 * Display neighbors across all VNIs (VTY command handler).
6324 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6325 bool print_dup
, bool use_json
)
6327 json_object
*json
= NULL
;
6330 if (!is_evpn_enabled())
6334 json
= json_object_new_object();
6338 args
[2] = (void *)(ptrdiff_t)print_dup
;
6340 hash_iterate(zvrf
->vni_table
,
6341 (void (*)(struct hash_bucket
*,
6342 void *))zvni_print_neigh_hash_all_vni
,
6345 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6346 json
, JSON_C_TO_STRING_PRETTY
));
6347 json_object_free(json
);
6352 * Display neighbors across all VNIs in detail(VTY command handler).
6354 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6355 struct zebra_vrf
*zvrf
,
6356 bool print_dup
, bool use_json
)
6358 json_object
*json
= NULL
;
6361 if (!is_evpn_enabled())
6365 json
= json_object_new_object();
6369 args
[2] = (void *)(ptrdiff_t)print_dup
;
6371 hash_iterate(zvrf
->vni_table
,
6372 (void (*)(struct hash_bucket
*,
6373 void *))zvni_print_neigh_hash_all_vni_detail
,
6376 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6377 json
, JSON_C_TO_STRING_PRETTY
));
6378 json_object_free(json
);
6383 * Display specific neighbor for a VNI, if present (VTY command handler).
6385 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6386 struct zebra_vrf
*zvrf
, vni_t vni
,
6387 struct ipaddr
*ip
, bool use_json
)
6391 json_object
*json
= NULL
;
6393 if (!is_evpn_enabled())
6395 zvni
= zvni_lookup(vni
);
6398 vty_out(vty
, "{}\n");
6400 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6403 n
= zvni_neigh_lookup(zvni
, ip
);
6407 "%% Requested neighbor does not exist in VNI %u\n",
6412 json
= json_object_new_object();
6414 zvni_print_neigh(n
, vty
, json
);
6417 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6418 json
, JSON_C_TO_STRING_PRETTY
));
6419 json_object_free(json
);
6424 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6425 * By definition, these are remote neighbors.
6427 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6428 vni_t vni
, struct in_addr vtep_ip
,
6433 struct neigh_walk_ctx wctx
;
6434 json_object
*json
= NULL
;
6436 if (!is_evpn_enabled())
6438 zvni
= zvni_lookup(vni
);
6441 vty_out(vty
, "{}\n");
6443 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6446 num_neigh
= hashcount(zvni
->neigh_table
);
6450 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6453 wctx
.addr_width
= 15;
6454 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6455 wctx
.r_vtep_ip
= vtep_ip
;
6457 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6458 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6461 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6462 json
, JSON_C_TO_STRING_PRETTY
));
6463 json_object_free(json
);
6468 * Display Duplicate detected Neighbors for a VNI
6469 * (VTY command handler).
6471 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6472 struct zebra_vrf
*zvrf
,
6478 struct neigh_walk_ctx wctx
;
6479 json_object
*json
= NULL
;
6481 if (!is_evpn_enabled())
6484 zvni
= zvni_lookup(vni
);
6486 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6490 num_neigh
= hashcount(zvni
->neigh_table
);
6494 num_neigh
= num_dup_detected_neighs(zvni
);
6499 json
= json_object_new_object();
6501 /* Since we have IPv6 addresses to deal with which can vary widely in
6502 * size, we try to be a bit more elegant in display by first computing
6503 * the maximum width.
6505 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6508 wctx
.addr_width
= 15;
6510 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6514 "Number of ARPs (local and remote) known for this VNI: %u\n",
6516 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6517 -wctx
.addr_width
, "IP", "Type",
6518 "State", "MAC", "Remote VTEP");
6520 json_object_int_add(json
, "numArpNd", num_neigh
);
6522 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6525 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6526 json
, JSON_C_TO_STRING_PRETTY
));
6527 json_object_free(json
);
6532 * Display MACs for a VNI (VTY command handler).
6534 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6535 vni_t vni
, bool use_json
)
6539 struct mac_walk_ctx wctx
;
6540 json_object
*json
= NULL
;
6541 json_object
*json_mac
= NULL
;
6543 if (!is_evpn_enabled())
6545 zvni
= zvni_lookup(vni
);
6548 vty_out(vty
, "{}\n");
6550 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6553 num_macs
= num_valid_macs(zvni
);
6558 json
= json_object_new_object();
6559 json_mac
= json_object_new_object();
6562 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6565 wctx
.json
= json_mac
;
6569 "Number of MACs (local and remote) known for this VNI: %u\n",
6571 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type",
6572 "Intf/Remote VTEP", "VLAN", "Seq #'s");
6574 json_object_int_add(json
, "numMacs", num_macs
);
6576 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6579 json_object_object_add(json
, "macs", json_mac
);
6580 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6581 json
, JSON_C_TO_STRING_PRETTY
));
6582 json_object_free(json
);
6587 * Display MACs for all VNIs (VTY command handler).
6589 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6590 bool print_dup
, bool use_json
)
6592 struct mac_walk_ctx wctx
;
6593 json_object
*json
= NULL
;
6595 if (!is_evpn_enabled()) {
6597 vty_out(vty
, "{}\n");
6601 json
= json_object_new_object();
6603 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6606 wctx
.print_dup
= print_dup
;
6607 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6610 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6611 json
, JSON_C_TO_STRING_PRETTY
));
6612 json_object_free(json
);
6617 * Display MACs in detail for all VNIs (VTY command handler).
6619 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6620 struct zebra_vrf
*zvrf
,
6621 bool print_dup
, bool use_json
)
6623 struct mac_walk_ctx wctx
;
6624 json_object
*json
= NULL
;
6626 if (!is_evpn_enabled()) {
6628 vty_out(vty
, "{}\n");
6632 json
= json_object_new_object();
6634 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6637 wctx
.print_dup
= print_dup
;
6638 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6642 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6643 json
, JSON_C_TO_STRING_PRETTY
));
6644 json_object_free(json
);
6649 * Display MACs for all VNIs (VTY command handler).
6651 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6652 struct zebra_vrf
*zvrf
,
6653 struct in_addr vtep_ip
, bool use_json
)
6655 struct mac_walk_ctx wctx
;
6656 json_object
*json
= NULL
;
6658 if (!is_evpn_enabled())
6662 json
= json_object_new_object();
6664 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6666 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6667 wctx
.r_vtep_ip
= vtep_ip
;
6669 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6672 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6673 json
, JSON_C_TO_STRING_PRETTY
));
6674 json_object_free(json
);
6679 * Display specific MAC for a VNI, if present (VTY command handler).
6681 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6682 vni_t vni
, struct ethaddr
*macaddr
,
6687 json_object
*json
= NULL
;
6689 if (!is_evpn_enabled())
6692 zvni
= zvni_lookup(vni
);
6695 vty_out(vty
, "{}\n");
6697 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6700 mac
= zvni_mac_lookup(zvni
, macaddr
);
6703 vty_out(vty
, "{}\n");
6706 "%% Requested MAC does not exist in VNI %u\n",
6712 json
= json_object_new_object();
6714 zvni_print_mac(mac
, vty
, json
);
6716 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6717 json
, JSON_C_TO_STRING_PRETTY
));
6718 json_object_free(json
);
6722 /* Print Duplicate MACs per VNI */
6723 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6724 struct zebra_vrf
*zvrf
,
6725 vni_t vni
, bool use_json
)
6728 struct mac_walk_ctx wctx
;
6730 json_object
*json
= NULL
;
6731 json_object
*json_mac
= NULL
;
6733 if (!is_evpn_enabled())
6736 zvni
= zvni_lookup(vni
);
6738 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6742 num_macs
= num_valid_macs(zvni
);
6746 num_macs
= num_dup_detected_macs(zvni
);
6751 json
= json_object_new_object();
6752 json_mac
= json_object_new_object();
6755 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6758 wctx
.json
= json_mac
;
6762 "Number of MACs (local and remote) known for this VNI: %u\n",
6764 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6765 "Intf/Remote VTEP", "VLAN");
6767 json_object_int_add(json
, "numMacs", num_macs
);
6769 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6772 json_object_object_add(json
, "macs", json_mac
);
6773 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6774 json
, JSON_C_TO_STRING_PRETTY
));
6775 json_object_free(json
);
6780 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6781 struct zebra_vrf
*zvrf
,
6782 vni_t vni
, struct ethaddr
*macaddr
)
6786 struct listnode
*node
= NULL
;
6787 zebra_neigh_t
*nbr
= NULL
;
6789 if (!is_evpn_enabled())
6792 zvni
= zvni_lookup(vni
);
6794 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6798 mac
= zvni_mac_lookup(zvni
, macaddr
);
6800 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6805 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6806 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6810 /* Remove all IPs as duplicate associcated with this MAC */
6811 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6812 /* For local neigh mark inactive so MACIP update is generated
6813 * to BGP. This is a scenario where MAC update received
6814 * and detected as duplicate which marked neigh as duplicate.
6815 * Later local neigh update did not get a chance to relay
6816 * to BGP. Similarly remote macip update, neigh needs to be
6817 * installed locally.
6819 if (zvrf
->dad_freeze
&&
6820 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6821 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6822 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6823 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6824 zvni_neigh_install(zvni
, nbr
);
6827 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6829 nbr
->detect_start_time
.tv_sec
= 0;
6830 nbr
->dad_dup_detect_time
= 0;
6833 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6835 mac
->detect_start_time
.tv_sec
= 0;
6836 mac
->detect_start_time
.tv_usec
= 0;
6837 mac
->dad_dup_detect_time
= 0;
6838 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6840 /* warn-only action return */
6841 if (!zvrf
->dad_freeze
)
6844 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6845 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6847 if (zvni_mac_send_add_to_client(zvni
->vni
,
6853 /* Process all neighbors associated with this MAC. */
6854 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6856 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6857 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6859 /* Install the entry. */
6860 zvni_mac_install(zvni
, mac
);
6866 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6867 struct zebra_vrf
*zvrf
,
6868 vni_t vni
, struct ipaddr
*ip
)
6873 char buf
[INET6_ADDRSTRLEN
];
6874 char buf2
[ETHER_ADDR_STRLEN
];
6876 if (!is_evpn_enabled())
6879 zvni
= zvni_lookup(vni
);
6881 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6885 nbr
= zvni_neigh_lookup(zvni
, ip
);
6888 "%% Requested host IP does not exist in VNI %u\n",
6893 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6895 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6897 "%% Requested host IP %s is not duplicate detected\n",
6902 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6904 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6906 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6907 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6908 return CMD_WARNING_CONFIG_FAILED
;
6911 if (IS_ZEBRA_DEBUG_VXLAN
)
6912 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6913 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6916 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6918 nbr
->detect_start_time
.tv_sec
= 0;
6919 nbr
->detect_start_time
.tv_usec
= 0;
6920 nbr
->dad_dup_detect_time
= 0;
6921 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6923 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6924 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6926 nbr
->flags
, nbr
->loc_seq
);
6927 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6928 zvni_neigh_install(zvni
, nbr
);
6934 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6936 struct mac_walk_ctx
*wctx
= ctxt
;
6939 struct listnode
*node
= NULL
;
6940 zebra_neigh_t
*nbr
= NULL
;
6942 mac
= (zebra_mac_t
*)bucket
->data
;
6948 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6951 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6953 mac
->detect_start_time
.tv_sec
= 0;
6954 mac
->detect_start_time
.tv_usec
= 0;
6955 mac
->dad_dup_detect_time
= 0;
6956 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6958 /* Remove all IPs as duplicate associcated with this MAC */
6959 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6960 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6962 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6964 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6966 nbr
->detect_start_time
.tv_sec
= 0;
6967 nbr
->dad_dup_detect_time
= 0;
6970 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6971 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6973 if (zvni_mac_send_add_to_client(zvni
->vni
,
6975 mac
->flags
, mac
->loc_seq
))
6978 /* Process all neighbors associated with this MAC. */
6979 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6981 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6982 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6984 /* Install the entry. */
6985 zvni_mac_install(zvni
, mac
);
6989 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6991 struct neigh_walk_ctx
*wctx
= ctxt
;
6994 char buf
[INET6_ADDRSTRLEN
];
6996 nbr
= (zebra_neigh_t
*)bucket
->data
;
7002 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7005 if (IS_ZEBRA_DEBUG_VXLAN
) {
7006 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
7008 "%s: clear neigh %s dup state, flags 0x%x seq %u",
7009 __PRETTY_FUNCTION__
, buf
,
7010 nbr
->flags
, nbr
->loc_seq
);
7013 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7015 nbr
->detect_start_time
.tv_sec
= 0;
7016 nbr
->detect_start_time
.tv_usec
= 0;
7017 nbr
->dad_dup_detect_time
= 0;
7018 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
7020 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7021 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
7023 nbr
->flags
, nbr
->loc_seq
);
7024 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7025 zvni_neigh_install(zvni
, nbr
);
7029 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
7034 struct zebra_vrf
*zvrf
;
7035 struct mac_walk_ctx m_wctx
;
7036 struct neigh_walk_ctx n_wctx
;
7038 zvni
= (zebra_vni_t
*)bucket
->data
;
7042 vty
= (struct vty
*)args
[0];
7043 zvrf
= (struct zebra_vrf
*)args
[1];
7045 if (hashcount(zvni
->neigh_table
)) {
7046 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7050 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7054 if (num_valid_macs(zvni
)) {
7055 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7059 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7064 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
7065 struct zebra_vrf
*zvrf
)
7069 if (!is_evpn_enabled())
7075 hash_iterate(zvrf
->vni_table
,
7076 (void (*)(struct hash_bucket
*, void *))
7077 zvni_clear_dup_detect_hash_vni_all
, args
);
7082 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
7083 struct zebra_vrf
*zvrf
,
7087 struct mac_walk_ctx m_wctx
;
7088 struct neigh_walk_ctx n_wctx
;
7090 if (!is_evpn_enabled())
7093 zvni
= zvni_lookup(vni
);
7095 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7099 if (hashcount(zvni
->neigh_table
)) {
7100 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7104 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7108 if (num_valid_macs(zvni
)) {
7109 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7113 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7120 * Display MACs for a VNI from specific VTEP (VTY command handler).
7122 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7123 vni_t vni
, struct in_addr vtep_ip
,
7128 struct mac_walk_ctx wctx
;
7129 json_object
*json
= NULL
;
7130 json_object
*json_mac
= NULL
;
7132 if (!is_evpn_enabled())
7134 zvni
= zvni_lookup(vni
);
7137 vty_out(vty
, "{}\n");
7139 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7142 num_macs
= num_valid_macs(zvni
);
7147 json
= json_object_new_object();
7148 json_mac
= json_object_new_object();
7151 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
7154 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
7155 wctx
.r_vtep_ip
= vtep_ip
;
7156 wctx
.json
= json_mac
;
7157 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
7160 json_object_int_add(json
, "numMacs", wctx
.count
);
7162 json_object_object_add(json
, "macs", json_mac
);
7163 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7164 json
, JSON_C_TO_STRING_PRETTY
));
7165 json_object_free(json
);
7171 * Display VNI information (VTY command handler).
7173 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
7176 json_object
*json
= NULL
;
7178 zebra_l3vni_t
*zl3vni
= NULL
;
7179 zebra_vni_t
*zvni
= NULL
;
7181 if (!is_evpn_enabled())
7185 json
= json_object_new_object();
7189 zl3vni
= zl3vni_lookup(vni
);
7191 zl3vni_print(zl3vni
, (void *)args
);
7193 zvni
= zvni_lookup(vni
);
7196 vty_out(vty
, "{}\n");
7198 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7202 zvni_print(zvni
, (void *)args
);
7206 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7207 json
, JSON_C_TO_STRING_PRETTY
));
7208 json_object_free(json
);
7212 /* Display all global details for EVPN */
7213 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7218 json_object
*json
= NULL
;
7219 struct zebra_vrf
*zvrf
= NULL
;
7221 if (!is_evpn_enabled())
7224 zvrf
= zebra_vrf_get_evpn();
7228 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7229 num_l2vnis
= hashcount(zvrf
->vni_table
);
7230 num_vnis
= num_l2vnis
+ num_l3vnis
;
7233 json
= json_object_new_object();
7234 json_object_string_add(json
, "advertiseGatewayMacip",
7235 zvrf
->advertise_gw_macip
? "Yes" : "No");
7236 json_object_int_add(json
, "numVnis", num_vnis
);
7237 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7238 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7239 if (zvrf
->dup_addr_detect
)
7240 json_object_boolean_true_add(json
,
7241 "isDuplicateAddrDetection");
7243 json_object_boolean_false_add(json
,
7244 "isDuplicateAddrDetection");
7245 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7246 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7247 json_object_int_add(json
, "detectionFreezeTime",
7248 zvrf
->dad_freeze_time
);
7251 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7252 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7253 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7254 zvrf
->advertise_gw_macip
? "Yes" : "No");
7255 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7256 zvrf
->advertise_svi_macip
? "Yes" : "No");
7257 vty_out(vty
, "Duplicate address detection: %s\n",
7258 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7259 vty_out(vty
, " Detection max-moves %u, time %d\n",
7260 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7261 if (zvrf
->dad_freeze
) {
7262 if (zvrf
->dad_freeze_time
)
7263 vty_out(vty
, " Detection freeze %u\n",
7264 zvrf
->dad_freeze_time
);
7266 vty_out(vty
, " Detection freeze %s\n",
7272 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7273 json
, JSON_C_TO_STRING_PRETTY
));
7274 json_object_free(json
);
7279 * Display VNI hash table (VTY command handler).
7281 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7284 json_object
*json
= NULL
;
7287 if (!is_evpn_enabled())
7291 json
= json_object_new_object();
7293 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7294 "Type", "VxLAN IF", "# MACs", "# ARPs",
7295 "# Remote VTEPs", "Tenant VRF");
7300 /* Display all L2-VNIs */
7301 hash_iterate(zvrf
->vni_table
,
7302 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7305 /* Display all L3-VNIs */
7306 hash_iterate(zrouter
.l3vni_table
,
7307 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7311 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7312 json
, JSON_C_TO_STRING_PRETTY
));
7313 json_object_free(json
);
7317 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7321 uint32_t max_moves
= 0;
7322 uint32_t freeze_time
= 0;
7323 bool dup_addr_detect
= false;
7324 bool freeze
= false;
7327 STREAM_GETL(s
, dup_addr_detect
);
7328 STREAM_GETL(s
, time
);
7329 STREAM_GETL(s
, max_moves
);
7330 STREAM_GETL(s
, freeze
);
7331 STREAM_GETL(s
, freeze_time
);
7333 /* DAD previous state was enabled, and new state is disable,
7334 * clear all duplicate detected addresses.
7336 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7337 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7339 zvrf
->dup_addr_detect
= dup_addr_detect
;
7340 zvrf
->dad_time
= time
;
7341 zvrf
->dad_max_moves
= max_moves
;
7342 zvrf
->dad_freeze
= freeze
;
7343 zvrf
->dad_freeze_time
= freeze_time
;
7345 if (IS_ZEBRA_DEBUG_VXLAN
)
7347 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7348 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7349 zvrf
->dup_addr_detect
? "enable" : "disable",
7350 zvrf
->dad_max_moves
,
7352 zvrf
->dad_freeze
? "enable" : "disable",
7353 zvrf
->dad_freeze_time
);
7360 * Display VNI hash table in detail(VTY command handler).
7362 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7365 json_object
*json
= NULL
;
7366 struct zebra_ns
*zns
= NULL
;
7367 struct zvni_evpn_show zes
;
7369 if (!is_evpn_enabled())
7372 zns
= zebra_ns_lookup(NS_DEFAULT
);
7378 json
= json_object_new_object();
7384 /* Display all L2-VNIs */
7387 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7390 /* Display all L3-VNIs */
7391 hash_iterate(zrouter
.l3vni_table
,
7392 (void (*)(struct hash_bucket
*,
7393 void *))zl3vni_print_hash_detail
,
7397 vty_out(vty
, "%s\n",
7398 json_object_to_json_string_ext(
7399 json
, JSON_C_TO_STRING_PRETTY
));
7400 json_object_free(json
);
7405 * Handle neighbor delete notification from the kernel (on a VLAN device
7406 * / L3 interface). This may result in either the neighbor getting deleted
7407 * from our database or being re-added to the kernel (if it is a valid
7410 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7411 struct interface
*link_if
,
7414 char buf
[INET6_ADDRSTRLEN
];
7415 char buf2
[ETHER_ADDR_STRLEN
];
7416 zebra_neigh_t
*n
= NULL
;
7417 zebra_vni_t
*zvni
= NULL
;
7418 zebra_mac_t
*zmac
= NULL
;
7419 zebra_l3vni_t
*zl3vni
= NULL
;
7420 struct zebra_vrf
*zvrf
;
7422 /* check if this is a remote neigh entry corresponding to remote
7425 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7427 return zl3vni_local_nh_del(zl3vni
, ip
);
7429 /* We are only interested in neighbors on an SVI that resides on top
7430 * of a VxLAN bridge.
7432 zvni
= zvni_from_svi(ifp
, link_if
);
7434 if (IS_ZEBRA_DEBUG_VXLAN
)
7435 zlog_debug("%s: Del neighbor %s VNI is not present for interface %s",
7436 __PRETTY_FUNCTION__
,
7437 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
);
7441 if (!zvni
->vxlan_if
) {
7443 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7448 if (IS_ZEBRA_DEBUG_VXLAN
)
7449 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7450 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7451 ifp
->ifindex
, zvni
->vni
);
7453 /* If entry doesn't exist, nothing to do. */
7454 n
= zvni_neigh_lookup(zvni
, ip
);
7458 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7460 if (IS_ZEBRA_DEBUG_VXLAN
)
7462 "Trying to del a neigh %s without a mac %s on VNI %u",
7463 ipaddr2str(ip
, buf
, sizeof(buf
)),
7464 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7470 /* If it is a remote entry, the kernel has aged this out or someone has
7471 * deleted it, it needs to be re-installed as Quagga is the owner.
7473 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7474 zvni_neigh_install(zvni
, n
);
7478 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7480 zlog_debug("%s: VNI %u vrf lookup failed.",
7481 __PRETTY_FUNCTION__
, zvni
->vni
);
7485 /* In case of feeze action, if local neigh is in duplicate state,
7486 * Mark the Neigh as inactive before sending delete request to BGPd,
7487 * If BGPd has remote entry, it will re-install
7489 if (zvrf
->dad_freeze
&&
7490 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7491 ZEBRA_NEIGH_SET_INACTIVE(n
);
7493 /* Remove neighbor from BGP. */
7494 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7496 /* Delete this neighbor entry. */
7497 zvni_neigh_del(zvni
, n
);
7499 /* see if the AUTO mac needs to be deleted */
7500 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7501 && !listcount(zmac
->neigh_list
))
7502 zvni_mac_del(zvni
, zmac
);
7508 * Handle neighbor add or update notification from the kernel (on a VLAN
7509 * device / L3 interface). This is typically for a local neighbor but can
7510 * also be for a remote neighbor (e.g., ageout notification). It could
7511 * also be a "move" scenario.
7513 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7514 struct interface
*link_if
,
7516 struct ethaddr
*macaddr
,
7521 char buf
[ETHER_ADDR_STRLEN
];
7522 char buf2
[INET6_ADDRSTRLEN
];
7523 zebra_vni_t
*zvni
= NULL
;
7524 zebra_l3vni_t
*zl3vni
= NULL
;
7526 /* check if this is a remote neigh entry corresponding to remote
7529 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7531 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7533 /* We are only interested in neighbors on an SVI that resides on top
7534 * of a VxLAN bridge.
7536 zvni
= zvni_from_svi(ifp
, link_if
);
7540 if (IS_ZEBRA_DEBUG_VXLAN
)
7542 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7543 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7544 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7545 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7546 is_router
? "router " : "",
7549 /* Is this about a local neighbor or a remote one? */
7551 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7554 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7559 * Handle message from client to delete a remote MACIP for a VNI.
7561 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7565 struct ethaddr macaddr
;
7567 struct in_addr vtep_ip
;
7568 uint16_t l
= 0, ipa_len
;
7569 char buf
[ETHER_ADDR_STRLEN
];
7570 char buf1
[INET6_ADDRSTRLEN
];
7572 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7573 memset(&ip
, 0, sizeof(struct ipaddr
));
7574 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7578 while (l
< hdr
->length
) {
7579 /* Obtain each remote MACIP and process. */
7580 /* Message contains VNI, followed by MAC followed by IP (if any)
7581 * followed by remote VTEP IP.
7583 memset(&ip
, 0, sizeof(ip
));
7584 STREAM_GETL(s
, vni
);
7585 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7586 STREAM_GETL(s
, ipa_len
);
7588 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7590 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7592 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7593 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7594 l
+= IPV4_MAX_BYTELEN
;
7596 if (IS_ZEBRA_DEBUG_VXLAN
)
7598 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7600 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7601 ipa_len
? " IP " : "",
7603 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7605 zebra_route_string(client
->proto
));
7607 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7615 * Handle message from client to add a remote MACIP for a VNI. This
7616 * could be just the add of a MAC address or the add of a neighbor
7619 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7623 struct ethaddr macaddr
;
7625 struct in_addr vtep_ip
;
7626 uint16_t l
= 0, ipa_len
;
7629 char buf
[ETHER_ADDR_STRLEN
];
7630 char buf1
[INET6_ADDRSTRLEN
];
7632 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7633 memset(&ip
, 0, sizeof(struct ipaddr
));
7634 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7636 if (!EVPN_ENABLED(zvrf
)) {
7637 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7643 while (l
< hdr
->length
) {
7644 /* Obtain each remote MACIP and process. */
7645 /* Message contains VNI, followed by MAC followed by IP (if any)
7646 * followed by remote VTEP IP.
7648 memset(&ip
, 0, sizeof(ip
));
7649 STREAM_GETL(s
, vni
);
7650 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7651 STREAM_GETL(s
, ipa_len
);
7653 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7655 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7657 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7658 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7659 l
+= IPV4_MAX_BYTELEN
;
7661 /* Get flags - sticky mac and/or gateway mac */
7662 STREAM_GETC(s
, flags
);
7664 STREAM_GETL(s
, seq
);
7667 if (IS_ZEBRA_DEBUG_VXLAN
)
7669 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7671 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7672 ipa_len
? " IP " : "",
7674 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7675 flags
, seq
, inet_ntoa(vtep_ip
),
7676 zebra_route_string(client
->proto
));
7678 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7679 flags
, seq
, vtep_ip
);
7687 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7688 * us, this must involve a multihoming scenario. Treat this as implicit delete
7689 * of any prior local MAC.
7691 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7692 struct interface
*br_if
,
7693 struct ethaddr
*macaddr
, vlanid_t vid
)
7695 struct zebra_if
*zif
;
7696 struct zebra_l2info_vxlan
*vxl
;
7700 char buf
[ETHER_ADDR_STRLEN
];
7704 vxl
= &zif
->l2info
.vxl
;
7707 /* Check if EVPN is enabled. */
7708 if (!is_evpn_enabled())
7711 /* Locate hash entry; it is expected to exist. */
7712 zvni
= zvni_lookup(vni
);
7716 /* If entry doesn't exist, nothing to do. */
7717 mac
= zvni_mac_lookup(zvni
, macaddr
);
7721 /* Is it a local entry? */
7722 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7725 if (IS_ZEBRA_DEBUG_VXLAN
)
7727 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7728 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7729 ifp
->ifindex
, vni
, mac
->flags
);
7731 /* Remove MAC from BGP. */
7732 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7735 * If there are no neigh associated with the mac delete the mac
7736 * else mark it as AUTO for forward reference
7738 if (!listcount(mac
->neigh_list
)) {
7739 zvni_mac_del(zvni
, mac
);
7741 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7742 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7743 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7750 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7751 * This can happen because the remote MAC entries are also added as "dynamic",
7752 * so the kernel can ageout the entry.
7754 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7755 struct interface
*br_if
,
7756 struct ethaddr
*macaddr
, vlanid_t vid
)
7758 struct zebra_if
*zif
= NULL
;
7759 struct zebra_l2info_vxlan
*vxl
= NULL
;
7761 zebra_vni_t
*zvni
= NULL
;
7762 zebra_l3vni_t
*zl3vni
= NULL
;
7763 zebra_mac_t
*mac
= NULL
;
7764 char buf
[ETHER_ADDR_STRLEN
];
7768 vxl
= &zif
->l2info
.vxl
;
7771 /* Check if EVPN is enabled. */
7772 if (!is_evpn_enabled())
7775 /* check if this is a remote RMAC and readd simillar to remote macs */
7776 zl3vni
= zl3vni_lookup(vni
);
7778 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7780 /* Locate hash entry; it is expected to exist. */
7781 zvni
= zvni_lookup(vni
);
7785 /* If entry doesn't exist, nothing to do. */
7786 mac
= zvni_mac_lookup(zvni
, macaddr
);
7790 /* Is it a remote entry? */
7791 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7794 if (IS_ZEBRA_DEBUG_VXLAN
)
7795 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7796 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7799 zvni_mac_install(zvni
, mac
);
7804 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7806 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7807 struct ethaddr
*macaddr
, vlanid_t vid
)
7811 char buf
[ETHER_ADDR_STRLEN
];
7813 /* We are interested in MACs only on ports or (port, VLAN) that
7816 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7819 if (!zvni
->vxlan_if
) {
7821 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7826 /* If entry doesn't exist, nothing to do. */
7827 mac
= zvni_mac_lookup(zvni
, macaddr
);
7831 /* Is it a local entry? */
7832 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7835 if (IS_ZEBRA_DEBUG_VXLAN
)
7836 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
7837 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7838 ifp
->ifindex
, vid
, zvni
->vni
, mac
->loc_seq
,
7839 mac
->flags
, listcount(mac
->neigh_list
));
7841 /* Update all the neigh entries associated with this mac */
7842 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7844 /* Remove MAC from BGP. */
7845 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7848 * If there are no neigh associated with the mac delete the mac
7849 * else mark it as AUTO for forward reference
7851 if (!listcount(mac
->neigh_list
)) {
7852 zvni_mac_del(zvni
, mac
);
7854 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7855 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7856 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7863 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7865 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7866 struct interface
*br_if
,
7867 struct ethaddr
*macaddr
, vlanid_t vid
,
7872 struct zebra_vrf
*zvrf
;
7873 char buf
[ETHER_ADDR_STRLEN
];
7874 bool mac_sticky
= false;
7875 bool inform_client
= false;
7876 bool upd_neigh
= false;
7877 bool is_dup_detect
= false;
7878 struct in_addr vtep_ip
= {.s_addr
= 0};
7880 /* We are interested in MACs only on ports or (port, VLAN) that
7883 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7885 if (IS_ZEBRA_DEBUG_VXLAN
)
7887 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7888 sticky
? "sticky " : "",
7889 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7890 ifp
->name
, ifp
->ifindex
, vid
);
7894 if (!zvni
->vxlan_if
) {
7895 if (IS_ZEBRA_DEBUG_VXLAN
)
7897 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7902 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7904 if (IS_ZEBRA_DEBUG_VXLAN
)
7905 zlog_debug("\tNo Vrf found for vrf_id: %d",
7906 zvni
->vxlan_if
->vrf_id
);
7910 /* Check if we need to create or update or it is a NO-OP. */
7911 mac
= zvni_mac_lookup(zvni
, macaddr
);
7913 if (IS_ZEBRA_DEBUG_VXLAN
)
7915 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7916 sticky
? "sticky " : "",
7917 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7918 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7920 mac
= zvni_mac_add(zvni
, macaddr
);
7923 EC_ZEBRA_MAC_ADD_FAILED
,
7924 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7925 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7926 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7929 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7930 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7931 mac
->fwd_info
.local
.vid
= vid
;
7933 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7934 inform_client
= true;
7937 if (IS_ZEBRA_DEBUG_VXLAN
)
7939 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7940 sticky
? "sticky " : "",
7941 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7942 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7945 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7946 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7950 * Update any changes and if changes are relevant to
7953 if (mac_sticky
== sticky
7954 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7955 && mac
->fwd_info
.local
.vid
== vid
) {
7956 if (IS_ZEBRA_DEBUG_VXLAN
)
7958 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7959 "entry exists and has not changed ",
7960 sticky
? "sticky " : "",
7961 prefix_mac2str(macaddr
, buf
,
7963 ifp
->name
, ifp
->ifindex
, vid
,
7967 if (mac_sticky
!= sticky
) {
7969 SET_FLAG(mac
->flags
,
7972 UNSET_FLAG(mac
->flags
,
7974 inform_client
= true;
7977 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7978 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7979 mac
->fwd_info
.local
.vid
= vid
;
7981 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7982 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7983 bool do_dad
= false;
7986 * MAC has either moved or was "internally" created due
7987 * to a neighbor learn and is now actually learnt. If
7988 * it was learnt as a remote sticky MAC, this is an
7991 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7993 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7994 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7995 prefix_mac2str(macaddr
, buf
,
7997 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
8002 /* If an actual move, compute MAC's seq number */
8003 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8004 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
8006 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
8007 /* Trigger DAD for remote MAC */
8011 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
8012 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
8013 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
8014 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
8015 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8016 mac
->fwd_info
.local
.vid
= vid
;
8018 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8020 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8022 * We have to inform BGP of this MAC as well as process
8025 inform_client
= true;
8028 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
8032 if (is_dup_detect
) {
8033 inform_client
= false;
8039 /* Inform BGP if required. */
8040 if (inform_client
) {
8041 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
8042 mac
->flags
, mac
->loc_seq
))
8046 /* Process all neighbors associated with this MAC, if required. */
8048 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
8054 * Handle message from client to delete a remote VTEP for a VNI.
8056 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
8059 unsigned short l
= 0;
8061 struct in_addr vtep_ip
;
8063 zebra_vtep_t
*zvtep
;
8064 struct interface
*ifp
;
8065 struct zebra_if
*zif
;
8067 if (!is_evpn_enabled()) {
8069 "%s: EVPN is not enabled yet we have received a vtep del command",
8070 __PRETTY_FUNCTION__
);
8074 if (!EVPN_ENABLED(zvrf
)) {
8075 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
8082 while (l
< hdr
->length
) {
8083 int flood_control
__attribute__((unused
));
8085 /* Obtain each remote VTEP and process. */
8086 STREAM_GETL(s
, vni
);
8088 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8089 l
+= IPV4_MAX_BYTELEN
;
8091 /* Flood control is intentionally ignored right now */
8092 STREAM_GETL(s
, flood_control
);
8095 if (IS_ZEBRA_DEBUG_VXLAN
)
8096 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
8097 inet_ntoa(vtep_ip
), vni
,
8098 zebra_route_string(client
->proto
));
8100 /* Locate VNI hash entry - expected to exist. */
8101 zvni
= zvni_lookup(vni
);
8103 if (IS_ZEBRA_DEBUG_VXLAN
)
8105 "Failed to locate VNI hash upon remote VTEP DEL, "
8111 ifp
= zvni
->vxlan_if
;
8114 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
8120 /* If down or not mapped to a bridge, we're done. */
8121 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8124 /* If the remote VTEP does not exist, there's nothing more to
8126 * Otherwise, uninstall any remote MACs pointing to this VTEP
8128 * then, the VTEP entry itself and remove it.
8130 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8134 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
8135 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
8136 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8137 zvni_vtep_del(zvni
, zvtep
);
8145 * Handle message from client to add a remote VTEP for a VNI.
8147 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
8150 unsigned short l
= 0;
8152 struct in_addr vtep_ip
;
8154 struct interface
*ifp
;
8155 struct zebra_if
*zif
;
8157 zebra_vtep_t
*zvtep
;
8159 if (!is_evpn_enabled()) {
8161 "%s: EVPN not enabled yet we received a vtep_add zapi call",
8162 __PRETTY_FUNCTION__
);
8166 if (!EVPN_ENABLED(zvrf
)) {
8167 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
8174 while (l
< hdr
->length
) {
8175 /* Obtain each remote VTEP and process. */
8176 STREAM_GETL(s
, vni
);
8178 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8179 STREAM_GETL(s
, flood_control
);
8180 l
+= IPV4_MAX_BYTELEN
+ 4;
8182 if (IS_ZEBRA_DEBUG_VXLAN
)
8183 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
8184 inet_ntoa(vtep_ip
), vni
, flood_control
,
8185 zebra_route_string(client
->proto
));
8187 /* Locate VNI hash entry - expected to exist. */
8188 zvni
= zvni_lookup(vni
);
8191 EC_ZEBRA_VTEP_ADD_FAILED
,
8192 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
8197 ifp
= zvni
->vxlan_if
;
8200 EC_ZEBRA_VTEP_ADD_FAILED
,
8201 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8208 /* If down or not mapped to a bridge, we're done. */
8209 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8212 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8214 /* If the remote VTEP already exists check if
8215 * the flood mode has changed
8217 if (zvtep
->flood_control
!= flood_control
) {
8218 if (zvtep
->flood_control
8219 == VXLAN_FLOOD_DISABLED
)
8220 /* old mode was head-end-replication but
8221 * is no longer; get rid of the HER fdb
8222 * entry installed before
8224 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8225 zvtep
->flood_control
= flood_control
;
8226 zvni_vtep_install(zvni
, zvtep
);
8229 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8231 zvni_vtep_install(zvni
, zvtep
);
8233 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8234 "Failed to add remote VTEP, VNI %u zvni %p",
8244 * Add/Del gateway macip to evpn
8246 * 1. SVI interface on a vlan aware bridge
8247 * 2. SVI interface on a vlan unaware bridge
8248 * 3. vrr interface (MACVLAN) associated to a SVI
8249 * We advertise macip routes for an interface if it is associated to VxLan vlan
8251 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8255 struct ethaddr macaddr
;
8256 zebra_vni_t
*zvni
= NULL
;
8258 memset(&ip
, 0, sizeof(struct ipaddr
));
8259 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8261 /* Check if EVPN is enabled. */
8262 if (!is_evpn_enabled())
8265 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8266 struct interface
*svi_if
=
8267 NULL
; /* SVI corresponding to the MACVLAN */
8268 struct zebra_if
*ifp_zif
=
8269 NULL
; /* Zebra daemon specific info for MACVLAN */
8270 struct zebra_if
*svi_if_zif
=
8271 NULL
; /* Zebra daemon specific info for SVI*/
8273 ifp_zif
= ifp
->info
;
8278 * for a MACVLAN interface the link represents the svi_if
8280 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8281 ifp_zif
->link_ifindex
);
8283 zlog_debug("MACVLAN %s(%u) without link information",
8284 ifp
->name
, ifp
->ifindex
);
8288 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8290 * If it is a vlan aware bridge then the link gives the
8291 * bridge information
8293 struct interface
*svi_if_link
= NULL
;
8295 svi_if_zif
= svi_if
->info
;
8297 svi_if_link
= if_lookup_by_index_per_ns(
8298 zebra_ns_lookup(NS_DEFAULT
),
8299 svi_if_zif
->link_ifindex
);
8300 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8302 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8304 * If it is a vlan unaware bridge then svi is the bridge
8307 zvni
= zvni_from_svi(svi_if
, svi_if
);
8309 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8310 struct zebra_if
*svi_if_zif
=
8311 NULL
; /* Zebra daemon specific info for SVI */
8312 struct interface
*svi_if_link
=
8313 NULL
; /* link info for the SVI = bridge info */
8315 svi_if_zif
= ifp
->info
;
8317 svi_if_link
= if_lookup_by_index_per_ns(
8318 zebra_ns_lookup(NS_DEFAULT
),
8319 svi_if_zif
->link_ifindex
);
8321 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8323 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8324 zvni
= zvni_from_svi(ifp
, ifp
);
8330 if (!zvni
->vxlan_if
) {
8331 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8337 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8339 if (p
->family
== AF_INET
) {
8340 ip
.ipa_type
= IPADDR_V4
;
8341 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8342 sizeof(struct in_addr
));
8343 } else if (p
->family
== AF_INET6
) {
8344 ip
.ipa_type
= IPADDR_V6
;
8345 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8346 sizeof(struct in6_addr
));
8351 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8353 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8359 * Handle SVI interface going down.
8360 * SVI can be associated to either L3-VNI or L2-VNI.
8361 * For L2-VNI: At this point, this is a NOP since
8362 * the kernel deletes the neighbor entries on this SVI (if any).
8363 * We only need to update the vrf corresponding to zvni.
8364 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8367 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8369 zebra_l3vni_t
*zl3vni
= NULL
;
8371 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8374 /* process l3-vni down */
8375 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8377 /* remove association with svi-if */
8378 zl3vni
->svi_if
= NULL
;
8380 zebra_vni_t
*zvni
= NULL
;
8382 /* since we dont have svi corresponding to zvni, we associate it
8383 * to default vrf. Note: the corresponding neigh entries on the
8384 * SVI would have already been deleted */
8385 zvni
= zvni_from_svi(ifp
, link_if
);
8387 zvni
->vrf_id
= VRF_DEFAULT
;
8389 /* update the tenant vrf in BGP */
8390 zvni_send_add_to_client(zvni
);
8397 * Handle SVI interface coming up.
8398 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8400 * For L2-VNI: we need to install any remote neighbors entried (used for
8402 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8404 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8406 zebra_vni_t
*zvni
= NULL
;
8407 zebra_l3vni_t
*zl3vni
= NULL
;
8409 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8412 /* associate with svi */
8413 zl3vni
->svi_if
= ifp
;
8415 /* process oper-up */
8416 if (is_l3vni_oper_up(zl3vni
))
8417 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8420 /* process SVI up for l2-vni */
8421 struct neigh_walk_ctx n_wctx
;
8423 zvni
= zvni_from_svi(ifp
, link_if
);
8427 if (!zvni
->vxlan_if
) {
8429 "VNI %u hash %p doesn't have intf upon SVI up",
8434 if (IS_ZEBRA_DEBUG_VXLAN
)
8436 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8437 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8438 vrf_id_to_name(ifp
->vrf_id
));
8440 /* update the vrf information for l2-vni and inform bgp */
8441 zvni
->vrf_id
= ifp
->vrf_id
;
8442 zvni_send_add_to_client(zvni
);
8444 /* Install any remote neighbors for this VNI. */
8445 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8447 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8455 * Handle VxLAN interface down
8457 int zebra_vxlan_if_down(struct interface
*ifp
)
8460 struct zebra_if
*zif
= NULL
;
8461 struct zebra_l2info_vxlan
*vxl
= NULL
;
8462 zebra_l3vni_t
*zl3vni
= NULL
;
8465 /* Check if EVPN is enabled. */
8466 if (!is_evpn_enabled())
8471 vxl
= &zif
->l2info
.vxl
;
8474 zl3vni
= zl3vni_lookup(vni
);
8476 /* process-if-down for l3-vni */
8477 if (IS_ZEBRA_DEBUG_VXLAN
)
8478 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8481 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8483 /* process if-down for l2-vni */
8484 if (IS_ZEBRA_DEBUG_VXLAN
)
8485 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8488 /* Locate hash entry; it is expected to exist. */
8489 zvni
= zvni_lookup(vni
);
8492 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8493 ifp
->name
, ifp
->ifindex
, vni
);
8497 assert(zvni
->vxlan_if
== ifp
);
8499 /* Delete this VNI from BGP. */
8500 zvni_send_del_to_client(zvni
->vni
);
8502 /* Free up all neighbors and MACs, if any. */
8503 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8504 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8506 /* Free up all remote VTEPs, if any. */
8507 zvni_vtep_del_all(zvni
, 1);
8513 * Handle VxLAN interface up - update BGP if required.
8515 int zebra_vxlan_if_up(struct interface
*ifp
)
8518 struct zebra_if
*zif
= NULL
;
8519 struct zebra_l2info_vxlan
*vxl
= NULL
;
8520 zebra_vni_t
*zvni
= NULL
;
8521 zebra_l3vni_t
*zl3vni
= NULL
;
8523 /* Check if EVPN is enabled. */
8524 if (!is_evpn_enabled())
8529 vxl
= &zif
->l2info
.vxl
;
8532 zl3vni
= zl3vni_lookup(vni
);
8535 if (IS_ZEBRA_DEBUG_VXLAN
)
8536 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8539 /* we need to associate with SVI, if any, we can associate with
8540 * svi-if only after association with vxlan-intf is complete
8542 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8544 if (is_l3vni_oper_up(zl3vni
))
8545 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8547 /* Handle L2-VNI add */
8548 struct interface
*vlan_if
= NULL
;
8550 if (IS_ZEBRA_DEBUG_VXLAN
)
8551 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8554 /* Locate hash entry; it is expected to exist. */
8555 zvni
= zvni_lookup(vni
);
8558 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8559 ifp
->name
, ifp
->ifindex
, vni
);
8563 assert(zvni
->vxlan_if
== ifp
);
8564 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8565 zif
->brslave_info
.br_if
);
8567 zvni
->vrf_id
= vlan_if
->vrf_id
;
8568 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8570 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8573 /* If part of a bridge, inform BGP about this VNI. */
8574 /* Also, read and populate local MACs and neighbors. */
8575 if (zif
->brslave_info
.br_if
) {
8576 zvni_send_add_to_client(zvni
);
8577 zvni_read_mac_neigh(zvni
, ifp
);
8585 * Handle VxLAN interface delete. Locate and remove entry in hash table
8586 * and update BGP, if required.
8588 int zebra_vxlan_if_del(struct interface
*ifp
)
8591 struct zebra_if
*zif
= NULL
;
8592 struct zebra_l2info_vxlan
*vxl
= NULL
;
8593 zebra_vni_t
*zvni
= NULL
;
8594 zebra_l3vni_t
*zl3vni
= NULL
;
8596 /* Check if EVPN is enabled. */
8597 if (!is_evpn_enabled())
8602 vxl
= &zif
->l2info
.vxl
;
8605 zl3vni
= zl3vni_lookup(vni
);
8608 if (IS_ZEBRA_DEBUG_VXLAN
)
8609 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8612 /* process oper-down for l3-vni */
8613 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8615 /* remove the association with vxlan_if */
8616 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8617 zl3vni
->vxlan_if
= NULL
;
8620 /* process if-del for l2-vni*/
8621 if (IS_ZEBRA_DEBUG_VXLAN
)
8622 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8625 /* Locate hash entry; it is expected to exist. */
8626 zvni
= zvni_lookup(vni
);
8629 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8630 ifp
->name
, ifp
->ifindex
, vni
);
8634 /* remove from l3-vni list */
8635 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8637 listnode_delete(zl3vni
->l2vnis
, zvni
);
8639 /* Delete VNI from BGP. */
8640 zvni_send_del_to_client(zvni
->vni
);
8642 /* Free up all neighbors and MAC, if any. */
8643 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8644 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8646 /* Free up all remote VTEPs, if any. */
8647 zvni_vtep_del_all(zvni
, 0);
8649 /* Delete the hash entry. */
8650 if (zvni_del(zvni
)) {
8651 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8652 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8653 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8661 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8663 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8666 struct zebra_if
*zif
= NULL
;
8667 struct zebra_l2info_vxlan
*vxl
= NULL
;
8668 zebra_vni_t
*zvni
= NULL
;
8669 zebra_l3vni_t
*zl3vni
= NULL
;
8671 /* Check if EVPN is enabled. */
8672 if (!is_evpn_enabled())
8677 vxl
= &zif
->l2info
.vxl
;
8680 zl3vni
= zl3vni_lookup(vni
);
8683 if (IS_ZEBRA_DEBUG_VXLAN
)
8685 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8686 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8687 inet_ntoa(vxl
->vtep_ip
),
8688 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8690 /* Removed from bridge? Cleanup and return */
8691 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8692 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8693 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8697 /* access-vlan change - process oper down, associate with new
8698 * svi_if and then process oper up again
8700 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8701 if (if_is_operative(ifp
)) {
8702 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8703 zl3vni
->svi_if
= NULL
;
8704 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8705 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8706 if (is_l3vni_oper_up(zl3vni
))
8707 zebra_vxlan_process_l3vni_oper_up(
8713 * local-ip change - process oper down, associate with new
8714 * local-ip and then process oper up again
8716 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8717 if (if_is_operative(ifp
)) {
8718 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8719 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8720 if (is_l3vni_oper_up(zl3vni
))
8721 zebra_vxlan_process_l3vni_oper_up(
8726 /* Update local tunnel IP. */
8727 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8729 /* if we have a valid new master, process l3-vni oper up */
8730 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8731 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8732 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8736 /* Update VNI hash. */
8737 zvni
= zvni_lookup(vni
);
8740 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8741 ifp
->name
, ifp
->ifindex
, vni
);
8745 if (IS_ZEBRA_DEBUG_VXLAN
)
8747 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8748 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8749 inet_ntoa(vxl
->vtep_ip
),
8750 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8752 /* Removed from bridge? Cleanup and return */
8753 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8754 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8755 /* Delete from client, remove all remote VTEPs */
8756 /* Also, free up all MACs and neighbors. */
8757 zvni_send_del_to_client(zvni
->vni
);
8758 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8759 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8760 zvni_vtep_del_all(zvni
, 1);
8764 /* Handle other changes. */
8765 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8766 /* Remove all existing local neigh and MACs for this VNI
8767 * (including from BGP)
8769 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8770 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8773 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8774 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8775 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8777 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8778 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8779 zvni
->mcast_grp
= vxl
->mcast_grp
;
8781 zvni
->vxlan_if
= ifp
;
8783 /* Take further actions needed.
8784 * Note that if we are here, there is a change of interest.
8786 /* If down or not mapped to a bridge, we're done. */
8787 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8790 /* Inform BGP, if there is a change of interest. */
8792 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8793 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8794 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8795 zvni_send_add_to_client(zvni
);
8797 /* If there is a valid new master or a VLAN mapping change,
8798 * read and populate local MACs and neighbors.
8799 * Also, reinstall any remote MACs and neighbors
8800 * for this VNI (based on new VLAN).
8802 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8803 zvni_read_mac_neigh(zvni
, ifp
);
8804 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8805 struct mac_walk_ctx m_wctx
;
8806 struct neigh_walk_ctx n_wctx
;
8808 zvni_read_mac_neigh(zvni
, ifp
);
8810 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8812 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8815 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8817 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8826 * Handle VxLAN interface add.
8828 int zebra_vxlan_if_add(struct interface
*ifp
)
8831 struct zebra_if
*zif
= NULL
;
8832 struct zebra_l2info_vxlan
*vxl
= NULL
;
8833 zebra_vni_t
*zvni
= NULL
;
8834 zebra_l3vni_t
*zl3vni
= NULL
;
8836 /* Check if EVPN is enabled. */
8837 if (!is_evpn_enabled())
8842 vxl
= &zif
->l2info
.vxl
;
8845 zl3vni
= zl3vni_lookup(vni
);
8848 /* process if-add for l3-vni*/
8849 if (IS_ZEBRA_DEBUG_VXLAN
)
8851 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8852 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8853 inet_ntoa(vxl
->vtep_ip
),
8854 zif
->brslave_info
.bridge_ifindex
);
8856 /* associate with vxlan_if */
8857 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8858 zl3vni
->vxlan_if
= ifp
;
8860 /* Associate with SVI, if any. We can associate with svi-if only
8861 * after association with vxlan_if is complete */
8862 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8864 if (is_l3vni_oper_up(zl3vni
))
8865 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8868 /* process if-add for l2-vni */
8869 struct interface
*vlan_if
= NULL
;
8871 /* Create or update VNI hash. */
8872 zvni
= zvni_lookup(vni
);
8874 zvni
= zvni_add(vni
);
8877 EC_ZEBRA_VNI_ADD_FAILED
,
8878 "Failed to add VNI hash, IF %s(%u) VNI %u",
8879 ifp
->name
, ifp
->ifindex
, vni
);
8884 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8885 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8886 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8888 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8889 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8890 zvni
->mcast_grp
= vxl
->mcast_grp
;
8892 zvni
->vxlan_if
= ifp
;
8893 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8894 zif
->brslave_info
.br_if
);
8896 zvni
->vrf_id
= vlan_if
->vrf_id
;
8897 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8899 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8902 if (IS_ZEBRA_DEBUG_VXLAN
) {
8903 char addr_buf1
[INET_ADDRSTRLEN
];
8904 char addr_buf2
[INET_ADDRSTRLEN
];
8906 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8907 addr_buf1
, INET_ADDRSTRLEN
);
8908 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8909 addr_buf2
, INET_ADDRSTRLEN
);
8912 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8914 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8916 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8917 addr_buf1
, addr_buf2
,
8918 zif
->brslave_info
.bridge_ifindex
);
8921 /* If down or not mapped to a bridge, we're done. */
8922 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8926 zvni_send_add_to_client(zvni
);
8928 /* Read and populate local MACs and neighbors */
8929 zvni_read_mac_neigh(zvni
, ifp
);
8935 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8936 char *err
, int err_str_sz
, int filter
,
8939 zebra_l3vni_t
*zl3vni
= NULL
;
8940 struct zebra_vrf
*zvrf_evpn
= NULL
;
8942 zvrf_evpn
= zebra_vrf_get_evpn();
8946 if (IS_ZEBRA_DEBUG_VXLAN
)
8947 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8948 add
? "ADD" : "DEL");
8952 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8954 /* check if the vni is already present under zvrf */
8956 snprintf(err
, err_str_sz
,
8957 "VNI is already configured under the vrf");
8961 /* check if this VNI is already present in the system */
8962 zl3vni
= zl3vni_lookup(vni
);
8964 snprintf(err
, err_str_sz
,
8965 "VNI is already configured as L3-VNI");
8969 /* add the L3-VNI to the global table */
8970 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8972 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8976 /* associate the vrf with vni */
8979 /* set the filter in l3vni to denote if we are using l3vni only
8983 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8985 /* associate with vxlan-intf;
8986 * we need to associate with the vxlan-intf first
8988 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8990 /* associate with corresponding SVI interface, we can associate
8991 * with svi-if only after vxlan interface association is
8994 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8996 /* formulate l2vni list */
8997 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
9000 if (is_l3vni_oper_up(zl3vni
))
9001 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9004 zl3vni
= zl3vni_lookup(vni
);
9006 snprintf(err
, err_str_sz
, "VNI doesn't exist");
9010 if (zvrf
->l3vni
!= vni
) {
9011 snprintf(err
, err_str_sz
,
9012 "VNI %d doesn't exist in VRF: %s",
9013 vni
, zvrf
->vrf
->name
);
9017 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
9018 snprintf(err
, ERR_STR_SZ
,
9019 "prefix-routes-only is not set for the vni");
9023 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9025 /* delete and uninstall all rmacs */
9026 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
9029 /* delete and uninstall all next-hops */
9030 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
9036 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
9041 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
9043 zebra_l3vni_t
*zl3vni
= NULL
;
9046 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9050 zl3vni
->vrf_id
= zvrf_id(zvrf
);
9051 if (is_l3vni_oper_up(zl3vni
))
9052 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9056 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
9058 zebra_l3vni_t
*zl3vni
= NULL
;
9061 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9065 zl3vni
->vrf_id
= VRF_UNKNOWN
;
9066 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9070 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
9072 zebra_l3vni_t
*zl3vni
= NULL
;
9076 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9082 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
9088 * Handle message from client to specify the flooding mechanism for
9089 * BUM packets. The default is to do head-end (ingress) replication
9090 * and the other supported option is to disable it. This applies to
9091 * all BUM traffic and disabling it applies to both the transmit and
9092 * receive direction.
9094 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
9097 enum vxlan_flood_control flood_ctrl
;
9099 if (!EVPN_ENABLED(zvrf
)) {
9100 zlog_err("EVPN flood control for non-EVPN VRF %u",
9106 STREAM_GETC(s
, flood_ctrl
);
9108 if (IS_ZEBRA_DEBUG_VXLAN
)
9109 zlog_debug("EVPN flood control %u, currently %u",
9110 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
9112 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
9115 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9117 /* Install or uninstall flood entries corresponding to
9120 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
9128 * Handle message from client to enable/disable advertisement of svi macip
9131 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
9136 zebra_vni_t
*zvni
= NULL
;
9137 struct interface
*ifp
= NULL
;
9139 if (!EVPN_ENABLED(zvrf
)) {
9140 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
9146 STREAM_GETC(s
, advertise
);
9147 STREAM_GETL(s
, vni
);
9150 if (IS_ZEBRA_DEBUG_VXLAN
)
9151 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
9152 advertise
? "enabled" : "disabled",
9153 advertise_svi_macip_enabled(NULL
)
9157 if (zvrf
->advertise_svi_macip
== advertise
)
9162 zvrf
->advertise_svi_macip
= advertise
;
9163 hash_iterate(zvrf
->vni_table
,
9164 zvni_gw_macip_add_for_vni_hash
, NULL
);
9166 hash_iterate(zvrf
->vni_table
,
9167 zvni_svi_macip_del_for_vni_hash
, NULL
);
9168 zvrf
->advertise_svi_macip
= advertise
;
9172 struct zebra_if
*zif
= NULL
;
9173 struct zebra_l2info_vxlan zl2_info
;
9174 struct interface
*vlan_if
= NULL
;
9176 zvni
= zvni_lookup(vni
);
9180 if (IS_ZEBRA_DEBUG_VXLAN
)
9182 "EVPN SVI macip Adv %s on VNI %d , currently %s",
9183 advertise
? "enabled" : "disabled", vni
,
9184 advertise_svi_macip_enabled(zvni
)
9188 if (zvni
->advertise_svi_macip
== advertise
)
9191 /* Store flag even though SVI is not present.
9192 * Once SVI comes up triggers self MAC-IP route add.
9194 zvni
->advertise_svi_macip
= advertise
;
9196 ifp
= zvni
->vxlan_if
;
9202 /* If down or not mapped to a bridge, we're done. */
9203 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9206 zl2_info
= zif
->l2info
.vxl
;
9207 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9208 zif
->brslave_info
.br_if
);
9213 /* Add primary SVI MAC-IP */
9214 zvni_add_macip_for_intf(vlan_if
, zvni
);
9216 /* Del primary SVI MAC-IP */
9217 zvni_del_macip_for_intf(vlan_if
, zvni
);
9226 * Handle message from client to enable/disable advertisement of g/w macip
9229 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9234 zebra_vni_t
*zvni
= NULL
;
9235 struct interface
*ifp
= NULL
;
9236 struct zebra_if
*zif
= NULL
;
9237 struct zebra_l2info_vxlan zl2_info
;
9238 struct interface
*vlan_if
= NULL
;
9240 if (!EVPN_ENABLED(zvrf
)) {
9241 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9247 STREAM_GETC(s
, advertise
);
9248 vni
= stream_get3(s
);
9250 zvni
= zvni_lookup(vni
);
9254 if (zvni
->advertise_subnet
== advertise
)
9257 if (IS_ZEBRA_DEBUG_VXLAN
)
9258 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9259 advertise
? "enabled" : "disabled", vni
,
9260 zvni
->advertise_subnet
? "enabled" : "disabled");
9263 zvni
->advertise_subnet
= advertise
;
9265 ifp
= zvni
->vxlan_if
;
9271 /* If down or not mapped to a bridge, we're done. */
9272 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9275 zl2_info
= zif
->l2info
.vxl
;
9278 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9282 if (zvni
->advertise_subnet
)
9283 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9285 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9292 * Handle message from client to enable/disable advertisement of g/w macip
9295 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9300 zebra_vni_t
*zvni
= NULL
;
9301 struct interface
*ifp
= NULL
;
9303 if (!EVPN_ENABLED(zvrf
)) {
9304 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9310 STREAM_GETC(s
, advertise
);
9311 STREAM_GETL(s
, vni
);
9314 if (IS_ZEBRA_DEBUG_VXLAN
)
9315 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9316 advertise
? "enabled" : "disabled",
9317 advertise_gw_macip_enabled(NULL
)
9321 if (zvrf
->advertise_gw_macip
== advertise
)
9324 zvrf
->advertise_gw_macip
= advertise
;
9326 if (advertise_gw_macip_enabled(zvni
))
9327 hash_iterate(zvrf
->vni_table
,
9328 zvni_gw_macip_add_for_vni_hash
, NULL
);
9330 hash_iterate(zvrf
->vni_table
,
9331 zvni_gw_macip_del_for_vni_hash
, NULL
);
9334 struct zebra_if
*zif
= NULL
;
9335 struct zebra_l2info_vxlan zl2_info
;
9336 struct interface
*vlan_if
= NULL
;
9337 struct interface
*vrr_if
= NULL
;
9339 zvni
= zvni_lookup(vni
);
9343 if (IS_ZEBRA_DEBUG_VXLAN
)
9345 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9346 advertise
? "enabled" : "disabled", vni
,
9347 advertise_gw_macip_enabled(zvni
) ? "enabled"
9350 if (zvni
->advertise_gw_macip
== advertise
)
9353 zvni
->advertise_gw_macip
= advertise
;
9355 ifp
= zvni
->vxlan_if
;
9361 /* If down or not mapped to a bridge, we're done. */
9362 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9365 zl2_info
= zif
->l2info
.vxl
;
9367 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9368 zif
->brslave_info
.br_if
);
9372 if (advertise_gw_macip_enabled(zvni
)) {
9373 /* Add primary SVI MAC-IP */
9374 zvni_add_macip_for_intf(vlan_if
, zvni
);
9376 /* Add VRR MAC-IP - if any*/
9377 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9379 zvni_add_macip_for_intf(vrr_if
, zvni
);
9381 /* Del primary MAC-IP */
9382 zvni_del_macip_for_intf(vlan_if
, zvni
);
9384 /* Del VRR MAC-IP - if any*/
9385 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9387 zvni_del_macip_for_intf(vrr_if
, zvni
);
9397 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9398 * When enabled, the VNI hash table will be built and MAC FDB table read;
9399 * when disabled, the entries should be deleted and remote VTEPs and MACs
9400 * uninstalled from the kernel.
9401 * This also informs the setting for BUM handling at the time this change
9402 * occurs; it is relevant only when specifying "learn".
9404 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9406 struct stream
*s
= NULL
;
9408 enum vxlan_flood_control flood_ctrl
;
9410 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9412 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9416 STREAM_GETC(s
, advertise
);
9417 STREAM_GETC(s
, flood_ctrl
);
9419 if (IS_ZEBRA_DEBUG_VXLAN
)
9420 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9421 zvrf_name(zvrf
), zvrf_id(zvrf
),
9422 advertise
? "enabled" : "disabled",
9423 is_evpn_enabled() ? "enabled" : "disabled",
9426 if (zvrf
->advertise_all_vni
== advertise
)
9429 zvrf
->advertise_all_vni
= advertise
;
9430 if (EVPN_ENABLED(zvrf
)) {
9431 zrouter
.evpn_vrf
= zvrf
;
9433 /* Note BUM handling */
9434 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9436 /* Build VNI hash table and inform BGP. */
9437 zvni_build_hash_table();
9439 /* Add all SVI (L3 GW) MACs to BGP*/
9440 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9443 /* Read the MAC FDB */
9444 macfdb_read(zvrf
->zns
);
9446 /* Read neighbors */
9447 neigh_read(zvrf
->zns
);
9449 /* Cleanup VTEPs for all VNIs - uninstall from
9450 * kernel and free entries.
9452 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9454 /* cleanup all l3vnis */
9455 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9457 /* Mark as "no EVPN VRF" */
9458 zrouter
.evpn_vrf
= NULL
;
9466 * Allocate VNI hash table for this VRF and do other initialization.
9467 * NOTE: Currently supported only for default VRF.
9469 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9473 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9474 "Zebra VRF VNI Table");
9475 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9476 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9479 /* Cleanup VNI info, but don't free the table. */
9480 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9484 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9485 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9488 /* Close all VNI handling */
9489 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9493 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9494 hash_free(zvrf
->vni_table
);
9497 /* init the l3vni table */
9498 void zebra_vxlan_init(void)
9500 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9501 "Zebra VRF L3 VNI table");
9502 zrouter
.evpn_vrf
= NULL
;
9505 /* free l3vni table */
9506 void zebra_vxlan_disable(void)
9508 hash_free(zrouter
.l3vni_table
);
9511 /* get the l3vni svi ifindex */
9512 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9514 zebra_l3vni_t
*zl3vni
= NULL
;
9516 zl3vni
= zl3vni_from_vrf(vrf_id
);
9517 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9520 return zl3vni
->svi_if
->ifindex
;
9523 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9525 struct zebra_vrf
*zvrf
= NULL
;
9526 zebra_neigh_t
*nbr
= NULL
;
9527 zebra_vni_t
*zvni
= NULL
;
9528 char buf1
[INET6_ADDRSTRLEN
];
9529 char buf2
[ETHER_ADDR_STRLEN
];
9531 nbr
= THREAD_ARG(t
);
9533 /* since this is asynchronous we need sanity checks*/
9534 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9538 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9542 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9546 if (IS_ZEBRA_DEBUG_VXLAN
)
9547 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9548 __PRETTY_FUNCTION__
,
9549 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9550 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9552 nbr
->dad_count
, zvni
->vni
);
9554 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9556 nbr
->detect_start_time
.tv_sec
= 0;
9557 nbr
->detect_start_time
.tv_usec
= 0;
9558 nbr
->dad_dup_detect_time
= 0;
9559 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9560 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9563 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9564 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9565 nbr
->flags
, nbr
->loc_seq
);
9566 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9567 zvni_neigh_install(zvni
, nbr
);
9573 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9575 struct zebra_vrf
*zvrf
= NULL
;
9576 zebra_mac_t
*mac
= NULL
;
9577 zebra_vni_t
*zvni
= NULL
;
9578 struct listnode
*node
= NULL
;
9579 zebra_neigh_t
*nbr
= NULL
;
9580 char buf
[ETHER_ADDR_STRLEN
];
9582 mac
= THREAD_ARG(t
);
9584 /* since this is asynchronous we need sanity checks*/
9585 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9589 zvni
= zvni_lookup(mac
->zvni
->vni
);
9593 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9597 if (IS_ZEBRA_DEBUG_VXLAN
)
9598 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9599 __PRETTY_FUNCTION__
,
9600 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9603 listcount(mac
->neigh_list
));
9605 /* Remove all IPs as duplicate associcated with this MAC */
9606 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9607 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9608 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9609 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9610 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9611 zvni_neigh_install(zvni
, nbr
);
9614 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9616 nbr
->detect_start_time
.tv_sec
= 0;
9617 nbr
->dad_dup_detect_time
= 0;
9620 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9622 mac
->detect_start_time
.tv_sec
= 0;
9623 mac
->detect_start_time
.tv_usec
= 0;
9624 mac
->dad_dup_detect_time
= 0;
9625 mac
->dad_mac_auto_recovery_timer
= NULL
;
9627 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9629 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9630 mac
->flags
, mac
->loc_seq
))
9633 /* Process all neighbors associated with this MAC. */
9634 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9636 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9637 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9639 /* Install the entry. */
9640 zvni_mac_install(zvni
, mac
);
9646 /************************** vxlan SG cache management ************************/
9647 /* Inform PIM about the mcast group */
9648 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
9649 struct prefix_sg
*sg
,
9650 char *sg_str
, uint16_t cmd
)
9652 struct zserv
*client
= NULL
;
9653 struct stream
*s
= NULL
;
9655 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9659 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
9662 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9664 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9665 stream_putl(s
, IPV4_MAX_BYTELEN
);
9666 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9667 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9669 /* Write packet size. */
9670 stream_putw_at(s
, 0, stream_get_endp(s
));
9672 if (IS_ZEBRA_DEBUG_VXLAN
)
9675 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9676 zebra_route_string(client
->proto
));
9678 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9679 client
->vxlan_sg_add_cnt
++;
9681 client
->vxlan_sg_del_cnt
++;
9683 return zserv_send_message(client
, s
);
9686 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9688 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9690 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9691 vxlan_sg
->sg
.grp
.s_addr
, 0));
9694 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9696 const zebra_vxlan_sg_t
*sg1
= p1
;
9697 const zebra_vxlan_sg_t
*sg2
= p2
;
9699 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9700 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9703 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9704 struct prefix_sg
*sg
)
9706 zebra_vxlan_sg_t
*vxlan_sg
;
9708 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9710 vxlan_sg
->zvrf
= zvrf
;
9712 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9714 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9716 if (IS_ZEBRA_DEBUG_VXLAN
)
9717 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9722 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9723 struct prefix_sg
*sg
)
9725 zebra_vxlan_sg_t lookup
;
9728 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9731 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9732 struct prefix_sg
*sg
)
9734 zebra_vxlan_sg_t
*vxlan_sg
;
9735 zebra_vxlan_sg_t
*parent
= NULL
;
9738 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9742 /* create a *G entry for every BUM group implicitly -
9743 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9744 * 2. the XG entry is used by pimd to setup the
9745 * vxlan-termination-mroute
9747 if (sg
->src
.s_addr
) {
9748 memset(&sip
, 0, sizeof(sip
));
9749 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9754 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9757 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9761 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
9762 ZEBRA_VXLAN_SG_ADD
);
9767 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9770 struct zebra_vrf
*zvrf
;
9772 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9776 /* On SG entry deletion remove the reference to its parent XG
9779 if (vxlan_sg
->sg
.src
.s_addr
) {
9780 memset(&sip
, 0, sizeof(sip
));
9781 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9784 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
9785 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
9787 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9789 if (IS_ZEBRA_DEBUG_VXLAN
)
9790 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9792 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9795 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9796 struct in_addr sip
, struct in_addr mcast_grp
)
9798 zebra_vxlan_sg_t
*vxlan_sg
;
9799 struct prefix_sg sg
;
9801 sg
.family
= AF_INET
;
9802 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9805 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9809 if (vxlan_sg
->ref_cnt
)
9810 --vxlan_sg
->ref_cnt
;
9812 if (!vxlan_sg
->ref_cnt
)
9813 zebra_vxlan_sg_del(vxlan_sg
);
9816 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9817 struct in_addr sip
, struct in_addr mcast_grp
)
9819 zebra_vxlan_sg_t
*vxlan_sg
;
9820 struct prefix_sg sg
;
9822 sg
.family
= AF_INET
;
9823 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9826 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9828 ++vxlan_sg
->ref_cnt
;
9833 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9834 struct in_addr mcast_grp
)
9836 struct zebra_vrf
*zvrf
;
9838 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9841 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9845 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9848 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9849 struct in_addr mcast_grp
)
9851 struct zebra_vrf
*zvrf
;
9853 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9856 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9859 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9862 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9864 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9866 zebra_vxlan_sg_del(vxlan_sg
);
9869 static void zebra_vxlan_sg_replay_send(struct hash_backet
*backet
, void *arg
)
9871 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9873 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
9874 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9877 /* Handle message from client to replay vxlan SG entries */
9878 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
9880 if (IS_ZEBRA_DEBUG_VXLAN
)
9881 zlog_debug("VxLAN SG updates to PIM, start");
9883 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
9885 if (!EVPN_ENABLED(zvrf
)) {
9886 if (IS_ZEBRA_DEBUG_VXLAN
)
9887 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
9892 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
9895 /************************** EVPN BGP config management ************************/
9896 /* Notify Local MACs to the clienti, skips GW MAC */
9897 static void zvni_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
9900 struct mac_walk_ctx
*wctx
= arg
;
9901 zebra_mac_t
*zmac
= bucket
->data
;
9903 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
9906 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
9907 zvni_mac_send_add_to_client(wctx
->zvni
->vni
, &zmac
->macaddr
,
9908 zmac
->flags
, zmac
->loc_seq
);
9911 /* Iterator to Notify Local MACs of a L2VNI */
9912 static void zvni_send_mac_to_client(zebra_vni_t
*zvni
)
9914 struct mac_walk_ctx wctx
;
9916 if (!zvni
->mac_table
)
9919 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
9922 hash_iterate(zvni
->mac_table
, zvni_send_mac_hash_entry_to_client
,
9926 /* Notify Neighbor entries to the Client, skips the GW entry */
9927 static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
9930 struct mac_walk_ctx
*wctx
= arg
;
9931 zebra_neigh_t
*zn
= bucket
->data
;
9932 zebra_mac_t
*zmac
= NULL
;
9934 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
9937 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
9938 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
9939 zmac
= zvni_mac_lookup(wctx
->zvni
, &zn
->emac
);
9943 zvni_neigh_send_add_to_client(wctx
->zvni
->vni
, &zn
->ip
,
9944 &zn
->emac
, zn
->flags
,
9949 /* Iterator of a specific L2VNI */
9950 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
)
9952 struct neigh_walk_ctx wctx
;
9954 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
9957 hash_iterate(zvni
->neigh_table
, zvni_send_neigh_hash_entry_to_client
,
9961 static void zvni_evpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
9963 zebra_vni_t
*zvni
= NULL
;
9965 zvni
= (zebra_vni_t
*)bucket
->data
;
9966 zvni
->advertise_gw_macip
= 0;
9967 zvni
->advertise_svi_macip
= 0;
9968 zvni
->advertise_subnet
= 0;
9970 zvni_neigh_del_all(zvni
, 1, 0,
9971 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
9972 zvni_mac_del_all(zvni
, 1, 0,
9973 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
9974 zvni_vtep_del_all(zvni
, 1);
9977 /* Cleanup EVPN configuration of a specific VRF */
9978 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
9980 zebra_l3vni_t
*zl3vni
= NULL
;
9982 zvrf
->advertise_all_vni
= 0;
9983 zvrf
->advertise_gw_macip
= 0;
9984 zvrf
->advertise_svi_macip
= 0;
9985 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
9987 hash_iterate(zvrf
->vni_table
, zvni_evpn_cfg_cleanup
, NULL
);
9990 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9992 /* delete and uninstall all rmacs */
9993 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
9995 /* delete and uninstall all next-hops */
9996 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
10001 /* Cleanup BGP EVPN configuration upon client disconnect */
10002 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
10005 struct zebra_vrf
*zvrf
;
10007 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
10010 zebra_evpn_vrf_cfg_cleanup(zvrf
);
10016 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
10018 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
10020 if (CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
10021 if (IS_ZEBRA_DEBUG_VXLAN
)
10022 zlog_debug("VxLAN SG updates to PIM, stop");
10023 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
10029 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
10031 if (client
->proto
== ZEBRA_ROUTE_BGP
)
10032 return zebra_evpn_bgp_cfg_clean_up(client
);
10034 if (client
->proto
== ZEBRA_ROUTE_PIM
)
10035 return zebra_evpn_pim_cfg_clean_up(client
);
10041 * Handle results for vxlan dataplane operations.
10043 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
10045 /* TODO -- anything other than freeing the context? */
10046 dplane_ctx_fini(&ctx
);
10049 /* Cleanup BGP EVPN configuration upon client disconnect */
10050 extern void zebra_evpn_init(void)
10052 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);