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};
736 zvrf
= zebra_vrf_get_evpn();
740 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
741 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
742 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
744 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
745 vty
= (struct vty
*)ctxt
;
747 vty_out(vty
, "IP: %s\n",
748 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
749 vty_out(vty
, " Type: %s\n", type_str
);
750 vty_out(vty
, " State: %s\n", state_str
);
751 vty_out(vty
, " MAC: %s\n",
752 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
754 json_object_string_add(json
, "ip", buf2
);
755 json_object_string_add(json
, "type", type_str
);
756 json_object_string_add(json
, "state", state_str
);
757 json_object_string_add(json
, "mac", buf1
);
759 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
761 vty_out(vty
, " Remote VTEP: %s\n",
762 inet_ntoa(n
->r_vtep_ip
));
764 json_object_string_add(json
, "remoteVtep",
765 inet_ntoa(n
->r_vtep_ip
));
767 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
769 vty_out(vty
, " Flags: Default-gateway");
770 flags_present
= true;
772 json_object_boolean_true_add(json
, "defaultGateway");
774 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
777 flags_present
? " ,Router" : " Flags: Router");
778 flags_present
= true;
784 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
785 n
->loc_seq
, n
->rem_seq
);
787 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
788 vty_out(vty
, " Duplicate, detected at %s",
789 time_to_string(n
->dad_dup_detect_time
));
790 } else if (n
->dad_count
) {
791 monotime_since(&n
->detect_start_time
,
793 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
794 char *buf
= time_to_string(
795 n
->detect_start_time
.tv_sec
);
798 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
800 " Duplicate detection started at %s, detection count %u\n",
801 tmp_buf
, n
->dad_count
);
805 json_object_int_add(json
, "localSequence", n
->loc_seq
);
806 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
807 json_object_int_add(json
, "detectionCount",
809 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
810 json_object_boolean_true_add(json
, "isDuplicate");
812 json_object_boolean_false_add(json
, "isDuplicate");
819 * Print neighbor hash entry - called for display of all neighbors.
821 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
824 json_object
*json_vni
= NULL
, *json_row
= NULL
;
826 char buf1
[ETHER_ADDR_STRLEN
];
827 char buf2
[INET6_ADDRSTRLEN
];
828 struct neigh_walk_ctx
*wctx
= ctxt
;
829 const char *state_str
;
832 json_vni
= wctx
->json
;
833 n
= (zebra_neigh_t
*)bucket
->data
;
836 json_row
= json_object_new_object();
838 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
839 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
840 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
841 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
842 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
845 if (json_vni
== NULL
) {
846 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
847 -wctx
->addr_width
, buf2
, "local",
848 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
850 json_object_string_add(json_row
, "type", "local");
851 json_object_string_add(json_row
, "state", state_str
);
852 json_object_string_add(json_row
, "mac", buf1
);
853 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
854 json_object_boolean_true_add(
855 json_row
, "defaultGateway");
856 json_object_int_add(json_row
, "localSequence",
858 json_object_int_add(json_row
, "remoteSequence",
860 json_object_int_add(json_row
, "detectionCount",
862 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
863 json_object_boolean_true_add(json_row
,
866 json_object_boolean_false_add(json_row
,
870 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
871 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
872 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
875 if (json_vni
== NULL
) {
876 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
878 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
879 -wctx
->addr_width
, "Neighbor", "Type",
880 "State", "MAC", "Remote VTEP",
882 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
883 -wctx
->addr_width
, buf2
, "remote", state_str
,
884 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
886 json_object_string_add(json_row
, "type", "remote");
887 json_object_string_add(json_row
, "state", state_str
);
888 json_object_string_add(json_row
, "mac", buf1
);
889 json_object_string_add(json_row
, "remoteVtep",
890 inet_ntoa(n
->r_vtep_ip
));
891 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
892 json_object_boolean_true_add(json_row
,
894 json_object_int_add(json_row
, "localSequence",
896 json_object_int_add(json_row
, "remoteSequence",
898 json_object_int_add(json_row
, "detectionCount",
900 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
901 json_object_boolean_true_add(json_row
,
904 json_object_boolean_false_add(json_row
,
911 json_object_object_add(json_vni
, buf2
, json_row
);
915 * Print neighbor hash entry in detail - called for display of all neighbors.
917 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
920 json_object
*json_vni
= NULL
, *json_row
= NULL
;
922 char buf
[INET6_ADDRSTRLEN
];
923 struct neigh_walk_ctx
*wctx
= ctxt
;
926 json_vni
= wctx
->json
;
927 n
= (zebra_neigh_t
*)bucket
->data
;
931 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
933 json_row
= json_object_new_object();
935 zvni_print_neigh(n
, vty
, json_row
);
938 json_object_object_add(json_vni
, buf
, json_row
);
942 * Print neighbors for all VNI.
944 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
948 json_object
*json
= NULL
, *json_vni
= NULL
;
951 struct neigh_walk_ctx wctx
;
952 char vni_str
[VNI_STR_LEN
];
955 vty
= (struct vty
*)args
[0];
956 json
= (json_object
*)args
[1];
957 print_dup
= (uint32_t)(uintptr_t)args
[2];
959 zvni
= (zebra_vni_t
*)bucket
->data
;
961 num_neigh
= hashcount(zvni
->neigh_table
);
964 num_neigh
= num_dup_detected_neighs(zvni
);
968 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
969 zvni
->vni
, num_neigh
);
971 json_vni
= json_object_new_object();
972 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
973 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
978 json_object_object_add(json
, vni_str
, json_vni
);
982 /* Since we have IPv6 addresses to deal with which can vary widely in
983 * size, we try to be a bit more elegant in display by first computing
986 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
989 wctx
.addr_width
= 15;
990 wctx
.json
= json_vni
;
991 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
994 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
995 -wctx
.addr_width
, "IP", "Type",
996 "State", "MAC", "Remote VTEP", "Seq #'s");
999 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
1002 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1005 json_object_object_add(json
, vni_str
, json_vni
);
1008 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1012 nbr
= (zebra_neigh_t
*)bucket
->data
;
1016 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1017 zvni_print_neigh_hash(bucket
, ctxt
);
1020 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1025 nbr
= (zebra_neigh_t
*)bucket
->data
;
1029 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1030 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1034 * Print neighbors for all VNIs in detail.
1036 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1040 json_object
*json
= NULL
, *json_vni
= NULL
;
1043 struct neigh_walk_ctx wctx
;
1044 char vni_str
[VNI_STR_LEN
];
1047 vty
= (struct vty
*)args
[0];
1048 json
= (json_object
*)args
[1];
1049 print_dup
= (uint32_t)(uintptr_t)args
[2];
1051 zvni
= (zebra_vni_t
*)bucket
->data
;
1054 vty_out(vty
, "{}\n");
1057 num_neigh
= hashcount(zvni
->neigh_table
);
1059 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1064 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1065 zvni
->vni
, num_neigh
);
1067 json_vni
= json_object_new_object();
1068 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1069 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1073 json_object_object_add(json
, vni_str
, json_vni
);
1077 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1080 wctx
.addr_width
= 15;
1081 wctx
.json
= json_vni
;
1084 hash_iterate(zvni
->neigh_table
,
1085 zvni_print_dad_neigh_hash_detail
, &wctx
);
1087 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1091 json_object_object_add(json
, vni_str
, json_vni
);
1094 /* print a specific next hop for an l3vni */
1095 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1098 char buf1
[ETHER_ADDR_STRLEN
];
1099 char buf2
[INET6_ADDRSTRLEN
];
1100 json_object
*json_hosts
= NULL
;
1101 struct host_rb_entry
*hle
;
1104 vty_out(vty
, "Ip: %s\n",
1105 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1106 vty_out(vty
, " RMAC: %s\n",
1107 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1108 vty_out(vty
, " Refcount: %d\n",
1109 rb_host_count(&n
->host_rb
));
1110 vty_out(vty
, " Prefixes:\n");
1111 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1112 vty_out(vty
, " %s\n",
1113 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1115 json_hosts
= json_object_new_array();
1116 json_object_string_add(
1117 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1118 json_object_string_add(
1120 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1121 json_object_int_add(json
, "refCount",
1122 rb_host_count(&n
->host_rb
));
1123 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1124 json_object_array_add(json_hosts
,
1125 json_object_new_string(prefix2str(
1126 &hle
->p
, buf2
, sizeof(buf2
))));
1127 json_object_object_add(json
, "prefixList", json_hosts
);
1131 /* Print a specific RMAC entry */
1132 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1135 char buf1
[ETHER_ADDR_STRLEN
];
1136 char buf2
[PREFIX_STRLEN
];
1137 json_object
*json_hosts
= NULL
;
1138 struct host_rb_entry
*hle
;
1141 vty_out(vty
, "MAC: %s\n",
1142 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1143 vty_out(vty
, " Remote VTEP: %s\n",
1144 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1145 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1146 vty_out(vty
, " Prefixes:\n");
1147 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1148 vty_out(vty
, " %s\n",
1149 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1151 json_hosts
= json_object_new_array();
1152 json_object_string_add(
1154 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1155 json_object_string_add(json
, "vtepIp",
1156 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1157 json_object_int_add(json
, "refCount",
1158 rb_host_count(&zrmac
->host_rb
));
1159 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1160 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1161 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1162 json_object_array_add(
1164 json_object_new_string(prefix2str(
1165 &hle
->p
, buf2
, sizeof(buf2
))));
1166 json_object_object_add(json
, "prefixList", json_hosts
);
1171 * Print a specific MAC entry.
1173 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1176 zebra_neigh_t
*n
= NULL
;
1177 struct listnode
*node
= NULL
;
1178 char buf1
[ETHER_ADDR_STRLEN
];
1179 char buf2
[INET6_ADDRSTRLEN
];
1180 struct zebra_vrf
*zvrf
;
1181 struct timeval detect_start_time
= {0, 0};
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
));
1313 } else if (mac
->dad_count
) {
1314 monotime_since(&mac
->detect_start_time
,
1315 &detect_start_time
);
1316 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1317 char *buf
= time_to_string(
1318 mac
->detect_start_time
.tv_sec
);
1321 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1323 " Duplicate detection started at %s, detection count %u\n",
1324 tmp_buf
, mac
->dad_count
);
1328 /* print all the associated neigh */
1329 vty_out(vty
, " Neighbors:\n");
1330 if (!listcount(mac
->neigh_list
))
1331 vty_out(vty
, " No Neighbors\n");
1333 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1334 vty_out(vty
, " %s %s\n",
1335 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1336 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1347 * Print MAC hash entry - called for display of all MACs.
1349 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1352 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1354 char buf1
[ETHER_ADDR_STRLEN
];
1355 struct mac_walk_ctx
*wctx
= ctxt
;
1358 json_mac_hdr
= wctx
->json
;
1359 mac
= (zebra_mac_t
*)bucket
->data
;
1361 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1364 json_mac
= json_object_new_object();
1366 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1367 struct zebra_ns
*zns
;
1369 struct interface
*ifp
;
1372 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1375 zns
= zebra_ns_lookup(NS_DEFAULT
);
1376 ifindex
= mac
->fwd_info
.local
.ifindex
;
1377 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1378 if (!ifp
) // unexpected
1380 vid
= mac
->fwd_info
.local
.vid
;
1381 if (json_mac_hdr
== NULL
)
1382 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1385 json_object_string_add(json_mac
, "type", "local");
1386 json_object_string_add(json_mac
, "intf", ifp
->name
);
1389 if (json_mac_hdr
== NULL
)
1390 vty_out(vty
, " %-5u", vid
);
1392 json_object_int_add(json_mac
, "vlan", vid
);
1393 } else /* No vid? fill out the space */
1394 if (json_mac_hdr
== NULL
)
1395 vty_out(vty
, " %-5s", "");
1396 if (json_mac_hdr
== NULL
) {
1397 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1400 json_object_int_add(json_mac
, "localSequence",
1402 json_object_int_add(json_mac
, "remoteSequence",
1404 json_object_int_add(json_mac
, "detectionCount",
1406 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1407 json_object_boolean_true_add(json_mac
,
1410 json_object_boolean_false_add(json_mac
,
1412 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1417 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1419 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1420 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1424 if (json_mac_hdr
== NULL
) {
1425 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1426 (wctx
->count
== 0)) {
1427 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1428 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n",
1429 "MAC", "Type", "Intf/Remote VTEP",
1432 vty_out(vty
, "%-17s %-6s %-21s %-5s %u/%u\n", buf1
,
1433 "remote", inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1434 "", mac
->loc_seq
, mac
->rem_seq
);
1436 json_object_string_add(json_mac
, "type", "remote");
1437 json_object_string_add(json_mac
, "remoteVtep",
1438 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1439 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1440 json_object_int_add(json_mac
, "localSequence",
1442 json_object_int_add(json_mac
, "remoteSequence",
1444 json_object_int_add(json_mac
, "detectionCount",
1446 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1447 json_object_boolean_true_add(json_mac
,
1450 json_object_boolean_false_add(json_mac
,
1459 /* Print Duplicate MAC */
1460 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1464 mac
= (zebra_mac_t
*)bucket
->data
;
1468 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1469 zvni_print_mac_hash(bucket
, ctxt
);
1473 * Print MAC hash entry in detail - called for display of all MACs.
1475 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1478 json_object
*json_mac_hdr
= NULL
;
1480 struct mac_walk_ctx
*wctx
= ctxt
;
1481 char buf1
[ETHER_ADDR_STRLEN
];
1484 json_mac_hdr
= wctx
->json
;
1485 mac
= (zebra_mac_t
*)bucket
->data
;
1490 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1492 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1495 /* Print Duplicate MAC in detail */
1496 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1501 mac
= (zebra_mac_t
*)bucket
->data
;
1505 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1506 zvni_print_mac_hash_detail(bucket
, ctxt
);
1510 * Print MACs for all VNI.
1512 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1515 json_object
*json
= NULL
, *json_vni
= NULL
;
1516 json_object
*json_mac
= NULL
;
1519 struct mac_walk_ctx
*wctx
= ctxt
;
1520 char vni_str
[VNI_STR_LEN
];
1522 vty
= (struct vty
*)wctx
->vty
;
1523 json
= (struct json_object
*)wctx
->json
;
1525 zvni
= (zebra_vni_t
*)bucket
->data
;
1528 /*We are iterating over a new VNI, set the count to 0*/
1531 num_macs
= num_valid_macs(zvni
);
1535 if (wctx
->print_dup
)
1536 num_macs
= num_dup_detected_macs(zvni
);
1539 json_vni
= json_object_new_object();
1540 json_mac
= json_object_new_object();
1541 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1544 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1546 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1547 zvni
->vni
, num_macs
);
1548 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC",
1549 "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
1551 json_object_int_add(json_vni
, "numMacs", num_macs
);
1556 json_object_int_add(json_vni
, "numMacs", num_macs
);
1557 json_object_object_add(json
, vni_str
, json_vni
);
1562 /* assign per-vni to wctx->json object to fill macs
1563 * under the vni. Re-assign primary json object to fill
1564 * next vni information.
1566 wctx
->json
= json_mac
;
1567 if (wctx
->print_dup
)
1568 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1570 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1574 json_object_object_add(json_vni
, "macs", json_mac
);
1575 json_object_object_add(json
, vni_str
, json_vni
);
1580 * Print MACs in detail for all VNI.
1582 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1586 json_object
*json
= NULL
, *json_vni
= NULL
;
1587 json_object
*json_mac
= NULL
;
1590 struct mac_walk_ctx
*wctx
= ctxt
;
1591 char vni_str
[VNI_STR_LEN
];
1593 vty
= (struct vty
*)wctx
->vty
;
1594 json
= (struct json_object
*)wctx
->json
;
1596 zvni
= (zebra_vni_t
*)bucket
->data
;
1599 vty_out(vty
, "{}\n");
1604 /*We are iterating over a new VNI, set the count to 0*/
1607 num_macs
= num_valid_macs(zvni
);
1611 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1615 json_vni
= json_object_new_object();
1616 json_mac
= json_object_new_object();
1617 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1620 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1622 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1623 zvni
->vni
, num_macs
);
1625 json_object_int_add(json_vni
, "numMacs", num_macs
);
1627 /* assign per-vni to wctx->json object to fill macs
1628 * under the vni. Re-assign primary json object to fill
1629 * next vni information.
1631 wctx
->json
= json_mac
;
1632 if (wctx
->print_dup
)
1633 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1636 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1640 json_object_object_add(json_vni
, "macs", json_mac
);
1641 json_object_object_add(json
, vni_str
, json_vni
);
1645 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1647 struct nh_walk_ctx
*wctx
= NULL
;
1648 struct vty
*vty
= NULL
;
1649 struct json_object
*json_vni
= NULL
;
1650 struct json_object
*json_nh
= NULL
;
1651 zebra_neigh_t
*n
= NULL
;
1652 char buf1
[ETHER_ADDR_STRLEN
];
1653 char buf2
[INET6_ADDRSTRLEN
];
1655 wctx
= (struct nh_walk_ctx
*)ctx
;
1657 json_vni
= wctx
->json
;
1659 json_nh
= json_object_new_object();
1660 n
= (zebra_neigh_t
*)bucket
->data
;
1663 vty_out(vty
, "%-15s %-17s\n",
1664 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1665 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1667 json_object_string_add(json_nh
, "nexthopIp",
1668 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1669 json_object_string_add(
1670 json_nh
, "routerMac",
1671 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1672 json_object_object_add(json_vni
,
1673 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1678 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1681 struct vty
*vty
= NULL
;
1682 json_object
*json
= NULL
;
1683 json_object
*json_vni
= NULL
;
1684 zebra_l3vni_t
*zl3vni
= NULL
;
1685 uint32_t num_nh
= 0;
1686 struct nh_walk_ctx wctx
;
1687 char vni_str
[VNI_STR_LEN
];
1689 vty
= (struct vty
*)args
[0];
1690 json
= (struct json_object
*)args
[1];
1692 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1694 num_nh
= hashcount(zl3vni
->nh_table
);
1699 json_vni
= json_object_new_object();
1700 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1704 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1705 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1707 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1709 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1711 wctx
.json
= json_vni
;
1712 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1714 json_object_object_add(json
, vni_str
, json_vni
);
1717 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1720 struct vty
*vty
= NULL
;
1721 json_object
*json
= NULL
;
1722 json_object
*json_vni
= NULL
;
1723 zebra_l3vni_t
*zl3vni
= NULL
;
1725 struct rmac_walk_ctx wctx
;
1726 char vni_str
[VNI_STR_LEN
];
1728 vty
= (struct vty
*)args
[0];
1729 json
= (struct json_object
*)args
[1];
1731 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1733 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1738 json_vni
= json_object_new_object();
1739 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1743 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1744 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1746 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1748 /* assign per-vni to wctx->json object to fill macs
1749 * under the vni. Re-assign primary json object to fill
1750 * next vni information.
1752 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1754 wctx
.json
= json_vni
;
1755 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1757 json_object_object_add(json
, vni_str
, json_vni
);
1760 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1762 zebra_mac_t
*zrmac
= NULL
;
1763 struct rmac_walk_ctx
*wctx
= NULL
;
1764 struct vty
*vty
= NULL
;
1765 struct json_object
*json
= NULL
;
1766 struct json_object
*json_rmac
= NULL
;
1767 char buf
[ETHER_ADDR_STRLEN
];
1769 wctx
= (struct rmac_walk_ctx
*)ctx
;
1773 json_rmac
= json_object_new_object();
1774 zrmac
= (zebra_mac_t
*)bucket
->data
;
1777 vty_out(vty
, "%-17s %-21s\n",
1778 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1779 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1781 json_object_string_add(
1782 json_rmac
, "routerMac",
1783 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1784 json_object_string_add(json_rmac
, "vtepIp",
1785 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1786 json_object_object_add(
1787 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1792 /* print a specific L3 VNI entry */
1793 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1795 char buf
[ETHER_ADDR_STRLEN
];
1796 struct vty
*vty
= NULL
;
1797 json_object
*json
= NULL
;
1798 zebra_vni_t
*zvni
= NULL
;
1799 json_object
*json_vni_list
= NULL
;
1800 struct listnode
*node
= NULL
, *nnode
= NULL
;
1806 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1807 vty_out(vty
, " Type: %s\n", "L3");
1808 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1809 vty_out(vty
, " Local Vtep Ip: %s\n",
1810 inet_ntoa(zl3vni
->local_vtep_ip
));
1811 vty_out(vty
, " Vxlan-Intf: %s\n",
1812 zl3vni_vxlan_if_name(zl3vni
));
1813 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1814 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1815 vty_out(vty
, " VNI Filter: %s\n",
1816 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1817 ? "prefix-routes-only"
1819 vty_out(vty
, " Router MAC: %s\n",
1820 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1821 vty_out(vty
, " L2 VNIs: ");
1822 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1823 vty_out(vty
, "%u ", zvni
->vni
);
1826 json_vni_list
= json_object_new_array();
1827 json_object_int_add(json
, "vni", zl3vni
->vni
);
1828 json_object_string_add(json
, "type", "L3");
1829 json_object_string_add(json
, "localVtepIp",
1830 inet_ntoa(zl3vni
->local_vtep_ip
));
1831 json_object_string_add(json
, "vxlanIntf",
1832 zl3vni_vxlan_if_name(zl3vni
));
1833 json_object_string_add(json
, "sviIntf",
1834 zl3vni_svi_if_name(zl3vni
));
1835 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1836 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1837 json_object_string_add(
1839 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1840 json_object_string_add(
1842 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1843 ? "prefix-routes-only"
1845 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1846 json_object_array_add(json_vni_list
,
1847 json_object_new_int(zvni
->vni
));
1849 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1854 * Print a specific VNI entry.
1856 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1859 zebra_vtep_t
*zvtep
;
1862 json_object
*json
= NULL
;
1863 json_object
*json_vtep_list
= NULL
;
1864 json_object
*json_ip_str
= NULL
;
1870 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1871 vty_out(vty
, " Type: %s\n", "L2");
1872 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1874 json_object_int_add(json
, "vni", zvni
->vni
);
1875 json_object_string_add(json
, "type", "L2");
1876 json_object_string_add(json
, "vrf",
1877 vrf_id_to_name(zvni
->vrf_id
));
1880 if (!zvni
->vxlan_if
) { // unexpected
1882 vty_out(vty
, " VxLAN interface: unknown\n");
1885 num_macs
= num_valid_macs(zvni
);
1886 num_neigh
= hashcount(zvni
->neigh_table
);
1888 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1889 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1890 vty_out(vty
, " Local VTEP IP: %s\n",
1891 inet_ntoa(zvni
->local_vtep_ip
));
1892 vty_out(vty
, " Mcast group: %s\n",
1893 inet_ntoa(zvni
->mcast_grp
));
1895 json_object_string_add(json
, "vxlanInterface",
1896 zvni
->vxlan_if
->name
);
1897 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1898 json_object_string_add(json
, "vtepIp",
1899 inet_ntoa(zvni
->local_vtep_ip
));
1900 json_object_string_add(json
, "mcastGroup",
1901 inet_ntoa(zvni
->mcast_grp
));
1902 json_object_string_add(json
, "advertiseGatewayMacip",
1903 zvni
->advertise_gw_macip
? "Yes" : "No");
1904 json_object_int_add(json
, "numMacs", num_macs
);
1905 json_object_int_add(json
, "numArpNd", num_neigh
);
1909 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1912 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1914 json_vtep_list
= json_object_new_array();
1915 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1916 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1917 zvtep
->flood_control
,
1918 VXLAN_FLOOD_STR_DEFAULT
);
1921 vty_out(vty
, " %s flood: %s\n",
1922 inet_ntoa(zvtep
->vtep_ip
),
1925 json_ip_str
= json_object_new_string(
1926 inet_ntoa(zvtep
->vtep_ip
));
1927 json_object_array_add(json_vtep_list
,
1932 json_object_object_add(json
, "numRemoteVteps",
1937 " Number of MACs (local and remote) known for this VNI: %u\n",
1940 " Number of ARPs (IPv4 and IPv6, local and remote) "
1941 "known for this VNI: %u\n",
1943 vty_out(vty
, " Advertise-gw-macip: %s\n",
1944 zvni
->advertise_gw_macip
? "Yes" : "No");
1948 /* print a L3 VNI hash entry */
1949 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1951 struct vty
*vty
= NULL
;
1952 json_object
*json
= NULL
;
1953 json_object
*json_vni
= NULL
;
1954 zebra_l3vni_t
*zl3vni
= NULL
;
1956 vty
= (struct vty
*)ctx
[0];
1957 json
= (json_object
*)ctx
[1];
1959 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1962 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1963 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1964 hashcount(zl3vni
->rmac_table
),
1965 hashcount(zl3vni
->nh_table
), "n/a",
1966 zl3vni_vrf_name(zl3vni
));
1968 char vni_str
[VNI_STR_LEN
];
1970 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1971 json_vni
= json_object_new_object();
1972 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1973 json_object_string_add(json_vni
, "vxlanIf",
1974 zl3vni_vxlan_if_name(zl3vni
));
1975 json_object_int_add(json_vni
, "numMacs",
1976 hashcount(zl3vni
->rmac_table
));
1977 json_object_int_add(json_vni
, "numArpNd",
1978 hashcount(zl3vni
->nh_table
));
1979 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1980 json_object_string_add(json_vni
, "type", "L3");
1981 json_object_string_add(json_vni
, "tenantVrf",
1982 zl3vni_vrf_name(zl3vni
));
1983 json_object_object_add(json
, vni_str
, json_vni
);
1987 /* Private Structure to pass callback data for hash iterator */
1988 struct zvni_evpn_show
{
1991 struct zebra_vrf
*zvrf
;
1994 /* print a L3 VNI hash entry in detail*/
1995 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1997 struct vty
*vty
= NULL
;
1998 zebra_l3vni_t
*zl3vni
= NULL
;
1999 json_object
*json
= NULL
;
2000 bool use_json
= false;
2001 struct zvni_evpn_show
*zes
= data
;
2009 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2011 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2017 * Print a VNI hash entry - called for display of all VNIs.
2019 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2023 zebra_vtep_t
*zvtep
;
2024 uint32_t num_vteps
= 0;
2025 uint32_t num_macs
= 0;
2026 uint32_t num_neigh
= 0;
2027 json_object
*json
= NULL
;
2028 json_object
*json_vni
= NULL
;
2029 json_object
*json_ip_str
= NULL
;
2030 json_object
*json_vtep_list
= NULL
;
2035 zvni
= (zebra_vni_t
*)bucket
->data
;
2037 zvtep
= zvni
->vteps
;
2040 zvtep
= zvtep
->next
;
2043 num_macs
= num_valid_macs(zvni
);
2044 num_neigh
= hashcount(zvni
->neigh_table
);
2046 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2048 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2049 num_macs
, num_neigh
, num_vteps
,
2050 vrf_id_to_name(zvni
->vrf_id
));
2052 char vni_str
[VNI_STR_LEN
];
2053 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2054 json_vni
= json_object_new_object();
2055 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2056 json_object_string_add(json_vni
, "type", "L2");
2057 json_object_string_add(json_vni
, "vxlanIf",
2058 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2060 json_object_int_add(json_vni
, "numMacs", num_macs
);
2061 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2062 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2063 json_object_string_add(json_vni
, "tenantVrf",
2064 vrf_id_to_name(zvni
->vrf_id
));
2066 json_vtep_list
= json_object_new_array();
2067 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2068 json_ip_str
= json_object_new_string(
2069 inet_ntoa(zvtep
->vtep_ip
));
2070 json_object_array_add(json_vtep_list
,
2073 json_object_object_add(json_vni
, "remoteVteps",
2076 json_object_object_add(json
, vni_str
, json_vni
);
2081 * Print a VNI hash entry in detail - called for display of all VNIs.
2083 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2087 json_object
*json
= NULL
;
2088 bool use_json
= false;
2089 struct zvni_evpn_show
*zes
= data
;
2097 zvni
= (zebra_vni_t
*)bucket
->data
;
2099 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2104 * Inform BGP about local MACIP.
2106 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2107 struct ipaddr
*ip
, uint8_t flags
,
2108 uint32_t seq
, int state
, uint16_t cmd
)
2110 char buf
[ETHER_ADDR_STRLEN
];
2111 char buf2
[INET6_ADDRSTRLEN
];
2113 struct zserv
*client
= NULL
;
2114 struct stream
*s
= NULL
;
2116 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2117 /* BGP may not be running. */
2121 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2123 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2124 stream_putl(s
, vni
);
2125 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2128 if (IS_IPADDR_V4(ip
))
2129 ipa_len
= IPV4_MAX_BYTELEN
;
2130 else if (IS_IPADDR_V6(ip
))
2131 ipa_len
= IPV6_MAX_BYTELEN
;
2133 stream_putl(s
, ipa_len
); /* IP address length */
2135 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2137 stream_putl(s
, 0); /* Just MAC. */
2139 if (cmd
== ZEBRA_MACIP_ADD
) {
2140 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2141 stream_putl(s
, seq
); /* sequence number */
2143 stream_putl(s
, state
); /* state - active/inactive */
2147 /* Write packet size. */
2148 stream_putw_at(s
, 0, stream_get_endp(s
));
2150 if (IS_ZEBRA_DEBUG_VXLAN
)
2152 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2153 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2154 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2155 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2156 zebra_route_string(client
->proto
));
2158 if (cmd
== ZEBRA_MACIP_ADD
)
2159 client
->macipadd_cnt
++;
2161 client
->macipdel_cnt
++;
2163 return zserv_send_message(client
, s
);
2167 * Make hash key for neighbors.
2169 static unsigned int neigh_hash_keymake(const void *p
)
2171 const zebra_neigh_t
*n
= p
;
2172 const struct ipaddr
*ip
= &n
->ip
;
2174 if (IS_IPADDR_V4(ip
))
2175 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2177 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2178 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2182 * Compare two neighbor hash structures.
2184 static bool neigh_cmp(const void *p1
, const void *p2
)
2186 const zebra_neigh_t
*n1
= p1
;
2187 const zebra_neigh_t
*n2
= p2
;
2189 if (n1
== NULL
&& n2
== NULL
)
2192 if (n1
== NULL
|| n2
== NULL
)
2195 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2198 static int neigh_list_cmp(void *p1
, void *p2
)
2200 const zebra_neigh_t
*n1
= p1
;
2201 const zebra_neigh_t
*n2
= p2
;
2203 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2207 * Callback to allocate neighbor hash entry.
2209 static void *zvni_neigh_alloc(void *p
)
2211 const zebra_neigh_t
*tmp_n
= p
;
2214 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2221 * Add neighbor entry.
2223 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2224 struct ethaddr
*mac
)
2226 zebra_neigh_t tmp_n
;
2227 zebra_neigh_t
*n
= NULL
;
2228 zebra_mac_t
*zmac
= NULL
;
2230 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2231 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2232 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2235 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2236 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2238 n
->dad_ip_auto_recovery_timer
= NULL
;
2240 /* Associate the neigh to mac */
2241 zmac
= zvni_mac_lookup(zvni
, mac
);
2243 listnode_add_sort(zmac
->neigh_list
, n
);
2249 * Delete neighbor entry.
2251 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2253 zebra_neigh_t
*tmp_n
;
2254 zebra_mac_t
*zmac
= NULL
;
2256 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2258 listnode_delete(zmac
->neigh_list
, n
);
2260 /* Cancel auto recovery */
2261 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2263 /* Free the VNI hash entry and allocated memory. */
2264 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2265 XFREE(MTYPE_NEIGH
, tmp_n
);
2271 * Free neighbor hash entry (callback)
2273 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2275 struct neigh_walk_ctx
*wctx
= arg
;
2276 zebra_neigh_t
*n
= bucket
->data
;
2278 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2279 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2280 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2281 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2282 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2283 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2284 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2285 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2286 &n
->emac
, 0, n
->state
);
2288 if (wctx
->uninstall
)
2289 zvni_neigh_uninstall(wctx
->zvni
, n
);
2291 zvni_neigh_del(wctx
->zvni
, n
);
2298 * Delete all neighbor entries from specific VTEP for a particular VNI.
2300 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2301 struct in_addr
*r_vtep_ip
)
2303 struct neigh_walk_ctx wctx
;
2305 if (!zvni
->neigh_table
)
2308 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2310 wctx
.uninstall
= uninstall
;
2311 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2312 wctx
.r_vtep_ip
= *r_vtep_ip
;
2314 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2318 * Delete all neighbor entries for this VNI.
2320 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2323 struct neigh_walk_ctx wctx
;
2325 if (!zvni
->neigh_table
)
2328 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2330 wctx
.uninstall
= uninstall
;
2331 wctx
.upd_client
= upd_client
;
2334 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2338 * Look up neighbor hash entry.
2340 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2345 memset(&tmp
, 0, sizeof(tmp
));
2346 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2347 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2353 * Process all neighbors associated with a MAC upon the MAC being learnt
2354 * locally or undergoing any other change (such as sequence number).
2356 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2360 zebra_neigh_t
*n
= NULL
;
2361 struct listnode
*node
= NULL
;
2362 struct zebra_vrf
*zvrf
= NULL
;
2363 char buf
[ETHER_ADDR_STRLEN
];
2365 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2367 if (IS_ZEBRA_DEBUG_VXLAN
)
2368 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2369 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2370 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2372 /* Walk all neighbors and mark any inactive local neighbors as
2373 * active and/or update sequence number upon a move, and inform BGP.
2374 * The action for remote neighbors is TBD.
2375 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2376 * accidentally end up deleting a just-learnt local neighbor.
2378 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2379 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2380 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2381 ZEBRA_NEIGH_SET_ACTIVE(n
);
2382 n
->loc_seq
= zmac
->loc_seq
;
2383 if (!(zvrf
->dup_addr_detect
&&
2384 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2385 ZEBRA_NEIGH_DUPLICATE
)))
2386 zvni_neigh_send_add_to_client(
2387 zvni
->vni
, &n
->ip
, &n
->emac
,
2388 n
->flags
, n
->loc_seq
);
2395 * Process all neighbors associated with a local MAC upon the MAC being
2398 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2401 zebra_neigh_t
*n
= NULL
;
2402 struct listnode
*node
= NULL
;
2403 char buf
[ETHER_ADDR_STRLEN
];
2405 if (IS_ZEBRA_DEBUG_VXLAN
)
2406 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2407 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2410 /* Walk all local neighbors and mark as inactive and inform
2412 * TBD: There is currently no handling for remote neighbors. We
2413 * don't expect them to exist, if they do, do we install the MAC
2414 * as a remote MAC and the neighbor as remote?
2416 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2417 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2418 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2419 ZEBRA_NEIGH_SET_INACTIVE(n
);
2421 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2422 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2429 * Process all neighbors associated with a MAC upon the MAC being remotely
2432 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2435 zebra_neigh_t
*n
= NULL
;
2436 struct listnode
*node
= NULL
;
2437 char buf
[ETHER_ADDR_STRLEN
];
2439 if (IS_ZEBRA_DEBUG_VXLAN
)
2440 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2441 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2444 /* Walk all local neighbors and mark as inactive and inform
2447 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2448 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2449 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2450 ZEBRA_NEIGH_SET_INACTIVE(n
);
2452 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2453 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2460 * Process all neighbors associated with a remote MAC upon the MAC being
2463 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2466 /* NOTE: Currently a NO-OP. */
2469 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2471 zebra_neigh_t
*nbr
= NULL
;
2472 struct listnode
*node
= NULL
;
2474 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2475 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2476 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2477 zvni_neigh_probe(zvni
, nbr
);
2482 * Inform BGP about local neighbor addition.
2484 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2485 struct ethaddr
*macaddr
,
2486 uint8_t neigh_flags
,
2491 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2492 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2493 /* Set router flag (R-bit) based on local neigh entry add */
2494 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2495 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2497 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2498 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2502 * Inform BGP about local neighbor deletion.
2504 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2505 struct ethaddr
*macaddr
, uint8_t flags
,
2508 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2509 0, state
, ZEBRA_MACIP_DEL
);
2513 * Install remote neighbor into the kernel.
2515 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2517 struct zebra_if
*zif
;
2518 struct zebra_l2info_vxlan
*vxl
;
2519 struct interface
*vlan_if
;
2525 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2528 zif
= zvni
->vxlan_if
->info
;
2531 vxl
= &zif
->l2info
.vxl
;
2533 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2537 flags
= NTF_EXT_LEARNED
;
2538 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2539 flags
|= NTF_ROUTER
;
2540 ZEBRA_NEIGH_SET_ACTIVE(n
);
2541 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2547 * Uninstall remote neighbor from the kernel.
2549 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2551 struct zebra_if
*zif
;
2552 struct zebra_l2info_vxlan
*vxl
;
2553 struct interface
*vlan_if
;
2555 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2558 if (!zvni
->vxlan_if
) {
2559 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2564 zif
= zvni
->vxlan_if
->info
;
2567 vxl
= &zif
->l2info
.vxl
;
2568 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2572 ZEBRA_NEIGH_SET_INACTIVE(n
);
2574 return kernel_del_neigh(vlan_if
, &n
->ip
);
2578 * Probe neighbor from the kernel.
2580 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2582 struct zebra_if
*zif
;
2583 struct zebra_l2info_vxlan
*vxl
;
2584 struct interface
*vlan_if
;
2586 zif
= zvni
->vxlan_if
->info
;
2589 vxl
= &zif
->l2info
.vxl
;
2591 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2596 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2604 * Install neighbor hash entry - called upon access VLAN change.
2606 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2609 struct neigh_walk_ctx
*wctx
= ctxt
;
2611 n
= (zebra_neigh_t
*)bucket
->data
;
2613 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2614 zvni_neigh_install(wctx
->zvni
, n
);
2617 /* Get the VRR interface for SVI if any */
2618 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2620 struct zebra_vrf
*zvrf
= NULL
;
2621 struct interface
*tmp_if
= NULL
;
2622 struct zebra_if
*zif
= NULL
;
2624 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2627 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2632 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2635 if (zif
->link
== ifp
)
2642 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2644 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2645 struct connected
*c
= NULL
;
2646 struct ethaddr macaddr
;
2648 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2650 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2653 memset(&ip
, 0, sizeof(struct ipaddr
));
2654 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2657 if (c
->address
->family
== AF_INET
) {
2658 ip
.ipa_type
= IPADDR_V4
;
2659 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2660 sizeof(struct in_addr
));
2661 } else if (c
->address
->family
== AF_INET6
) {
2662 ip
.ipa_type
= IPADDR_V6
;
2663 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2664 sizeof(struct in6_addr
));
2669 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2675 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2677 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2678 struct connected
*c
= NULL
;
2679 struct ethaddr macaddr
;
2681 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2683 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2686 memset(&ip
, 0, sizeof(struct ipaddr
));
2687 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2690 if (c
->address
->family
== AF_INET
) {
2691 ip
.ipa_type
= IPADDR_V4
;
2692 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2693 sizeof(struct in_addr
));
2694 } else if (c
->address
->family
== AF_INET6
) {
2695 ip
.ipa_type
= IPADDR_V6
;
2696 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2697 sizeof(struct in6_addr
));
2702 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2708 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2711 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2712 struct connected
*c
= NULL
;
2713 struct ethaddr macaddr
;
2715 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2717 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2720 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2722 /* skip link local address */
2723 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2728 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2729 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2731 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2732 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2738 * zvni_gw_macip_add_to_client
2740 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2741 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2743 char buf
[ETHER_ADDR_STRLEN
];
2744 char buf2
[INET6_ADDRSTRLEN
];
2745 zebra_neigh_t
*n
= NULL
;
2746 zebra_mac_t
*mac
= NULL
;
2747 struct zebra_if
*zif
= NULL
;
2748 struct zebra_l2info_vxlan
*vxl
= NULL
;
2750 zif
= zvni
->vxlan_if
->info
;
2754 vxl
= &zif
->l2info
.vxl
;
2756 mac
= zvni_mac_lookup(zvni
, macaddr
);
2758 mac
= zvni_mac_add(zvni
, macaddr
);
2760 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2761 "Failed to add MAC %s intf %s(%u) VID %u",
2762 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2763 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2768 /* Set "local" forwarding info. */
2769 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2770 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2771 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2772 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2773 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2774 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2776 n
= zvni_neigh_lookup(zvni
, ip
);
2778 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2781 EC_ZEBRA_MAC_ADD_FAILED
,
2782 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2783 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2784 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2785 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2790 /* Set "local" forwarding info. */
2791 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2792 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2793 ZEBRA_NEIGH_SET_ACTIVE(n
);
2794 /* Set Router flag (R-bit) */
2795 if (ip
->ipa_type
== IPADDR_V6
)
2796 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2797 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2798 n
->ifindex
= ifp
->ifindex
;
2800 /* Only advertise in BGP if the knob is enabled */
2801 if (!advertise_gw_macip_enabled(zvni
))
2804 if (IS_ZEBRA_DEBUG_VXLAN
)
2806 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2807 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2808 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2809 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2811 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2812 n
->flags
, n
->loc_seq
);
2818 * zvni_gw_macip_del_from_client
2820 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2823 char buf1
[ETHER_ADDR_STRLEN
];
2824 char buf2
[INET6_ADDRSTRLEN
];
2825 zebra_neigh_t
*n
= NULL
;
2826 zebra_mac_t
*mac
= NULL
;
2828 /* If the neigh entry is not present nothing to do*/
2829 n
= zvni_neigh_lookup(zvni
, ip
);
2833 /* mac entry should be present */
2834 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2836 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2837 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2838 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2842 /* If the entry is not local nothing to do*/
2843 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2846 /* only need to delete the entry from bgp if we sent it before */
2847 if (IS_ZEBRA_DEBUG_VXLAN
)
2849 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2850 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2851 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2852 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2854 /* Remove neighbor from BGP. */
2855 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2856 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2858 /* Delete this neighbor entry. */
2859 zvni_neigh_del(zvni
, n
);
2861 /* see if the mac needs to be deleted as well*/
2863 zvni_deref_ip2mac(zvni
, mac
);
2868 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2871 zebra_vni_t
*zvni
= NULL
;
2872 struct zebra_if
*zif
= NULL
;
2873 struct zebra_l2info_vxlan zl2_info
;
2874 struct interface
*vlan_if
= NULL
;
2875 struct interface
*vrr_if
= NULL
;
2876 struct interface
*ifp
;
2878 /* Add primary SVI MAC*/
2879 zvni
= (zebra_vni_t
*)bucket
->data
;
2881 /* Global (Zvrf) advertise-default-gw is disabled,
2882 * but zvni advertise-default-gw is enabled
2884 if (zvni
->advertise_gw_macip
) {
2885 if (IS_ZEBRA_DEBUG_VXLAN
)
2886 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
2891 ifp
= zvni
->vxlan_if
;
2896 /* If down or not mapped to a bridge, we're done. */
2897 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2900 zl2_info
= zif
->l2info
.vxl
;
2903 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2907 /* Del primary MAC-IP */
2908 zvni_del_macip_for_intf(vlan_if
, zvni
);
2910 /* Del VRR MAC-IP - if any*/
2911 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2913 zvni_del_macip_for_intf(vrr_if
, zvni
);
2918 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2921 zebra_vni_t
*zvni
= NULL
;
2922 struct zebra_if
*zif
= NULL
;
2923 struct zebra_l2info_vxlan zl2_info
;
2924 struct interface
*vlan_if
= NULL
;
2925 struct interface
*vrr_if
= NULL
;
2926 struct interface
*ifp
= NULL
;
2928 zvni
= (zebra_vni_t
*)bucket
->data
;
2930 ifp
= zvni
->vxlan_if
;
2935 /* If down or not mapped to a bridge, we're done. */
2936 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2938 zl2_info
= zif
->l2info
.vxl
;
2941 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2945 /* Add primary SVI MAC-IP */
2946 zvni_add_macip_for_intf(vlan_if
, zvni
);
2948 if (advertise_gw_macip_enabled(zvni
)) {
2949 /* Add VRR MAC-IP - if any*/
2950 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2952 zvni_add_macip_for_intf(vrr_if
, zvni
);
2958 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2961 zebra_vni_t
*zvni
= NULL
;
2962 struct zebra_if
*zif
= NULL
;
2963 struct zebra_l2info_vxlan zl2_info
;
2964 struct interface
*vlan_if
= NULL
;
2965 struct interface
*ifp
;
2967 /* Add primary SVI MAC*/
2968 zvni
= (zebra_vni_t
*)bucket
->data
;
2972 /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
2975 if (zvni
->advertise_svi_macip
) {
2976 if (IS_ZEBRA_DEBUG_VXLAN
)
2977 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
2982 ifp
= zvni
->vxlan_if
;
2987 /* If down or not mapped to a bridge, we're done. */
2988 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2991 zl2_info
= zif
->l2info
.vxl
;
2993 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2994 zif
->brslave_info
.br_if
);
2998 /* Del primary MAC-IP */
2999 zvni_del_macip_for_intf(vlan_if
, zvni
);
3004 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
3005 struct interface
*ifp
,
3007 struct ethaddr
*macaddr
,
3010 char buf
[ETHER_ADDR_STRLEN
];
3011 char buf2
[INET6_ADDRSTRLEN
];
3012 struct zebra_vrf
*zvrf
;
3013 zebra_neigh_t
*n
= NULL
;
3014 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3015 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3016 bool upd_mac_seq
= false;
3017 bool neigh_mac_change
= false;
3018 bool neigh_on_hold
= false;
3019 bool neigh_was_remote
= false;
3020 bool do_dad
= false;
3021 struct in_addr vtep_ip
= {.s_addr
= 0};
3023 /* Check if the MAC exists. */
3024 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3026 /* create a dummy MAC if the MAC is not already present */
3027 if (IS_ZEBRA_DEBUG_VXLAN
)
3029 "AUTO MAC %s created for neigh %s on VNI %u",
3030 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3031 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3033 zmac
= zvni_mac_add(zvni
, macaddr
);
3035 zlog_debug("Failed to add MAC %s VNI %u",
3036 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3041 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3042 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3043 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3045 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3047 * We don't change the MAC to local upon a neighbor
3048 * learn event, we wait for the explicit local MAC
3049 * learn. However, we have to compute its sequence
3050 * number in preparation for when it actually turns
3057 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3059 if (IS_ZEBRA_DEBUG_VXLAN
)
3060 zlog_debug("\tUnable to find vrf for: %d",
3061 zvni
->vxlan_if
->vrf_id
);
3065 /* Check if the neighbor exists. */
3066 n
= zvni_neigh_lookup(zvni
, ip
);
3068 /* New neighbor - create */
3069 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3072 EC_ZEBRA_MAC_ADD_FAILED
,
3073 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3074 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3075 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3076 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3079 /* Set "local" forwarding info. */
3080 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3081 n
->ifindex
= ifp
->ifindex
;
3083 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3087 /* Note any changes and see if of interest to BGP. */
3088 mac_different
= (memcmp(n
->emac
.octet
,
3089 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3090 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3091 ZEBRA_NEIGH_ROUTER_FLAG
);
3092 if (!mac_different
&& is_router
== cur_is_router
) {
3093 if (IS_ZEBRA_DEBUG_VXLAN
)
3095 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3096 n
->ifindex
= ifp
->ifindex
;
3100 if (!mac_different
) {
3101 bool is_neigh_freezed
= false;
3103 /* Only the router flag has changed. */
3106 ZEBRA_NEIGH_ROUTER_FLAG
);
3108 UNSET_FLAG(n
->flags
,
3109 ZEBRA_NEIGH_ROUTER_FLAG
);
3111 /* Neigh is in freeze state and freeze action
3112 * is enabled, do not send update to client.
3114 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3116 CHECK_FLAG(n
->flags
,
3117 ZEBRA_NEIGH_DUPLICATE
));
3119 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3121 return zvni_neigh_send_add_to_client(
3122 zvni
->vni
, ip
, macaddr
,
3123 n
->flags
, n
->loc_seq
);
3125 if (IS_ZEBRA_DEBUG_VXLAN
)
3127 "\tNeighbor active and frozen");
3132 /* The MAC has changed, need to issue a delete
3133 * first as this means a different MACIP route.
3134 * Also, need to do some unlinking/relinking.
3135 * We also need to update the MAC's sequence number
3136 * in different situations.
3138 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3139 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3140 &n
->emac
, 0, n
->state
);
3141 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3143 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3145 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3146 neigh_mac_change
= upd_mac_seq
= true;
3147 listnode_delete(old_zmac
->neigh_list
, n
);
3148 zvni_deref_ip2mac(zvni
, old_zmac
);
3151 /* Update the forwarding info. */
3152 n
->ifindex
= ifp
->ifindex
;
3153 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3155 /* Link to new MAC */
3156 listnode_add_sort(zmac
->neigh_list
, n
);
3157 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3159 * Neighbor has moved from remote to local. Its
3160 * MAC could have also changed as part of the move.
3162 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3164 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3166 old_mac_seq
= CHECK_FLAG(
3171 neigh_mac_change
= upd_mac_seq
= true;
3172 listnode_delete(old_zmac
->neigh_list
,
3174 zvni_deref_ip2mac(zvni
, old_zmac
);
3177 /* Link to new MAC */
3178 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3179 listnode_add_sort(zmac
->neigh_list
, n
);
3181 /* Based on Mobility event Scenario-B from the
3182 * draft, neigh's previous state was remote treat this
3185 neigh_was_remote
= true;
3186 vtep_ip
= n
->r_vtep_ip
;
3187 /* Mark appropriately */
3188 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3189 n
->r_vtep_ip
.s_addr
= 0;
3190 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3191 n
->ifindex
= ifp
->ifindex
;
3195 /* If MAC was previously remote, or the neighbor had a different
3196 * MAC earlier, recompute the sequence number.
3199 uint32_t seq1
, seq2
;
3201 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3202 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3203 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3204 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3205 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3208 /* Mark Router flag (R-bit) */
3210 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3212 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3214 /* Check old and/or new MAC detected as duplicate mark
3215 * the neigh as duplicate
3217 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3218 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3219 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3221 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3222 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3225 /* For IP Duplicate Address Detection (DAD) is trigger,
3226 * when the event is extended mobility based on scenario-B
3227 * from the draft, IP/Neigh's MAC binding changed and
3228 * neigh's previous state was remote.
3230 if (neigh_mac_change
&& neigh_was_remote
)
3233 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3234 &neigh_on_hold
, true);
3236 /* Before we program this in BGP, we need to check if MAC is locally
3237 * learnt. If not, force neighbor to be inactive and reset its seq.
3239 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3240 ZEBRA_NEIGH_SET_INACTIVE(n
);
3242 zmac
->loc_seq
= mac_new_seq
;
3246 /* If the MAC's sequence number has changed, inform the MAC and all
3247 * neighbors associated with the MAC to BGP, else just inform this
3250 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3251 if (IS_ZEBRA_DEBUG_VXLAN
)
3252 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3253 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3254 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3255 zmac
->loc_seq
= mac_new_seq
;
3256 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3257 zmac
->flags
, zmac
->loc_seq
))
3259 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3263 n
->loc_seq
= zmac
->loc_seq
;
3265 if (!neigh_on_hold
) {
3266 ZEBRA_NEIGH_SET_ACTIVE(n
);
3268 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3269 n
->flags
, n
->loc_seq
);
3271 if (IS_ZEBRA_DEBUG_VXLAN
)
3272 zlog_debug("\tNeighbor on hold not sending");
3277 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3278 struct interface
*ifp
,
3280 struct ethaddr
*macaddr
,
3283 char buf
[ETHER_ADDR_STRLEN
];
3284 char buf2
[INET6_ADDRSTRLEN
];
3285 zebra_neigh_t
*n
= NULL
;
3286 zebra_mac_t
*zmac
= NULL
;
3288 /* If the neighbor is unknown, there is no further action. */
3289 n
= zvni_neigh_lookup(zvni
, ip
);
3293 /* If a remote entry, see if it needs to be refreshed */
3294 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3296 if (state
& NUD_STALE
)
3297 zvni_neigh_install(zvni
, n
);
3300 /* We got a "remote" neighbor notification for an entry
3301 * we think is local. This can happen in a multihoming
3302 * scenario - but only if the MAC is already "remote".
3303 * Just mark our entry as "remote".
3305 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3306 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3308 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3309 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3310 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3315 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3316 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3317 ZEBRA_NEIGH_SET_ACTIVE(n
);
3318 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3325 * Make hash key for MAC.
3327 static unsigned int mac_hash_keymake(const void *p
)
3329 const zebra_mac_t
*pmac
= p
;
3330 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3332 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3336 * Compare two MAC addresses.
3338 static bool mac_cmp(const void *p1
, const void *p2
)
3340 const zebra_mac_t
*pmac1
= p1
;
3341 const zebra_mac_t
*pmac2
= p2
;
3343 if (pmac1
== NULL
&& pmac2
== NULL
)
3346 if (pmac1
== NULL
|| pmac2
== NULL
)
3349 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3354 * Callback to allocate MAC hash entry.
3356 static void *zvni_mac_alloc(void *p
)
3358 const zebra_mac_t
*tmp_mac
= p
;
3361 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3364 return ((void *)mac
);
3370 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3372 zebra_mac_t tmp_mac
;
3373 zebra_mac_t
*mac
= NULL
;
3375 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3376 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3377 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3381 mac
->dad_mac_auto_recovery_timer
= NULL
;
3383 mac
->neigh_list
= list_new();
3384 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3392 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3394 zebra_mac_t
*tmp_mac
;
3396 /* Cancel auto recovery */
3397 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3399 list_delete(&mac
->neigh_list
);
3401 /* Free the VNI hash entry and allocated memory. */
3402 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3403 XFREE(MTYPE_MAC
, tmp_mac
);
3409 * Free MAC hash entry (callback)
3411 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3413 struct mac_walk_ctx
*wctx
= arg
;
3414 zebra_mac_t
*mac
= bucket
->data
;
3416 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3417 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3418 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3419 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3420 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3421 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3422 &wctx
->r_vtep_ip
))) {
3423 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3424 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3428 if (wctx
->uninstall
)
3429 zvni_mac_uninstall(wctx
->zvni
, mac
);
3431 zvni_mac_del(wctx
->zvni
, mac
);
3438 * Delete all MAC entries from specific VTEP for a particular VNI.
3440 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3441 struct in_addr
*r_vtep_ip
)
3443 struct mac_walk_ctx wctx
;
3445 if (!zvni
->mac_table
)
3448 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3450 wctx
.uninstall
= uninstall
;
3451 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3452 wctx
.r_vtep_ip
= *r_vtep_ip
;
3454 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3458 * Delete all MAC entries for this VNI.
3460 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3463 struct mac_walk_ctx wctx
;
3465 if (!zvni
->mac_table
)
3468 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3470 wctx
.uninstall
= uninstall
;
3471 wctx
.upd_client
= upd_client
;
3474 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3478 * Look up MAC hash entry.
3480 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3485 memset(&tmp
, 0, sizeof(tmp
));
3486 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3487 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3493 * Inform BGP about local MAC addition.
3495 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3496 uint8_t mac_flags
, uint32_t seq
)
3500 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3501 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3502 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3503 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3505 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3506 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3510 * Inform BGP about local MAC deletion.
3512 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3514 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3515 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3519 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3520 * notifications, to see if they are of interest.
3522 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3523 struct interface
*br_if
, vlanid_t vid
)
3525 struct zebra_ns
*zns
;
3526 struct route_node
*rn
;
3527 struct interface
*tmp_if
= NULL
;
3528 struct zebra_if
*zif
;
3529 struct zebra_l2info_bridge
*br
;
3530 struct zebra_l2info_vxlan
*vxl
= NULL
;
3531 uint8_t bridge_vlan_aware
;
3535 /* Determine if bridge is VLAN-aware or not */
3538 br
= &zif
->l2info
.br
;
3539 bridge_vlan_aware
= br
->vlan_aware
;
3541 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3542 /* TODO: Optimize with a hash. */
3543 zns
= zebra_ns_lookup(NS_DEFAULT
);
3544 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3545 tmp_if
= (struct interface
*)rn
->info
;
3549 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3551 if (!if_is_operative(tmp_if
))
3553 vxl
= &zif
->l2info
.vxl
;
3555 if (zif
->brslave_info
.br_if
!= br_if
)
3558 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3567 zvni
= zvni_lookup(vxl
->vni
);
3572 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3573 * neighbor notifications, to see if they are of interest.
3575 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3576 struct interface
*br_if
)
3578 struct zebra_ns
*zns
;
3579 struct route_node
*rn
;
3580 struct interface
*tmp_if
= NULL
;
3581 struct zebra_if
*zif
;
3582 struct zebra_l2info_bridge
*br
;
3583 struct zebra_l2info_vxlan
*vxl
= NULL
;
3584 uint8_t bridge_vlan_aware
;
3592 /* Make sure the linked interface is a bridge. */
3593 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3596 /* Determine if bridge is VLAN-aware or not */
3599 br
= &zif
->l2info
.br
;
3600 bridge_vlan_aware
= br
->vlan_aware
;
3601 if (bridge_vlan_aware
) {
3602 struct zebra_l2info_vlan
*vl
;
3604 if (!IS_ZEBRA_IF_VLAN(ifp
))
3609 vl
= &zif
->l2info
.vl
;
3613 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3614 /* TODO: Optimize with a hash. */
3615 zns
= zebra_ns_lookup(NS_DEFAULT
);
3616 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3617 tmp_if
= (struct interface
*)rn
->info
;
3621 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3623 if (!if_is_operative(tmp_if
))
3625 vxl
= &zif
->l2info
.vxl
;
3627 if (zif
->brslave_info
.br_if
!= br_if
)
3630 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3639 zvni
= zvni_lookup(vxl
->vni
);
3643 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3645 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3646 * linked to the bridge
3647 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3650 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3652 struct zebra_ns
*zns
;
3653 struct route_node
*rn
;
3654 struct interface
*tmp_if
= NULL
;
3655 struct zebra_if
*zif
;
3656 struct zebra_l2info_bridge
*br
;
3657 struct zebra_l2info_vlan
*vl
;
3658 uint8_t bridge_vlan_aware
;
3661 /* Defensive check, caller expected to invoke only with valid bridge. */
3665 /* Determine if bridge is VLAN-aware or not */
3668 br
= &zif
->l2info
.br
;
3669 bridge_vlan_aware
= br
->vlan_aware
;
3671 /* Check oper status of the SVI. */
3672 if (!bridge_vlan_aware
)
3673 return if_is_operative(br_if
) ? br_if
: NULL
;
3675 /* Identify corresponding VLAN interface. */
3676 /* TODO: Optimize with a hash. */
3677 zns
= zebra_ns_lookup(NS_DEFAULT
);
3678 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3679 tmp_if
= (struct interface
*)rn
->info
;
3680 /* Check oper status of the SVI. */
3681 if (!tmp_if
|| !if_is_operative(tmp_if
))
3684 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3685 || zif
->link
!= br_if
)
3687 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3689 if (vl
->vid
== vid
) {
3695 return found
? tmp_if
: NULL
;
3699 * Install remote MAC into the kernel.
3701 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3703 struct zebra_if
*zif
;
3704 struct zebra_l2info_vxlan
*vxl
;
3707 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3710 zif
= zvni
->vxlan_if
->info
;
3713 vxl
= &zif
->l2info
.vxl
;
3715 sticky
= !!CHECK_FLAG(mac
->flags
,
3716 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3718 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3719 mac
->fwd_info
.r_vtep_ip
, sticky
);
3723 * Uninstall remote MAC from the kernel.
3725 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3727 struct zebra_if
*zif
;
3728 struct zebra_l2info_vxlan
*vxl
;
3729 struct in_addr vtep_ip
;
3730 struct interface
*ifp
;
3732 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3735 if (!zvni
->vxlan_if
) {
3736 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3741 zif
= zvni
->vxlan_if
->info
;
3744 vxl
= &zif
->l2info
.vxl
;
3746 ifp
= zvni
->vxlan_if
;
3747 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3749 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3753 * Install MAC hash entry - called upon access VLAN change.
3755 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3758 struct mac_walk_ctx
*wctx
= ctxt
;
3760 mac
= (zebra_mac_t
*)bucket
->data
;
3762 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3763 zvni_mac_install(wctx
->zvni
, mac
);
3767 * Count of remote neighbors referencing this MAC.
3769 static int remote_neigh_count(zebra_mac_t
*zmac
)
3771 zebra_neigh_t
*n
= NULL
;
3772 struct listnode
*node
= NULL
;
3775 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3776 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3784 * Decrement neighbor refcount of MAC; uninstall and free it if
3787 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3789 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3792 /* If all remote neighbors referencing a remote MAC go away,
3793 * we need to uninstall the MAC.
3795 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3796 remote_neigh_count(mac
) == 0) {
3797 zvni_mac_uninstall(zvni
, mac
);
3798 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3801 /* If no neighbors, delete the MAC. */
3802 if (list_isempty(mac
->neigh_list
))
3803 zvni_mac_del(zvni
, mac
);
3807 * Read and populate local MACs and neighbors corresponding to this VNI.
3809 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3811 struct zebra_ns
*zns
;
3812 struct zebra_if
*zif
;
3813 struct interface
*vlan_if
;
3814 struct zebra_l2info_vxlan
*vxl
;
3815 struct interface
*vrr_if
;
3818 vxl
= &zif
->l2info
.vxl
;
3819 zns
= zebra_ns_lookup(NS_DEFAULT
);
3821 if (IS_ZEBRA_DEBUG_VXLAN
)
3823 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3824 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3825 zif
->brslave_info
.bridge_ifindex
);
3827 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3828 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3831 /* Add SVI MAC-IP */
3832 zvni_add_macip_for_intf(vlan_if
, zvni
);
3834 /* Add VRR MAC-IP - if any*/
3835 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3837 zvni_add_macip_for_intf(vrr_if
, zvni
);
3839 neigh_read_for_vlan(zns
, vlan_if
);
3844 * Hash function for VNI.
3846 static unsigned int vni_hash_keymake(const void *p
)
3848 const zebra_vni_t
*zvni
= p
;
3850 return (jhash_1word(zvni
->vni
, 0));
3854 * Compare 2 VNI hash entries.
3856 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3858 const zebra_vni_t
*zvni1
= p1
;
3859 const zebra_vni_t
*zvni2
= p2
;
3861 return (zvni1
->vni
== zvni2
->vni
);
3864 static int vni_list_cmp(void *p1
, void *p2
)
3866 const zebra_vni_t
*zvni1
= p1
;
3867 const zebra_vni_t
*zvni2
= p2
;
3869 if (zvni1
->vni
== zvni2
->vni
)
3871 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3875 * Callback to allocate VNI hash entry.
3877 static void *zvni_alloc(void *p
)
3879 const zebra_vni_t
*tmp_vni
= p
;
3882 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3883 zvni
->vni
= tmp_vni
->vni
;
3884 return ((void *)zvni
);
3888 * Look up VNI hash entry.
3890 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3892 struct zebra_vrf
*zvrf
;
3893 zebra_vni_t tmp_vni
;
3894 zebra_vni_t
*zvni
= NULL
;
3896 zvrf
= zebra_vrf_get_evpn();
3898 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3900 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3906 * Add VNI hash entry.
3908 static zebra_vni_t
*zvni_add(vni_t vni
)
3910 struct zebra_vrf
*zvrf
;
3911 zebra_vni_t tmp_zvni
;
3912 zebra_vni_t
*zvni
= NULL
;
3914 zvrf
= zebra_vrf_get_evpn();
3916 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3918 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3921 /* Create hash table for MAC */
3923 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3925 /* Create hash table for neighbors */
3926 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3927 "Zebra VNI Neighbor Table");
3933 * Delete VNI hash entry.
3935 static int zvni_del(zebra_vni_t
*zvni
)
3937 struct zebra_vrf
*zvrf
;
3938 zebra_vni_t
*tmp_zvni
;
3940 zvrf
= zebra_vrf_get_evpn();
3943 zvni
->vxlan_if
= NULL
;
3945 /* Remove references to the BUM mcast grp */
3946 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3948 /* Free the neighbor hash table. */
3949 hash_free(zvni
->neigh_table
);
3950 zvni
->neigh_table
= NULL
;
3952 /* Free the MAC hash table. */
3953 hash_free(zvni
->mac_table
);
3954 zvni
->mac_table
= NULL
;
3956 /* Free the VNI hash entry and allocated memory. */
3957 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3958 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3964 * Inform BGP about local VNI addition.
3966 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3968 struct zserv
*client
;
3971 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3972 /* BGP may not be running. */
3976 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3978 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3979 stream_putl(s
, zvni
->vni
);
3980 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3981 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3982 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3984 /* Write packet size. */
3985 stream_putw_at(s
, 0, stream_get_endp(s
));
3987 if (IS_ZEBRA_DEBUG_VXLAN
)
3988 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3989 inet_ntoa(zvni
->local_vtep_ip
),
3990 vrf_id_to_name(zvni
->vrf_id
),
3991 zebra_route_string(client
->proto
));
3993 client
->vniadd_cnt
++;
3994 return zserv_send_message(client
, s
);
3998 * Inform BGP about local VNI deletion.
4000 static int zvni_send_del_to_client(vni_t vni
)
4002 struct zserv
*client
;
4005 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4006 /* BGP may not be running. */
4010 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4013 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4014 stream_putl(s
, vni
);
4016 /* Write packet size. */
4017 stream_putw_at(s
, 0, stream_get_endp(s
));
4019 if (IS_ZEBRA_DEBUG_VXLAN
)
4020 zlog_debug("Send VNI_DEL %u to %s", vni
,
4021 zebra_route_string(client
->proto
));
4023 client
->vnidel_cnt
++;
4024 return zserv_send_message(client
, s
);
4028 * Build the VNI hash table by going over the VxLAN interfaces. This
4029 * is called when EVPN (advertise-all-vni) is enabled.
4031 static void zvni_build_hash_table(void)
4033 struct zebra_ns
*zns
;
4034 struct route_node
*rn
;
4035 struct interface
*ifp
;
4037 /* Walk VxLAN interfaces and create VNI hash. */
4038 zns
= zebra_ns_lookup(NS_DEFAULT
);
4039 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4041 zebra_vni_t
*zvni
= NULL
;
4042 zebra_l3vni_t
*zl3vni
= NULL
;
4043 struct zebra_if
*zif
;
4044 struct zebra_l2info_vxlan
*vxl
;
4046 ifp
= (struct interface
*)rn
->info
;
4050 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4053 vxl
= &zif
->l2info
.vxl
;
4056 /* L3-VNI and L2-VNI are handled seperately */
4057 zl3vni
= zl3vni_lookup(vni
);
4060 if (IS_ZEBRA_DEBUG_VXLAN
)
4062 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4063 ifp
->name
, ifp
->ifindex
, vni
);
4065 /* associate with vxlan_if */
4066 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4067 zl3vni
->vxlan_if
= ifp
;
4070 * we need to associate with SVI.
4071 * we can associate with svi-if only after association
4072 * with vxlan-intf is complete
4074 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4076 if (is_l3vni_oper_up(zl3vni
))
4077 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4080 struct interface
*vlan_if
= NULL
;
4082 if (IS_ZEBRA_DEBUG_VXLAN
)
4084 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4085 ifp
->name
, ifp
->ifindex
, vni
,
4086 inet_ntoa(vxl
->vtep_ip
));
4088 /* VNI hash entry is expected to exist, if the BGP process is killed */
4089 zvni
= zvni_lookup(vni
);
4092 "VNI hash already present for IF %s(%u) L2-VNI %u",
4093 ifp
->name
, ifp
->ifindex
, vni
);
4096 * Inform BGP if intf is up and mapped to
4099 if (if_is_operative(ifp
) &&
4100 zif
->brslave_info
.br_if
)
4101 zvni_send_add_to_client(zvni
);
4103 /* Send Local MAC-entries to client */
4104 zvni_send_mac_to_client(zvni
);
4106 /* Send Loval Neighbor entries to client */
4107 zvni_send_neigh_to_client(zvni
);
4109 zvni
= zvni_add(vni
);
4112 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4113 ifp
->name
, ifp
->ifindex
, vni
);
4117 if (zvni
->local_vtep_ip
.s_addr
!=
4118 vxl
->vtep_ip
.s_addr
||
4119 zvni
->mcast_grp
.s_addr
!=
4120 vxl
->mcast_grp
.s_addr
) {
4121 zebra_vxlan_sg_deref(
4122 zvni
->local_vtep_ip
,
4124 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4126 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4127 zvni
->mcast_grp
= vxl
->mcast_grp
;
4129 zvni
->vxlan_if
= ifp
;
4130 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4131 zif
->brslave_info
.br_if
);
4133 zvni
->vrf_id
= vlan_if
->vrf_id
;
4134 zl3vni
= zl3vni_from_vrf(
4138 zl3vni
->l2vnis
, zvni
);
4142 * Inform BGP if intf is up and mapped to
4145 if (if_is_operative(ifp
) &&
4146 zif
->brslave_info
.br_if
)
4147 zvni_send_add_to_client(zvni
);
4154 * See if remote VTEP matches with prefix.
4156 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4158 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4162 * Locate remote VTEP in VNI hash table.
4164 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4166 zebra_vtep_t
*zvtep
;
4171 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4172 if (zvni_vtep_match(vtep_ip
, zvtep
))
4180 * Add remote VTEP to VNI hash table.
4182 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4186 zebra_vtep_t
*zvtep
;
4188 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4190 zvtep
->vtep_ip
= *vtep_ip
;
4191 zvtep
->flood_control
= flood_control
;
4194 zvni
->vteps
->prev
= zvtep
;
4195 zvtep
->next
= zvni
->vteps
;
4196 zvni
->vteps
= zvtep
;
4202 * Remove remote VTEP from VNI hash table.
4204 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4207 zvtep
->next
->prev
= zvtep
->prev
;
4209 zvtep
->prev
->next
= zvtep
->next
;
4211 zvni
->vteps
= zvtep
->next
;
4213 zvtep
->prev
= zvtep
->next
= NULL
;
4214 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4220 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4221 * uninstall from kernel if asked to.
4223 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4225 zebra_vtep_t
*zvtep
, *zvtep_next
;
4230 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4231 zvtep_next
= zvtep
->next
;
4233 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4234 zvni_vtep_del(zvni
, zvtep
);
4241 * Install remote VTEP into the kernel if the remote VTEP has asked
4242 * for head-end-replication.
4244 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4246 if (is_vxlan_flooding_head_end() &&
4247 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4248 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4254 * Uninstall remote VTEP from the kernel.
4256 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4258 if (!zvni
->vxlan_if
) {
4259 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4264 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4268 * Install or uninstall flood entries in the kernel corresponding to
4269 * remote VTEPs. This is invoked upon change to BUM handling.
4271 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4275 zebra_vtep_t
*zvtep
;
4277 zvni
= (zebra_vni_t
*)bucket
->data
;
4281 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4282 if (is_vxlan_flooding_head_end())
4283 zvni_vtep_install(zvni
, zvtep
);
4285 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4290 * Cleanup VNI/VTEP and update kernel
4292 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4294 zebra_vni_t
*zvni
= NULL
;
4295 zebra_l3vni_t
*zl3vni
= NULL
;
4296 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4298 zvni
= (zebra_vni_t
*)bucket
->data
;
4300 /* remove from l3-vni list */
4302 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4304 listnode_delete(zl3vni
->l2vnis
, zvni
);
4306 /* Free up all neighbors and MACs, if any. */
4307 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4308 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4310 /* Free up all remote VTEPs, if any. */
4311 zvni_vtep_del_all(zvni
, 1);
4313 /* Delete the hash entry. */
4318 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4320 zebra_l3vni_t
*zl3vni
= NULL
;
4322 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4324 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4327 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4328 struct prefix
*host
)
4330 struct host_rb_entry lookup
;
4331 struct host_rb_entry
*hle
;
4333 memset(&lookup
, 0, sizeof(lookup
));
4334 memcpy(&lookup
.p
, host
, sizeof(*host
));
4336 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4340 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4341 memcpy(hle
, &lookup
, sizeof(lookup
));
4343 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4346 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4348 struct host_rb_entry lookup
;
4349 struct host_rb_entry
*hle
;
4351 memset(&lookup
, 0, sizeof(lookup
));
4352 memcpy(&lookup
.p
, host
, sizeof(*host
));
4354 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4356 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4357 XFREE(MTYPE_HOST_PREFIX
, hle
);
4364 * Look up MAC hash entry.
4366 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4367 struct ethaddr
*rmac
)
4372 memset(&tmp
, 0, sizeof(tmp
));
4373 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4374 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4380 * Callback to allocate RMAC hash entry.
4382 static void *zl3vni_rmac_alloc(void *p
)
4384 const zebra_mac_t
*tmp_rmac
= p
;
4387 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4390 return ((void *)zrmac
);
4394 * Add RMAC entry to l3-vni
4396 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4398 zebra_mac_t tmp_rmac
;
4399 zebra_mac_t
*zrmac
= NULL
;
4401 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4402 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4403 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4406 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4408 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4409 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4417 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4419 zebra_mac_t
*tmp_rmac
;
4420 struct host_rb_entry
*hle
;
4422 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4423 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4425 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4426 XFREE(MTYPE_HOST_PREFIX
, hle
);
4429 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4430 XFREE(MTYPE_MAC
, tmp_rmac
);
4436 * Install remote RMAC into the kernel.
4438 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4440 struct zebra_if
*zif
= NULL
;
4441 struct zebra_l2info_vxlan
*vxl
= NULL
;
4443 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4444 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4447 zif
= zl3vni
->vxlan_if
->info
;
4451 vxl
= &zif
->l2info
.vxl
;
4453 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4454 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4458 * Uninstall remote RMAC from the kernel.
4460 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4462 char buf
[ETHER_ADDR_STRLEN
];
4463 struct zebra_if
*zif
= NULL
;
4464 struct zebra_l2info_vxlan
*vxl
= NULL
;
4466 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4467 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4470 if (!zl3vni
->vxlan_if
) {
4472 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4473 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4474 zl3vni
->vni
, zl3vni
);
4478 zif
= zl3vni
->vxlan_if
->info
;
4482 vxl
= &zif
->l2info
.vxl
;
4484 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4485 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4488 /* handle rmac add */
4489 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4490 struct ipaddr
*vtep_ip
,
4491 struct prefix
*host_prefix
)
4493 char buf
[ETHER_ADDR_STRLEN
];
4494 char buf1
[INET6_ADDRSTRLEN
];
4495 zebra_mac_t
*zrmac
= NULL
;
4497 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4500 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4503 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4504 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4506 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4509 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4510 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4512 /* Send RMAC for FPM processing */
4513 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
4516 /* install rmac in kernel */
4517 zl3vni_rmac_install(zl3vni
, zrmac
);
4520 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4526 /* handle rmac delete */
4527 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4528 struct prefix
*host_prefix
)
4530 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4532 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4533 /* uninstall from kernel */
4534 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4536 /* Send RMAC for FPM processing */
4537 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
4540 /* del the rmac entry */
4541 zl3vni_rmac_del(zl3vni
, zrmac
);
4546 * Look up nh hash entry on a l3-vni.
4548 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4553 memset(&tmp
, 0, sizeof(tmp
));
4554 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4555 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4562 * Callback to allocate NH hash entry on L3-VNI.
4564 static void *zl3vni_nh_alloc(void *p
)
4566 const zebra_neigh_t
*tmp_n
= p
;
4569 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4576 * Add neighbor entry.
4578 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4579 struct ethaddr
*mac
)
4581 zebra_neigh_t tmp_n
;
4582 zebra_neigh_t
*n
= NULL
;
4584 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4585 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4586 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4589 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4591 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4592 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4593 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4599 * Delete neighbor entry.
4601 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4603 zebra_neigh_t
*tmp_n
;
4604 struct host_rb_entry
*hle
;
4606 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4607 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4609 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4610 XFREE(MTYPE_HOST_PREFIX
, hle
);
4613 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4614 XFREE(MTYPE_NEIGH
, tmp_n
);
4620 * Install remote nh as neigh into the kernel.
4622 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4629 if (!is_l3vni_oper_up(zl3vni
))
4632 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4633 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4636 flags
= NTF_EXT_LEARNED
;
4637 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4638 flags
|= NTF_ROUTER
;
4639 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4645 * Uninstall remote nh from the kernel.
4647 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4649 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4650 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4653 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4656 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4659 /* add remote vtep as a neigh entry */
4660 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4661 struct ethaddr
*rmac
,
4662 struct prefix
*host_prefix
)
4664 char buf
[ETHER_ADDR_STRLEN
];
4665 char buf1
[INET6_ADDRSTRLEN
];
4666 zebra_neigh_t
*nh
= NULL
;
4668 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4670 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4674 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4675 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4676 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4681 /* install the nh neigh in kernel */
4682 zl3vni_nh_install(zl3vni
, nh
);
4685 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4690 /* handle nh neigh delete */
4691 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4692 struct prefix
*host_prefix
)
4694 rb_delete_host(&nh
->host_rb
, host_prefix
);
4696 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4697 /* uninstall from kernel */
4698 zl3vni_nh_uninstall(zl3vni
, nh
);
4700 /* delete the nh entry */
4701 zl3vni_nh_del(zl3vni
, nh
);
4705 /* handle neigh update from kernel - the only thing of interest is to
4706 * readd stale entries.
4708 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4712 zebra_neigh_t
*n
= NULL
;
4714 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4718 /* all next hop neigh are remote and installed by frr.
4719 * If the kernel has aged this entry, re-install.
4721 if (state
& NUD_STALE
)
4722 zl3vni_nh_install(zl3vni
, n
);
4727 /* handle neigh delete from kernel */
4728 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4730 zebra_neigh_t
*n
= NULL
;
4732 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4736 /* all next hop neigh are remote and installed by frr.
4737 * If we get an age out notification for these neigh entries, we have to
4740 zl3vni_nh_install(zl3vni
, n
);
4746 * Hash function for L3 VNI.
4748 static unsigned int l3vni_hash_keymake(const void *p
)
4750 const zebra_l3vni_t
*zl3vni
= p
;
4752 return jhash_1word(zl3vni
->vni
, 0);
4756 * Compare 2 L3 VNI hash entries.
4758 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4760 const zebra_l3vni_t
*zl3vni1
= p1
;
4761 const zebra_l3vni_t
*zl3vni2
= p2
;
4763 return (zl3vni1
->vni
== zl3vni2
->vni
);
4767 * Callback to allocate L3 VNI hash entry.
4769 static void *zl3vni_alloc(void *p
)
4771 zebra_l3vni_t
*zl3vni
= NULL
;
4772 const zebra_l3vni_t
*tmp_l3vni
= p
;
4774 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4775 zl3vni
->vni
= tmp_l3vni
->vni
;
4776 return ((void *)zl3vni
);
4780 * Look up L3 VNI hash entry.
4782 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4784 zebra_l3vni_t tmp_l3vni
;
4785 zebra_l3vni_t
*zl3vni
= NULL
;
4787 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4788 tmp_l3vni
.vni
= vni
;
4789 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4795 * Add L3 VNI hash entry.
4797 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4799 zebra_l3vni_t tmp_zl3vni
;
4800 zebra_l3vni_t
*zl3vni
= NULL
;
4802 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4803 tmp_zl3vni
.vni
= vni
;
4805 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4808 zl3vni
->vrf_id
= vrf_id
;
4809 zl3vni
->svi_if
= NULL
;
4810 zl3vni
->vxlan_if
= NULL
;
4811 zl3vni
->l2vnis
= list_new();
4812 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4814 /* Create hash table for remote RMAC */
4815 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4816 "Zebra L3-VNI RMAC-Table");
4818 /* Create hash table for neighbors */
4819 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4820 "Zebra L3-VNI next-hop table");
4826 * Delete L3 VNI hash entry.
4828 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4830 zebra_l3vni_t
*tmp_zl3vni
;
4832 /* free the list of l2vnis */
4833 list_delete(&zl3vni
->l2vnis
);
4834 zl3vni
->l2vnis
= NULL
;
4836 /* Free the rmac table */
4837 hash_free(zl3vni
->rmac_table
);
4838 zl3vni
->rmac_table
= NULL
;
4840 /* Free the nh table */
4841 hash_free(zl3vni
->nh_table
);
4842 zl3vni
->nh_table
= NULL
;
4844 /* Free the VNI hash entry and allocated memory. */
4845 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4846 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4851 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4853 struct zebra_ns
*zns
= NULL
;
4854 struct route_node
*rn
= NULL
;
4855 struct interface
*ifp
= NULL
;
4857 /* loop through all vxlan-interface */
4858 zns
= zebra_ns_lookup(NS_DEFAULT
);
4859 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4861 struct zebra_if
*zif
= NULL
;
4862 struct zebra_l2info_vxlan
*vxl
= NULL
;
4864 ifp
= (struct interface
*)rn
->info
;
4869 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4872 vxl
= &zif
->l2info
.vxl
;
4873 if (vxl
->vni
== zl3vni
->vni
) {
4874 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4882 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4884 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4885 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4890 if (!zl3vni
->vxlan_if
)
4893 zif
= zl3vni
->vxlan_if
->info
;
4897 vxl
= &zif
->l2info
.vxl
;
4899 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4902 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4904 struct zebra_vrf
*zvrf
= NULL
;
4906 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4910 return zl3vni_lookup(zvrf
->l3vni
);
4914 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4915 * neighbor notifications, to see if they are of interest.
4917 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4918 struct interface
*br_if
)
4922 uint8_t bridge_vlan_aware
= 0;
4923 zebra_l3vni_t
*zl3vni
= NULL
;
4924 struct zebra_ns
*zns
= NULL
;
4925 struct route_node
*rn
= NULL
;
4926 struct zebra_if
*zif
= NULL
;
4927 struct interface
*tmp_if
= NULL
;
4928 struct zebra_l2info_bridge
*br
= NULL
;
4929 struct zebra_l2info_vxlan
*vxl
= NULL
;
4934 /* Make sure the linked interface is a bridge. */
4935 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4938 /* Determine if bridge is VLAN-aware or not */
4941 br
= &zif
->l2info
.br
;
4942 bridge_vlan_aware
= br
->vlan_aware
;
4943 if (bridge_vlan_aware
) {
4944 struct zebra_l2info_vlan
*vl
;
4946 if (!IS_ZEBRA_IF_VLAN(ifp
))
4951 vl
= &zif
->l2info
.vl
;
4955 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4956 /* TODO: Optimize with a hash. */
4957 zns
= zebra_ns_lookup(NS_DEFAULT
);
4958 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4959 tmp_if
= (struct interface
*)rn
->info
;
4963 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4965 if (!if_is_operative(tmp_if
))
4967 vxl
= &zif
->l2info
.vxl
;
4969 if (zif
->brslave_info
.br_if
!= br_if
)
4972 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4981 zl3vni
= zl3vni_lookup(vxl
->vni
);
4986 * Inform BGP about l3-vni.
4988 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4990 struct stream
*s
= NULL
;
4991 struct zserv
*client
= NULL
;
4992 struct ethaddr rmac
;
4993 char buf
[ETHER_ADDR_STRLEN
];
4995 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4996 /* BGP may not be running. */
5001 memset(&rmac
, 0, sizeof(struct ethaddr
));
5002 zl3vni_get_rmac(zl3vni
, &rmac
);
5004 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5006 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
5007 stream_putl(s
, zl3vni
->vni
);
5008 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
5009 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
5010 stream_put(s
, &zl3vni
->filter
, sizeof(int));
5011 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
5013 /* Write packet size. */
5014 stream_putw_at(s
, 0, stream_get_endp(s
));
5016 if (IS_ZEBRA_DEBUG_VXLAN
)
5018 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
5019 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5020 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
5021 inet_ntoa(zl3vni
->local_vtep_ip
),
5022 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5023 ? "prefix-routes-only"
5025 zebra_route_string(client
->proto
));
5027 client
->l3vniadd_cnt
++;
5028 return zserv_send_message(client
, s
);
5032 * Inform BGP about local l3-VNI deletion.
5034 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5036 struct stream
*s
= NULL
;
5037 struct zserv
*client
= NULL
;
5039 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5040 /* BGP may not be running. */
5044 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5046 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5047 stream_putl(s
, zl3vni
->vni
);
5049 /* Write packet size. */
5050 stream_putw_at(s
, 0, stream_get_endp(s
));
5052 if (IS_ZEBRA_DEBUG_VXLAN
)
5053 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5054 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5055 zebra_route_string(client
->proto
));
5057 client
->l3vnidel_cnt
++;
5058 return zserv_send_message(client
, s
);
5061 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5066 /* send l3vni add to BGP */
5067 zl3vni_send_add_to_client(zl3vni
);
5070 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5075 /* send l3-vni del to BGP*/
5076 zl3vni_send_del_to_client(zl3vni
);
5079 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5081 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5082 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5084 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5085 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5089 * handle transition of vni from l2 to l3 and vice versa
5091 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5094 zebra_vni_t
*zvni
= NULL
;
5096 /* There is a possibility that VNI notification was already received
5097 * from kernel and we programmed it as L2-VNI
5098 * In such a case we need to delete this L2-VNI first, so
5099 * that it can be reprogrammed as L3-VNI in the system. It is also
5100 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5101 * interface is still present in kernel. In this case to keep it
5102 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5105 /* Locate hash entry */
5106 zvni
= zvni_lookup(vni
);
5110 if (IS_ZEBRA_DEBUG_VXLAN
)
5111 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5113 /* Delete VNI from BGP. */
5114 zvni_send_del_to_client(zvni
->vni
);
5116 /* Free up all neighbors and MAC, if any. */
5117 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5118 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5120 /* Free up all remote VTEPs, if any. */
5121 zvni_vtep_del_all(zvni
, 0);
5123 /* Delete the hash entry. */
5124 if (zvni_del(zvni
)) {
5125 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5126 "Failed to del VNI hash %p, VNI %u", zvni
,
5131 /* TODO_MITESH: This needs to be thought through. We don't have
5132 * enough information at this point to reprogram the vni as
5133 * l2-vni. One way is to store the required info in l3-vni and
5134 * used it solely for this purpose
5141 /* delete and uninstall rmac hash entry */
5142 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5144 zebra_mac_t
*zrmac
= NULL
;
5145 zebra_l3vni_t
*zl3vni
= NULL
;
5147 zrmac
= (zebra_mac_t
*)bucket
->data
;
5148 zl3vni
= (zebra_l3vni_t
*)ctx
;
5149 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5151 /* Send RMAC for FPM processing */
5152 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5154 zl3vni_rmac_del(zl3vni
, zrmac
);
5157 /* delete and uninstall nh hash entry */
5158 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5160 zebra_neigh_t
*n
= NULL
;
5161 zebra_l3vni_t
*zl3vni
= NULL
;
5163 n
= (zebra_neigh_t
*)bucket
->data
;
5164 zl3vni
= (zebra_l3vni_t
*)ctx
;
5165 zl3vni_nh_uninstall(zl3vni
, n
);
5166 zl3vni_nh_del(zl3vni
, n
);
5169 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5172 struct zserv
*client
= NULL
;
5173 struct stream
*s
= NULL
;
5174 char buf
[PREFIX_STRLEN
];
5176 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5177 /* BGP may not be running. */
5181 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5183 zclient_create_header(s
, cmd
, vrf_id
);
5184 stream_put(s
, p
, sizeof(struct prefix
));
5186 /* Write packet size. */
5187 stream_putw_at(s
, 0, stream_get_endp(s
));
5189 if (IS_ZEBRA_DEBUG_VXLAN
)
5190 zlog_debug("Send ip prefix %s %s on vrf %s",
5191 prefix2str(p
, buf
, sizeof(buf
)),
5192 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5193 vrf_id_to_name(vrf_id
));
5195 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5196 client
->prefixadd_cnt
++;
5198 client
->prefixdel_cnt
++;
5200 return zserv_send_message(client
, s
);
5203 /* re-add remote rmac if needed */
5204 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5205 struct ethaddr
*rmac
)
5207 char buf
[ETHER_ADDR_STRLEN
];
5208 zebra_mac_t
*zrmac
= NULL
;
5210 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5214 if (IS_ZEBRA_DEBUG_VXLAN
)
5215 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5216 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5218 zl3vni_rmac_install(zl3vni
, zrmac
);
5222 /* Process a remote MACIP add from BGP. */
5223 static void process_remote_macip_add(vni_t vni
,
5224 struct ethaddr
*macaddr
,
5226 struct ipaddr
*ipaddr
,
5229 struct in_addr vtep_ip
)
5232 zebra_vtep_t
*zvtep
;
5233 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5234 zebra_neigh_t
*n
= NULL
;
5235 int update_mac
= 0, update_neigh
= 0;
5236 char buf
[ETHER_ADDR_STRLEN
];
5237 char buf1
[INET6_ADDRSTRLEN
];
5238 struct interface
*ifp
= NULL
;
5239 struct zebra_if
*zif
= NULL
;
5240 struct zebra_vrf
*zvrf
;
5245 bool do_dad
= false;
5246 bool is_dup_detect
= false;
5248 /* Locate VNI hash entry - expected to exist. */
5249 zvni
= zvni_lookup(vni
);
5251 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5255 ifp
= zvni
->vxlan_if
;
5259 !if_is_operative(ifp
) ||
5261 !zif
->brslave_info
.br_if
) {
5262 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5267 /* The remote VTEP specified should normally exist, but it is
5268 * possible that when peering comes up, peer may advertise MACIP
5269 * routes before advertising type-3 routes.
5271 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5273 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5276 EC_ZEBRA_VTEP_ADD_FAILED
,
5277 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5282 zvni_vtep_install(zvni
, zvtep
);
5285 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5286 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5287 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5289 mac
= zvni_mac_lookup(zvni
, macaddr
);
5291 /* Ignore if the mac is already present as a gateway mac */
5293 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5294 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5295 if (IS_ZEBRA_DEBUG_VXLAN
)
5296 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5298 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5299 ipa_len
? " IP " : "",
5301 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5305 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5309 /* check if the remote MAC is unknown or has a change.
5310 * If so, that needs to be updated first. Note that client could
5311 * install MAC and MACIP separately or just install the latter.
5314 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5315 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5316 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5317 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5318 || seq
!= mac
->rem_seq
)
5323 mac
= zvni_mac_add(zvni
, macaddr
);
5326 "Failed to add MAC %s VNI %u Remote VTEP %s",
5327 prefix_mac2str(macaddr
, buf
,
5329 vni
, inet_ntoa(vtep_ip
));
5333 /* Is this MAC created for a MACIP? */
5335 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5337 const char *mac_type
;
5339 /* When host moves but changes its (MAC,IP)
5340 * binding, BGP may install a MACIP entry that
5341 * corresponds to "older" location of the host
5342 * in transient situations (because {IP1,M1}
5343 * is a different route from {IP1,M2}). Check
5344 * the sequence number and ignore this update
5347 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5348 tmp_seq
= mac
->loc_seq
;
5351 tmp_seq
= mac
->rem_seq
;
5352 mac_type
= "remote";
5354 if (seq
< tmp_seq
) {
5355 if (IS_ZEBRA_DEBUG_VXLAN
)
5356 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5358 prefix_mac2str(macaddr
,
5360 ipa_len
? " IP " : "",
5363 buf1
, sizeof(buf1
)) : "",
5370 /* Check MAC's curent state is local (this is the case
5371 * where MAC has moved from L->R) and check previous
5372 * detection started via local learning.
5373 * RFC-7432: A PE/VTEP that detects a MAC mobility
5374 * event via local learning starts an M-second timer.
5376 * VTEP-IP or seq. change alone is not considered
5377 * for dup. detection.
5379 * MAC is already marked duplicate set dad, then
5380 * is_dup_detect will be set to not install the entry.
5382 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5384 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5387 /* Remove local MAC from BGP. */
5388 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5389 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5391 /* Set "auto" and "remote" forwarding info. */
5392 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5393 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5394 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5395 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5398 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5400 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5403 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5405 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5407 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5408 mac
->fwd_info
.r_vtep_ip
,
5409 do_dad
, &is_dup_detect
,
5412 if (!is_dup_detect
) {
5413 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5414 /* Install the entry. */
5415 zvni_mac_install(zvni
, mac
);
5419 /* Update seq number. */
5422 /* If there is no IP, return after clearing AUTO flag of MAC. */
5424 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5431 /* Check if the remote neighbor itself is unknown or has a
5432 * change. If so, create or update and then install the entry.
5434 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5436 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5437 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5438 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5439 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5440 || seq
!= n
->rem_seq
)
5445 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5448 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5449 ipaddr2str(ipaddr
, buf1
,
5451 prefix_mac2str(macaddr
, buf
,
5453 vni
, inet_ntoa(vtep_ip
));
5460 /* When host moves but changes its (MAC,IP)
5461 * binding, BGP may install a MACIP entry that
5462 * corresponds to "older" location of the host
5463 * in transient situations (because {IP1,M1}
5464 * is a different route from {IP1,M2}). Check
5465 * the sequence number and ignore this update
5468 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5469 tmp_seq
= n
->loc_seq
;
5472 tmp_seq
= n
->rem_seq
;
5475 if (seq
< tmp_seq
) {
5476 if (IS_ZEBRA_DEBUG_VXLAN
)
5477 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5479 prefix_mac2str(macaddr
,
5482 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5487 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5488 /* MAC change, send a delete for old
5489 * neigh if learnt locally.
5491 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5492 IS_ZEBRA_NEIGH_ACTIVE(n
))
5493 zvni_neigh_send_del_to_client(
5495 &n
->emac
, 0, n
->state
);
5497 /* update neigh list for macs */
5498 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5500 listnode_delete(old_mac
->neigh_list
, n
);
5501 zvni_deref_ip2mac(zvni
, old_mac
);
5503 listnode_add_sort(mac
->neigh_list
, n
);
5504 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5506 /* Check Neigh's curent state is local
5507 * (this is the case where neigh/host has moved
5508 * from L->R) and check previous detction
5509 * started via local learning.
5511 * RFC-7432: A PE/VTEP that detects a MAC
5512 * mobilit event via local learning starts
5513 * an M-second timer.
5514 * VTEP-IP or seq. change along is not
5515 * considered for dup. detection.
5517 * Mobilty event scenario-B IP-MAC binding
5520 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5527 /* Set "remote" forwarding info. */
5528 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5529 n
->r_vtep_ip
= vtep_ip
;
5530 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5532 /* Set router flag (R-bit) to this Neighbor entry */
5533 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5534 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5536 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5538 /* Check old or new MAC detected as duplicate,
5539 * inherit duplicate flag to this neigh.
5541 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5543 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5544 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5546 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5547 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5550 /* Check duplicate address detection for IP */
5551 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5556 /* Install the entry. */
5558 zvni_neigh_install(zvni
, n
);
5561 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5563 /* Update seq number. */
5567 /* Process a remote MACIP delete from BGP. */
5568 static void process_remote_macip_del(vni_t vni
,
5569 struct ethaddr
*macaddr
,
5571 struct ipaddr
*ipaddr
,
5572 struct in_addr vtep_ip
)
5575 zebra_mac_t
*mac
= NULL
;
5576 zebra_neigh_t
*n
= NULL
;
5577 struct interface
*ifp
= NULL
;
5578 struct zebra_if
*zif
= NULL
;
5579 struct zebra_ns
*zns
;
5580 struct zebra_l2info_vxlan
*vxl
;
5581 struct zebra_vrf
*zvrf
;
5582 char buf
[ETHER_ADDR_STRLEN
];
5583 char buf1
[INET6_ADDRSTRLEN
];
5585 /* Locate VNI hash entry - expected to exist. */
5586 zvni
= zvni_lookup(vni
);
5588 if (IS_ZEBRA_DEBUG_VXLAN
)
5589 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5593 ifp
= zvni
->vxlan_if
;
5597 !if_is_operative(ifp
) ||
5599 !zif
->brslave_info
.br_if
) {
5600 if (IS_ZEBRA_DEBUG_VXLAN
)
5601 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5605 zns
= zebra_ns_lookup(NS_DEFAULT
);
5606 vxl
= &zif
->l2info
.vxl
;
5608 /* The remote VTEP specified is normally expected to exist, but
5609 * it is possible that the peer may delete the VTEP before deleting
5610 * any MACs referring to the VTEP, in which case the handler (see
5611 * remote_vtep_del) would have already deleted the MACs.
5613 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5616 mac
= zvni_mac_lookup(zvni
, macaddr
);
5618 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5621 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5622 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5623 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5627 /* If the remote mac or neighbor doesn't exist there is nothing
5628 * more to do. Otherwise, uninstall the entry and then remove it.
5633 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5635 /* Ignore the delete if this mac is a gateway mac-ip */
5636 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5637 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5639 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5641 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5642 ipa_len
? " IP " : "",
5644 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5648 /* Uninstall remote neighbor or MAC. */
5650 if (zvrf
->dad_freeze
&&
5651 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5652 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5653 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5654 struct interface
*vlan_if
;
5656 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5657 zif
->brslave_info
.br_if
);
5658 if (IS_ZEBRA_DEBUG_VXLAN
)
5659 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5660 __PRETTY_FUNCTION__
,
5661 ipaddr2str(ipaddr
, buf1
,
5662 sizeof(buf1
)), n
->flags
,
5664 neigh_read_specific_ip(ipaddr
, vlan_if
);
5667 /* When the MAC changes for an IP, it is possible the
5668 * client may update the new MAC before trying to delete the
5669 * "old" neighbor (as these are two different MACIP routes).
5670 * Do the delete only if the MAC matches.
5672 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5673 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5674 zvni_neigh_uninstall(zvni
, n
);
5675 zvni_neigh_del(zvni
, n
);
5676 zvni_deref_ip2mac(zvni
, mac
);
5679 /* DAD: when MAC is freeze state as remote learn event,
5680 * remote mac-ip delete event is received will result in freeze
5681 * entry removal, first fetch kernel for the same entry present
5682 * as LOCAL and reachable, avoid deleting this entry instead
5683 * use kerenel local entry to update during unfreeze time.
5685 if (zvrf
->dad_freeze
&&
5686 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5687 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5688 if (IS_ZEBRA_DEBUG_VXLAN
)
5689 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5690 __PRETTY_FUNCTION__
,
5691 prefix_mac2str(macaddr
, buf
,
5694 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5695 macaddr
, vxl
->access_vlan
);
5698 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5699 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5701 * the remote sequence number in the auto mac entry
5702 * needs to be reset to 0 as the mac entry may have
5703 * been removed on all VTEPs (including
5704 * the originating one)
5708 /* If all remote neighbors referencing a remote MAC
5709 * go away, we need to uninstall the MAC.
5711 if (remote_neigh_count(mac
) == 0) {
5712 zvni_mac_uninstall(zvni
, mac
);
5713 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5715 if (list_isempty(mac
->neigh_list
))
5716 zvni_mac_del(zvni
, mac
);
5718 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5724 /* Public functions */
5726 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5728 zebra_l3vni_t
*zl3vni
= NULL
;
5730 zl3vni
= zl3vni_lookup(vni
);
5734 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5737 /* handle evpn route in vrf table */
5738 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5739 struct ipaddr
*vtep_ip
,
5740 struct prefix
*host_prefix
)
5742 zebra_l3vni_t
*zl3vni
= NULL
;
5743 struct ipaddr ipv4_vtep
;
5745 zl3vni
= zl3vni_from_vrf(vrf_id
);
5746 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5750 * add the next hop neighbor -
5751 * neigh to be installed is the ipv6 nexthop neigh
5753 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5756 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5757 * address. Rmac is programmed against the ipv4 vtep because we only
5758 * support ipv4 tunnels in the h/w right now
5760 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5761 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5762 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5763 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5764 &(ipv4_vtep
.ipaddr_v4
));
5766 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5767 sizeof(struct in_addr
));
5770 * add the rmac - remote rmac to be installed is against the ipv4
5773 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5776 /* handle evpn vrf route delete */
5777 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5778 struct ipaddr
*vtep_ip
,
5779 struct prefix
*host_prefix
)
5781 zebra_l3vni_t
*zl3vni
= NULL
;
5782 zebra_neigh_t
*nh
= NULL
;
5783 zebra_mac_t
*zrmac
= NULL
;
5785 zl3vni
= zl3vni_from_vrf(vrf_id
);
5789 /* find the next hop entry and rmac entry */
5790 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5793 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5795 /* delete the next hop entry */
5796 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5798 /* delete the rmac entry */
5800 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5804 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5805 struct ethaddr
*rmac
, bool use_json
)
5807 zebra_l3vni_t
*zl3vni
= NULL
;
5808 zebra_mac_t
*zrmac
= NULL
;
5809 json_object
*json
= NULL
;
5811 if (!is_evpn_enabled()) {
5813 vty_out(vty
, "{}\n");
5818 json
= json_object_new_object();
5820 zl3vni
= zl3vni_lookup(l3vni
);
5823 vty_out(vty
, "{}\n");
5825 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5829 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5832 vty_out(vty
, "{}\n");
5835 "%% Requested RMAC doesn't exist in L3-VNI %u",
5840 zl3vni_print_rmac(zrmac
, vty
, json
);
5843 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5844 json
, JSON_C_TO_STRING_PRETTY
));
5845 json_object_free(json
);
5849 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5851 zebra_l3vni_t
*zl3vni
;
5853 struct rmac_walk_ctx wctx
;
5854 json_object
*json
= NULL
;
5856 if (!is_evpn_enabled())
5859 zl3vni
= zl3vni_lookup(l3vni
);
5862 vty_out(vty
, "{}\n");
5864 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5867 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5872 json
= json_object_new_object();
5874 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5878 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5880 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5882 json_object_int_add(json
, "numRmacs", num_rmacs
);
5884 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5887 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5888 json
, JSON_C_TO_STRING_PRETTY
));
5889 json_object_free(json
);
5893 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5895 json_object
*json
= NULL
;
5898 if (!is_evpn_enabled()) {
5900 vty_out(vty
, "{}\n");
5905 json
= json_object_new_object();
5909 hash_iterate(zrouter
.l3vni_table
,
5910 (void (*)(struct hash_bucket
*,
5911 void *))zl3vni_print_rmac_hash_all_vni
,
5915 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5916 json
, JSON_C_TO_STRING_PRETTY
));
5917 json_object_free(json
);
5921 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5922 struct ipaddr
*ip
, bool use_json
)
5924 zebra_l3vni_t
*zl3vni
= NULL
;
5925 zebra_neigh_t
*n
= NULL
;
5926 json_object
*json
= NULL
;
5928 if (!is_evpn_enabled()) {
5930 vty_out(vty
, "{}\n");
5935 json
= json_object_new_object();
5937 zl3vni
= zl3vni_lookup(l3vni
);
5940 vty_out(vty
, "{}\n");
5942 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5946 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5949 vty_out(vty
, "{}\n");
5952 "%% Requested next-hop not present for L3-VNI %u",
5957 zl3vni_print_nh(n
, vty
, json
);
5960 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5961 json
, JSON_C_TO_STRING_PRETTY
));
5962 json_object_free(json
);
5966 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5969 struct nh_walk_ctx wctx
;
5970 json_object
*json
= NULL
;
5971 zebra_l3vni_t
*zl3vni
= NULL
;
5973 if (!is_evpn_enabled())
5976 zl3vni
= zl3vni_lookup(l3vni
);
5979 vty_out(vty
, "{}\n");
5981 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5985 num_nh
= hashcount(zl3vni
->nh_table
);
5990 json
= json_object_new_object();
5995 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5997 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5999 json_object_int_add(json
, "numNextHops", num_nh
);
6001 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
6004 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6005 json
, JSON_C_TO_STRING_PRETTY
));
6006 json_object_free(json
);
6010 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
6012 json_object
*json
= NULL
;
6015 if (!is_evpn_enabled()) {
6017 vty_out(vty
, "{}\n");
6022 json
= json_object_new_object();
6026 hash_iterate(zrouter
.l3vni_table
,
6027 (void (*)(struct hash_bucket
*,
6028 void *))zl3vni_print_nh_hash_all_vni
,
6032 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6033 json
, JSON_C_TO_STRING_PRETTY
));
6034 json_object_free(json
);
6039 * Display L3 VNI information (VTY command handler).
6041 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
6044 json_object
*json
= NULL
;
6045 zebra_l3vni_t
*zl3vni
= NULL
;
6047 if (!is_evpn_enabled()) {
6049 vty_out(vty
, "{}\n");
6053 zl3vni
= zl3vni_lookup(vni
);
6056 vty_out(vty
, "{}\n");
6058 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6063 json
= json_object_new_object();
6067 zl3vni_print(zl3vni
, (void *)args
);
6070 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6071 json
, JSON_C_TO_STRING_PRETTY
));
6072 json_object_free(json
);
6076 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6077 json_object
*json_vrfs
)
6079 char buf
[ETHER_ADDR_STRLEN
];
6080 zebra_l3vni_t
*zl3vni
= NULL
;
6082 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6087 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6088 zvrf_name(zvrf
), zl3vni
->vni
,
6089 zl3vni_vxlan_if_name(zl3vni
),
6090 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6091 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6093 json_object
*json_vrf
= NULL
;
6095 json_vrf
= json_object_new_object();
6096 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6097 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6098 json_object_string_add(json_vrf
, "vxlanIntf",
6099 zl3vni_vxlan_if_name(zl3vni
));
6100 json_object_string_add(json_vrf
, "sviIntf",
6101 zl3vni_svi_if_name(zl3vni
));
6102 json_object_string_add(json_vrf
, "state",
6103 zl3vni_state2str(zl3vni
));
6104 json_object_string_add(
6105 json_vrf
, "routerMac",
6106 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6107 json_object_array_add(json_vrfs
, json_vrf
);
6112 * Display Neighbors for a VNI (VTY command handler).
6114 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6115 vni_t vni
, bool use_json
)
6119 struct neigh_walk_ctx wctx
;
6120 json_object
*json
= NULL
;
6122 if (!is_evpn_enabled())
6124 zvni
= zvni_lookup(vni
);
6127 vty_out(vty
, "{}\n");
6129 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6132 num_neigh
= hashcount(zvni
->neigh_table
);
6137 json
= json_object_new_object();
6139 /* Since we have IPv6 addresses to deal with which can vary widely in
6140 * size, we try to be a bit more elegant in display by first computing
6141 * the maximum width.
6143 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6146 wctx
.addr_width
= 15;
6148 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6152 "Number of ARPs (local and remote) known for this VNI: %u\n",
6154 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx
.addr_width
,
6155 "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s");
6157 json_object_int_add(json
, "numArpNd", num_neigh
);
6159 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6161 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6162 json
, JSON_C_TO_STRING_PRETTY
));
6163 json_object_free(json
);
6168 * Display neighbors across all VNIs (VTY command handler).
6170 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6171 bool print_dup
, bool use_json
)
6173 json_object
*json
= NULL
;
6176 if (!is_evpn_enabled())
6180 json
= json_object_new_object();
6184 args
[2] = (void *)(ptrdiff_t)print_dup
;
6186 hash_iterate(zvrf
->vni_table
,
6187 (void (*)(struct hash_bucket
*,
6188 void *))zvni_print_neigh_hash_all_vni
,
6191 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6192 json
, JSON_C_TO_STRING_PRETTY
));
6193 json_object_free(json
);
6198 * Display neighbors across all VNIs in detail(VTY command handler).
6200 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6201 struct zebra_vrf
*zvrf
,
6202 bool print_dup
, bool use_json
)
6204 json_object
*json
= NULL
;
6207 if (!is_evpn_enabled())
6211 json
= json_object_new_object();
6215 args
[2] = (void *)(ptrdiff_t)print_dup
;
6217 hash_iterate(zvrf
->vni_table
,
6218 (void (*)(struct hash_bucket
*,
6219 void *))zvni_print_neigh_hash_all_vni_detail
,
6222 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6223 json
, JSON_C_TO_STRING_PRETTY
));
6224 json_object_free(json
);
6229 * Display specific neighbor for a VNI, if present (VTY command handler).
6231 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6232 struct zebra_vrf
*zvrf
, vni_t vni
,
6233 struct ipaddr
*ip
, bool use_json
)
6237 json_object
*json
= NULL
;
6239 if (!is_evpn_enabled())
6241 zvni
= zvni_lookup(vni
);
6244 vty_out(vty
, "{}\n");
6246 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6249 n
= zvni_neigh_lookup(zvni
, ip
);
6253 "%% Requested neighbor does not exist in VNI %u\n",
6258 json
= json_object_new_object();
6260 zvni_print_neigh(n
, vty
, json
);
6263 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6264 json
, JSON_C_TO_STRING_PRETTY
));
6265 json_object_free(json
);
6270 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6271 * By definition, these are remote neighbors.
6273 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6274 vni_t vni
, struct in_addr vtep_ip
,
6279 struct neigh_walk_ctx wctx
;
6280 json_object
*json
= NULL
;
6282 if (!is_evpn_enabled())
6284 zvni
= zvni_lookup(vni
);
6287 vty_out(vty
, "{}\n");
6289 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6292 num_neigh
= hashcount(zvni
->neigh_table
);
6296 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6299 wctx
.addr_width
= 15;
6300 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6301 wctx
.r_vtep_ip
= vtep_ip
;
6303 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6304 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6307 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6308 json
, JSON_C_TO_STRING_PRETTY
));
6309 json_object_free(json
);
6314 * Display Duplicate detected Neighbors for a VNI
6315 * (VTY command handler).
6317 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6318 struct zebra_vrf
*zvrf
,
6324 struct neigh_walk_ctx wctx
;
6325 json_object
*json
= NULL
;
6327 if (!is_evpn_enabled())
6330 zvni
= zvni_lookup(vni
);
6332 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6336 num_neigh
= hashcount(zvni
->neigh_table
);
6340 num_neigh
= num_dup_detected_neighs(zvni
);
6345 json
= json_object_new_object();
6347 /* Since we have IPv6 addresses to deal with which can vary widely in
6348 * size, we try to be a bit more elegant in display by first computing
6349 * the maximum width.
6351 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6354 wctx
.addr_width
= 15;
6356 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6360 "Number of ARPs (local and remote) known for this VNI: %u\n",
6362 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6363 -wctx
.addr_width
, "IP", "Type",
6364 "State", "MAC", "Remote VTEP");
6366 json_object_int_add(json
, "numArpNd", num_neigh
);
6368 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6371 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6372 json
, JSON_C_TO_STRING_PRETTY
));
6373 json_object_free(json
);
6378 * Display MACs for a VNI (VTY command handler).
6380 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6381 vni_t vni
, bool use_json
)
6385 struct mac_walk_ctx wctx
;
6386 json_object
*json
= NULL
;
6387 json_object
*json_mac
= NULL
;
6389 if (!is_evpn_enabled())
6391 zvni
= zvni_lookup(vni
);
6394 vty_out(vty
, "{}\n");
6396 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6399 num_macs
= num_valid_macs(zvni
);
6404 json
= json_object_new_object();
6405 json_mac
= json_object_new_object();
6408 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6411 wctx
.json
= json_mac
;
6415 "Number of MACs (local and remote) known for this VNI: %u\n",
6417 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type",
6418 "Intf/Remote VTEP", "VLAN", "Seq #'s");
6420 json_object_int_add(json
, "numMacs", num_macs
);
6422 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6425 json_object_object_add(json
, "macs", json_mac
);
6426 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6427 json
, JSON_C_TO_STRING_PRETTY
));
6428 json_object_free(json
);
6433 * Display MACs for all VNIs (VTY command handler).
6435 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6436 bool print_dup
, bool use_json
)
6438 struct mac_walk_ctx wctx
;
6439 json_object
*json
= NULL
;
6441 if (!is_evpn_enabled()) {
6443 vty_out(vty
, "{}\n");
6447 json
= json_object_new_object();
6449 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6452 wctx
.print_dup
= print_dup
;
6453 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6456 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6457 json
, JSON_C_TO_STRING_PRETTY
));
6458 json_object_free(json
);
6463 * Display MACs in detail for all VNIs (VTY command handler).
6465 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6466 struct zebra_vrf
*zvrf
,
6467 bool print_dup
, bool use_json
)
6469 struct mac_walk_ctx wctx
;
6470 json_object
*json
= NULL
;
6472 if (!is_evpn_enabled()) {
6474 vty_out(vty
, "{}\n");
6478 json
= json_object_new_object();
6480 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6483 wctx
.print_dup
= print_dup
;
6484 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6488 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6489 json
, JSON_C_TO_STRING_PRETTY
));
6490 json_object_free(json
);
6495 * Display MACs for all VNIs (VTY command handler).
6497 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6498 struct zebra_vrf
*zvrf
,
6499 struct in_addr vtep_ip
, bool use_json
)
6501 struct mac_walk_ctx wctx
;
6502 json_object
*json
= NULL
;
6504 if (!is_evpn_enabled())
6508 json
= json_object_new_object();
6510 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6512 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6513 wctx
.r_vtep_ip
= vtep_ip
;
6515 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6518 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6519 json
, JSON_C_TO_STRING_PRETTY
));
6520 json_object_free(json
);
6525 * Display specific MAC for a VNI, if present (VTY command handler).
6527 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6528 vni_t vni
, struct ethaddr
*macaddr
,
6533 json_object
*json
= NULL
;
6535 if (!is_evpn_enabled())
6538 zvni
= zvni_lookup(vni
);
6541 vty_out(vty
, "{}\n");
6543 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6546 mac
= zvni_mac_lookup(zvni
, macaddr
);
6549 vty_out(vty
, "{}\n");
6552 "%% Requested MAC does not exist in VNI %u\n",
6558 json
= json_object_new_object();
6560 zvni_print_mac(mac
, vty
, json
);
6562 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6563 json
, JSON_C_TO_STRING_PRETTY
));
6564 json_object_free(json
);
6568 /* Print Duplicate MACs per VNI */
6569 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6570 struct zebra_vrf
*zvrf
,
6571 vni_t vni
, bool use_json
)
6574 struct mac_walk_ctx wctx
;
6576 json_object
*json
= NULL
;
6577 json_object
*json_mac
= NULL
;
6579 if (!is_evpn_enabled())
6582 zvni
= zvni_lookup(vni
);
6584 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6588 num_macs
= num_valid_macs(zvni
);
6592 num_macs
= num_dup_detected_macs(zvni
);
6597 json
= json_object_new_object();
6598 json_mac
= json_object_new_object();
6601 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6604 wctx
.json
= json_mac
;
6608 "Number of MACs (local and remote) known for this VNI: %u\n",
6610 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6611 "Intf/Remote VTEP", "VLAN");
6613 json_object_int_add(json
, "numMacs", num_macs
);
6615 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6618 json_object_object_add(json
, "macs", json_mac
);
6619 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6620 json
, JSON_C_TO_STRING_PRETTY
));
6621 json_object_free(json
);
6626 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6627 struct zebra_vrf
*zvrf
,
6628 vni_t vni
, struct ethaddr
*macaddr
)
6632 struct listnode
*node
= NULL
;
6633 zebra_neigh_t
*nbr
= NULL
;
6635 if (!is_evpn_enabled())
6638 zvni
= zvni_lookup(vni
);
6640 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6644 mac
= zvni_mac_lookup(zvni
, macaddr
);
6646 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6651 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6652 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6656 /* Remove all IPs as duplicate associcated with this MAC */
6657 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6658 /* For local neigh mark inactive so MACIP update is generated
6659 * to BGP. This is a scenario where MAC update received
6660 * and detected as duplicate which marked neigh as duplicate.
6661 * Later local neigh update did not get a chance to relay
6662 * to BGP. Similarly remote macip update, neigh needs to be
6663 * installed locally.
6665 if (zvrf
->dad_freeze
&&
6666 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6667 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6668 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6669 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6670 zvni_neigh_install(zvni
, nbr
);
6673 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6675 nbr
->detect_start_time
.tv_sec
= 0;
6676 nbr
->dad_dup_detect_time
= 0;
6679 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6681 mac
->detect_start_time
.tv_sec
= 0;
6682 mac
->detect_start_time
.tv_usec
= 0;
6683 mac
->dad_dup_detect_time
= 0;
6684 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6686 /* warn-only action return */
6687 if (!zvrf
->dad_freeze
)
6690 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6691 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6693 if (zvni_mac_send_add_to_client(zvni
->vni
,
6699 /* Process all neighbors associated with this MAC. */
6700 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6702 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6703 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6705 /* Install the entry. */
6706 zvni_mac_install(zvni
, mac
);
6712 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6713 struct zebra_vrf
*zvrf
,
6714 vni_t vni
, struct ipaddr
*ip
)
6719 char buf
[INET6_ADDRSTRLEN
];
6720 char buf2
[ETHER_ADDR_STRLEN
];
6722 if (!is_evpn_enabled())
6725 zvni
= zvni_lookup(vni
);
6727 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6731 nbr
= zvni_neigh_lookup(zvni
, ip
);
6734 "%% Requested host IP does not exist in VNI %u\n",
6739 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6741 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6743 "%% Requsted host IP %s is not duplicate detected\n",
6748 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6750 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6752 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6753 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6754 return CMD_WARNING_CONFIG_FAILED
;
6757 if (IS_ZEBRA_DEBUG_VXLAN
)
6758 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6759 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6762 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6764 nbr
->detect_start_time
.tv_sec
= 0;
6765 nbr
->detect_start_time
.tv_usec
= 0;
6766 nbr
->dad_dup_detect_time
= 0;
6767 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6769 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6770 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6772 nbr
->flags
, nbr
->loc_seq
);
6773 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6774 zvni_neigh_install(zvni
, nbr
);
6780 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6782 struct mac_walk_ctx
*wctx
= ctxt
;
6785 struct listnode
*node
= NULL
;
6786 zebra_neigh_t
*nbr
= NULL
;
6788 mac
= (zebra_mac_t
*)bucket
->data
;
6794 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6797 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6799 mac
->detect_start_time
.tv_sec
= 0;
6800 mac
->detect_start_time
.tv_usec
= 0;
6801 mac
->dad_dup_detect_time
= 0;
6802 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6804 /* Remove all IPs as duplicate associcated with this MAC */
6805 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6806 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6808 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6810 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6812 nbr
->detect_start_time
.tv_sec
= 0;
6813 nbr
->dad_dup_detect_time
= 0;
6816 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6817 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6819 if (zvni_mac_send_add_to_client(zvni
->vni
,
6821 mac
->flags
, mac
->loc_seq
))
6824 /* Process all neighbors associated with this MAC. */
6825 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6827 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6828 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6830 /* Install the entry. */
6831 zvni_mac_install(zvni
, mac
);
6835 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6837 struct neigh_walk_ctx
*wctx
= ctxt
;
6840 char buf
[INET6_ADDRSTRLEN
];
6842 nbr
= (zebra_neigh_t
*)bucket
->data
;
6848 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6851 if (IS_ZEBRA_DEBUG_VXLAN
) {
6852 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6854 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6855 __PRETTY_FUNCTION__
, buf
,
6856 nbr
->flags
, nbr
->loc_seq
);
6859 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6861 nbr
->detect_start_time
.tv_sec
= 0;
6862 nbr
->detect_start_time
.tv_usec
= 0;
6863 nbr
->dad_dup_detect_time
= 0;
6864 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6866 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6867 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6869 nbr
->flags
, nbr
->loc_seq
);
6870 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6871 zvni_neigh_install(zvni
, nbr
);
6875 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6880 struct zebra_vrf
*zvrf
;
6881 struct mac_walk_ctx m_wctx
;
6882 struct neigh_walk_ctx n_wctx
;
6884 zvni
= (zebra_vni_t
*)bucket
->data
;
6888 vty
= (struct vty
*)args
[0];
6889 zvrf
= (struct zebra_vrf
*)args
[1];
6891 if (hashcount(zvni
->neigh_table
)) {
6892 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6896 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6900 if (num_valid_macs(zvni
)) {
6901 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6905 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6910 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6911 struct zebra_vrf
*zvrf
)
6915 if (!is_evpn_enabled())
6921 hash_iterate(zvrf
->vni_table
,
6922 (void (*)(struct hash_bucket
*, void *))
6923 zvni_clear_dup_detect_hash_vni_all
, args
);
6928 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6929 struct zebra_vrf
*zvrf
,
6933 struct mac_walk_ctx m_wctx
;
6934 struct neigh_walk_ctx n_wctx
;
6936 if (!is_evpn_enabled())
6939 zvni
= zvni_lookup(vni
);
6941 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6945 if (hashcount(zvni
->neigh_table
)) {
6946 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6950 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6954 if (num_valid_macs(zvni
)) {
6955 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6959 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6966 * Display MACs for a VNI from specific VTEP (VTY command handler).
6968 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6969 vni_t vni
, struct in_addr vtep_ip
,
6974 struct mac_walk_ctx wctx
;
6975 json_object
*json
= NULL
;
6976 json_object
*json_mac
= NULL
;
6978 if (!is_evpn_enabled())
6980 zvni
= zvni_lookup(vni
);
6983 vty_out(vty
, "{}\n");
6985 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6988 num_macs
= num_valid_macs(zvni
);
6993 json
= json_object_new_object();
6994 json_mac
= json_object_new_object();
6997 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
7000 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
7001 wctx
.r_vtep_ip
= vtep_ip
;
7002 wctx
.json
= json_mac
;
7003 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
7006 json_object_int_add(json
, "numMacs", wctx
.count
);
7008 json_object_object_add(json
, "macs", json_mac
);
7009 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7010 json
, JSON_C_TO_STRING_PRETTY
));
7011 json_object_free(json
);
7017 * Display VNI information (VTY command handler).
7019 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
7022 json_object
*json
= NULL
;
7024 zebra_l3vni_t
*zl3vni
= NULL
;
7025 zebra_vni_t
*zvni
= NULL
;
7027 if (!is_evpn_enabled())
7031 json
= json_object_new_object();
7035 zl3vni
= zl3vni_lookup(vni
);
7037 zl3vni_print(zl3vni
, (void *)args
);
7039 zvni
= zvni_lookup(vni
);
7042 vty_out(vty
, "{}\n");
7044 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7048 zvni_print(zvni
, (void *)args
);
7052 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7053 json
, JSON_C_TO_STRING_PRETTY
));
7054 json_object_free(json
);
7058 /* Display all global details for EVPN */
7059 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7064 json_object
*json
= NULL
;
7065 struct zebra_vrf
*zvrf
= NULL
;
7067 if (!is_evpn_enabled())
7070 zvrf
= zebra_vrf_get_evpn();
7074 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7075 num_l2vnis
= hashcount(zvrf
->vni_table
);
7076 num_vnis
= num_l2vnis
+ num_l3vnis
;
7079 json
= json_object_new_object();
7080 json_object_string_add(json
, "advertiseGatewayMacip",
7081 zvrf
->advertise_gw_macip
? "Yes" : "No");
7082 json_object_int_add(json
, "numVnis", num_vnis
);
7083 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7084 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7085 if (zvrf
->dup_addr_detect
)
7086 json_object_boolean_true_add(json
,
7087 "isDuplicateAddrDetection");
7089 json_object_boolean_false_add(json
,
7090 "isDuplicateAddrDetection");
7091 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7092 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7093 json_object_int_add(json
, "detectionFreezeTime",
7094 zvrf
->dad_freeze_time
);
7097 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7098 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7099 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7100 zvrf
->advertise_gw_macip
? "Yes" : "No");
7101 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7102 zvrf
->advertise_svi_macip
? "Yes" : "No");
7103 vty_out(vty
, "Duplicate address detection: %s\n",
7104 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7105 vty_out(vty
, " Detection max-moves %u, time %d\n",
7106 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7107 if (zvrf
->dad_freeze
) {
7108 if (zvrf
->dad_freeze_time
)
7109 vty_out(vty
, " Detection freeze %u\n",
7110 zvrf
->dad_freeze_time
);
7112 vty_out(vty
, " Detection freeze %s\n",
7118 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7119 json
, JSON_C_TO_STRING_PRETTY
));
7120 json_object_free(json
);
7125 * Display VNI hash table (VTY command handler).
7127 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7130 json_object
*json
= NULL
;
7133 if (!is_evpn_enabled())
7137 json
= json_object_new_object();
7139 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7140 "Type", "VxLAN IF", "# MACs", "# ARPs",
7141 "# Remote VTEPs", "Tenant VRF");
7146 /* Display all L2-VNIs */
7147 hash_iterate(zvrf
->vni_table
,
7148 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7151 /* Display all L3-VNIs */
7152 hash_iterate(zrouter
.l3vni_table
,
7153 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7157 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7158 json
, JSON_C_TO_STRING_PRETTY
));
7159 json_object_free(json
);
7163 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7167 uint32_t max_moves
= 0;
7168 uint32_t freeze_time
= 0;
7169 bool dup_addr_detect
= false;
7170 bool freeze
= false;
7173 STREAM_GETL(s
, dup_addr_detect
);
7174 STREAM_GETL(s
, time
);
7175 STREAM_GETL(s
, max_moves
);
7176 STREAM_GETL(s
, freeze
);
7177 STREAM_GETL(s
, freeze_time
);
7179 /* DAD previous state was enabled, and new state is disable,
7180 * clear all duplicate detected addresses.
7182 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7183 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7185 zvrf
->dup_addr_detect
= dup_addr_detect
;
7186 zvrf
->dad_time
= time
;
7187 zvrf
->dad_max_moves
= max_moves
;
7188 zvrf
->dad_freeze
= freeze
;
7189 zvrf
->dad_freeze_time
= freeze_time
;
7191 if (IS_ZEBRA_DEBUG_VXLAN
)
7193 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7194 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7195 zvrf
->dup_addr_detect
? "enable" : "disable",
7196 zvrf
->dad_max_moves
,
7198 zvrf
->dad_freeze
? "enable" : "disable",
7199 zvrf
->dad_freeze_time
);
7206 * Display VNI hash table in detail(VTY command handler).
7208 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7211 json_object
*json
= NULL
;
7212 struct zebra_ns
*zns
= NULL
;
7213 struct zvni_evpn_show zes
;
7215 if (!is_evpn_enabled())
7218 zns
= zebra_ns_lookup(NS_DEFAULT
);
7224 json
= json_object_new_object();
7230 /* Display all L2-VNIs */
7233 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7236 /* Display all L3-VNIs */
7237 hash_iterate(zrouter
.l3vni_table
,
7238 (void (*)(struct hash_bucket
*,
7239 void *))zl3vni_print_hash_detail
,
7243 vty_out(vty
, "%s\n",
7244 json_object_to_json_string_ext(
7245 json
, JSON_C_TO_STRING_PRETTY
));
7246 json_object_free(json
);
7251 * Handle neighbor delete notification from the kernel (on a VLAN device
7252 * / L3 interface). This may result in either the neighbor getting deleted
7253 * from our database or being re-added to the kernel (if it is a valid
7256 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7257 struct interface
*link_if
,
7260 char buf
[INET6_ADDRSTRLEN
];
7261 char buf2
[ETHER_ADDR_STRLEN
];
7262 zebra_neigh_t
*n
= NULL
;
7263 zebra_vni_t
*zvni
= NULL
;
7264 zebra_mac_t
*zmac
= NULL
;
7265 zebra_l3vni_t
*zl3vni
= NULL
;
7266 struct zebra_vrf
*zvrf
;
7268 /* check if this is a remote neigh entry corresponding to remote
7271 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7273 return zl3vni_local_nh_del(zl3vni
, ip
);
7275 /* We are only interested in neighbors on an SVI that resides on top
7276 * of a VxLAN bridge.
7278 zvni
= zvni_from_svi(ifp
, link_if
);
7282 if (!zvni
->vxlan_if
) {
7284 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7289 if (IS_ZEBRA_DEBUG_VXLAN
)
7290 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7291 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7292 ifp
->ifindex
, zvni
->vni
);
7294 /* If entry doesn't exist, nothing to do. */
7295 n
= zvni_neigh_lookup(zvni
, ip
);
7299 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7301 if (IS_ZEBRA_DEBUG_VXLAN
)
7303 "Trying to del a neigh %s without a mac %s on VNI %u",
7304 ipaddr2str(ip
, buf
, sizeof(buf
)),
7305 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7311 /* If it is a remote entry, the kernel has aged this out or someone has
7312 * deleted it, it needs to be re-installed as Quagga is the owner.
7314 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7315 zvni_neigh_install(zvni
, n
);
7319 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7321 zlog_debug("%s: VNI %u vrf lookup failed.",
7322 __PRETTY_FUNCTION__
, zvni
->vni
);
7326 /* In case of feeze action, if local neigh is in duplicate state,
7327 * Mark the Neigh as inactive before sending delete request to BGPd,
7328 * If BGPd has remote entry, it will re-install
7330 if (zvrf
->dad_freeze
&&
7331 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7332 ZEBRA_NEIGH_SET_INACTIVE(n
);
7334 /* Remove neighbor from BGP. */
7335 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7337 /* Delete this neighbor entry. */
7338 zvni_neigh_del(zvni
, n
);
7340 /* see if the AUTO mac needs to be deleted */
7341 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7342 && !listcount(zmac
->neigh_list
))
7343 zvni_mac_del(zvni
, zmac
);
7349 * Handle neighbor add or update notification from the kernel (on a VLAN
7350 * device / L3 interface). This is typically for a local neighbor but can
7351 * also be for a remote neighbor (e.g., ageout notification). It could
7352 * also be a "move" scenario.
7354 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7355 struct interface
*link_if
,
7357 struct ethaddr
*macaddr
,
7362 char buf
[ETHER_ADDR_STRLEN
];
7363 char buf2
[INET6_ADDRSTRLEN
];
7364 zebra_vni_t
*zvni
= NULL
;
7365 zebra_l3vni_t
*zl3vni
= NULL
;
7367 /* check if this is a remote neigh entry corresponding to remote
7370 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7372 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7374 /* We are only interested in neighbors on an SVI that resides on top
7375 * of a VxLAN bridge.
7377 zvni
= zvni_from_svi(ifp
, link_if
);
7381 if (IS_ZEBRA_DEBUG_VXLAN
)
7383 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7384 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7385 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7386 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7387 is_router
? "router " : "",
7390 /* Is this about a local neighbor or a remote one? */
7392 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7395 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7400 * Handle message from client to delete a remote MACIP for a VNI.
7402 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7406 struct ethaddr macaddr
;
7408 struct in_addr vtep_ip
;
7409 uint16_t l
= 0, ipa_len
;
7410 char buf
[ETHER_ADDR_STRLEN
];
7411 char buf1
[INET6_ADDRSTRLEN
];
7413 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7414 memset(&ip
, 0, sizeof(struct ipaddr
));
7415 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7419 while (l
< hdr
->length
) {
7420 /* Obtain each remote MACIP and process. */
7421 /* Message contains VNI, followed by MAC followed by IP (if any)
7422 * followed by remote VTEP IP.
7424 memset(&ip
, 0, sizeof(ip
));
7425 STREAM_GETL(s
, vni
);
7426 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7427 STREAM_GETL(s
, ipa_len
);
7429 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7431 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7433 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7434 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7435 l
+= IPV4_MAX_BYTELEN
;
7437 if (IS_ZEBRA_DEBUG_VXLAN
)
7439 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7441 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7442 ipa_len
? " IP " : "",
7444 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7446 zebra_route_string(client
->proto
));
7448 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7456 * Handle message from client to add a remote MACIP for a VNI. This
7457 * could be just the add of a MAC address or the add of a neighbor
7460 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7464 struct ethaddr macaddr
;
7466 struct in_addr vtep_ip
;
7467 uint16_t l
= 0, ipa_len
;
7470 char buf
[ETHER_ADDR_STRLEN
];
7471 char buf1
[INET6_ADDRSTRLEN
];
7473 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7474 memset(&ip
, 0, sizeof(struct ipaddr
));
7475 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7477 if (!EVPN_ENABLED(zvrf
)) {
7478 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7484 while (l
< hdr
->length
) {
7485 /* Obtain each remote MACIP and process. */
7486 /* Message contains VNI, followed by MAC followed by IP (if any)
7487 * followed by remote VTEP IP.
7489 memset(&ip
, 0, sizeof(ip
));
7490 STREAM_GETL(s
, vni
);
7491 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7492 STREAM_GETL(s
, ipa_len
);
7494 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7496 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7498 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7499 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7500 l
+= IPV4_MAX_BYTELEN
;
7502 /* Get flags - sticky mac and/or gateway mac */
7503 STREAM_GETC(s
, flags
);
7505 STREAM_GETL(s
, seq
);
7508 if (IS_ZEBRA_DEBUG_VXLAN
)
7510 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7512 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7513 ipa_len
? " IP " : "",
7515 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7516 flags
, seq
, inet_ntoa(vtep_ip
),
7517 zebra_route_string(client
->proto
));
7519 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7520 flags
, seq
, vtep_ip
);
7528 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7529 * us, this must involve a multihoming scenario. Treat this as implicit delete
7530 * of any prior local MAC.
7532 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7533 struct interface
*br_if
,
7534 struct ethaddr
*macaddr
, vlanid_t vid
)
7536 struct zebra_if
*zif
;
7537 struct zebra_l2info_vxlan
*vxl
;
7541 char buf
[ETHER_ADDR_STRLEN
];
7545 vxl
= &zif
->l2info
.vxl
;
7548 /* Check if EVPN is enabled. */
7549 if (!is_evpn_enabled())
7552 /* Locate hash entry; it is expected to exist. */
7553 zvni
= zvni_lookup(vni
);
7557 /* If entry doesn't exist, nothing to do. */
7558 mac
= zvni_mac_lookup(zvni
, macaddr
);
7562 /* Is it a local entry? */
7563 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7566 if (IS_ZEBRA_DEBUG_VXLAN
)
7568 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7569 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7570 ifp
->ifindex
, vni
, mac
->flags
);
7572 /* Remove MAC from BGP. */
7573 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7576 * If there are no neigh associated with the mac delete the mac
7577 * else mark it as AUTO for forward reference
7579 if (!listcount(mac
->neigh_list
)) {
7580 zvni_mac_del(zvni
, mac
);
7582 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7583 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7584 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7591 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7592 * This can happen because the remote MAC entries are also added as "dynamic",
7593 * so the kernel can ageout the entry.
7595 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7596 struct interface
*br_if
,
7597 struct ethaddr
*macaddr
, vlanid_t vid
)
7599 struct zebra_if
*zif
= NULL
;
7600 struct zebra_l2info_vxlan
*vxl
= NULL
;
7602 zebra_vni_t
*zvni
= NULL
;
7603 zebra_l3vni_t
*zl3vni
= NULL
;
7604 zebra_mac_t
*mac
= NULL
;
7605 char buf
[ETHER_ADDR_STRLEN
];
7609 vxl
= &zif
->l2info
.vxl
;
7612 /* Check if EVPN is enabled. */
7613 if (!is_evpn_enabled())
7616 /* check if this is a remote RMAC and readd simillar to remote macs */
7617 zl3vni
= zl3vni_lookup(vni
);
7619 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7621 /* Locate hash entry; it is expected to exist. */
7622 zvni
= zvni_lookup(vni
);
7626 /* If entry doesn't exist, nothing to do. */
7627 mac
= zvni_mac_lookup(zvni
, macaddr
);
7631 /* Is it a remote entry? */
7632 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7635 if (IS_ZEBRA_DEBUG_VXLAN
)
7636 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7637 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7640 zvni_mac_install(zvni
, mac
);
7645 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7647 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7648 struct ethaddr
*macaddr
, vlanid_t vid
)
7652 char buf
[ETHER_ADDR_STRLEN
];
7654 /* We are interested in MACs only on ports or (port, VLAN) that
7657 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7660 if (!zvni
->vxlan_if
) {
7662 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7667 /* If entry doesn't exist, nothing to do. */
7668 mac
= zvni_mac_lookup(zvni
, macaddr
);
7672 /* Is it a local entry? */
7673 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7676 if (IS_ZEBRA_DEBUG_VXLAN
)
7677 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7678 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7679 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7681 /* Update all the neigh entries associated with this mac */
7682 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7684 /* Remove MAC from BGP. */
7685 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7688 * If there are no neigh associated with the mac delete the mac
7689 * else mark it as AUTO for forward reference
7691 if (!listcount(mac
->neigh_list
)) {
7692 zvni_mac_del(zvni
, mac
);
7694 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7695 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7696 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7703 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7705 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7706 struct interface
*br_if
,
7707 struct ethaddr
*macaddr
, vlanid_t vid
,
7712 struct zebra_vrf
*zvrf
;
7713 char buf
[ETHER_ADDR_STRLEN
];
7714 bool mac_sticky
= false;
7715 bool inform_client
= false;
7716 bool upd_neigh
= false;
7717 bool is_dup_detect
= false;
7718 struct in_addr vtep_ip
= {.s_addr
= 0};
7720 /* We are interested in MACs only on ports or (port, VLAN) that
7723 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7725 if (IS_ZEBRA_DEBUG_VXLAN
)
7727 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7728 sticky
? "sticky " : "",
7729 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7730 ifp
->name
, ifp
->ifindex
, vid
);
7734 if (!zvni
->vxlan_if
) {
7735 if (IS_ZEBRA_DEBUG_VXLAN
)
7737 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7742 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7744 if (IS_ZEBRA_DEBUG_VXLAN
)
7745 zlog_debug("\tNo Vrf found for vrf_id: %d",
7746 zvni
->vxlan_if
->vrf_id
);
7750 /* Check if we need to create or update or it is a NO-OP. */
7751 mac
= zvni_mac_lookup(zvni
, macaddr
);
7753 if (IS_ZEBRA_DEBUG_VXLAN
)
7755 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7756 sticky
? "sticky " : "",
7757 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7758 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7760 mac
= zvni_mac_add(zvni
, macaddr
);
7763 EC_ZEBRA_MAC_ADD_FAILED
,
7764 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7765 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7766 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7769 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7770 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7771 mac
->fwd_info
.local
.vid
= vid
;
7773 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7774 inform_client
= true;
7777 if (IS_ZEBRA_DEBUG_VXLAN
)
7779 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7780 sticky
? "sticky " : "",
7781 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7782 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7785 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7786 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7790 * Update any changes and if changes are relevant to
7793 if (mac_sticky
== sticky
7794 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7795 && mac
->fwd_info
.local
.vid
== vid
) {
7796 if (IS_ZEBRA_DEBUG_VXLAN
)
7798 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7799 "entry exists and has not changed ",
7800 sticky
? "sticky " : "",
7801 prefix_mac2str(macaddr
, buf
,
7803 ifp
->name
, ifp
->ifindex
, vid
,
7807 if (mac_sticky
!= sticky
) {
7809 SET_FLAG(mac
->flags
,
7812 UNSET_FLAG(mac
->flags
,
7814 inform_client
= true;
7817 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7818 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7819 mac
->fwd_info
.local
.vid
= vid
;
7821 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7822 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7823 bool do_dad
= false;
7826 * MAC has either moved or was "internally" created due
7827 * to a neighbor learn and is now actually learnt. If
7828 * it was learnt as a remote sticky MAC, this is an
7831 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7833 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7834 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7835 prefix_mac2str(macaddr
, buf
,
7837 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7842 /* If an actual move, compute MAC's seq number */
7843 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7844 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7846 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7847 /* Trigger DAD for remote MAC */
7851 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7852 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7853 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7854 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7855 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7856 mac
->fwd_info
.local
.vid
= vid
;
7858 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7860 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7862 * We have to inform BGP of this MAC as well as process
7865 inform_client
= true;
7868 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7872 if (is_dup_detect
) {
7873 inform_client
= false;
7879 /* Inform BGP if required. */
7880 if (inform_client
) {
7881 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7882 mac
->flags
, mac
->loc_seq
))
7886 /* Process all neighbors associated with this MAC, if required. */
7888 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7894 * Handle message from client to delete a remote VTEP for a VNI.
7896 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7899 unsigned short l
= 0;
7901 struct in_addr vtep_ip
;
7903 zebra_vtep_t
*zvtep
;
7904 struct interface
*ifp
;
7905 struct zebra_if
*zif
;
7907 if (!is_evpn_enabled()) {
7909 "%s: EVPN is not enabled yet we have received a vtep del command",
7910 __PRETTY_FUNCTION__
);
7914 if (!EVPN_ENABLED(zvrf
)) {
7915 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7922 while (l
< hdr
->length
) {
7923 int flood_control
__attribute__((unused
));
7925 /* Obtain each remote VTEP and process. */
7926 STREAM_GETL(s
, vni
);
7928 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7929 l
+= IPV4_MAX_BYTELEN
;
7931 /* Flood control is intentionally ignored right now */
7932 STREAM_GETL(s
, flood_control
);
7935 if (IS_ZEBRA_DEBUG_VXLAN
)
7936 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7937 inet_ntoa(vtep_ip
), vni
,
7938 zebra_route_string(client
->proto
));
7940 /* Locate VNI hash entry - expected to exist. */
7941 zvni
= zvni_lookup(vni
);
7943 if (IS_ZEBRA_DEBUG_VXLAN
)
7945 "Failed to locate VNI hash upon remote VTEP DEL, "
7951 ifp
= zvni
->vxlan_if
;
7954 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7960 /* If down or not mapped to a bridge, we're done. */
7961 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7964 /* If the remote VTEP does not exist, there's nothing more to
7966 * Otherwise, uninstall any remote MACs pointing to this VTEP
7968 * then, the VTEP entry itself and remove it.
7970 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7974 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7975 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7976 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7977 zvni_vtep_del(zvni
, zvtep
);
7985 * Handle message from client to add a remote VTEP for a VNI.
7987 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7990 unsigned short l
= 0;
7992 struct in_addr vtep_ip
;
7994 struct interface
*ifp
;
7995 struct zebra_if
*zif
;
7997 zebra_vtep_t
*zvtep
;
7999 if (!is_evpn_enabled()) {
8001 "%s: EVPN not enabled yet we received a vtep_add zapi call",
8002 __PRETTY_FUNCTION__
);
8006 if (!EVPN_ENABLED(zvrf
)) {
8007 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
8014 while (l
< hdr
->length
) {
8015 /* Obtain each remote VTEP and process. */
8016 STREAM_GETL(s
, vni
);
8018 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8019 STREAM_GETL(s
, flood_control
);
8020 l
+= IPV4_MAX_BYTELEN
+ 4;
8022 if (IS_ZEBRA_DEBUG_VXLAN
)
8023 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
8024 inet_ntoa(vtep_ip
), vni
, flood_control
,
8025 zebra_route_string(client
->proto
));
8027 /* Locate VNI hash entry - expected to exist. */
8028 zvni
= zvni_lookup(vni
);
8031 EC_ZEBRA_VTEP_ADD_FAILED
,
8032 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
8037 ifp
= zvni
->vxlan_if
;
8040 EC_ZEBRA_VTEP_ADD_FAILED
,
8041 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8048 /* If down or not mapped to a bridge, we're done. */
8049 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8052 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8054 /* If the remote VTEP already exists check if
8055 * the flood mode has changed
8057 if (zvtep
->flood_control
!= flood_control
) {
8058 if (zvtep
->flood_control
8059 == VXLAN_FLOOD_DISABLED
)
8060 /* old mode was head-end-replication but
8061 * is no longer; get rid of the HER fdb
8062 * entry installed before
8064 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8065 zvtep
->flood_control
= flood_control
;
8066 zvni_vtep_install(zvni
, zvtep
);
8069 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8071 zvni_vtep_install(zvni
, zvtep
);
8073 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8074 "Failed to add remote VTEP, VNI %u zvni %p",
8084 * Add/Del gateway macip to evpn
8086 * 1. SVI interface on a vlan aware bridge
8087 * 2. SVI interface on a vlan unaware bridge
8088 * 3. vrr interface (MACVLAN) associated to a SVI
8089 * We advertise macip routes for an interface if it is associated to VxLan vlan
8091 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8095 struct ethaddr macaddr
;
8096 zebra_vni_t
*zvni
= NULL
;
8098 memset(&ip
, 0, sizeof(struct ipaddr
));
8099 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8101 /* Check if EVPN is enabled. */
8102 if (!is_evpn_enabled())
8105 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8106 struct interface
*svi_if
=
8107 NULL
; /* SVI corresponding to the MACVLAN */
8108 struct zebra_if
*ifp_zif
=
8109 NULL
; /* Zebra daemon specific info for MACVLAN */
8110 struct zebra_if
*svi_if_zif
=
8111 NULL
; /* Zebra daemon specific info for SVI*/
8113 ifp_zif
= ifp
->info
;
8118 * for a MACVLAN interface the link represents the svi_if
8120 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8121 ifp_zif
->link_ifindex
);
8123 zlog_debug("MACVLAN %s(%u) without link information",
8124 ifp
->name
, ifp
->ifindex
);
8128 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8130 * If it is a vlan aware bridge then the link gives the
8131 * bridge information
8133 struct interface
*svi_if_link
= NULL
;
8135 svi_if_zif
= svi_if
->info
;
8137 svi_if_link
= if_lookup_by_index_per_ns(
8138 zebra_ns_lookup(NS_DEFAULT
),
8139 svi_if_zif
->link_ifindex
);
8140 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8142 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8144 * If it is a vlan unaware bridge then svi is the bridge
8147 zvni
= zvni_from_svi(svi_if
, svi_if
);
8149 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8150 struct zebra_if
*svi_if_zif
=
8151 NULL
; /* Zebra daemon specific info for SVI */
8152 struct interface
*svi_if_link
=
8153 NULL
; /* link info for the SVI = bridge info */
8155 svi_if_zif
= ifp
->info
;
8157 svi_if_link
= if_lookup_by_index_per_ns(
8158 zebra_ns_lookup(NS_DEFAULT
),
8159 svi_if_zif
->link_ifindex
);
8161 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8163 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8164 zvni
= zvni_from_svi(ifp
, ifp
);
8170 if (!zvni
->vxlan_if
) {
8171 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8177 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8179 if (p
->family
== AF_INET
) {
8180 ip
.ipa_type
= IPADDR_V4
;
8181 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8182 sizeof(struct in_addr
));
8183 } else if (p
->family
== AF_INET6
) {
8184 ip
.ipa_type
= IPADDR_V6
;
8185 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8186 sizeof(struct in6_addr
));
8191 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8193 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8199 * Handle SVI interface going down.
8200 * SVI can be associated to either L3-VNI or L2-VNI.
8201 * For L2-VNI: At this point, this is a NOP since
8202 * the kernel deletes the neighbor entries on this SVI (if any).
8203 * We only need to update the vrf corresponding to zvni.
8204 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8207 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8209 zebra_l3vni_t
*zl3vni
= NULL
;
8211 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8214 /* process l3-vni down */
8215 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8217 /* remove association with svi-if */
8218 zl3vni
->svi_if
= NULL
;
8220 zebra_vni_t
*zvni
= NULL
;
8222 /* since we dont have svi corresponding to zvni, we associate it
8223 * to default vrf. Note: the corresponding neigh entries on the
8224 * SVI would have already been deleted */
8225 zvni
= zvni_from_svi(ifp
, link_if
);
8227 zvni
->vrf_id
= VRF_DEFAULT
;
8229 /* update the tenant vrf in BGP */
8230 zvni_send_add_to_client(zvni
);
8237 * Handle SVI interface coming up.
8238 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8240 * For L2-VNI: we need to install any remote neighbors entried (used for
8242 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8244 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8246 zebra_vni_t
*zvni
= NULL
;
8247 zebra_l3vni_t
*zl3vni
= NULL
;
8249 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8252 /* associate with svi */
8253 zl3vni
->svi_if
= ifp
;
8255 /* process oper-up */
8256 if (is_l3vni_oper_up(zl3vni
))
8257 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8260 /* process SVI up for l2-vni */
8261 struct neigh_walk_ctx n_wctx
;
8263 zvni
= zvni_from_svi(ifp
, link_if
);
8267 if (!zvni
->vxlan_if
) {
8269 "VNI %u hash %p doesn't have intf upon SVI up",
8274 if (IS_ZEBRA_DEBUG_VXLAN
)
8276 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8277 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8278 vrf_id_to_name(ifp
->vrf_id
));
8280 /* update the vrf information for l2-vni and inform bgp */
8281 zvni
->vrf_id
= ifp
->vrf_id
;
8282 zvni_send_add_to_client(zvni
);
8284 /* Install any remote neighbors for this VNI. */
8285 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8287 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8295 * Handle VxLAN interface down
8297 int zebra_vxlan_if_down(struct interface
*ifp
)
8300 struct zebra_if
*zif
= NULL
;
8301 struct zebra_l2info_vxlan
*vxl
= NULL
;
8302 zebra_l3vni_t
*zl3vni
= NULL
;
8305 /* Check if EVPN is enabled. */
8306 if (!is_evpn_enabled())
8311 vxl
= &zif
->l2info
.vxl
;
8314 zl3vni
= zl3vni_lookup(vni
);
8316 /* process-if-down for l3-vni */
8317 if (IS_ZEBRA_DEBUG_VXLAN
)
8318 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8321 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8323 /* process if-down for l2-vni */
8324 if (IS_ZEBRA_DEBUG_VXLAN
)
8325 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8328 /* Locate hash entry; it is expected to exist. */
8329 zvni
= zvni_lookup(vni
);
8332 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8333 ifp
->name
, ifp
->ifindex
, vni
);
8337 assert(zvni
->vxlan_if
== ifp
);
8339 /* Delete this VNI from BGP. */
8340 zvni_send_del_to_client(zvni
->vni
);
8342 /* Free up all neighbors and MACs, if any. */
8343 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8344 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8346 /* Free up all remote VTEPs, if any. */
8347 zvni_vtep_del_all(zvni
, 1);
8353 * Handle VxLAN interface up - update BGP if required.
8355 int zebra_vxlan_if_up(struct interface
*ifp
)
8358 struct zebra_if
*zif
= NULL
;
8359 struct zebra_l2info_vxlan
*vxl
= NULL
;
8360 zebra_vni_t
*zvni
= NULL
;
8361 zebra_l3vni_t
*zl3vni
= NULL
;
8363 /* Check if EVPN is enabled. */
8364 if (!is_evpn_enabled())
8369 vxl
= &zif
->l2info
.vxl
;
8372 zl3vni
= zl3vni_lookup(vni
);
8375 if (IS_ZEBRA_DEBUG_VXLAN
)
8376 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8379 /* we need to associate with SVI, if any, we can associate with
8380 * svi-if only after association with vxlan-intf is complete
8382 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8384 if (is_l3vni_oper_up(zl3vni
))
8385 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8387 /* Handle L2-VNI add */
8388 struct interface
*vlan_if
= NULL
;
8390 if (IS_ZEBRA_DEBUG_VXLAN
)
8391 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8394 /* Locate hash entry; it is expected to exist. */
8395 zvni
= zvni_lookup(vni
);
8398 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8399 ifp
->name
, ifp
->ifindex
, vni
);
8403 assert(zvni
->vxlan_if
== ifp
);
8404 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8405 zif
->brslave_info
.br_if
);
8407 zvni
->vrf_id
= vlan_if
->vrf_id
;
8408 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8410 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8413 /* If part of a bridge, inform BGP about this VNI. */
8414 /* Also, read and populate local MACs and neighbors. */
8415 if (zif
->brslave_info
.br_if
) {
8416 zvni_send_add_to_client(zvni
);
8417 zvni_read_mac_neigh(zvni
, ifp
);
8425 * Handle VxLAN interface delete. Locate and remove entry in hash table
8426 * and update BGP, if required.
8428 int zebra_vxlan_if_del(struct interface
*ifp
)
8431 struct zebra_if
*zif
= NULL
;
8432 struct zebra_l2info_vxlan
*vxl
= NULL
;
8433 zebra_vni_t
*zvni
= NULL
;
8434 zebra_l3vni_t
*zl3vni
= NULL
;
8436 /* Check if EVPN is enabled. */
8437 if (!is_evpn_enabled())
8442 vxl
= &zif
->l2info
.vxl
;
8445 zl3vni
= zl3vni_lookup(vni
);
8448 if (IS_ZEBRA_DEBUG_VXLAN
)
8449 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8452 /* process oper-down for l3-vni */
8453 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8455 /* remove the association with vxlan_if */
8456 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8457 zl3vni
->vxlan_if
= NULL
;
8460 /* process if-del for l2-vni*/
8461 if (IS_ZEBRA_DEBUG_VXLAN
)
8462 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8465 /* Locate hash entry; it is expected to exist. */
8466 zvni
= zvni_lookup(vni
);
8469 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8470 ifp
->name
, ifp
->ifindex
, vni
);
8474 /* remove from l3-vni list */
8475 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8477 listnode_delete(zl3vni
->l2vnis
, zvni
);
8479 /* Delete VNI from BGP. */
8480 zvni_send_del_to_client(zvni
->vni
);
8482 /* Free up all neighbors and MAC, if any. */
8483 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8484 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8486 /* Free up all remote VTEPs, if any. */
8487 zvni_vtep_del_all(zvni
, 0);
8489 /* Delete the hash entry. */
8490 if (zvni_del(zvni
)) {
8491 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8492 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8493 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8501 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8503 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8506 struct zebra_if
*zif
= NULL
;
8507 struct zebra_l2info_vxlan
*vxl
= NULL
;
8508 zebra_vni_t
*zvni
= NULL
;
8509 zebra_l3vni_t
*zl3vni
= NULL
;
8511 /* Check if EVPN is enabled. */
8512 if (!is_evpn_enabled())
8517 vxl
= &zif
->l2info
.vxl
;
8520 zl3vni
= zl3vni_lookup(vni
);
8523 if (IS_ZEBRA_DEBUG_VXLAN
)
8525 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8526 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8527 inet_ntoa(vxl
->vtep_ip
),
8528 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8530 /* Removed from bridge? Cleanup and return */
8531 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8532 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8533 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8537 /* access-vlan change - process oper down, associate with new
8538 * svi_if and then process oper up again
8540 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8541 if (if_is_operative(ifp
)) {
8542 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8543 zl3vni
->svi_if
= NULL
;
8544 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8545 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8546 if (is_l3vni_oper_up(zl3vni
))
8547 zebra_vxlan_process_l3vni_oper_up(
8553 * local-ip change - process oper down, associate with new
8554 * local-ip and then process oper up again
8556 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8557 if (if_is_operative(ifp
)) {
8558 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8559 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8560 if (is_l3vni_oper_up(zl3vni
))
8561 zebra_vxlan_process_l3vni_oper_up(
8566 /* Update local tunnel IP. */
8567 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8569 /* if we have a valid new master, process l3-vni oper up */
8570 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8571 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8572 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8576 /* Update VNI hash. */
8577 zvni
= zvni_lookup(vni
);
8580 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8581 ifp
->name
, ifp
->ifindex
, vni
);
8585 if (IS_ZEBRA_DEBUG_VXLAN
)
8587 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8588 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8589 inet_ntoa(vxl
->vtep_ip
),
8590 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8592 /* Removed from bridge? Cleanup and return */
8593 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8594 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8595 /* Delete from client, remove all remote VTEPs */
8596 /* Also, free up all MACs and neighbors. */
8597 zvni_send_del_to_client(zvni
->vni
);
8598 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8599 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8600 zvni_vtep_del_all(zvni
, 1);
8604 /* Handle other changes. */
8605 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8606 /* Remove all existing local neigh and MACs for this VNI
8607 * (including from BGP)
8609 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8610 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8613 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8614 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8615 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8617 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8618 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8619 zvni
->mcast_grp
= vxl
->mcast_grp
;
8621 zvni
->vxlan_if
= ifp
;
8623 /* Take further actions needed.
8624 * Note that if we are here, there is a change of interest.
8626 /* If down or not mapped to a bridge, we're done. */
8627 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8630 /* Inform BGP, if there is a change of interest. */
8632 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8633 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8634 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8635 zvni_send_add_to_client(zvni
);
8637 /* If there is a valid new master or a VLAN mapping change,
8638 * read and populate local MACs and neighbors.
8639 * Also, reinstall any remote MACs and neighbors
8640 * for this VNI (based on new VLAN).
8642 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8643 zvni_read_mac_neigh(zvni
, ifp
);
8644 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8645 struct mac_walk_ctx m_wctx
;
8646 struct neigh_walk_ctx n_wctx
;
8648 zvni_read_mac_neigh(zvni
, ifp
);
8650 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8652 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8655 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8657 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8666 * Handle VxLAN interface add.
8668 int zebra_vxlan_if_add(struct interface
*ifp
)
8671 struct zebra_if
*zif
= NULL
;
8672 struct zebra_l2info_vxlan
*vxl
= NULL
;
8673 zebra_vni_t
*zvni
= NULL
;
8674 zebra_l3vni_t
*zl3vni
= NULL
;
8676 /* Check if EVPN is enabled. */
8677 if (!is_evpn_enabled())
8682 vxl
= &zif
->l2info
.vxl
;
8685 zl3vni
= zl3vni_lookup(vni
);
8688 /* process if-add for l3-vni*/
8689 if (IS_ZEBRA_DEBUG_VXLAN
)
8691 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8692 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8693 inet_ntoa(vxl
->vtep_ip
),
8694 zif
->brslave_info
.bridge_ifindex
);
8696 /* associate with vxlan_if */
8697 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8698 zl3vni
->vxlan_if
= ifp
;
8700 /* Associate with SVI, if any. We can associate with svi-if only
8701 * after association with vxlan_if is complete */
8702 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8704 if (is_l3vni_oper_up(zl3vni
))
8705 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8708 /* process if-add for l2-vni */
8709 struct interface
*vlan_if
= NULL
;
8711 /* Create or update VNI hash. */
8712 zvni
= zvni_lookup(vni
);
8714 zvni
= zvni_add(vni
);
8717 EC_ZEBRA_VNI_ADD_FAILED
,
8718 "Failed to add VNI hash, IF %s(%u) VNI %u",
8719 ifp
->name
, ifp
->ifindex
, vni
);
8724 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8725 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8726 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8728 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8729 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8730 zvni
->mcast_grp
= vxl
->mcast_grp
;
8732 zvni
->vxlan_if
= ifp
;
8733 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8734 zif
->brslave_info
.br_if
);
8736 zvni
->vrf_id
= vlan_if
->vrf_id
;
8737 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8739 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8742 if (IS_ZEBRA_DEBUG_VXLAN
) {
8743 char addr_buf1
[INET_ADDRSTRLEN
];
8744 char addr_buf2
[INET_ADDRSTRLEN
];
8746 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8747 addr_buf1
, INET_ADDRSTRLEN
);
8748 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8749 addr_buf2
, INET_ADDRSTRLEN
);
8752 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8754 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8756 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8757 addr_buf1
, addr_buf2
,
8758 zif
->brslave_info
.bridge_ifindex
);
8761 /* If down or not mapped to a bridge, we're done. */
8762 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8766 zvni_send_add_to_client(zvni
);
8768 /* Read and populate local MACs and neighbors */
8769 zvni_read_mac_neigh(zvni
, ifp
);
8775 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8776 char *err
, int err_str_sz
, int filter
,
8779 zebra_l3vni_t
*zl3vni
= NULL
;
8780 struct zebra_vrf
*zvrf_evpn
= NULL
;
8782 zvrf_evpn
= zebra_vrf_get_evpn();
8786 if (IS_ZEBRA_DEBUG_VXLAN
)
8787 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8788 add
? "ADD" : "DEL");
8792 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8794 /* check if the vni is already present under zvrf */
8796 snprintf(err
, err_str_sz
,
8797 "VNI is already configured under the vrf");
8801 /* check if this VNI is already present in the system */
8802 zl3vni
= zl3vni_lookup(vni
);
8804 snprintf(err
, err_str_sz
,
8805 "VNI is already configured as L3-VNI");
8809 /* add the L3-VNI to the global table */
8810 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8812 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8816 /* associate the vrf with vni */
8819 /* set the filter in l3vni to denote if we are using l3vni only
8823 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8825 /* associate with vxlan-intf;
8826 * we need to associate with the vxlan-intf first
8828 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8830 /* associate with corresponding SVI interface, we can associate
8831 * with svi-if only after vxlan interface association is
8834 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8836 /* formulate l2vni list */
8837 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8840 if (is_l3vni_oper_up(zl3vni
))
8841 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8844 zl3vni
= zl3vni_lookup(vni
);
8846 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8850 if (zvrf
->l3vni
!= vni
) {
8851 snprintf(err
, err_str_sz
,
8852 "VNI %d doesn't exist in VRF: %s",
8853 vni
, zvrf
->vrf
->name
);
8857 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8858 snprintf(err
, ERR_STR_SZ
,
8859 "prefix-routes-only is not set for the vni");
8863 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8865 /* delete and uninstall all rmacs */
8866 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8869 /* delete and uninstall all next-hops */
8870 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8876 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8881 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8883 zebra_l3vni_t
*zl3vni
= NULL
;
8886 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8890 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8891 if (is_l3vni_oper_up(zl3vni
))
8892 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8896 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8898 zebra_l3vni_t
*zl3vni
= NULL
;
8901 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8905 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8906 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8910 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8912 zebra_l3vni_t
*zl3vni
= NULL
;
8916 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8922 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8928 * Handle message from client to specify the flooding mechanism for
8929 * BUM packets. The default is to do head-end (ingress) replication
8930 * and the other supported option is to disable it. This applies to
8931 * all BUM traffic and disabling it applies to both the transmit and
8932 * receive direction.
8934 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8937 enum vxlan_flood_control flood_ctrl
;
8939 if (!EVPN_ENABLED(zvrf
)) {
8940 zlog_err("EVPN flood control for non-EVPN VRF %u",
8946 STREAM_GETC(s
, flood_ctrl
);
8948 if (IS_ZEBRA_DEBUG_VXLAN
)
8949 zlog_debug("EVPN flood control %u, currently %u",
8950 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8952 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8955 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8957 /* Install or uninstall flood entries corresponding to
8960 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8968 * Handle message from client to enable/disable advertisement of svi macip
8971 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8976 zebra_vni_t
*zvni
= NULL
;
8977 struct interface
*ifp
= NULL
;
8979 if (!EVPN_ENABLED(zvrf
)) {
8980 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
8986 STREAM_GETC(s
, advertise
);
8987 STREAM_GETL(s
, vni
);
8990 if (IS_ZEBRA_DEBUG_VXLAN
)
8991 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
8992 advertise
? "enabled" : "disabled",
8993 advertise_gw_macip_enabled(NULL
)
8997 if (zvrf
->advertise_svi_macip
== advertise
)
9002 zvrf
->advertise_svi_macip
= advertise
;
9003 hash_iterate(zvrf
->vni_table
,
9004 zvni_gw_macip_add_for_vni_hash
, NULL
);
9006 hash_iterate(zvrf
->vni_table
,
9007 zvni_svi_macip_del_for_vni_hash
, NULL
);
9008 zvrf
->advertise_svi_macip
= advertise
;
9012 struct zebra_if
*zif
= NULL
;
9013 struct zebra_l2info_vxlan zl2_info
;
9014 struct interface
*vlan_if
= NULL
;
9016 zvni
= zvni_lookup(vni
);
9020 if (IS_ZEBRA_DEBUG_VXLAN
)
9022 "EVPN SVI macip Adv %s on VNI %d , currently %s",
9023 advertise
? "enabled" : "disabled", vni
,
9024 advertise_svi_macip_enabled(zvni
)
9028 if (zvni
->advertise_svi_macip
== advertise
)
9031 ifp
= zvni
->vxlan_if
;
9037 /* If down or not mapped to a bridge, we're done. */
9038 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9041 zl2_info
= zif
->l2info
.vxl
;
9043 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9044 zif
->brslave_info
.br_if
);
9049 zvni
->advertise_svi_macip
= advertise
;
9050 /* Add primary SVI MAC-IP */
9051 zvni_add_macip_for_intf(vlan_if
, zvni
);
9053 /* Del primary MAC-IP */
9054 zvni_del_macip_for_intf(vlan_if
, zvni
);
9055 zvni
->advertise_svi_macip
= advertise
;
9064 * Handle message from client to enable/disable advertisement of g/w macip
9067 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9072 zebra_vni_t
*zvni
= NULL
;
9073 struct interface
*ifp
= NULL
;
9074 struct zebra_if
*zif
= NULL
;
9075 struct zebra_l2info_vxlan zl2_info
;
9076 struct interface
*vlan_if
= NULL
;
9078 if (!EVPN_ENABLED(zvrf
)) {
9079 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9085 STREAM_GETC(s
, advertise
);
9086 vni
= stream_get3(s
);
9088 zvni
= zvni_lookup(vni
);
9092 if (zvni
->advertise_subnet
== advertise
)
9095 if (IS_ZEBRA_DEBUG_VXLAN
)
9096 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9097 advertise
? "enabled" : "disabled", vni
,
9098 zvni
->advertise_subnet
? "enabled" : "disabled");
9101 zvni
->advertise_subnet
= advertise
;
9103 ifp
= zvni
->vxlan_if
;
9109 /* If down or not mapped to a bridge, we're done. */
9110 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9113 zl2_info
= zif
->l2info
.vxl
;
9116 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9120 if (zvni
->advertise_subnet
)
9121 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9123 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9130 * Handle message from client to enable/disable advertisement of g/w macip
9133 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9138 zebra_vni_t
*zvni
= NULL
;
9139 struct interface
*ifp
= NULL
;
9141 if (!EVPN_ENABLED(zvrf
)) {
9142 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9148 STREAM_GETC(s
, advertise
);
9149 STREAM_GETL(s
, vni
);
9152 if (IS_ZEBRA_DEBUG_VXLAN
)
9153 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9154 advertise
? "enabled" : "disabled",
9155 advertise_gw_macip_enabled(NULL
)
9159 if (zvrf
->advertise_gw_macip
== advertise
)
9162 zvrf
->advertise_gw_macip
= advertise
;
9164 if (advertise_gw_macip_enabled(zvni
))
9165 hash_iterate(zvrf
->vni_table
,
9166 zvni_gw_macip_add_for_vni_hash
, NULL
);
9168 hash_iterate(zvrf
->vni_table
,
9169 zvni_gw_macip_del_for_vni_hash
, NULL
);
9172 struct zebra_if
*zif
= NULL
;
9173 struct zebra_l2info_vxlan zl2_info
;
9174 struct interface
*vlan_if
= NULL
;
9175 struct interface
*vrr_if
= NULL
;
9177 zvni
= zvni_lookup(vni
);
9181 if (IS_ZEBRA_DEBUG_VXLAN
)
9183 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9184 advertise
? "enabled" : "disabled", vni
,
9185 advertise_gw_macip_enabled(zvni
) ? "enabled"
9188 if (zvni
->advertise_gw_macip
== advertise
)
9191 zvni
->advertise_gw_macip
= advertise
;
9193 ifp
= zvni
->vxlan_if
;
9199 /* If down or not mapped to a bridge, we're done. */
9200 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9203 zl2_info
= zif
->l2info
.vxl
;
9205 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9206 zif
->brslave_info
.br_if
);
9210 if (advertise_gw_macip_enabled(zvni
)) {
9211 /* Add primary SVI MAC-IP */
9212 zvni_add_macip_for_intf(vlan_if
, zvni
);
9214 /* Add VRR MAC-IP - if any*/
9215 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9217 zvni_add_macip_for_intf(vrr_if
, zvni
);
9219 /* Del primary MAC-IP */
9220 zvni_del_macip_for_intf(vlan_if
, zvni
);
9222 /* Del VRR MAC-IP - if any*/
9223 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9225 zvni_del_macip_for_intf(vrr_if
, zvni
);
9235 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9236 * When enabled, the VNI hash table will be built and MAC FDB table read;
9237 * when disabled, the entries should be deleted and remote VTEPs and MACs
9238 * uninstalled from the kernel.
9239 * This also informs the setting for BUM handling at the time this change
9240 * occurs; it is relevant only when specifying "learn".
9242 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9244 struct stream
*s
= NULL
;
9246 enum vxlan_flood_control flood_ctrl
;
9248 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9250 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9254 STREAM_GETC(s
, advertise
);
9255 STREAM_GETC(s
, flood_ctrl
);
9257 if (IS_ZEBRA_DEBUG_VXLAN
)
9258 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9259 zvrf_name(zvrf
), zvrf_id(zvrf
),
9260 advertise
? "enabled" : "disabled",
9261 is_evpn_enabled() ? "enabled" : "disabled",
9264 if (zvrf
->advertise_all_vni
== advertise
)
9267 zvrf
->advertise_all_vni
= advertise
;
9268 if (EVPN_ENABLED(zvrf
)) {
9269 zrouter
.evpn_vrf
= zvrf
;
9271 /* Note BUM handling */
9272 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9274 /* Build VNI hash table and inform BGP. */
9275 zvni_build_hash_table();
9277 /* Add all SVI (L3 GW) MACs to BGP*/
9278 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9281 /* Read the MAC FDB */
9282 macfdb_read(zvrf
->zns
);
9284 /* Read neighbors */
9285 neigh_read(zvrf
->zns
);
9287 /* Cleanup VTEPs for all VNIs - uninstall from
9288 * kernel and free entries.
9290 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9292 /* cleanup all l3vnis */
9293 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9295 /* Mark as "no EVPN VRF" */
9296 zrouter
.evpn_vrf
= NULL
;
9304 * Allocate VNI hash table for this VRF and do other initialization.
9305 * NOTE: Currently supported only for default VRF.
9307 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9311 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9312 "Zebra VRF VNI Table");
9313 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9314 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9317 /* Cleanup VNI info, but don't free the table. */
9318 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9322 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9323 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9326 /* Close all VNI handling */
9327 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9331 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9332 hash_free(zvrf
->vni_table
);
9335 /* init the l3vni table */
9336 void zebra_vxlan_init(void)
9338 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9339 "Zebra VRF L3 VNI table");
9340 zrouter
.evpn_vrf
= NULL
;
9343 /* free l3vni table */
9344 void zebra_vxlan_disable(void)
9346 hash_free(zrouter
.l3vni_table
);
9349 /* get the l3vni svi ifindex */
9350 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9352 zebra_l3vni_t
*zl3vni
= NULL
;
9354 zl3vni
= zl3vni_from_vrf(vrf_id
);
9355 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9358 return zl3vni
->svi_if
->ifindex
;
9361 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9363 struct zebra_vrf
*zvrf
= NULL
;
9364 zebra_neigh_t
*nbr
= NULL
;
9365 zebra_vni_t
*zvni
= NULL
;
9366 char buf1
[INET6_ADDRSTRLEN
];
9367 char buf2
[ETHER_ADDR_STRLEN
];
9369 nbr
= THREAD_ARG(t
);
9371 /* since this is asynchronous we need sanity checks*/
9372 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9376 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9380 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9384 if (IS_ZEBRA_DEBUG_VXLAN
)
9385 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9386 __PRETTY_FUNCTION__
,
9387 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9388 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9390 nbr
->dad_count
, zvni
->vni
);
9392 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9394 nbr
->detect_start_time
.tv_sec
= 0;
9395 nbr
->detect_start_time
.tv_usec
= 0;
9396 nbr
->dad_dup_detect_time
= 0;
9397 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9398 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9401 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9402 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9403 nbr
->flags
, nbr
->loc_seq
);
9404 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9405 zvni_neigh_install(zvni
, nbr
);
9411 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9413 struct zebra_vrf
*zvrf
= NULL
;
9414 zebra_mac_t
*mac
= NULL
;
9415 zebra_vni_t
*zvni
= NULL
;
9416 struct listnode
*node
= NULL
;
9417 zebra_neigh_t
*nbr
= NULL
;
9418 char buf
[ETHER_ADDR_STRLEN
];
9420 mac
= THREAD_ARG(t
);
9422 /* since this is asynchronous we need sanity checks*/
9423 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9427 zvni
= zvni_lookup(mac
->zvni
->vni
);
9431 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9435 if (IS_ZEBRA_DEBUG_VXLAN
)
9436 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9437 __PRETTY_FUNCTION__
,
9438 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9441 listcount(mac
->neigh_list
));
9443 /* Remove all IPs as duplicate associcated with this MAC */
9444 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9445 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9446 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9447 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9448 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9449 zvni_neigh_install(zvni
, nbr
);
9452 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9454 nbr
->detect_start_time
.tv_sec
= 0;
9455 nbr
->dad_dup_detect_time
= 0;
9458 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9460 mac
->detect_start_time
.tv_sec
= 0;
9461 mac
->detect_start_time
.tv_usec
= 0;
9462 mac
->dad_dup_detect_time
= 0;
9463 mac
->dad_mac_auto_recovery_timer
= NULL
;
9465 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9467 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9468 mac
->flags
, mac
->loc_seq
))
9471 /* Process all neighbors associated with this MAC. */
9472 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9474 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9475 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9477 /* Install the entry. */
9478 zvni_mac_install(zvni
, mac
);
9484 /************************** vxlan SG cache management ************************/
9485 /* Inform PIM about the mcast group */
9486 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9487 char *sg_str
, uint16_t cmd
)
9489 struct zserv
*client
= NULL
;
9490 struct stream
*s
= NULL
;
9492 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9496 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9498 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9499 stream_putl(s
, IPV4_MAX_BYTELEN
);
9500 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9501 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9503 /* Write packet size. */
9504 stream_putw_at(s
, 0, stream_get_endp(s
));
9506 if (IS_ZEBRA_DEBUG_VXLAN
)
9509 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9510 zebra_route_string(client
->proto
));
9512 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9513 client
->vxlan_sg_add_cnt
++;
9515 client
->vxlan_sg_del_cnt
++;
9517 return zserv_send_message(client
, s
);
9520 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9522 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9524 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9525 vxlan_sg
->sg
.grp
.s_addr
, 0));
9528 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9530 const zebra_vxlan_sg_t
*sg1
= p1
;
9531 const zebra_vxlan_sg_t
*sg2
= p2
;
9533 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9534 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9537 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9538 struct prefix_sg
*sg
)
9540 zebra_vxlan_sg_t
*vxlan_sg
;
9542 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9544 vxlan_sg
->zvrf
= zvrf
;
9546 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9548 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9550 if (IS_ZEBRA_DEBUG_VXLAN
)
9551 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9556 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9557 struct prefix_sg
*sg
)
9559 zebra_vxlan_sg_t lookup
;
9562 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9565 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9566 struct prefix_sg
*sg
)
9568 zebra_vxlan_sg_t
*vxlan_sg
;
9569 zebra_vxlan_sg_t
*parent
= NULL
;
9572 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9576 /* create a *G entry for every BUM group implicitly -
9577 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9578 * 2. the XG entry is used by pimd to setup the
9579 * vxlan-termination-mroute
9581 if (sg
->src
.s_addr
) {
9582 memset(&sip
, 0, sizeof(sip
));
9583 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9588 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9591 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9595 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9600 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9603 struct zebra_vrf
*zvrf
;
9605 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9609 /* On SG entry deletion remove the reference to its parent XG
9612 if (vxlan_sg
->sg
.src
.s_addr
) {
9613 memset(&sip
, 0, sizeof(sip
));
9614 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9617 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9618 ZEBRA_VXLAN_SG_DEL
);
9620 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9622 if (IS_ZEBRA_DEBUG_VXLAN
)
9623 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9625 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9628 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9629 struct in_addr sip
, struct in_addr mcast_grp
)
9631 zebra_vxlan_sg_t
*vxlan_sg
;
9632 struct prefix_sg sg
;
9634 sg
.family
= AF_INET
;
9635 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9638 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9642 if (vxlan_sg
->ref_cnt
)
9643 --vxlan_sg
->ref_cnt
;
9645 if (!vxlan_sg
->ref_cnt
)
9646 zebra_vxlan_sg_del(vxlan_sg
);
9649 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9650 struct in_addr sip
, struct in_addr mcast_grp
)
9652 zebra_vxlan_sg_t
*vxlan_sg
;
9653 struct prefix_sg sg
;
9655 sg
.family
= AF_INET
;
9656 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9659 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9661 ++vxlan_sg
->ref_cnt
;
9666 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9667 struct in_addr mcast_grp
)
9669 struct zebra_vrf
*zvrf
;
9671 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9674 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9678 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9681 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9682 struct in_addr mcast_grp
)
9684 struct zebra_vrf
*zvrf
;
9686 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9689 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9692 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9695 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9697 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9699 zebra_vxlan_sg_del(vxlan_sg
);
9702 /************************** EVPN BGP config management ************************/
9703 /* Notify Local MACs to the clienti, skips GW MAC */
9704 static void zvni_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
9707 struct mac_walk_ctx
*wctx
= arg
;
9708 zebra_mac_t
*zmac
= bucket
->data
;
9710 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
9713 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
9714 zvni_mac_send_add_to_client(wctx
->zvni
->vni
, &zmac
->macaddr
,
9715 zmac
->flags
, zmac
->loc_seq
);
9718 /* Iterator to Notify Local MACs of a L2VNI */
9719 static void zvni_send_mac_to_client(zebra_vni_t
*zvni
)
9721 struct mac_walk_ctx wctx
;
9723 if (!zvni
->mac_table
)
9726 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
9729 hash_iterate(zvni
->mac_table
, zvni_send_mac_hash_entry_to_client
,
9733 /* Notify Neighbor entries to the Client, skips the GW entry */
9734 static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
9737 struct mac_walk_ctx
*wctx
= arg
;
9738 zebra_neigh_t
*zn
= bucket
->data
;
9739 zebra_mac_t
*zmac
= NULL
;
9741 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
9744 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
9745 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
9746 zmac
= zvni_mac_lookup(wctx
->zvni
, &zn
->emac
);
9750 zvni_neigh_send_add_to_client(wctx
->zvni
->vni
, &zn
->ip
,
9751 &zn
->emac
, zn
->flags
,
9756 /* Iterator of a specific L2VNI */
9757 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
)
9759 struct neigh_walk_ctx wctx
;
9761 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
9764 hash_iterate(zvni
->neigh_table
, zvni_send_neigh_hash_entry_to_client
,
9768 static void zvni_evpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
9770 zebra_vni_t
*zvni
= NULL
;
9772 zvni
= (zebra_vni_t
*)bucket
->data
;
9773 zvni
->advertise_gw_macip
= 0;
9774 zvni
->advertise_svi_macip
= 0;
9775 zvni
->advertise_subnet
= 0;
9777 zvni_neigh_del_all(zvni
, 0, 0,
9778 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
9779 zvni_mac_del_all(zvni
, 0, 0,
9780 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
9781 zvni_vtep_del_all(zvni
, 0);
9784 /* Cleanup EVPN configuration of a specific VRF */
9785 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
9787 zvrf
->advertise_all_vni
= 0;
9788 zvrf
->advertise_gw_macip
= 0;
9789 zvrf
->advertise_svi_macip
= 0;
9790 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
9792 hash_iterate(zvrf
->vni_table
, zvni_evpn_cfg_cleanup
, NULL
);
9795 /* Cleanup BGP EVPN configuration upon client disconnect */
9796 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
9799 struct zebra_vrf
*zvrf
;
9801 if (client
->proto
!= ZEBRA_ROUTE_BGP
)
9804 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
9807 zebra_evpn_vrf_cfg_cleanup(zvrf
);
9813 /* Cleanup BGP EVPN configuration upon client disconnect */
9814 extern void zebra_evpn_init(void)
9816 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);