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/zserv.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");
64 /* static function declarations */
65 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
67 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
68 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
69 static void zvni_print_dad_neigh_hash(struct hash_backet
*backet
, void *ctxt
);
70 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
72 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
74 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
76 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
77 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
);
78 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
);
79 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
80 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[]);
82 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
83 struct ipaddr
*ip
, uint8_t flags
,
84 uint32_t seq
, int state
, uint16_t cmd
);
85 static unsigned int neigh_hash_keymake(void *p
);
86 static void *zvni_neigh_alloc(void *p
);
87 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
89 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
90 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
91 struct in_addr
*r_vtep_ip
);
92 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
94 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
95 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
96 struct ethaddr
*macaddr
,
97 uint8_t flags
, uint32_t seq
);
98 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
99 struct ethaddr
*macaddr
,
100 uint8_t flags
, int state
);
101 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
102 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
103 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
104 struct interface
*br_if
);
105 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
107 /* l3-vni next-hop neigh related APIs */
108 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
110 static void *zl3vni_nh_alloc(void *p
);
111 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
112 struct ipaddr
*vtep_ip
,
113 struct ethaddr
*rmac
);
114 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
115 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
116 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
118 /* l3-vni rmac related APIs */
119 static void zl3vni_print_rmac_hash(struct hash_backet
*, void *);
120 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
121 struct ethaddr
*rmac
);
122 static void *zl3vni_rmac_alloc(void *p
);
123 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
124 struct ethaddr
*rmac
);
125 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
126 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
127 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
129 /* l3-vni related APIs*/
130 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
131 static void *zl3vni_alloc(void *p
);
132 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
133 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
134 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
135 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
136 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
137 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
138 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
140 static unsigned int mac_hash_keymake(void *p
);
141 static bool mac_cmp(const void *p1
, const void *p2
);
142 static void *zvni_mac_alloc(void *p
);
143 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
144 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
145 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
146 struct in_addr
*r_vtep_ip
);
147 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
149 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
150 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
151 uint8_t flags
, uint32_t seq
);
152 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
153 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
154 struct interface
*br_if
, vlanid_t vid
);
155 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
156 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
157 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
);
159 static unsigned int vni_hash_keymake(void *p
);
160 static void *zvni_alloc(void *p
);
161 static zebra_vni_t
*zvni_lookup(vni_t vni
);
162 static zebra_vni_t
*zvni_add(vni_t vni
);
163 static int zvni_del(zebra_vni_t
*zvni
);
164 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
165 static int zvni_send_del_to_client(vni_t vni
);
166 static void zvni_build_hash_table(void);
167 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
168 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
169 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
171 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
172 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
173 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
175 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
176 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
177 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
178 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
180 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
181 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
182 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
183 zebra_mac_t
*old_zmac
,
184 zebra_mac_t
*new_zmac
,
186 static int remote_neigh_count(zebra_mac_t
*zmac
);
187 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
188 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
189 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
190 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
192 struct in_addr vtep_ip
,
196 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
198 struct in_addr vtep_ip
,
203 /* Private functions */
204 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
205 const struct host_rb_entry
*hle2
)
207 if (hle1
->p
.family
< hle2
->p
.family
)
210 if (hle1
->p
.family
> hle2
->p
.family
)
213 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
216 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
219 if (hle1
->p
.family
== AF_INET
) {
220 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
223 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
227 } else if (hle1
->p
.family
== AF_INET6
) {
228 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
231 zlog_debug("%s: Unexpected family type: %d",
232 __PRETTY_FUNCTION__
, hle1
->p
.family
);
236 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
238 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
240 struct host_rb_entry
*hle
;
243 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
250 * Return number of valid MACs in a VNI's MAC hash table - all
251 * remote MACs and non-internal (auto) local MACs count.
253 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
256 uint32_t num_macs
= 0;
258 struct hash_backet
*hb
;
261 hash
= zvni
->mac_table
;
264 for (i
= 0; i
< hash
->size
; i
++) {
265 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
266 mac
= (zebra_mac_t
*)hb
->data
;
267 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
268 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
269 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
277 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
280 uint32_t num_macs
= 0;
282 struct hash_backet
*hb
;
285 hash
= zvni
->mac_table
;
288 for (i
= 0; i
< hash
->size
; i
++) {
289 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
290 mac
= (zebra_mac_t
*)hb
->data
;
291 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
299 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
302 uint32_t num_neighs
= 0;
304 struct hash_backet
*hb
;
307 hash
= zvni
->neigh_table
;
310 for (i
= 0; i
< hash
->size
; i
++) {
311 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
312 nbr
= (zebra_neigh_t
*)hb
->data
;
313 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
321 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
323 struct zebra_vrf
*zvrf
;
325 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
326 if (zvrf
&& zvrf
->advertise_gw_macip
)
329 if (zvni
&& zvni
->advertise_gw_macip
)
335 /* As part Duplicate Address Detection (DAD) for IP mobility
336 * MAC binding changes, ensure to inherit duplicate flag
339 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
340 zebra_mac_t
*old_zmac
,
341 zebra_mac_t
*new_zmac
,
344 bool is_old_mac_dup
= false;
345 bool is_new_mac_dup
= false;
347 if (!zvrf
->dup_addr_detect
)
349 /* Check old or new MAC is detected as duplicate
350 * mark this neigh as duplicate
353 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
354 ZEBRA_MAC_DUPLICATE
);
356 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
357 ZEBRA_MAC_DUPLICATE
);
358 /* Old and/or new MAC can be in duplicate state,
359 * based on that IP/Neigh Inherits the flag.
360 * If New MAC is marked duplicate, inherit to the IP.
361 * If old MAC is duplicate but new MAC is not, clear
362 * duplicate flag for IP and reset detection params
363 * and let IP DAD retrigger.
365 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
366 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
367 /* Capture Duplicate detection time */
368 nbr
->dad_dup_detect_time
= monotime(NULL
);
370 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
371 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
373 nbr
->detect_start_time
.tv_sec
= 0;
374 nbr
->detect_start_time
.tv_usec
= 0;
379 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
381 struct in_addr vtep_ip
,
387 struct listnode
*node
= NULL
;
388 struct timeval elapsed
= {0, 0};
389 char buf
[ETHER_ADDR_STRLEN
];
390 char buf1
[INET6_ADDRSTRLEN
];
391 bool reset_params
= false;
393 if (!(zvrf
->dup_addr_detect
&& do_dad
))
396 /* MAC is detected as duplicate,
397 * Local MAC event -> hold on advertising to BGP.
398 * Remote MAC event -> hold on installing it.
400 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
401 if (IS_ZEBRA_DEBUG_VXLAN
)
403 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
405 prefix_mac2str(&mac
->macaddr
, buf
,
407 mac
->flags
, mac
->dad_count
,
408 zvrf
->dad_freeze_time
);
410 /* For duplicate MAC do not update
411 * client but update neigh due to
414 if (zvrf
->dad_freeze
)
415 *is_dup_detect
= true;
420 /* Check if detection time (M-secs) expired.
421 * Reset learn count and detection start time.
423 monotime_since(&mac
->detect_start_time
, &elapsed
);
424 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
425 if (is_local
&& !reset_params
) {
426 /* RFC-7432: A PE/VTEP that detects a MAC mobility
427 * event via LOCAL learning starts an M-second timer.
429 * NOTE: This is the START of the probe with count is
430 * 0 during LOCAL learn event.
431 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
433 reset_params
= !mac
->dad_count
;
437 if (IS_ZEBRA_DEBUG_VXLAN
)
439 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
440 , __PRETTY_FUNCTION__
,
441 prefix_mac2str(&mac
->macaddr
, buf
,
443 mac
->flags
, mac
->dad_count
);
446 /* Start dup. addr detection (DAD) start time,
447 * ONLY during LOCAL learn.
450 monotime(&mac
->detect_start_time
);
452 } else if (!is_local
) {
453 /* For REMOTE MAC, increment detection count
454 * ONLY while in probe window, once window passed,
455 * next local learn event should trigger DAD.
460 /* For LOCAL MAC learn event, once count is reset above via either
461 * initial/start detection time or passed the probe time, the count
462 * needs to be incremented.
467 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
468 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
469 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
471 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
472 is_local
? "local update, last" :
473 "remote update, from", inet_ntoa(vtep_ip
));
475 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
477 /* Capture Duplicate detection time */
478 mac
->dad_dup_detect_time
= monotime(NULL
);
480 /* Mark all IPs/Neighs as duplicate
481 * associcated with this MAC
483 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
485 /* Ony Mark IPs which are Local */
486 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
489 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
491 nbr
->dad_dup_detect_time
= monotime(NULL
);
493 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
494 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
496 prefix_mac2str(&mac
->macaddr
,
498 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
499 is_local
? "local" : "remote");
502 /* Start auto recovery timer for this MAC */
503 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
504 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
505 if (IS_ZEBRA_DEBUG_VXLAN
)
507 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
508 , __PRETTY_FUNCTION__
,
509 prefix_mac2str(&mac
->macaddr
, buf
,
511 mac
->flags
, zvrf
->dad_freeze_time
);
513 thread_add_timer(zebrad
.master
,
514 zebra_vxlan_dad_mac_auto_recovery_exp
,
515 mac
, zvrf
->dad_freeze_time
,
516 &mac
->dad_mac_auto_recovery_timer
);
519 /* In case of local update, do not inform to client (BGPd),
520 * upd_neigh for neigh sequence change.
522 if (zvrf
->dad_freeze
)
523 *is_dup_detect
= true;
527 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
529 struct in_addr vtep_ip
,
535 struct timeval elapsed
= {0, 0};
536 char buf
[ETHER_ADDR_STRLEN
];
537 char buf1
[INET6_ADDRSTRLEN
];
538 bool reset_params
= false;
540 if (!zvrf
->dup_addr_detect
)
543 /* IP is detected as duplicate or inherit dup
544 * state, hold on to install as remote entry
545 * only if freeze is enabled.
547 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
548 if (IS_ZEBRA_DEBUG_VXLAN
)
550 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
552 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
553 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
554 nbr
->flags
, nbr
->dad_count
,
555 zvrf
->dad_freeze_time
);
557 if (zvrf
->dad_freeze
)
558 *is_dup_detect
= true;
559 /* warn-only action, neigh will be installed.
560 * freeze action, it wil not be installed.
568 /* Check if detection time (M-secs) expired.
569 * Reset learn count and detection start time.
570 * During remote mac add, count should already be 1
571 * via local learning.
573 monotime_since(&nbr
->detect_start_time
, &elapsed
);
574 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
576 if (is_local
&& !reset_params
) {
577 /* RFC-7432: A PE/VTEP that detects a MAC mobility
578 * event via LOCAL learning starts an M-second timer.
580 * NOTE: This is the START of the probe with count is
581 * 0 during LOCAL learn event.
583 reset_params
= !nbr
->dad_count
;
587 if (IS_ZEBRA_DEBUG_VXLAN
)
589 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
591 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
592 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
593 nbr
->flags
, nbr
->dad_count
);
594 /* Reset learn count but do not start detection
595 * during REMOTE learn event.
598 /* Start dup. addr detection (DAD) start time,
599 * ONLY during LOCAL learn.
602 monotime(&nbr
->detect_start_time
);
604 } else if (!is_local
) {
605 /* For REMOTE IP/Neigh, increment detection count
606 * ONLY while in probe window, once window passed,
607 * next local learn event should trigger DAD.
612 /* For LOCAL IP/Neigh learn event, once count is reset above via either
613 * initial/start detection time or passed the probe time, the count
614 * needs to be incremented.
619 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
620 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
621 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
623 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
624 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
625 is_local
? "local update, last" :
626 "remote update, from",
629 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
631 /* Capture Duplicate detection time */
632 nbr
->dad_dup_detect_time
= monotime(NULL
);
634 /* Start auto recovery timer for this IP */
635 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
636 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
637 if (IS_ZEBRA_DEBUG_VXLAN
)
639 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
641 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
642 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
643 nbr
->flags
, zvrf
->dad_freeze_time
);
645 thread_add_timer(zebrad
.master
,
646 zebra_vxlan_dad_ip_auto_recovery_exp
,
647 nbr
, zvrf
->dad_freeze_time
,
648 &nbr
->dad_ip_auto_recovery_timer
);
650 if (zvrf
->dad_freeze
)
651 *is_dup_detect
= true;
656 * Helper function to determine maximum width of neighbor IP address for
657 * display - just because we're dealing with IPv6 addresses that can
660 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
663 char buf
[INET6_ADDRSTRLEN
];
664 struct neigh_walk_ctx
*wctx
= ctxt
;
667 n
= (zebra_neigh_t
*)backet
->data
;
669 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
671 if (width
> wctx
->addr_width
)
672 wctx
->addr_width
= width
;
677 * Print a specific neighbor entry.
679 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
682 char buf1
[ETHER_ADDR_STRLEN
];
683 char buf2
[INET6_ADDRSTRLEN
];
684 const char *type_str
;
685 const char *state_str
;
686 bool flags_present
= false;
687 struct zebra_vrf
*zvrf
= NULL
;
688 struct timeval detect_start_time
= {0, 0};
690 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
694 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
695 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
696 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
697 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
699 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
700 vty
= (struct vty
*)ctxt
;
702 vty_out(vty
, "IP: %s\n",
703 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
704 vty_out(vty
, " Type: %s\n", type_str
);
705 vty_out(vty
, " State: %s\n", state_str
);
706 vty_out(vty
, " MAC: %s\n",
707 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
709 json_object_string_add(json
, "ip", buf2
);
710 json_object_string_add(json
, "type", type_str
);
711 json_object_string_add(json
, "state", state_str
);
712 json_object_string_add(json
, "mac", buf1
);
714 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
716 vty_out(vty
, " Remote VTEP: %s\n",
717 inet_ntoa(n
->r_vtep_ip
));
719 json_object_string_add(json
, "remoteVtep",
720 inet_ntoa(n
->r_vtep_ip
));
722 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
724 vty_out(vty
, " Flags: Default-gateway");
725 flags_present
= true;
727 json_object_boolean_true_add(json
, "defaultGateway");
729 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
732 flags_present
? " ,Router" : " Flags: Router");
733 flags_present
= true;
739 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
740 n
->loc_seq
, n
->rem_seq
);
742 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
743 vty_out(vty
, " Duplicate, detected at %s",
744 time_to_string(n
->dad_dup_detect_time
));
745 } else if (n
->dad_count
) {
746 monotime_since(&n
->detect_start_time
,
748 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
749 char *buf
= time_to_string(
750 n
->detect_start_time
.tv_sec
);
753 memset(tmp_buf
, 0, 30);
754 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
756 " Duplicate detection started at %s, detection count %u\n",
757 tmp_buf
, n
->dad_count
);
761 json_object_int_add(json
, "localSequence", n
->loc_seq
);
762 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
763 json_object_int_add(json
, "detectionCount",
765 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
766 json_object_boolean_true_add(json
, "isDuplicate");
768 json_object_boolean_false_add(json
, "isDuplicate");
775 * Print neighbor hash entry - called for display of all neighbors.
777 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
780 json_object
*json_vni
= NULL
, *json_row
= NULL
;
782 char buf1
[ETHER_ADDR_STRLEN
];
783 char buf2
[INET6_ADDRSTRLEN
];
784 struct neigh_walk_ctx
*wctx
= ctxt
;
785 const char *state_str
;
788 json_vni
= wctx
->json
;
789 n
= (zebra_neigh_t
*)backet
->data
;
792 json_row
= json_object_new_object();
794 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
795 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
796 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
797 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
798 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
801 if (json_vni
== NULL
) {
802 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
803 -wctx
->addr_width
, buf2
, "local",
806 json_object_string_add(json_row
, "type", "local");
807 json_object_string_add(json_row
, "state", state_str
);
808 json_object_string_add(json_row
, "mac", buf1
);
809 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
810 json_object_boolean_true_add(
811 json_row
, "defaultGateway");
812 json_object_int_add(json_row
, "localSequence",
814 json_object_int_add(json_row
, "remoteSequence",
816 json_object_int_add(json_row
, "detectionCount",
818 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
819 json_object_boolean_true_add(json_row
,
822 json_object_boolean_false_add(json_row
,
826 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
827 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
828 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
831 if (json_vni
== NULL
) {
832 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
835 "%*s %-6s %-8s %-17s %-21s\n",
836 -wctx
->addr_width
, "Neighbor", "Type",
837 "State", "MAC", "Remote VTEP");
838 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
839 -wctx
->addr_width
, buf2
, "remote", state_str
,
840 buf1
, inet_ntoa(n
->r_vtep_ip
));
842 json_object_string_add(json_row
, "type", "remote");
843 json_object_string_add(json_row
, "state", state_str
);
844 json_object_string_add(json_row
, "mac", buf1
);
845 json_object_string_add(json_row
, "remoteVtep",
846 inet_ntoa(n
->r_vtep_ip
));
847 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
848 json_object_boolean_true_add(json_row
,
850 json_object_int_add(json_row
, "localSequence",
852 json_object_int_add(json_row
, "remoteSequence",
854 json_object_int_add(json_row
, "detectionCount",
856 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
857 json_object_boolean_true_add(json_row
,
860 json_object_boolean_false_add(json_row
,
867 json_object_object_add(json_vni
, buf2
, json_row
);
871 * Print neighbor hash entry in detail - called for display of all neighbors.
873 static void zvni_print_neigh_hash_detail(struct hash_backet
*backet
, void *ctxt
)
876 json_object
*json_vni
= NULL
, *json_row
= NULL
;
878 char buf
[INET6_ADDRSTRLEN
];
879 struct neigh_walk_ctx
*wctx
= ctxt
;
882 json_vni
= wctx
->json
;
883 n
= (zebra_neigh_t
*)backet
->data
;
887 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
889 json_row
= json_object_new_object();
891 zvni_print_neigh(n
, vty
, json_row
);
894 json_object_object_add(json_vni
, buf
, json_row
);
898 * Print neighbors for all VNI.
900 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
904 json_object
*json
= NULL
, *json_vni
= NULL
;
907 struct neigh_walk_ctx wctx
;
908 char vni_str
[VNI_STR_LEN
];
911 vty
= (struct vty
*)args
[0];
912 json
= (json_object
*)args
[1];
913 print_dup
= (uint32_t)(uintptr_t)args
[2];
915 zvni
= (zebra_vni_t
*)backet
->data
;
917 num_neigh
= hashcount(zvni
->neigh_table
);
920 num_neigh
= num_dup_detected_neighs(zvni
);
924 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
925 zvni
->vni
, num_neigh
);
927 json_vni
= json_object_new_object();
928 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
929 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
934 json_object_object_add(json
, vni_str
, json_vni
);
938 /* Since we have IPv6 addresses to deal with which can vary widely in
939 * size, we try to be a bit more elegant in display by first computing
942 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
945 wctx
.addr_width
= 15;
946 wctx
.json
= json_vni
;
947 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
950 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
951 -wctx
.addr_width
, "IP", "Type",
952 "State", "MAC", "Remote VTEP");
955 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
958 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
961 json_object_object_add(json
, vni_str
, json_vni
);
964 static void zvni_print_dad_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
968 nbr
= (zebra_neigh_t
*)backet
->data
;
972 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
973 zvni_print_neigh_hash(backet
, ctxt
);
976 static void zvni_print_dad_neigh_hash_detail(struct hash_backet
*backet
,
981 nbr
= (zebra_neigh_t
*)backet
->data
;
985 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
986 zvni_print_neigh_hash_detail(backet
, ctxt
);
990 * Print neighbors for all VNIs in detail.
992 static void zvni_print_neigh_hash_all_vni_detail(struct hash_backet
*backet
,
996 json_object
*json
= NULL
, *json_vni
= NULL
;
999 struct neigh_walk_ctx wctx
;
1000 char vni_str
[VNI_STR_LEN
];
1003 vty
= (struct vty
*)args
[0];
1004 json
= (json_object
*)args
[1];
1005 print_dup
= (uint32_t)(uintptr_t)args
[2];
1007 zvni
= (zebra_vni_t
*)backet
->data
;
1010 vty_out(vty
, "{}\n");
1013 num_neigh
= hashcount(zvni
->neigh_table
);
1015 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1020 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1021 zvni
->vni
, num_neigh
);
1023 json_vni
= json_object_new_object();
1024 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1025 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1029 json_object_object_add(json
, vni_str
, json_vni
);
1033 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1036 wctx
.addr_width
= 15;
1037 wctx
.json
= json_vni
;
1040 hash_iterate(zvni
->neigh_table
,
1041 zvni_print_dad_neigh_hash_detail
, &wctx
);
1043 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1047 json_object_object_add(json
, vni_str
, json_vni
);
1050 /* print a specific next hop for an l3vni */
1051 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1054 char buf1
[ETHER_ADDR_STRLEN
];
1055 char buf2
[INET6_ADDRSTRLEN
];
1056 json_object
*json_hosts
= NULL
;
1057 struct host_rb_entry
*hle
;
1060 vty_out(vty
, "Ip: %s\n",
1061 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1062 vty_out(vty
, " RMAC: %s\n",
1063 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1064 vty_out(vty
, " Refcount: %d\n",
1065 rb_host_count(&n
->host_rb
));
1066 vty_out(vty
, " Prefixes:\n");
1067 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1068 vty_out(vty
, " %s\n",
1069 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1071 json_hosts
= json_object_new_array();
1072 json_object_string_add(
1073 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1074 json_object_string_add(
1076 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1077 json_object_int_add(json
, "refCount",
1078 rb_host_count(&n
->host_rb
));
1079 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1080 json_object_array_add(json_hosts
,
1081 json_object_new_string(prefix2str(
1082 &hle
->p
, buf2
, sizeof(buf2
))));
1083 json_object_object_add(json
, "prefixList", json_hosts
);
1087 /* Print a specific RMAC entry */
1088 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1091 char buf1
[ETHER_ADDR_STRLEN
];
1092 char buf2
[PREFIX_STRLEN
];
1093 json_object
*json_hosts
= NULL
;
1094 struct host_rb_entry
*hle
;
1097 vty_out(vty
, "MAC: %s\n",
1098 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1099 vty_out(vty
, " Remote VTEP: %s\n",
1100 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1101 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1102 vty_out(vty
, " Prefixes:\n");
1103 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1104 vty_out(vty
, " %s\n",
1105 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1107 json_hosts
= json_object_new_array();
1108 json_object_string_add(
1110 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1111 json_object_string_add(json
, "vtepIp",
1112 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1113 json_object_int_add(json
, "refCount",
1114 rb_host_count(&zrmac
->host_rb
));
1115 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1116 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1117 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1118 json_object_array_add(
1120 json_object_new_string(prefix2str(
1121 &hle
->p
, buf2
, sizeof(buf2
))));
1122 json_object_object_add(json
, "prefixList", json_hosts
);
1127 * Print a specific MAC entry.
1129 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1132 zebra_neigh_t
*n
= NULL
;
1133 struct listnode
*node
= NULL
;
1135 char buf2
[INET6_ADDRSTRLEN
];
1136 struct zebra_vrf
*zvrf
;
1137 struct timeval detect_start_time
= {0, 0};
1139 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1141 vty
= (struct vty
*)ctxt
;
1142 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1145 json_object
*json_mac
= json_object_new_object();
1147 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1148 struct zebra_ns
*zns
;
1149 struct interface
*ifp
;
1152 ifindex
= mac
->fwd_info
.local
.ifindex
;
1153 zns
= zebra_ns_lookup(NS_DEFAULT
);
1154 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1157 json_object_string_add(json_mac
, "type", "local");
1158 json_object_string_add(json_mac
, "intf", ifp
->name
);
1159 json_object_int_add(json_mac
, "ifindex", ifindex
);
1160 if (mac
->fwd_info
.local
.vid
)
1161 json_object_int_add(json_mac
, "vlan",
1162 mac
->fwd_info
.local
.vid
);
1163 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1164 json_object_string_add(json_mac
, "type", "remote");
1165 json_object_string_add(
1166 json_mac
, "remoteVtep",
1167 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1168 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1169 json_object_string_add(json_mac
, "type", "auto");
1171 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1172 json_object_boolean_true_add(json_mac
, "stickyMac");
1174 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1175 json_object_boolean_true_add(json_mac
,
1178 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1179 json_object_boolean_true_add(json_mac
,
1180 "remoteGatewayMac");
1182 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1183 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1185 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1186 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1187 json_object_boolean_true_add(json_mac
, "isDuplicate");
1189 json_object_boolean_false_add(json_mac
, "isDuplicate");
1191 /* print all the associated neigh */
1192 if (!listcount(mac
->neigh_list
))
1193 json_object_string_add(json_mac
, "neighbors", "none");
1195 json_object
*json_active_nbrs
= json_object_new_array();
1196 json_object
*json_inactive_nbrs
=
1197 json_object_new_array();
1198 json_object
*json_nbrs
= json_object_new_object();
1200 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1201 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1202 json_object_array_add(
1204 json_object_new_string(
1209 json_object_array_add(
1211 json_object_new_string(
1217 json_object_object_add(json_nbrs
, "active",
1219 json_object_object_add(json_nbrs
, "inactive",
1220 json_inactive_nbrs
);
1221 json_object_object_add(json_mac
, "neighbors",
1225 json_object_object_add(json
, buf1
, json_mac
);
1227 vty_out(vty
, "MAC: %s\n", buf1
);
1229 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1230 struct zebra_ns
*zns
;
1231 struct interface
*ifp
;
1234 ifindex
= mac
->fwd_info
.local
.ifindex
;
1235 zns
= zebra_ns_lookup(NS_DEFAULT
);
1236 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1239 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1240 if (mac
->fwd_info
.local
.vid
)
1241 vty_out(vty
, " VLAN: %u",
1242 mac
->fwd_info
.local
.vid
);
1243 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1244 vty_out(vty
, " Remote VTEP: %s",
1245 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1246 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1247 vty_out(vty
, " Auto Mac ");
1250 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1251 vty_out(vty
, " Sticky Mac ");
1253 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1254 vty_out(vty
, " Default-gateway Mac ");
1256 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1257 vty_out(vty
, " Remote-gateway Mac ");
1260 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1264 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1265 vty_out(vty
, " Duplicate, detected at %s",
1266 time_to_string(mac
->dad_dup_detect_time
));
1267 } else if (mac
->dad_count
) {
1268 monotime_since(&mac
->detect_start_time
,
1269 &detect_start_time
);
1270 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1271 char *buf
= time_to_string(
1272 mac
->detect_start_time
.tv_sec
);
1275 memset(tmp_buf
, 0, 30);
1276 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
1278 " Duplicate detection started at %s, detection count %u\n",
1279 tmp_buf
, mac
->dad_count
);
1283 /* print all the associated neigh */
1284 vty_out(vty
, " Neighbors:\n");
1285 if (!listcount(mac
->neigh_list
))
1286 vty_out(vty
, " No Neighbors\n");
1288 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1289 vty_out(vty
, " %s %s\n",
1290 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1291 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1302 * Print MAC hash entry - called for display of all MACs.
1304 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1307 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1310 struct mac_walk_ctx
*wctx
= ctxt
;
1313 json_mac_hdr
= wctx
->json
;
1314 mac
= (zebra_mac_t
*)backet
->data
;
1316 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1319 json_mac
= json_object_new_object();
1321 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1322 struct zebra_ns
*zns
;
1324 struct interface
*ifp
;
1327 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1330 zns
= zebra_ns_lookup(NS_DEFAULT
);
1331 ifindex
= mac
->fwd_info
.local
.ifindex
;
1332 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1333 if (!ifp
) // unexpected
1335 vid
= mac
->fwd_info
.local
.vid
;
1336 if (json_mac_hdr
== NULL
)
1337 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1340 json_object_string_add(json_mac
, "type", "local");
1341 json_object_string_add(json_mac
, "intf", ifp
->name
);
1344 if (json_mac_hdr
== NULL
)
1345 vty_out(vty
, " %-5u", vid
);
1347 json_object_int_add(json_mac
, "vlan", vid
);
1349 if (json_mac_hdr
== NULL
) {
1352 json_object_int_add(json_mac
, "localSequence",
1354 json_object_int_add(json_mac
, "remoteSequence",
1356 json_object_int_add(json_mac
, "detectionCount",
1358 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1359 json_object_boolean_true_add(json_mac
,
1362 json_object_boolean_false_add(json_mac
,
1364 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1369 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1371 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1372 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1376 if (json_mac_hdr
== NULL
) {
1377 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1378 (wctx
->count
== 0)) {
1379 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1380 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1381 "Type", "Intf/Remote VTEP", "VLAN");
1383 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1384 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1386 json_object_string_add(json_mac
, "type", "remote");
1387 json_object_string_add(json_mac
, "remoteVtep",
1388 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1389 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1390 json_object_int_add(json_mac
, "localSequence",
1392 json_object_int_add(json_mac
, "remoteSequence",
1394 json_object_int_add(json_mac
, "detectionCount",
1396 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1397 json_object_boolean_true_add(json_mac
,
1400 json_object_boolean_false_add(json_mac
,
1409 /* Print Duplicate MAC */
1410 static void zvni_print_dad_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1414 mac
= (zebra_mac_t
*)backet
->data
;
1418 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1419 zvni_print_mac_hash(backet
, ctxt
);
1423 * Print MAC hash entry in detail - called for display of all MACs.
1425 static void zvni_print_mac_hash_detail(struct hash_backet
*backet
, void *ctxt
)
1428 json_object
*json_mac_hdr
= NULL
;
1430 struct mac_walk_ctx
*wctx
= ctxt
;
1434 json_mac_hdr
= wctx
->json
;
1435 mac
= (zebra_mac_t
*)backet
->data
;
1440 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1442 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1445 /* Print Duplicate MAC in detail */
1446 static void zvni_print_dad_mac_hash_detail(struct hash_backet
*backet
,
1451 mac
= (zebra_mac_t
*)backet
->data
;
1455 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1456 zvni_print_mac_hash_detail(backet
, ctxt
);
1460 * Print MACs for all VNI.
1462 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
1465 json_object
*json
= NULL
, *json_vni
= NULL
;
1466 json_object
*json_mac
= NULL
;
1469 struct mac_walk_ctx
*wctx
= ctxt
;
1470 char vni_str
[VNI_STR_LEN
];
1472 vty
= (struct vty
*)wctx
->vty
;
1473 json
= (struct json_object
*)wctx
->json
;
1475 zvni
= (zebra_vni_t
*)backet
->data
;
1478 /*We are iterating over a new VNI, set the count to 0*/
1481 num_macs
= num_valid_macs(zvni
);
1485 if (wctx
->print_dup
)
1486 num_macs
= num_dup_detected_macs(zvni
);
1489 json_vni
= json_object_new_object();
1490 json_mac
= json_object_new_object();
1491 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1494 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1496 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1497 zvni
->vni
, num_macs
);
1498 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1499 "Intf/Remote VTEP", "VLAN");
1501 json_object_int_add(json_vni
, "numMacs", num_macs
);
1506 json_object_int_add(json_vni
, "numMacs", num_macs
);
1507 json_object_object_add(json
, vni_str
, json_vni
);
1512 /* assign per-vni to wctx->json object to fill macs
1513 * under the vni. Re-assign primary json object to fill
1514 * next vni information.
1516 wctx
->json
= json_mac
;
1517 if (wctx
->print_dup
)
1518 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1520 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1524 json_object_object_add(json_vni
, "macs", json_mac
);
1525 json_object_object_add(json
, vni_str
, json_vni
);
1530 * Print MACs in detail for all VNI.
1532 static void zvni_print_mac_hash_all_vni_detail(struct hash_backet
*backet
,
1536 json_object
*json
= NULL
, *json_vni
= NULL
;
1537 json_object
*json_mac
= NULL
;
1540 struct mac_walk_ctx
*wctx
= ctxt
;
1541 char vni_str
[VNI_STR_LEN
];
1543 vty
= (struct vty
*)wctx
->vty
;
1544 json
= (struct json_object
*)wctx
->json
;
1546 zvni
= (zebra_vni_t
*)backet
->data
;
1549 vty_out(vty
, "{}\n");
1554 /*We are iterating over a new VNI, set the count to 0*/
1557 num_macs
= num_valid_macs(zvni
);
1561 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1565 json_vni
= json_object_new_object();
1566 json_mac
= json_object_new_object();
1567 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1570 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1572 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1573 zvni
->vni
, num_macs
);
1575 json_object_int_add(json_vni
, "numMacs", num_macs
);
1577 /* assign per-vni to wctx->json object to fill macs
1578 * under the vni. Re-assign primary json object to fill
1579 * next vni information.
1581 wctx
->json
= json_mac
;
1582 if (wctx
->print_dup
)
1583 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1586 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1590 json_object_object_add(json_vni
, "macs", json_mac
);
1591 json_object_object_add(json
, vni_str
, json_vni
);
1595 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
1597 struct nh_walk_ctx
*wctx
= NULL
;
1598 struct vty
*vty
= NULL
;
1599 struct json_object
*json_vni
= NULL
;
1600 struct json_object
*json_nh
= NULL
;
1601 zebra_neigh_t
*n
= NULL
;
1602 char buf1
[ETHER_ADDR_STRLEN
];
1603 char buf2
[INET6_ADDRSTRLEN
];
1605 wctx
= (struct nh_walk_ctx
*)ctx
;
1607 json_vni
= wctx
->json
;
1609 json_nh
= json_object_new_object();
1610 n
= (zebra_neigh_t
*)backet
->data
;
1613 vty_out(vty
, "%-15s %-17s\n",
1614 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1615 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1617 json_object_string_add(json_nh
, "nexthopIp",
1618 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1619 json_object_string_add(
1620 json_nh
, "routerMac",
1621 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1622 json_object_object_add(json_vni
,
1623 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1628 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
1631 struct vty
*vty
= NULL
;
1632 json_object
*json
= NULL
;
1633 json_object
*json_vni
= NULL
;
1634 zebra_l3vni_t
*zl3vni
= NULL
;
1635 uint32_t num_nh
= 0;
1636 struct nh_walk_ctx wctx
;
1637 char vni_str
[VNI_STR_LEN
];
1639 vty
= (struct vty
*)args
[0];
1640 json
= (struct json_object
*)args
[1];
1642 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1644 num_nh
= hashcount(zl3vni
->nh_table
);
1649 json_vni
= json_object_new_object();
1650 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1654 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1655 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1657 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1659 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1661 wctx
.json
= json_vni
;
1662 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1664 json_object_object_add(json
, vni_str
, json_vni
);
1667 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
1670 struct vty
*vty
= NULL
;
1671 json_object
*json
= NULL
;
1672 json_object
*json_vni
= NULL
;
1673 zebra_l3vni_t
*zl3vni
= NULL
;
1675 struct rmac_walk_ctx wctx
;
1676 char vni_str
[VNI_STR_LEN
];
1678 vty
= (struct vty
*)args
[0];
1679 json
= (struct json_object
*)args
[1];
1681 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1683 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1688 json_vni
= json_object_new_object();
1689 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1693 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1694 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1696 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1698 /* assign per-vni to wctx->json object to fill macs
1699 * under the vni. Re-assign primary json object to fill
1700 * next vni information.
1702 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1704 wctx
.json
= json_vni
;
1705 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1707 json_object_object_add(json
, vni_str
, json_vni
);
1710 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
1712 zebra_mac_t
*zrmac
= NULL
;
1713 struct rmac_walk_ctx
*wctx
= NULL
;
1714 struct vty
*vty
= NULL
;
1715 struct json_object
*json
= NULL
;
1716 struct json_object
*json_rmac
= NULL
;
1717 char buf
[ETHER_ADDR_STRLEN
];
1719 wctx
= (struct rmac_walk_ctx
*)ctx
;
1723 json_rmac
= json_object_new_object();
1724 zrmac
= (zebra_mac_t
*)backet
->data
;
1727 vty_out(vty
, "%-17s %-21s\n",
1728 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1729 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1731 json_object_string_add(
1732 json_rmac
, "routerMac",
1733 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1734 json_object_string_add(json_rmac
, "vtepIp",
1735 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1736 json_object_object_add(
1737 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1742 /* print a specific L3 VNI entry */
1743 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1745 char buf
[ETHER_ADDR_STRLEN
];
1746 struct vty
*vty
= NULL
;
1747 json_object
*json
= NULL
;
1748 zebra_vni_t
*zvni
= NULL
;
1749 json_object
*json_vni_list
= NULL
;
1750 struct listnode
*node
= NULL
, *nnode
= NULL
;
1756 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1757 vty_out(vty
, " Type: %s\n", "L3");
1758 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1759 vty_out(vty
, " Local Vtep Ip: %s\n",
1760 inet_ntoa(zl3vni
->local_vtep_ip
));
1761 vty_out(vty
, " Vxlan-Intf: %s\n",
1762 zl3vni_vxlan_if_name(zl3vni
));
1763 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1764 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1765 vty_out(vty
, " VNI Filter: %s\n",
1766 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1767 ? "prefix-routes-only"
1769 vty_out(vty
, " Router MAC: %s\n",
1770 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1771 vty_out(vty
, " L2 VNIs: ");
1772 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1773 vty_out(vty
, "%u ", zvni
->vni
);
1776 json_vni_list
= json_object_new_array();
1777 json_object_int_add(json
, "vni", zl3vni
->vni
);
1778 json_object_string_add(json
, "type", "L3");
1779 json_object_string_add(json
, "localVtepIp",
1780 inet_ntoa(zl3vni
->local_vtep_ip
));
1781 json_object_string_add(json
, "vxlanIntf",
1782 zl3vni_vxlan_if_name(zl3vni
));
1783 json_object_string_add(json
, "sviIntf",
1784 zl3vni_svi_if_name(zl3vni
));
1785 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1786 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1787 json_object_string_add(
1789 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1790 json_object_string_add(
1792 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1793 ? "prefix-routes-only"
1795 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1796 json_object_array_add(json_vni_list
,
1797 json_object_new_int(zvni
->vni
));
1799 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1804 * Print a specific VNI entry.
1806 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1809 zebra_vtep_t
*zvtep
;
1812 json_object
*json
= NULL
;
1813 json_object
*json_vtep_list
= NULL
;
1814 json_object
*json_ip_str
= NULL
;
1820 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1821 vty_out(vty
, " Type: %s\n", "L2");
1822 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1824 json_object_int_add(json
, "vni", zvni
->vni
);
1825 json_object_string_add(json
, "type", "L2");
1826 json_object_string_add(json
, "vrf",
1827 vrf_id_to_name(zvni
->vrf_id
));
1830 if (!zvni
->vxlan_if
) { // unexpected
1832 vty_out(vty
, " VxLAN interface: unknown\n");
1835 num_macs
= num_valid_macs(zvni
);
1836 num_neigh
= hashcount(zvni
->neigh_table
);
1838 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1839 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1840 vty_out(vty
, " Local VTEP IP: %s\n",
1841 inet_ntoa(zvni
->local_vtep_ip
));
1843 json_object_string_add(json
, "vxlanInterface",
1844 zvni
->vxlan_if
->name
);
1845 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1846 json_object_string_add(json
, "vtepIp",
1847 inet_ntoa(zvni
->local_vtep_ip
));
1848 json_object_string_add(json
, "advertiseGatewayMacip",
1849 zvni
->advertise_gw_macip
? "Yes" : "No");
1850 json_object_int_add(json
, "numMacs", num_macs
);
1851 json_object_int_add(json
, "numArpNd", num_neigh
);
1855 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1858 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1860 json_vtep_list
= json_object_new_array();
1861 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1863 vty_out(vty
, " %s\n",
1864 inet_ntoa(zvtep
->vtep_ip
));
1866 json_ip_str
= json_object_new_string(
1867 inet_ntoa(zvtep
->vtep_ip
));
1868 json_object_array_add(json_vtep_list
,
1873 json_object_object_add(json
, "numRemoteVteps",
1878 " Number of MACs (local and remote) known for this VNI: %u\n",
1881 " Number of ARPs (IPv4 and IPv6, local and remote) "
1882 "known for this VNI: %u\n",
1884 vty_out(vty
, " Advertise-gw-macip: %s\n",
1885 zvni
->advertise_gw_macip
? "Yes" : "No");
1889 /* print a L3 VNI hash entry */
1890 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1892 struct vty
*vty
= NULL
;
1893 json_object
*json
= NULL
;
1894 json_object
*json_vni
= NULL
;
1895 zebra_l3vni_t
*zl3vni
= NULL
;
1897 vty
= (struct vty
*)ctx
[0];
1898 json
= (json_object
*)ctx
[1];
1900 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1903 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1904 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1905 hashcount(zl3vni
->rmac_table
),
1906 hashcount(zl3vni
->nh_table
), "n/a",
1907 zl3vni_vrf_name(zl3vni
));
1909 char vni_str
[VNI_STR_LEN
];
1911 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1912 json_vni
= json_object_new_object();
1913 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1914 json_object_string_add(json_vni
, "vxlanIf",
1915 zl3vni_vxlan_if_name(zl3vni
));
1916 json_object_int_add(json_vni
, "numMacs",
1917 hashcount(zl3vni
->rmac_table
));
1918 json_object_int_add(json_vni
, "numArpNd",
1919 hashcount(zl3vni
->nh_table
));
1920 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1921 json_object_string_add(json_vni
, "type", "L3");
1922 json_object_string_add(json_vni
, "tenantVrf",
1923 zl3vni_vrf_name(zl3vni
));
1924 json_object_object_add(json
, vni_str
, json_vni
);
1928 /* Private Structure to pass callback data for hash iterator */
1929 struct zvni_evpn_show
{
1932 struct zebra_vrf
*zvrf
;
1935 /* print a L3 VNI hash entry in detail*/
1936 static void zl3vni_print_hash_detail(struct hash_backet
*backet
, void *data
)
1938 struct vty
*vty
= NULL
;
1939 zebra_l3vni_t
*zl3vni
= NULL
;
1940 json_object
*json
= NULL
;
1941 bool use_json
= false;
1942 struct zvni_evpn_show
*zes
= data
;
1950 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1952 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1958 * Print a VNI hash entry - called for display of all VNIs.
1960 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1964 zebra_vtep_t
*zvtep
;
1965 uint32_t num_vteps
= 0;
1966 uint32_t num_macs
= 0;
1967 uint32_t num_neigh
= 0;
1968 json_object
*json
= NULL
;
1969 json_object
*json_vni
= NULL
;
1970 json_object
*json_ip_str
= NULL
;
1971 json_object
*json_vtep_list
= NULL
;
1976 zvni
= (zebra_vni_t
*)backet
->data
;
1978 zvtep
= zvni
->vteps
;
1981 zvtep
= zvtep
->next
;
1984 num_macs
= num_valid_macs(zvni
);
1985 num_neigh
= hashcount(zvni
->neigh_table
);
1987 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1989 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1990 num_macs
, num_neigh
, num_vteps
,
1991 vrf_id_to_name(zvni
->vrf_id
));
1993 char vni_str
[VNI_STR_LEN
];
1994 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1995 json_vni
= json_object_new_object();
1996 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1997 json_object_string_add(json_vni
, "type", "L2");
1998 json_object_string_add(json_vni
, "vxlanIf",
1999 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2001 json_object_int_add(json_vni
, "numMacs", num_macs
);
2002 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2003 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2004 json_object_string_add(json_vni
, "tenantVrf",
2005 vrf_id_to_name(zvni
->vrf_id
));
2007 json_vtep_list
= json_object_new_array();
2008 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2009 json_ip_str
= json_object_new_string(
2010 inet_ntoa(zvtep
->vtep_ip
));
2011 json_object_array_add(json_vtep_list
,
2014 json_object_object_add(json_vni
, "remoteVteps",
2017 json_object_object_add(json
, vni_str
, json_vni
);
2022 * Print a VNI hash entry in detail - called for display of all VNIs.
2024 static void zvni_print_hash_detail(struct hash_backet
*backet
, void *data
)
2028 json_object
*json
= NULL
;
2029 bool use_json
= false;
2030 struct zvni_evpn_show
*zes
= data
;
2038 zvni
= (zebra_vni_t
*)backet
->data
;
2040 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2045 * Inform BGP about local MACIP.
2047 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2048 struct ipaddr
*ip
, uint8_t flags
,
2049 uint32_t seq
, int state
, uint16_t cmd
)
2051 char buf
[ETHER_ADDR_STRLEN
];
2052 char buf2
[INET6_ADDRSTRLEN
];
2054 struct zserv
*client
= NULL
;
2055 struct stream
*s
= NULL
;
2057 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2058 /* BGP may not be running. */
2062 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2064 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
2065 stream_putl(s
, vni
);
2066 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2069 if (IS_IPADDR_V4(ip
))
2070 ipa_len
= IPV4_MAX_BYTELEN
;
2071 else if (IS_IPADDR_V6(ip
))
2072 ipa_len
= IPV6_MAX_BYTELEN
;
2074 stream_putl(s
, ipa_len
); /* IP address length */
2076 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2078 stream_putl(s
, 0); /* Just MAC. */
2080 if (cmd
== ZEBRA_MACIP_ADD
) {
2081 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2082 stream_putl(s
, seq
); /* sequence number */
2084 stream_putl(s
, state
); /* state - active/inactive */
2088 /* Write packet size. */
2089 stream_putw_at(s
, 0, stream_get_endp(s
));
2091 if (IS_ZEBRA_DEBUG_VXLAN
)
2093 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2094 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2095 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2096 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2097 zebra_route_string(client
->proto
));
2099 if (cmd
== ZEBRA_MACIP_ADD
)
2100 client
->macipadd_cnt
++;
2102 client
->macipdel_cnt
++;
2104 return zserv_send_message(client
, s
);
2108 * Make hash key for neighbors.
2110 static unsigned int neigh_hash_keymake(void *p
)
2112 zebra_neigh_t
*n
= p
;
2113 struct ipaddr
*ip
= &n
->ip
;
2115 if (IS_IPADDR_V4(ip
))
2116 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2118 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2119 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2123 * Compare two neighbor hash structures.
2125 static bool neigh_cmp(const void *p1
, const void *p2
)
2127 const zebra_neigh_t
*n1
= p1
;
2128 const zebra_neigh_t
*n2
= p2
;
2130 if (n1
== NULL
&& n2
== NULL
)
2133 if (n1
== NULL
|| n2
== NULL
)
2136 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2139 static int neigh_list_cmp(void *p1
, void *p2
)
2141 const zebra_neigh_t
*n1
= p1
;
2142 const zebra_neigh_t
*n2
= p2
;
2144 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2148 * Callback to allocate neighbor hash entry.
2150 static void *zvni_neigh_alloc(void *p
)
2152 const zebra_neigh_t
*tmp_n
= p
;
2155 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2162 * Add neighbor entry.
2164 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2165 struct ethaddr
*mac
)
2167 zebra_neigh_t tmp_n
;
2168 zebra_neigh_t
*n
= NULL
;
2169 zebra_mac_t
*zmac
= NULL
;
2171 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2172 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2173 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2176 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2177 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2179 /* Associate the neigh to mac */
2180 zmac
= zvni_mac_lookup(zvni
, mac
);
2182 listnode_add_sort(zmac
->neigh_list
, n
);
2188 * Delete neighbor entry.
2190 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2192 zebra_neigh_t
*tmp_n
;
2193 zebra_mac_t
*zmac
= NULL
;
2195 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2197 listnode_delete(zmac
->neigh_list
, n
);
2199 /* Free the VNI hash entry and allocated memory. */
2200 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2202 XFREE(MTYPE_NEIGH
, tmp_n
);
2208 * Free neighbor hash entry (callback)
2210 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2212 struct neigh_walk_ctx
*wctx
= arg
;
2213 zebra_neigh_t
*n
= backet
->data
;
2215 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2216 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2217 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2218 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2219 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2220 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2221 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2222 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2223 &n
->emac
, 0, n
->state
);
2225 if (wctx
->uninstall
)
2226 zvni_neigh_uninstall(wctx
->zvni
, n
);
2228 zvni_neigh_del(wctx
->zvni
, n
);
2235 * Delete all neighbor entries from specific VTEP for a particular VNI.
2237 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2238 struct in_addr
*r_vtep_ip
)
2240 struct neigh_walk_ctx wctx
;
2242 if (!zvni
->neigh_table
)
2245 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2247 wctx
.uninstall
= uninstall
;
2248 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2249 wctx
.r_vtep_ip
= *r_vtep_ip
;
2251 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2255 * Delete all neighbor entries for this VNI.
2257 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2260 struct neigh_walk_ctx wctx
;
2262 if (!zvni
->neigh_table
)
2265 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2267 wctx
.uninstall
= uninstall
;
2268 wctx
.upd_client
= upd_client
;
2271 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2275 * Look up neighbor hash entry.
2277 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2282 memset(&tmp
, 0, sizeof(tmp
));
2283 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2284 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2290 * Process all neighbors associated with a MAC upon the MAC being learnt
2291 * locally or undergoing any other change (such as sequence number).
2293 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2297 zebra_neigh_t
*n
= NULL
;
2298 struct listnode
*node
= NULL
;
2299 struct zebra_vrf
*zvrf
= NULL
;
2300 char buf
[ETHER_ADDR_STRLEN
];
2302 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2304 if (IS_ZEBRA_DEBUG_VXLAN
)
2305 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2306 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2307 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2309 /* Walk all neighbors and mark any inactive local neighbors as
2310 * active and/or update sequence number upon a move, and inform BGP.
2311 * The action for remote neighbors is TBD.
2312 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2313 * accidentally end up deleting a just-learnt local neighbor.
2315 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2316 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2317 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2318 ZEBRA_NEIGH_SET_ACTIVE(n
);
2319 n
->loc_seq
= zmac
->loc_seq
;
2320 if (!(zvrf
->dup_addr_detect
&&
2321 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2322 ZEBRA_NEIGH_DUPLICATE
)))
2323 zvni_neigh_send_add_to_client(
2324 zvni
->vni
, &n
->ip
, &n
->emac
,
2325 n
->flags
, n
->loc_seq
);
2332 * Process all neighbors associated with a local MAC upon the MAC being
2335 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2338 zebra_neigh_t
*n
= NULL
;
2339 struct listnode
*node
= NULL
;
2340 char buf
[ETHER_ADDR_STRLEN
];
2342 if (IS_ZEBRA_DEBUG_VXLAN
)
2343 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2344 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2347 /* Walk all local neighbors and mark as inactive and inform
2349 * TBD: There is currently no handling for remote neighbors. We
2350 * don't expect them to exist, if they do, do we install the MAC
2351 * as a remote MAC and the neighbor as remote?
2353 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2354 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2355 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2356 ZEBRA_NEIGH_SET_INACTIVE(n
);
2358 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2359 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2366 * Process all neighbors associated with a MAC upon the MAC being remotely
2369 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2372 zebra_neigh_t
*n
= NULL
;
2373 struct listnode
*node
= NULL
;
2374 char buf
[ETHER_ADDR_STRLEN
];
2376 if (IS_ZEBRA_DEBUG_VXLAN
)
2377 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2378 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2381 /* Walk all local neighbors and mark as inactive and inform
2384 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2385 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2386 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2387 ZEBRA_NEIGH_SET_INACTIVE(n
);
2389 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2390 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2397 * Process all neighbors associated with a remote MAC upon the MAC being
2400 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2403 /* NOTE: Currently a NO-OP. */
2407 * Inform BGP about local neighbor addition.
2409 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2410 struct ethaddr
*macaddr
,
2411 uint8_t neigh_flags
,
2416 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2417 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2418 /* Set router flag (R-bit) based on local neigh entry add */
2419 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2420 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2422 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2423 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2427 * Inform BGP about local neighbor deletion.
2429 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2430 struct ethaddr
*macaddr
, uint8_t flags
,
2433 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2434 0, state
, ZEBRA_MACIP_DEL
);
2438 * Install remote neighbor into the kernel.
2440 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2442 struct zebra_if
*zif
;
2443 struct zebra_l2info_vxlan
*vxl
;
2444 struct interface
*vlan_if
;
2450 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2453 zif
= zvni
->vxlan_if
->info
;
2456 vxl
= &zif
->l2info
.vxl
;
2458 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2462 flags
= NTF_EXT_LEARNED
;
2463 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2464 flags
|= NTF_ROUTER
;
2465 ZEBRA_NEIGH_SET_ACTIVE(n
);
2466 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2472 * Uninstall remote neighbor from the kernel.
2474 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2476 struct zebra_if
*zif
;
2477 struct zebra_l2info_vxlan
*vxl
;
2478 struct interface
*vlan_if
;
2480 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2483 if (!zvni
->vxlan_if
) {
2484 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2489 zif
= zvni
->vxlan_if
->info
;
2492 vxl
= &zif
->l2info
.vxl
;
2493 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2497 ZEBRA_NEIGH_SET_INACTIVE(n
);
2499 return kernel_del_neigh(vlan_if
, &n
->ip
);
2503 * Install neighbor hash entry - called upon access VLAN change.
2505 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
2508 struct neigh_walk_ctx
*wctx
= ctxt
;
2510 n
= (zebra_neigh_t
*)backet
->data
;
2512 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2513 zvni_neigh_install(wctx
->zvni
, n
);
2516 /* Get the VRR interface for SVI if any */
2517 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2519 struct zebra_vrf
*zvrf
= NULL
;
2520 struct interface
*tmp_if
= NULL
;
2521 struct zebra_if
*zif
= NULL
;
2523 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2526 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2531 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2534 if (zif
->link
== ifp
)
2541 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2543 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2544 struct connected
*c
= NULL
;
2545 struct ethaddr macaddr
;
2547 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2549 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2552 memset(&ip
, 0, sizeof(struct ipaddr
));
2553 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2556 if (c
->address
->family
== AF_INET
) {
2557 ip
.ipa_type
= IPADDR_V4
;
2558 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2559 sizeof(struct in_addr
));
2560 } else if (c
->address
->family
== AF_INET6
) {
2561 ip
.ipa_type
= IPADDR_V6
;
2562 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2563 sizeof(struct in6_addr
));
2568 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2574 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2576 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2577 struct connected
*c
= NULL
;
2578 struct ethaddr macaddr
;
2580 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2582 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2585 memset(&ip
, 0, sizeof(struct ipaddr
));
2586 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2589 if (c
->address
->family
== AF_INET
) {
2590 ip
.ipa_type
= IPADDR_V4
;
2591 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2592 sizeof(struct in_addr
));
2593 } else if (c
->address
->family
== AF_INET6
) {
2594 ip
.ipa_type
= IPADDR_V6
;
2595 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2596 sizeof(struct in6_addr
));
2601 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2607 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2610 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2611 struct connected
*c
= NULL
;
2612 struct ethaddr macaddr
;
2614 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2616 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2619 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2621 /* skip link local address */
2622 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2627 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2628 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2630 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2631 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2637 * zvni_gw_macip_add_to_client
2639 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2640 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2642 char buf
[ETHER_ADDR_STRLEN
];
2643 char buf2
[INET6_ADDRSTRLEN
];
2644 zebra_neigh_t
*n
= NULL
;
2645 zebra_mac_t
*mac
= NULL
;
2646 struct zebra_if
*zif
= NULL
;
2647 struct zebra_l2info_vxlan
*vxl
= NULL
;
2649 zif
= zvni
->vxlan_if
->info
;
2653 vxl
= &zif
->l2info
.vxl
;
2655 mac
= zvni_mac_lookup(zvni
, macaddr
);
2657 mac
= zvni_mac_add(zvni
, macaddr
);
2659 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2660 "Failed to add MAC %s intf %s(%u) VID %u",
2661 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2662 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2667 /* Set "local" forwarding info. */
2668 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2669 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2670 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2671 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2672 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2673 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2675 n
= zvni_neigh_lookup(zvni
, ip
);
2677 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2680 EC_ZEBRA_MAC_ADD_FAILED
,
2681 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2682 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2683 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2684 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2689 /* Set "local" forwarding info. */
2690 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2691 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2692 ZEBRA_NEIGH_SET_ACTIVE(n
);
2693 /* Set Router flag (R-bit) */
2694 if (ip
->ipa_type
== IPADDR_V6
)
2695 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2696 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2697 n
->ifindex
= ifp
->ifindex
;
2699 /* Only advertise in BGP if the knob is enabled */
2700 if (!advertise_gw_macip_enabled(zvni
))
2703 if (IS_ZEBRA_DEBUG_VXLAN
)
2705 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2706 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2707 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2708 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2710 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2711 n
->flags
, n
->loc_seq
);
2717 * zvni_gw_macip_del_from_client
2719 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2722 char buf1
[ETHER_ADDR_STRLEN
];
2723 char buf2
[INET6_ADDRSTRLEN
];
2724 zebra_neigh_t
*n
= NULL
;
2725 zebra_mac_t
*mac
= NULL
;
2727 /* If the neigh entry is not present nothing to do*/
2728 n
= zvni_neigh_lookup(zvni
, ip
);
2732 /* mac entry should be present */
2733 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2735 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2736 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2737 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2741 /* If the entry is not local nothing to do*/
2742 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2745 /* only need to delete the entry from bgp if we sent it before */
2746 if (IS_ZEBRA_DEBUG_VXLAN
)
2748 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2749 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2750 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2751 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2753 /* Remove neighbor from BGP. */
2754 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2755 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2757 /* Delete this neighbor entry. */
2758 zvni_neigh_del(zvni
, n
);
2760 /* see if the mac needs to be deleted as well*/
2762 zvni_deref_ip2mac(zvni
, mac
);
2767 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
2770 zebra_vni_t
*zvni
= NULL
;
2771 struct zebra_if
*zif
= NULL
;
2772 struct zebra_l2info_vxlan zl2_info
;
2773 struct interface
*vlan_if
= NULL
;
2774 struct interface
*vrr_if
= NULL
;
2775 struct interface
*ifp
;
2777 /* Add primary SVI MAC*/
2778 zvni
= (zebra_vni_t
*)backet
->data
;
2780 ifp
= zvni
->vxlan_if
;
2785 /* If down or not mapped to a bridge, we're done. */
2786 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2789 zl2_info
= zif
->l2info
.vxl
;
2792 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2796 /* Del primary MAC-IP */
2797 zvni_del_macip_for_intf(vlan_if
, zvni
);
2799 /* Del VRR MAC-IP - if any*/
2800 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2802 zvni_del_macip_for_intf(vrr_if
, zvni
);
2807 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2810 zebra_vni_t
*zvni
= NULL
;
2811 struct zebra_if
*zif
= NULL
;
2812 struct zebra_l2info_vxlan zl2_info
;
2813 struct interface
*vlan_if
= NULL
;
2814 struct interface
*vrr_if
= NULL
;
2815 struct interface
*ifp
= NULL
;
2817 zvni
= (zebra_vni_t
*)backet
->data
;
2819 ifp
= zvni
->vxlan_if
;
2824 /* If down or not mapped to a bridge, we're done. */
2825 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2827 zl2_info
= zif
->l2info
.vxl
;
2830 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2834 /* Add primary SVI MAC-IP */
2835 zvni_add_macip_for_intf(vlan_if
, zvni
);
2837 /* Add VRR MAC-IP - if any*/
2838 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2840 zvni_add_macip_for_intf(vrr_if
, zvni
);
2845 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2846 struct interface
*ifp
,
2848 struct ethaddr
*macaddr
,
2851 char buf
[ETHER_ADDR_STRLEN
];
2852 char buf2
[INET6_ADDRSTRLEN
];
2853 struct zebra_vrf
*zvrf
;
2854 zebra_neigh_t
*n
= NULL
;
2855 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2856 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2857 bool upd_mac_seq
= false;
2858 bool neigh_mac_change
= false;
2859 bool neigh_on_hold
= false;
2860 bool neigh_was_remote
= false;
2861 bool do_dad
= false;
2862 struct in_addr vtep_ip
= {.s_addr
= 0};
2864 /* Check if the MAC exists. */
2865 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2867 /* create a dummy MAC if the MAC is not already present */
2868 if (IS_ZEBRA_DEBUG_VXLAN
)
2870 "AUTO MAC %s created for neigh %s on VNI %u",
2871 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2872 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2874 zmac
= zvni_mac_add(zvni
, macaddr
);
2876 zlog_debug("Failed to add MAC %s VNI %u",
2877 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2882 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2883 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2884 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2886 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2888 * We don't change the MAC to local upon a neighbor
2889 * learn event, we wait for the explicit local MAC
2890 * learn. However, we have to compute its sequence
2891 * number in preparation for when it actually turns
2898 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2902 /* Check if the neighbor exists. */
2903 n
= zvni_neigh_lookup(zvni
, ip
);
2905 /* New neighbor - create */
2906 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2909 EC_ZEBRA_MAC_ADD_FAILED
,
2910 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2911 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2912 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2913 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2916 /* Set "local" forwarding info. */
2917 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2918 n
->ifindex
= ifp
->ifindex
;
2920 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2924 /* Note any changes and see if of interest to BGP. */
2925 mac_different
= (memcmp(n
->emac
.octet
,
2926 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2927 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2928 ZEBRA_NEIGH_ROUTER_FLAG
);
2929 if (!mac_different
&& is_router
== cur_is_router
) {
2930 n
->ifindex
= ifp
->ifindex
;
2934 if (!mac_different
) {
2935 bool is_neigh_freezed
= false;
2937 /* Only the router flag has changed. */
2940 ZEBRA_NEIGH_ROUTER_FLAG
);
2942 UNSET_FLAG(n
->flags
,
2943 ZEBRA_NEIGH_ROUTER_FLAG
);
2945 /* Neigh is in freeze state and freeze action
2946 * is enabled, do not send update to client.
2948 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
2950 CHECK_FLAG(n
->flags
,
2951 ZEBRA_NEIGH_DUPLICATE
));
2953 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
2955 return zvni_neigh_send_add_to_client(
2956 zvni
->vni
, ip
, macaddr
,
2957 n
->flags
, n
->loc_seq
);
2961 /* The MAC has changed, need to issue a delete
2962 * first as this means a different MACIP route.
2963 * Also, need to do some unlinking/relinking.
2964 * We also need to update the MAC's sequence number
2965 * in different situations.
2967 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2968 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2969 &n
->emac
, 0, n
->state
);
2970 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2972 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2974 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2975 neigh_mac_change
= upd_mac_seq
= true;
2976 listnode_delete(old_zmac
->neigh_list
, n
);
2977 zvni_deref_ip2mac(zvni
, old_zmac
);
2980 /* Update the forwarding info. */
2981 n
->ifindex
= ifp
->ifindex
;
2982 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2984 /* Link to new MAC */
2985 listnode_add_sort(zmac
->neigh_list
, n
);
2986 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2988 * Neighbor has moved from remote to local. Its
2989 * MAC could have also changed as part of the move.
2991 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2993 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2995 old_mac_seq
= CHECK_FLAG(
3000 neigh_mac_change
= upd_mac_seq
= true;
3001 listnode_delete(old_zmac
->neigh_list
,
3003 zvni_deref_ip2mac(zvni
, old_zmac
);
3006 /* Link to new MAC */
3007 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3008 listnode_add_sort(zmac
->neigh_list
, n
);
3010 /* Based on Mobility event Scenario-B from the
3011 * draft, neigh's previous state was remote treat this
3014 neigh_was_remote
= true;
3015 vtep_ip
= n
->r_vtep_ip
;
3016 /* Mark appropriately */
3017 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3018 n
->r_vtep_ip
.s_addr
= 0;
3019 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3020 n
->ifindex
= ifp
->ifindex
;
3024 /* If MAC was previously remote, or the neighbor had a different
3025 * MAC earlier, recompute the sequence number.
3028 uint32_t seq1
, seq2
;
3030 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3031 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3032 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3033 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3034 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3037 /* Mark Router flag (R-bit) */
3039 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3041 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3043 /* Check old and/or new MAC detected as duplicate mark
3044 * the neigh as duplicate
3046 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3047 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3048 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3050 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3051 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3054 /* For IP Duplicate Address Detection (DAD) is trigger,
3055 * when the event is extended mobility based on scenario-B
3056 * from the draft, IP/Neigh's MAC binding changed and
3057 * neigh's previous state was remote.
3059 if (neigh_mac_change
&& neigh_was_remote
)
3062 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3063 &neigh_on_hold
, true);
3065 /* Before we program this in BGP, we need to check if MAC is locally
3066 * learnt. If not, force neighbor to be inactive and reset its seq.
3068 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3069 ZEBRA_NEIGH_SET_INACTIVE(n
);
3071 zmac
->loc_seq
= mac_new_seq
;
3075 /* If the MAC's sequence number has changed, inform the MAC and all
3076 * neighbors associated with the MAC to BGP, else just inform this
3079 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3080 if (IS_ZEBRA_DEBUG_VXLAN
)
3081 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3082 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3083 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3084 zmac
->loc_seq
= mac_new_seq
;
3085 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3086 zmac
->flags
, zmac
->loc_seq
))
3088 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3092 ZEBRA_NEIGH_SET_ACTIVE(n
);
3093 n
->loc_seq
= zmac
->loc_seq
;
3096 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3097 n
->flags
, n
->loc_seq
);
3101 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3102 struct interface
*ifp
,
3104 struct ethaddr
*macaddr
,
3107 char buf
[ETHER_ADDR_STRLEN
];
3108 char buf2
[INET6_ADDRSTRLEN
];
3109 zebra_neigh_t
*n
= NULL
;
3110 zebra_mac_t
*zmac
= NULL
;
3112 /* If the neighbor is unknown, there is no further action. */
3113 n
= zvni_neigh_lookup(zvni
, ip
);
3117 /* If a remote entry, see if it needs to be refreshed */
3118 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3120 if (state
& NUD_STALE
)
3121 zvni_neigh_install(zvni
, n
);
3124 /* We got a "remote" neighbor notification for an entry
3125 * we think is local. This can happen in a multihoming
3126 * scenario - but only if the MAC is already "remote".
3127 * Just mark our entry as "remote".
3129 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3130 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3132 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3133 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3134 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3139 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3140 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3141 ZEBRA_NEIGH_SET_ACTIVE(n
);
3142 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3149 * Make hash key for MAC.
3151 static unsigned int mac_hash_keymake(void *p
)
3153 zebra_mac_t
*pmac
= p
;
3154 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3156 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3160 * Compare two MAC addresses.
3162 static bool mac_cmp(const void *p1
, const void *p2
)
3164 const zebra_mac_t
*pmac1
= p1
;
3165 const zebra_mac_t
*pmac2
= p2
;
3167 if (pmac1
== NULL
&& pmac2
== NULL
)
3170 if (pmac1
== NULL
|| pmac2
== NULL
)
3173 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3178 * Callback to allocate MAC hash entry.
3180 static void *zvni_mac_alloc(void *p
)
3182 const zebra_mac_t
*tmp_mac
= p
;
3185 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3188 return ((void *)mac
);
3194 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3196 zebra_mac_t tmp_mac
;
3197 zebra_mac_t
*mac
= NULL
;
3199 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3200 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3201 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3204 mac
->neigh_list
= list_new();
3205 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3213 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3215 zebra_mac_t
*tmp_mac
;
3217 list_delete(&mac
->neigh_list
);
3219 /* Free the VNI hash entry and allocated memory. */
3220 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3222 XFREE(MTYPE_MAC
, tmp_mac
);
3228 * Free MAC hash entry (callback)
3230 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
3232 struct mac_walk_ctx
*wctx
= arg
;
3233 zebra_mac_t
*mac
= backet
->data
;
3235 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3236 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3237 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3238 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3239 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3240 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3241 &wctx
->r_vtep_ip
))) {
3242 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3243 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3247 if (wctx
->uninstall
)
3248 zvni_mac_uninstall(wctx
->zvni
, mac
);
3250 zvni_mac_del(wctx
->zvni
, mac
);
3257 * Delete all MAC entries from specific VTEP for a particular VNI.
3259 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3260 struct in_addr
*r_vtep_ip
)
3262 struct mac_walk_ctx wctx
;
3264 if (!zvni
->mac_table
)
3267 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3269 wctx
.uninstall
= uninstall
;
3270 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3271 wctx
.r_vtep_ip
= *r_vtep_ip
;
3273 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3277 * Delete all MAC entries for this VNI.
3279 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3282 struct mac_walk_ctx wctx
;
3284 if (!zvni
->mac_table
)
3287 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3289 wctx
.uninstall
= uninstall
;
3290 wctx
.upd_client
= upd_client
;
3293 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3297 * Look up MAC hash entry.
3299 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3304 memset(&tmp
, 0, sizeof(tmp
));
3305 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3306 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3312 * Inform BGP about local MAC addition.
3314 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3315 uint8_t mac_flags
, uint32_t seq
)
3319 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3320 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3321 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3322 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3324 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3325 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3329 * Inform BGP about local MAC deletion.
3331 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3333 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3334 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3338 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3339 * notifications, to see if they are of interest.
3341 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3342 struct interface
*br_if
, vlanid_t vid
)
3344 struct zebra_ns
*zns
;
3345 struct route_node
*rn
;
3346 struct interface
*tmp_if
= NULL
;
3347 struct zebra_if
*zif
;
3348 struct zebra_l2info_bridge
*br
;
3349 struct zebra_l2info_vxlan
*vxl
= NULL
;
3350 uint8_t bridge_vlan_aware
;
3354 /* Determine if bridge is VLAN-aware or not */
3357 br
= &zif
->l2info
.br
;
3358 bridge_vlan_aware
= br
->vlan_aware
;
3360 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3361 /* TODO: Optimize with a hash. */
3362 zns
= zebra_ns_lookup(NS_DEFAULT
);
3363 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3364 tmp_if
= (struct interface
*)rn
->info
;
3368 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3370 if (!if_is_operative(tmp_if
))
3372 vxl
= &zif
->l2info
.vxl
;
3374 if (zif
->brslave_info
.br_if
!= br_if
)
3377 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3386 zvni
= zvni_lookup(vxl
->vni
);
3391 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3392 * neighbor notifications, to see if they are of interest.
3394 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3395 struct interface
*br_if
)
3397 struct zebra_ns
*zns
;
3398 struct route_node
*rn
;
3399 struct interface
*tmp_if
= NULL
;
3400 struct zebra_if
*zif
;
3401 struct zebra_l2info_bridge
*br
;
3402 struct zebra_l2info_vxlan
*vxl
= NULL
;
3403 uint8_t bridge_vlan_aware
;
3411 /* Make sure the linked interface is a bridge. */
3412 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3415 /* Determine if bridge is VLAN-aware or not */
3418 br
= &zif
->l2info
.br
;
3419 bridge_vlan_aware
= br
->vlan_aware
;
3420 if (bridge_vlan_aware
) {
3421 struct zebra_l2info_vlan
*vl
;
3423 if (!IS_ZEBRA_IF_VLAN(ifp
))
3428 vl
= &zif
->l2info
.vl
;
3432 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3433 /* TODO: Optimize with a hash. */
3434 zns
= zebra_ns_lookup(NS_DEFAULT
);
3435 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3436 tmp_if
= (struct interface
*)rn
->info
;
3440 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3442 if (!if_is_operative(tmp_if
))
3444 vxl
= &zif
->l2info
.vxl
;
3446 if (zif
->brslave_info
.br_if
!= br_if
)
3449 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3458 zvni
= zvni_lookup(vxl
->vni
);
3462 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3464 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3465 * linked to the bridge
3466 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3469 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3471 struct zebra_ns
*zns
;
3472 struct route_node
*rn
;
3473 struct interface
*tmp_if
= NULL
;
3474 struct zebra_if
*zif
;
3475 struct zebra_l2info_bridge
*br
;
3476 struct zebra_l2info_vlan
*vl
;
3477 uint8_t bridge_vlan_aware
;
3480 /* Defensive check, caller expected to invoke only with valid bridge. */
3484 /* Determine if bridge is VLAN-aware or not */
3487 br
= &zif
->l2info
.br
;
3488 bridge_vlan_aware
= br
->vlan_aware
;
3490 /* Check oper status of the SVI. */
3491 if (!bridge_vlan_aware
)
3492 return if_is_operative(br_if
) ? br_if
: NULL
;
3494 /* Identify corresponding VLAN interface. */
3495 /* TODO: Optimize with a hash. */
3496 zns
= zebra_ns_lookup(NS_DEFAULT
);
3497 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3498 tmp_if
= (struct interface
*)rn
->info
;
3499 /* Check oper status of the SVI. */
3500 if (!tmp_if
|| !if_is_operative(tmp_if
))
3503 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3504 || zif
->link
!= br_if
)
3506 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3508 if (vl
->vid
== vid
) {
3514 return found
? tmp_if
: NULL
;
3518 * Install remote MAC into the kernel.
3520 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3522 struct zebra_if
*zif
;
3523 struct zebra_l2info_vxlan
*vxl
;
3526 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3529 zif
= zvni
->vxlan_if
->info
;
3532 vxl
= &zif
->l2info
.vxl
;
3534 sticky
= !!CHECK_FLAG(mac
->flags
,
3535 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3537 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3538 mac
->fwd_info
.r_vtep_ip
, sticky
);
3542 * Uninstall remote MAC from the kernel.
3544 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3546 struct zebra_if
*zif
;
3547 struct zebra_l2info_vxlan
*vxl
;
3548 struct in_addr vtep_ip
;
3549 struct interface
*ifp
;
3551 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3554 if (!zvni
->vxlan_if
) {
3555 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3560 zif
= zvni
->vxlan_if
->info
;
3563 vxl
= &zif
->l2info
.vxl
;
3565 ifp
= zvni
->vxlan_if
;
3566 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3568 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3572 * Install MAC hash entry - called upon access VLAN change.
3574 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
3577 struct mac_walk_ctx
*wctx
= ctxt
;
3579 mac
= (zebra_mac_t
*)backet
->data
;
3581 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3582 zvni_mac_install(wctx
->zvni
, mac
);
3586 * Count of remote neighbors referencing this MAC.
3588 static int remote_neigh_count(zebra_mac_t
*zmac
)
3590 zebra_neigh_t
*n
= NULL
;
3591 struct listnode
*node
= NULL
;
3594 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3595 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3603 * Decrement neighbor refcount of MAC; uninstall and free it if
3606 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3608 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3611 /* If all remote neighbors referencing a remote MAC go away,
3612 * we need to uninstall the MAC.
3614 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3615 remote_neigh_count(mac
) == 0) {
3616 zvni_mac_uninstall(zvni
, mac
);
3617 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3620 /* If no neighbors, delete the MAC. */
3621 if (list_isempty(mac
->neigh_list
))
3622 zvni_mac_del(zvni
, mac
);
3626 * Read and populate local MACs and neighbors corresponding to this VNI.
3628 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3630 struct zebra_ns
*zns
;
3631 struct zebra_if
*zif
;
3632 struct interface
*vlan_if
;
3633 struct zebra_l2info_vxlan
*vxl
;
3634 struct interface
*vrr_if
;
3637 vxl
= &zif
->l2info
.vxl
;
3638 zns
= zebra_ns_lookup(NS_DEFAULT
);
3640 if (IS_ZEBRA_DEBUG_VXLAN
)
3642 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3643 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3644 zif
->brslave_info
.bridge_ifindex
);
3646 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3647 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3650 /* Add SVI MAC-IP */
3651 zvni_add_macip_for_intf(vlan_if
, zvni
);
3653 /* Add VRR MAC-IP - if any*/
3654 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3656 zvni_add_macip_for_intf(vrr_if
, zvni
);
3658 neigh_read_for_vlan(zns
, vlan_if
);
3663 * Hash function for VNI.
3665 static unsigned int vni_hash_keymake(void *p
)
3667 const zebra_vni_t
*zvni
= p
;
3669 return (jhash_1word(zvni
->vni
, 0));
3673 * Compare 2 VNI hash entries.
3675 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3677 const zebra_vni_t
*zvni1
= p1
;
3678 const zebra_vni_t
*zvni2
= p2
;
3680 return (zvni1
->vni
== zvni2
->vni
);
3683 static int vni_list_cmp(void *p1
, void *p2
)
3685 const zebra_vni_t
*zvni1
= p1
;
3686 const zebra_vni_t
*zvni2
= p2
;
3688 if (zvni1
->vni
== zvni2
->vni
)
3690 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3694 * Callback to allocate VNI hash entry.
3696 static void *zvni_alloc(void *p
)
3698 const zebra_vni_t
*tmp_vni
= p
;
3701 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3702 zvni
->vni
= tmp_vni
->vni
;
3703 return ((void *)zvni
);
3707 * Look up VNI hash entry.
3709 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3711 struct zebra_vrf
*zvrf
;
3712 zebra_vni_t tmp_vni
;
3713 zebra_vni_t
*zvni
= NULL
;
3715 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3717 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3719 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3725 * Add VNI hash entry.
3727 static zebra_vni_t
*zvni_add(vni_t vni
)
3729 struct zebra_vrf
*zvrf
;
3730 zebra_vni_t tmp_zvni
;
3731 zebra_vni_t
*zvni
= NULL
;
3733 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3735 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3737 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3740 /* Create hash table for MAC */
3742 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3744 /* Create hash table for neighbors */
3745 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3746 "Zebra VNI Neighbor Table");
3752 * Delete VNI hash entry.
3754 static int zvni_del(zebra_vni_t
*zvni
)
3756 struct zebra_vrf
*zvrf
;
3757 zebra_vni_t
*tmp_zvni
;
3759 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3762 zvni
->vxlan_if
= NULL
;
3764 /* Free the neighbor hash table. */
3765 hash_free(zvni
->neigh_table
);
3766 zvni
->neigh_table
= NULL
;
3768 /* Free the MAC hash table. */
3769 hash_free(zvni
->mac_table
);
3770 zvni
->mac_table
= NULL
;
3772 /* Free the VNI hash entry and allocated memory. */
3773 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3775 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3781 * Inform BGP about local VNI addition.
3783 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3785 struct zserv
*client
;
3788 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3789 /* BGP may not be running. */
3793 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3795 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3796 stream_putl(s
, zvni
->vni
);
3797 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3798 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3800 /* Write packet size. */
3801 stream_putw_at(s
, 0, stream_get_endp(s
));
3803 if (IS_ZEBRA_DEBUG_VXLAN
)
3804 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3805 inet_ntoa(zvni
->local_vtep_ip
),
3806 vrf_id_to_name(zvni
->vrf_id
),
3807 zebra_route_string(client
->proto
));
3809 client
->vniadd_cnt
++;
3810 return zserv_send_message(client
, s
);
3814 * Inform BGP about local VNI deletion.
3816 static int zvni_send_del_to_client(vni_t vni
)
3818 struct zserv
*client
;
3821 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3822 /* BGP may not be running. */
3826 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3829 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3830 stream_putl(s
, vni
);
3832 /* Write packet size. */
3833 stream_putw_at(s
, 0, stream_get_endp(s
));
3835 if (IS_ZEBRA_DEBUG_VXLAN
)
3836 zlog_debug("Send VNI_DEL %u to %s", vni
,
3837 zebra_route_string(client
->proto
));
3839 client
->vnidel_cnt
++;
3840 return zserv_send_message(client
, s
);
3844 * Build the VNI hash table by going over the VxLAN interfaces. This
3845 * is called when EVPN (advertise-all-vni) is enabled.
3847 static void zvni_build_hash_table(void)
3849 struct zebra_ns
*zns
;
3850 struct route_node
*rn
;
3851 struct interface
*ifp
;
3853 /* Walk VxLAN interfaces and create VNI hash. */
3854 zns
= zebra_ns_lookup(NS_DEFAULT
);
3855 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3857 zebra_vni_t
*zvni
= NULL
;
3858 zebra_l3vni_t
*zl3vni
= NULL
;
3859 struct zebra_if
*zif
;
3860 struct zebra_l2info_vxlan
*vxl
;
3862 ifp
= (struct interface
*)rn
->info
;
3866 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3869 vxl
= &zif
->l2info
.vxl
;
3872 /* L3-VNI and L2-VNI are handled seperately */
3873 zl3vni
= zl3vni_lookup(vni
);
3876 if (IS_ZEBRA_DEBUG_VXLAN
)
3878 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3879 ifp
->name
, ifp
->ifindex
, vni
);
3881 /* associate with vxlan_if */
3882 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3883 zl3vni
->vxlan_if
= ifp
;
3886 * we need to associate with SVI.
3887 * we can associate with svi-if only after association
3888 * with vxlan-intf is complete
3890 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3892 if (is_l3vni_oper_up(zl3vni
))
3893 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3896 struct interface
*vlan_if
= NULL
;
3898 if (IS_ZEBRA_DEBUG_VXLAN
)
3900 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3901 ifp
->name
, ifp
->ifindex
, vni
,
3902 inet_ntoa(vxl
->vtep_ip
));
3904 /* VNI hash entry is not expected to exist. */
3905 zvni
= zvni_lookup(vni
);
3908 "VNI hash already present for IF %s(%u) L2-VNI %u",
3909 ifp
->name
, ifp
->ifindex
, vni
);
3913 zvni
= zvni_add(vni
);
3916 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3917 ifp
->name
, ifp
->ifindex
, vni
);
3921 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3922 zvni
->vxlan_if
= ifp
;
3923 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3924 zif
->brslave_info
.br_if
);
3926 zvni
->vrf_id
= vlan_if
->vrf_id
;
3927 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3929 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3933 /* Inform BGP if intf is up and mapped to bridge. */
3934 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3935 zvni_send_add_to_client(zvni
);
3941 * See if remote VTEP matches with prefix.
3943 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3945 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3949 * Locate remote VTEP in VNI hash table.
3951 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3953 zebra_vtep_t
*zvtep
;
3958 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3959 if (zvni_vtep_match(vtep_ip
, zvtep
))
3967 * Add remote VTEP to VNI hash table.
3969 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3971 zebra_vtep_t
*zvtep
;
3973 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3975 zvtep
->vtep_ip
= *vtep_ip
;
3978 zvni
->vteps
->prev
= zvtep
;
3979 zvtep
->next
= zvni
->vteps
;
3980 zvni
->vteps
= zvtep
;
3986 * Remove remote VTEP from VNI hash table.
3988 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3991 zvtep
->next
->prev
= zvtep
->prev
;
3993 zvtep
->prev
->next
= zvtep
->next
;
3995 zvni
->vteps
= zvtep
->next
;
3997 zvtep
->prev
= zvtep
->next
= NULL
;
3998 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4004 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4005 * uninstall from kernel if asked to.
4007 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4009 zebra_vtep_t
*zvtep
, *zvtep_next
;
4014 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4015 zvtep_next
= zvtep
->next
;
4017 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4018 zvni_vtep_del(zvni
, zvtep
);
4025 * Install remote VTEP into the kernel.
4027 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4029 if (is_vxlan_flooding_head_end())
4030 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4035 * Uninstall remote VTEP from the kernel.
4037 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4039 if (!zvni
->vxlan_if
) {
4040 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4045 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4049 * Install or uninstall flood entries in the kernel corresponding to
4050 * remote VTEPs. This is invoked upon change to BUM handling.
4052 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
4056 zebra_vtep_t
*zvtep
;
4058 zvni
= (zebra_vni_t
*)backet
->data
;
4062 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4063 if (is_vxlan_flooding_head_end())
4064 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4066 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4071 * Cleanup VNI/VTEP and update kernel
4073 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
4075 zebra_vni_t
*zvni
= NULL
;
4076 zebra_l3vni_t
*zl3vni
= NULL
;
4077 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4079 zvni
= (zebra_vni_t
*)backet
->data
;
4081 /* remove from l3-vni list */
4083 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4085 listnode_delete(zl3vni
->l2vnis
, zvni
);
4087 /* Free up all neighbors and MACs, if any. */
4088 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4089 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4091 /* Free up all remote VTEPs, if any. */
4092 zvni_vtep_del_all(zvni
, 1);
4094 /* Delete the hash entry. */
4099 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
4101 zebra_l3vni_t
*zl3vni
= NULL
;
4103 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
4105 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4108 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4109 struct prefix
*host
)
4111 struct host_rb_entry lookup
;
4112 struct host_rb_entry
*hle
;
4114 memset(&lookup
, 0, sizeof(lookup
));
4115 memcpy(&lookup
.p
, host
, sizeof(*host
));
4117 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4121 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4122 memcpy(hle
, &lookup
, sizeof(lookup
));
4124 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4127 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4129 struct host_rb_entry lookup
;
4130 struct host_rb_entry
*hle
;
4132 memset(&lookup
, 0, sizeof(lookup
));
4133 memcpy(&lookup
.p
, host
, sizeof(*host
));
4135 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4137 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4138 XFREE(MTYPE_HOST_PREFIX
, hle
);
4145 * Look up MAC hash entry.
4147 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4148 struct ethaddr
*rmac
)
4153 memset(&tmp
, 0, sizeof(tmp
));
4154 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4155 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4161 * Callback to allocate RMAC hash entry.
4163 static void *zl3vni_rmac_alloc(void *p
)
4165 const zebra_mac_t
*tmp_rmac
= p
;
4168 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4171 return ((void *)zrmac
);
4175 * Add RMAC entry to l3-vni
4177 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4179 zebra_mac_t tmp_rmac
;
4180 zebra_mac_t
*zrmac
= NULL
;
4182 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4183 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4184 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4187 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4189 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4190 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4198 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4200 zebra_mac_t
*tmp_rmac
;
4201 struct host_rb_entry
*hle
;
4203 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4204 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4206 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4207 XFREE(MTYPE_HOST_PREFIX
, hle
);
4210 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4212 XFREE(MTYPE_MAC
, tmp_rmac
);
4218 * Install remote RMAC into the kernel.
4220 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4222 struct zebra_if
*zif
= NULL
;
4223 struct zebra_l2info_vxlan
*vxl
= NULL
;
4225 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4226 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4229 zif
= zl3vni
->vxlan_if
->info
;
4233 vxl
= &zif
->l2info
.vxl
;
4235 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4236 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4240 * Uninstall remote RMAC from the kernel.
4242 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4244 char buf
[ETHER_ADDR_STRLEN
];
4245 struct zebra_if
*zif
= NULL
;
4246 struct zebra_l2info_vxlan
*vxl
= NULL
;
4248 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4249 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4252 if (!zl3vni
->vxlan_if
) {
4254 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4255 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4256 zl3vni
->vni
, zl3vni
);
4260 zif
= zl3vni
->vxlan_if
->info
;
4264 vxl
= &zif
->l2info
.vxl
;
4266 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4267 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4270 /* handle rmac add */
4271 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4272 struct ipaddr
*vtep_ip
,
4273 struct prefix
*host_prefix
)
4275 char buf
[ETHER_ADDR_STRLEN
];
4276 char buf1
[INET6_ADDRSTRLEN
];
4277 zebra_mac_t
*zrmac
= NULL
;
4279 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4282 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4285 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4286 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4288 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4291 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4292 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4294 /* install rmac in kernel */
4295 zl3vni_rmac_install(zl3vni
, zrmac
);
4298 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4304 /* handle rmac delete */
4305 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4306 struct prefix
*host_prefix
)
4308 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4310 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4311 /* uninstall from kernel */
4312 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4314 /* del the rmac entry */
4315 zl3vni_rmac_del(zl3vni
, zrmac
);
4320 * Look up nh hash entry on a l3-vni.
4322 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4327 memset(&tmp
, 0, sizeof(tmp
));
4328 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4329 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4336 * Callback to allocate NH hash entry on L3-VNI.
4338 static void *zl3vni_nh_alloc(void *p
)
4340 const zebra_neigh_t
*tmp_n
= p
;
4343 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4350 * Add neighbor entry.
4352 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4353 struct ethaddr
*mac
)
4355 zebra_neigh_t tmp_n
;
4356 zebra_neigh_t
*n
= NULL
;
4358 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4359 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4360 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4363 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4365 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4366 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4367 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4373 * Delete neighbor entry.
4375 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4377 zebra_neigh_t
*tmp_n
;
4378 struct host_rb_entry
*hle
;
4380 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4381 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4383 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4384 XFREE(MTYPE_HOST_PREFIX
, hle
);
4387 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4389 XFREE(MTYPE_NEIGH
, tmp_n
);
4395 * Install remote nh as neigh into the kernel.
4397 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4404 if (!is_l3vni_oper_up(zl3vni
))
4407 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4408 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4411 flags
= NTF_EXT_LEARNED
;
4412 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4413 flags
|= NTF_ROUTER
;
4414 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4420 * Uninstall remote nh from the kernel.
4422 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4424 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4425 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4428 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4431 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4434 /* add remote vtep as a neigh entry */
4435 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4436 struct ethaddr
*rmac
,
4437 struct prefix
*host_prefix
)
4439 char buf
[ETHER_ADDR_STRLEN
];
4440 char buf1
[INET6_ADDRSTRLEN
];
4441 zebra_neigh_t
*nh
= NULL
;
4443 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4445 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4449 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4450 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4451 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4456 /* install the nh neigh in kernel */
4457 zl3vni_nh_install(zl3vni
, nh
);
4460 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4465 /* handle nh neigh delete */
4466 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4467 struct prefix
*host_prefix
)
4469 rb_delete_host(&nh
->host_rb
, host_prefix
);
4471 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4472 /* uninstall from kernel */
4473 zl3vni_nh_uninstall(zl3vni
, nh
);
4475 /* delete the nh entry */
4476 zl3vni_nh_del(zl3vni
, nh
);
4480 /* handle neigh update from kernel - the only thing of interest is to
4481 * readd stale entries.
4483 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4487 zebra_neigh_t
*n
= NULL
;
4489 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4493 /* all next hop neigh are remote and installed by frr.
4494 * If the kernel has aged this entry, re-install.
4496 if (state
& NUD_STALE
)
4497 zl3vni_nh_install(zl3vni
, n
);
4502 /* handle neigh delete from kernel */
4503 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4505 zebra_neigh_t
*n
= NULL
;
4507 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4511 /* all next hop neigh are remote and installed by frr.
4512 * If we get an age out notification for these neigh entries, we have to
4515 zl3vni_nh_install(zl3vni
, n
);
4521 * Hash function for L3 VNI.
4523 static unsigned int l3vni_hash_keymake(void *p
)
4525 const zebra_l3vni_t
*zl3vni
= p
;
4527 return jhash_1word(zl3vni
->vni
, 0);
4531 * Compare 2 L3 VNI hash entries.
4533 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4535 const zebra_l3vni_t
*zl3vni1
= p1
;
4536 const zebra_l3vni_t
*zl3vni2
= p2
;
4538 return (zl3vni1
->vni
== zl3vni2
->vni
);
4542 * Callback to allocate L3 VNI hash entry.
4544 static void *zl3vni_alloc(void *p
)
4546 zebra_l3vni_t
*zl3vni
= NULL
;
4547 const zebra_l3vni_t
*tmp_l3vni
= p
;
4549 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4550 zl3vni
->vni
= tmp_l3vni
->vni
;
4551 return ((void *)zl3vni
);
4555 * Look up L3 VNI hash entry.
4557 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4559 zebra_l3vni_t tmp_l3vni
;
4560 zebra_l3vni_t
*zl3vni
= NULL
;
4562 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4563 tmp_l3vni
.vni
= vni
;
4564 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4570 * Add L3 VNI hash entry.
4572 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4574 zebra_l3vni_t tmp_zl3vni
;
4575 zebra_l3vni_t
*zl3vni
= NULL
;
4577 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4578 tmp_zl3vni
.vni
= vni
;
4580 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4583 zl3vni
->vrf_id
= vrf_id
;
4584 zl3vni
->svi_if
= NULL
;
4585 zl3vni
->vxlan_if
= NULL
;
4586 zl3vni
->l2vnis
= list_new();
4587 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4589 /* Create hash table for remote RMAC */
4590 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4591 "Zebra L3-VNI RMAC-Table");
4593 /* Create hash table for neighbors */
4594 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4595 "Zebra L3-VNI next-hop table");
4601 * Delete L3 VNI hash entry.
4603 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4605 zebra_l3vni_t
*tmp_zl3vni
;
4607 /* free the list of l2vnis */
4608 list_delete(&zl3vni
->l2vnis
);
4609 zl3vni
->l2vnis
= NULL
;
4611 /* Free the rmac table */
4612 hash_free(zl3vni
->rmac_table
);
4613 zl3vni
->rmac_table
= NULL
;
4615 /* Free the nh table */
4616 hash_free(zl3vni
->nh_table
);
4617 zl3vni
->nh_table
= NULL
;
4619 /* Free the VNI hash entry and allocated memory. */
4620 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4622 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4627 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4629 struct zebra_ns
*zns
= NULL
;
4630 struct route_node
*rn
= NULL
;
4631 struct interface
*ifp
= NULL
;
4633 /* loop through all vxlan-interface */
4634 zns
= zebra_ns_lookup(NS_DEFAULT
);
4635 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4637 struct zebra_if
*zif
= NULL
;
4638 struct zebra_l2info_vxlan
*vxl
= NULL
;
4640 ifp
= (struct interface
*)rn
->info
;
4645 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4648 vxl
= &zif
->l2info
.vxl
;
4649 if (vxl
->vni
== zl3vni
->vni
) {
4650 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4658 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4660 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4661 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4666 if (!zl3vni
->vxlan_if
)
4669 zif
= zl3vni
->vxlan_if
->info
;
4673 vxl
= &zif
->l2info
.vxl
;
4675 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4678 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4680 struct zebra_vrf
*zvrf
= NULL
;
4682 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4686 return zl3vni_lookup(zvrf
->l3vni
);
4690 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4691 * neighbor notifications, to see if they are of interest.
4693 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4694 struct interface
*br_if
)
4698 uint8_t bridge_vlan_aware
= 0;
4699 zebra_l3vni_t
*zl3vni
= NULL
;
4700 struct zebra_ns
*zns
= NULL
;
4701 struct route_node
*rn
= NULL
;
4702 struct zebra_if
*zif
= NULL
;
4703 struct interface
*tmp_if
= NULL
;
4704 struct zebra_l2info_bridge
*br
= NULL
;
4705 struct zebra_l2info_vxlan
*vxl
= NULL
;
4710 /* Make sure the linked interface is a bridge. */
4711 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4714 /* Determine if bridge is VLAN-aware or not */
4717 br
= &zif
->l2info
.br
;
4718 bridge_vlan_aware
= br
->vlan_aware
;
4719 if (bridge_vlan_aware
) {
4720 struct zebra_l2info_vlan
*vl
;
4722 if (!IS_ZEBRA_IF_VLAN(ifp
))
4727 vl
= &zif
->l2info
.vl
;
4731 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4732 /* TODO: Optimize with a hash. */
4733 zns
= zebra_ns_lookup(NS_DEFAULT
);
4734 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4735 tmp_if
= (struct interface
*)rn
->info
;
4739 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4741 if (!if_is_operative(tmp_if
))
4743 vxl
= &zif
->l2info
.vxl
;
4745 if (zif
->brslave_info
.br_if
!= br_if
)
4748 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4757 zl3vni
= zl3vni_lookup(vxl
->vni
);
4762 * Inform BGP about l3-vni.
4764 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4766 struct stream
*s
= NULL
;
4767 struct zserv
*client
= NULL
;
4768 struct ethaddr rmac
;
4769 char buf
[ETHER_ADDR_STRLEN
];
4771 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4772 /* BGP may not be running. */
4777 memset(&rmac
, 0, sizeof(struct ethaddr
));
4778 zl3vni_get_rmac(zl3vni
, &rmac
);
4780 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4782 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4783 stream_putl(s
, zl3vni
->vni
);
4784 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4785 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4786 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4788 /* Write packet size. */
4789 stream_putw_at(s
, 0, stream_get_endp(s
));
4791 if (IS_ZEBRA_DEBUG_VXLAN
)
4793 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4794 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4795 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4796 inet_ntoa(zl3vni
->local_vtep_ip
),
4797 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4798 ? "prefix-routes-only"
4800 zebra_route_string(client
->proto
));
4802 client
->l3vniadd_cnt
++;
4803 return zserv_send_message(client
, s
);
4807 * Inform BGP about local l3-VNI deletion.
4809 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4811 struct stream
*s
= NULL
;
4812 struct zserv
*client
= NULL
;
4814 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4815 /* BGP may not be running. */
4819 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4821 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4822 stream_putl(s
, zl3vni
->vni
);
4824 /* Write packet size. */
4825 stream_putw_at(s
, 0, stream_get_endp(s
));
4827 if (IS_ZEBRA_DEBUG_VXLAN
)
4828 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4829 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4830 zebra_route_string(client
->proto
));
4832 client
->l3vnidel_cnt
++;
4833 return zserv_send_message(client
, s
);
4836 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4841 /* send l3vni add to BGP */
4842 zl3vni_send_add_to_client(zl3vni
);
4845 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4850 /* send l3-vni del to BGP*/
4851 zl3vni_send_del_to_client(zl3vni
);
4854 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4856 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4857 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4859 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4860 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4864 * handle transition of vni from l2 to l3 and vice versa
4866 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4869 zebra_vni_t
*zvni
= NULL
;
4871 /* There is a possibility that VNI notification was already received
4872 * from kernel and we programmed it as L2-VNI
4873 * In such a case we need to delete this L2-VNI first, so
4874 * that it can be reprogrammed as L3-VNI in the system. It is also
4875 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4876 * interface is still present in kernel. In this case to keep it
4877 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4880 /* Locate hash entry */
4881 zvni
= zvni_lookup(vni
);
4885 if (IS_ZEBRA_DEBUG_VXLAN
)
4886 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4888 /* Delete VNI from BGP. */
4889 zvni_send_del_to_client(zvni
->vni
);
4891 /* Free up all neighbors and MAC, if any. */
4892 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4893 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4895 /* Free up all remote VTEPs, if any. */
4896 zvni_vtep_del_all(zvni
, 0);
4898 /* Delete the hash entry. */
4899 if (zvni_del(zvni
)) {
4900 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4901 "Failed to del VNI hash %p, VNI %u", zvni
,
4906 /* TODO_MITESH: This needs to be thought through. We don't have
4907 * enough information at this point to reprogram the vni as
4908 * l2-vni. One way is to store the required info in l3-vni and
4909 * used it solely for this purpose
4916 /* delete and uninstall rmac hash entry */
4917 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4919 zebra_mac_t
*zrmac
= NULL
;
4920 zebra_l3vni_t
*zl3vni
= NULL
;
4922 zrmac
= (zebra_mac_t
*)backet
->data
;
4923 zl3vni
= (zebra_l3vni_t
*)ctx
;
4924 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4925 zl3vni_rmac_del(zl3vni
, zrmac
);
4928 /* delete and uninstall nh hash entry */
4929 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4931 zebra_neigh_t
*n
= NULL
;
4932 zebra_l3vni_t
*zl3vni
= NULL
;
4934 n
= (zebra_neigh_t
*)backet
->data
;
4935 zl3vni
= (zebra_l3vni_t
*)ctx
;
4936 zl3vni_nh_uninstall(zl3vni
, n
);
4937 zl3vni_nh_del(zl3vni
, n
);
4940 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4943 struct zserv
*client
= NULL
;
4944 struct stream
*s
= NULL
;
4945 char buf
[PREFIX_STRLEN
];
4947 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4948 /* BGP may not be running. */
4952 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4954 zclient_create_header(s
, cmd
, vrf_id
);
4955 stream_put(s
, p
, sizeof(struct prefix
));
4957 /* Write packet size. */
4958 stream_putw_at(s
, 0, stream_get_endp(s
));
4960 if (IS_ZEBRA_DEBUG_VXLAN
)
4961 zlog_debug("Send ip prefix %s %s on vrf %s",
4962 prefix2str(p
, buf
, sizeof(buf
)),
4963 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4964 vrf_id_to_name(vrf_id
));
4966 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4967 client
->prefixadd_cnt
++;
4969 client
->prefixdel_cnt
++;
4971 return zserv_send_message(client
, s
);
4974 /* re-add remote rmac if needed */
4975 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4976 struct ethaddr
*rmac
)
4978 char buf
[ETHER_ADDR_STRLEN
];
4979 zebra_mac_t
*zrmac
= NULL
;
4981 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4985 if (IS_ZEBRA_DEBUG_VXLAN
)
4986 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4987 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4989 zl3vni_rmac_install(zl3vni
, zrmac
);
4993 /* Process a remote MACIP add from BGP. */
4994 static void process_remote_macip_add(vni_t vni
,
4995 struct ethaddr
*macaddr
,
4997 struct ipaddr
*ipaddr
,
5000 struct in_addr vtep_ip
)
5003 zebra_vtep_t
*zvtep
;
5004 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5005 zebra_neigh_t
*n
= NULL
;
5006 int update_mac
= 0, update_neigh
= 0;
5007 char buf
[ETHER_ADDR_STRLEN
];
5008 char buf1
[INET6_ADDRSTRLEN
];
5009 struct interface
*ifp
= NULL
;
5010 struct zebra_if
*zif
= NULL
;
5011 struct zebra_vrf
*zvrf
;
5016 bool do_dad
= false;
5017 bool is_dup_detect
= false;
5019 /* Locate VNI hash entry - expected to exist. */
5020 zvni
= zvni_lookup(vni
);
5022 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5026 ifp
= zvni
->vxlan_if
;
5030 !if_is_operative(ifp
) ||
5032 !zif
->brslave_info
.br_if
) {
5033 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5038 /* The remote VTEP specified should normally exist, but it is
5039 * possible that when peering comes up, peer may advertise MACIP
5040 * routes before advertising type-3 routes.
5042 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5044 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5046 EC_ZEBRA_VTEP_ADD_FAILED
,
5047 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5052 zvni_vtep_install(zvni
, &vtep_ip
);
5055 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5056 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5057 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5059 mac
= zvni_mac_lookup(zvni
, macaddr
);
5061 /* Ignore if the mac is already present as a gateway mac */
5063 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5064 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5065 if (IS_ZEBRA_DEBUG_VXLAN
)
5066 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5068 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5069 ipa_len
? " IP " : "",
5071 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5075 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5079 /* check if the remote MAC is unknown or has a change.
5080 * If so, that needs to be updated first. Note that client could
5081 * install MAC and MACIP separately or just install the latter.
5084 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5085 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5086 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5087 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5088 || seq
!= mac
->rem_seq
)
5093 mac
= zvni_mac_add(zvni
, macaddr
);
5096 "Failed to add MAC %s VNI %u Remote VTEP %s",
5097 prefix_mac2str(macaddr
, buf
,
5099 vni
, inet_ntoa(vtep_ip
));
5103 /* Is this MAC created for a MACIP? */
5105 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5107 const char *mac_type
;
5109 /* When host moves but changes its (MAC,IP)
5110 * binding, BGP may install a MACIP entry that
5111 * corresponds to "older" location of the host
5112 * in transient situations (because {IP1,M1}
5113 * is a different route from {IP1,M2}). Check
5114 * the sequence number and ignore this update
5117 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5118 tmp_seq
= mac
->loc_seq
;
5121 tmp_seq
= mac
->rem_seq
;
5122 mac_type
= "remote";
5124 if (seq
< tmp_seq
) {
5125 if (IS_ZEBRA_DEBUG_VXLAN
)
5126 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5128 prefix_mac2str(macaddr
,
5130 ipa_len
? " IP " : "",
5133 buf1
, sizeof(buf1
)) : "",
5140 /* Check MAC's curent state is local (this is the case
5141 * where MAC has moved from L->R) and check previous
5142 * detection started via local learning.
5143 * RFC-7432: A PE/VTEP that detects a MAC mobility
5144 * event via local learning starts an M-second timer.
5146 * VTEP-IP or seq. change along is not considered
5147 * for dup. detection.
5149 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) &&
5153 /* Remove local MAC from BGP. */
5154 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5155 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5157 /* Set "auto" and "remote" forwarding info. */
5158 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5159 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5160 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5161 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5164 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5166 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5169 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5171 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5173 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5174 mac
->fwd_info
.r_vtep_ip
,
5175 do_dad
, &is_dup_detect
,
5178 if (!is_dup_detect
) {
5179 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5180 /* Install the entry. */
5181 zvni_mac_install(zvni
, mac
);
5185 /* Update seq number. */
5188 /* If there is no IP, return after clearing AUTO flag of MAC. */
5190 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5197 /* Check if the remote neighbor itself is unknown or has a
5198 * change. If so, create or update and then install the entry.
5200 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5202 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5203 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5204 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5205 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5206 || seq
!= n
->rem_seq
)
5211 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5214 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5215 ipaddr2str(ipaddr
, buf1
,
5217 prefix_mac2str(macaddr
, buf
,
5219 vni
, inet_ntoa(vtep_ip
));
5226 /* When host moves but changes its (MAC,IP)
5227 * binding, BGP may install a MACIP entry that
5228 * corresponds to "older" location of the host
5229 * in transient situations (because {IP1,M1}
5230 * is a different route from {IP1,M2}). Check
5231 * the sequence number and ignore this update
5234 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5235 tmp_seq
= n
->loc_seq
;
5238 tmp_seq
= n
->rem_seq
;
5241 if (seq
< tmp_seq
) {
5242 if (IS_ZEBRA_DEBUG_VXLAN
)
5243 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5245 prefix_mac2str(macaddr
,
5248 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5253 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5254 /* MAC change, send a delete for old
5255 * neigh if learnt locally.
5257 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5258 IS_ZEBRA_NEIGH_ACTIVE(n
))
5259 zvni_neigh_send_del_to_client(
5261 &n
->emac
, 0, n
->state
);
5263 /* update neigh list for macs */
5264 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5266 listnode_delete(old_mac
->neigh_list
, n
);
5267 zvni_deref_ip2mac(zvni
, old_mac
);
5269 listnode_add_sort(mac
->neigh_list
, n
);
5270 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5272 /* Check Neigh's curent state is local
5273 * (this is the case where neigh/host has moved
5274 * from L->R) and check previous detction
5275 * started via local learning.
5277 * RFC-7432: A PE/VTEP that detects a MAC
5278 * mobilit event via local learning starts
5279 * an M-second timer.
5280 * VTEP-IP or seq. change along is not
5281 * considered for dup. detection.
5283 * Mobilty event scenario-B IP-MAC binding
5286 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5293 /* Set "remote" forwarding info. */
5294 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5295 n
->r_vtep_ip
= vtep_ip
;
5296 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5298 /* Set router flag (R-bit) to this Neighbor entry */
5299 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5300 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5302 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5304 /* Check old or new MAC detected as duplicate,
5305 * inherit duplicate flag to this neigh.
5307 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5309 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5310 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5312 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5313 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5316 /* Check duplicate address detection for IP */
5317 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5322 /* Install the entry. */
5324 zvni_neigh_install(zvni
, n
);
5327 /* Update seq number. */
5331 /* Process a remote MACIP delete from BGP. */
5332 static void process_remote_macip_del(vni_t vni
,
5333 struct ethaddr
*macaddr
,
5335 struct ipaddr
*ipaddr
,
5336 struct in_addr vtep_ip
)
5339 zebra_mac_t
*mac
= NULL
;
5340 zebra_neigh_t
*n
= NULL
;
5341 struct interface
*ifp
= NULL
;
5342 struct zebra_if
*zif
= NULL
;
5343 struct zebra_ns
*zns
;
5344 struct zebra_l2info_vxlan
*vxl
;
5345 struct zebra_vrf
*zvrf
;
5346 char buf
[ETHER_ADDR_STRLEN
];
5347 char buf1
[INET6_ADDRSTRLEN
];
5349 /* Locate VNI hash entry - expected to exist. */
5350 zvni
= zvni_lookup(vni
);
5352 if (IS_ZEBRA_DEBUG_VXLAN
)
5353 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5357 ifp
= zvni
->vxlan_if
;
5361 !if_is_operative(ifp
) ||
5363 !zif
->brslave_info
.br_if
) {
5364 if (IS_ZEBRA_DEBUG_VXLAN
)
5365 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5369 zns
= zebra_ns_lookup(NS_DEFAULT
);
5370 vxl
= &zif
->l2info
.vxl
;
5372 /* The remote VTEP specified is normally expected to exist, but
5373 * it is possible that the peer may delete the VTEP before deleting
5374 * any MACs referring to the VTEP, in which case the handler (see
5375 * remote_vtep_del) would have already deleted the MACs.
5377 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5380 mac
= zvni_mac_lookup(zvni
, macaddr
);
5382 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5385 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5386 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5387 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5391 /* If the remote mac or neighbor doesn't exist there is nothing
5392 * more to do. Otherwise, uninstall the entry and then remove it.
5397 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5399 /* Ignore the delete if this mac is a gateway mac-ip */
5400 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5401 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5403 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5405 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5406 ipa_len
? " IP " : "",
5408 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5412 /* Uninstall remote neighbor or MAC. */
5414 if (zvrf
->dad_freeze
&&
5415 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5416 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5417 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5418 struct interface
*vlan_if
;
5420 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5421 zif
->brslave_info
.br_if
);
5422 if (IS_ZEBRA_DEBUG_VXLAN
)
5423 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5424 __PRETTY_FUNCTION__
,
5425 ipaddr2str(ipaddr
, buf1
,
5426 sizeof(buf1
)), n
->flags
,
5428 neigh_read_specific_ip(ipaddr
, vlan_if
);
5431 /* When the MAC changes for an IP, it is possible the
5432 * client may update the new MAC before trying to delete the
5433 * "old" neighbor (as these are two different MACIP routes).
5434 * Do the delete only if the MAC matches.
5436 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5437 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5438 zvni_neigh_uninstall(zvni
, n
);
5439 zvni_neigh_del(zvni
, n
);
5440 zvni_deref_ip2mac(zvni
, mac
);
5443 /* DAD: when MAC is freeze state as remote learn event,
5444 * remote mac-ip delete event is received will result in freeze
5445 * entry removal, first fetch kernel for the same entry present
5446 * as LOCAL and reachable, avoid deleting this entry instead
5447 * use kerenel local entry to update during unfreeze time.
5449 if (zvrf
->dad_freeze
&&
5450 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5451 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5452 if (IS_ZEBRA_DEBUG_VXLAN
)
5453 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5454 __PRETTY_FUNCTION__
,
5455 prefix_mac2str(macaddr
, buf
,
5458 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5459 macaddr
, vxl
->access_vlan
);
5462 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5463 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5465 * the remote sequence number in the auto mac entry
5466 * needs to be reset to 0 as the mac entry may have
5467 * been removed on all VTEPs (including
5468 * the originating one)
5472 /* If all remote neighbors referencing a remote MAC
5473 * go away, we need to uninstall the MAC.
5475 if (remote_neigh_count(mac
) == 0) {
5476 zvni_mac_uninstall(zvni
, mac
);
5477 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5479 if (list_isempty(mac
->neigh_list
))
5480 zvni_mac_del(zvni
, mac
);
5482 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5488 /* Public functions */
5490 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5492 zebra_l3vni_t
*zl3vni
= NULL
;
5494 zl3vni
= zl3vni_lookup(vni
);
5498 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5501 /* handle evpn route in vrf table */
5502 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5503 struct ipaddr
*vtep_ip
,
5504 struct prefix
*host_prefix
)
5506 zebra_l3vni_t
*zl3vni
= NULL
;
5507 struct ipaddr ipv4_vtep
;
5509 zl3vni
= zl3vni_from_vrf(vrf_id
);
5510 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5514 * add the next hop neighbor -
5515 * neigh to be installed is the ipv6 nexthop neigh
5517 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5520 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5521 * address. Rmac is programmed against the ipv4 vtep because we only
5522 * support ipv4 tunnels in the h/w right now
5524 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5525 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5526 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5527 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5528 &(ipv4_vtep
.ipaddr_v4
));
5530 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5531 sizeof(struct in_addr
));
5534 * add the rmac - remote rmac to be installed is against the ipv4
5537 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5540 /* handle evpn vrf route delete */
5541 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5542 struct ipaddr
*vtep_ip
,
5543 struct prefix
*host_prefix
)
5545 zebra_l3vni_t
*zl3vni
= NULL
;
5546 zebra_neigh_t
*nh
= NULL
;
5547 zebra_mac_t
*zrmac
= NULL
;
5549 zl3vni
= zl3vni_from_vrf(vrf_id
);
5553 /* find the next hop entry and rmac entry */
5554 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5557 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5559 /* delete the next hop entry */
5560 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5562 /* delete the rmac entry */
5564 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5568 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5569 struct ethaddr
*rmac
, bool use_json
)
5571 zebra_l3vni_t
*zl3vni
= NULL
;
5572 zebra_mac_t
*zrmac
= NULL
;
5573 json_object
*json
= NULL
;
5575 if (!is_evpn_enabled()) {
5577 vty_out(vty
, "{}\n");
5582 json
= json_object_new_object();
5584 zl3vni
= zl3vni_lookup(l3vni
);
5587 vty_out(vty
, "{}\n");
5589 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5593 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5596 vty_out(vty
, "{}\n");
5599 "%% Requested RMAC doesn't exist in L3-VNI %u",
5604 zl3vni_print_rmac(zrmac
, vty
, json
);
5607 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5608 json
, JSON_C_TO_STRING_PRETTY
));
5609 json_object_free(json
);
5613 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5615 zebra_l3vni_t
*zl3vni
;
5617 struct rmac_walk_ctx wctx
;
5618 json_object
*json
= NULL
;
5620 if (!is_evpn_enabled())
5623 zl3vni
= zl3vni_lookup(l3vni
);
5626 vty_out(vty
, "{}\n");
5628 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5631 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5636 json
= json_object_new_object();
5638 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5642 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5644 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5646 json_object_int_add(json
, "numRmacs", num_rmacs
);
5648 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5651 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5652 json
, JSON_C_TO_STRING_PRETTY
));
5653 json_object_free(json
);
5657 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5659 json_object
*json
= NULL
;
5662 if (!is_evpn_enabled()) {
5664 vty_out(vty
, "{}\n");
5669 json
= json_object_new_object();
5673 hash_iterate(zrouter
.l3vni_table
,
5674 (void (*)(struct hash_backet
*,
5675 void *))zl3vni_print_rmac_hash_all_vni
,
5679 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5680 json
, JSON_C_TO_STRING_PRETTY
));
5681 json_object_free(json
);
5685 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5686 struct ipaddr
*ip
, bool use_json
)
5688 zebra_l3vni_t
*zl3vni
= NULL
;
5689 zebra_neigh_t
*n
= NULL
;
5690 json_object
*json
= NULL
;
5692 if (!is_evpn_enabled()) {
5694 vty_out(vty
, "{}\n");
5699 json
= json_object_new_object();
5701 zl3vni
= zl3vni_lookup(l3vni
);
5704 vty_out(vty
, "{}\n");
5706 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5710 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5713 vty_out(vty
, "{}\n");
5716 "%% Requested next-hop not present for L3-VNI %u",
5721 zl3vni_print_nh(n
, vty
, json
);
5724 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5725 json
, JSON_C_TO_STRING_PRETTY
));
5726 json_object_free(json
);
5730 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5733 struct nh_walk_ctx wctx
;
5734 json_object
*json
= NULL
;
5735 zebra_l3vni_t
*zl3vni
= NULL
;
5737 if (!is_evpn_enabled())
5740 zl3vni
= zl3vni_lookup(l3vni
);
5743 vty_out(vty
, "{}\n");
5745 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5749 num_nh
= hashcount(zl3vni
->nh_table
);
5754 json
= json_object_new_object();
5759 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5761 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5763 json_object_int_add(json
, "numNextHops", num_nh
);
5765 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5768 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5769 json
, JSON_C_TO_STRING_PRETTY
));
5770 json_object_free(json
);
5774 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5776 json_object
*json
= NULL
;
5779 if (!is_evpn_enabled()) {
5781 vty_out(vty
, "{}\n");
5786 json
= json_object_new_object();
5790 hash_iterate(zrouter
.l3vni_table
,
5791 (void (*)(struct hash_backet
*,
5792 void *))zl3vni_print_nh_hash_all_vni
,
5796 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5797 json
, JSON_C_TO_STRING_PRETTY
));
5798 json_object_free(json
);
5803 * Display L3 VNI information (VTY command handler).
5805 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5808 json_object
*json
= NULL
;
5809 zebra_l3vni_t
*zl3vni
= NULL
;
5811 if (!is_evpn_enabled()) {
5813 vty_out(vty
, "{}\n");
5817 zl3vni
= zl3vni_lookup(vni
);
5820 vty_out(vty
, "{}\n");
5822 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5827 json
= json_object_new_object();
5831 zl3vni_print(zl3vni
, (void *)args
);
5834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5835 json
, JSON_C_TO_STRING_PRETTY
));
5836 json_object_free(json
);
5840 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5841 json_object
*json_vrfs
)
5843 char buf
[ETHER_ADDR_STRLEN
];
5844 zebra_l3vni_t
*zl3vni
= NULL
;
5846 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5851 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5852 zvrf_name(zvrf
), zl3vni
->vni
,
5853 zl3vni_vxlan_if_name(zl3vni
),
5854 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5855 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5857 json_object
*json_vrf
= NULL
;
5859 json_vrf
= json_object_new_object();
5860 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5861 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5862 json_object_string_add(json_vrf
, "vxlanIntf",
5863 zl3vni_vxlan_if_name(zl3vni
));
5864 json_object_string_add(json_vrf
, "sviIntf",
5865 zl3vni_svi_if_name(zl3vni
));
5866 json_object_string_add(json_vrf
, "state",
5867 zl3vni_state2str(zl3vni
));
5868 json_object_string_add(
5869 json_vrf
, "routerMac",
5870 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5871 json_object_array_add(json_vrfs
, json_vrf
);
5876 * Display Neighbors for a VNI (VTY command handler).
5878 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5879 vni_t vni
, bool use_json
)
5883 struct neigh_walk_ctx wctx
;
5884 json_object
*json
= NULL
;
5886 if (!is_evpn_enabled())
5888 zvni
= zvni_lookup(vni
);
5891 vty_out(vty
, "{}\n");
5893 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5896 num_neigh
= hashcount(zvni
->neigh_table
);
5901 json
= json_object_new_object();
5903 /* Since we have IPv6 addresses to deal with which can vary widely in
5904 * size, we try to be a bit more elegant in display by first computing
5905 * the maximum width.
5907 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5910 wctx
.addr_width
= 15;
5912 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5916 "Number of ARPs (local and remote) known for this VNI: %u\n",
5918 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5919 -wctx
.addr_width
, "IP", "Type",
5920 "State", "MAC", "Remote VTEP");
5922 json_object_int_add(json
, "numArpNd", num_neigh
);
5924 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5926 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5927 json
, JSON_C_TO_STRING_PRETTY
));
5928 json_object_free(json
);
5933 * Display neighbors across all VNIs (VTY command handler).
5935 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5936 bool print_dup
, bool use_json
)
5938 json_object
*json
= NULL
;
5941 if (!is_evpn_enabled())
5945 json
= json_object_new_object();
5949 args
[2] = (void *)(ptrdiff_t)print_dup
;
5951 hash_iterate(zvrf
->vni_table
,
5952 (void (*)(struct hash_backet
*,
5953 void *))zvni_print_neigh_hash_all_vni
,
5956 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5957 json
, JSON_C_TO_STRING_PRETTY
));
5958 json_object_free(json
);
5963 * Display neighbors across all VNIs in detail(VTY command handler).
5965 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
5966 struct zebra_vrf
*zvrf
,
5967 bool print_dup
, bool use_json
)
5969 json_object
*json
= NULL
;
5972 if (!is_evpn_enabled())
5976 json
= json_object_new_object();
5980 args
[2] = (void *)(ptrdiff_t)print_dup
;
5982 hash_iterate(zvrf
->vni_table
,
5983 (void (*)(struct hash_backet
*,
5984 void *))zvni_print_neigh_hash_all_vni_detail
,
5987 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5988 json
, JSON_C_TO_STRING_PRETTY
));
5989 json_object_free(json
);
5994 * Display specific neighbor for a VNI, if present (VTY command handler).
5996 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5997 struct zebra_vrf
*zvrf
, vni_t vni
,
5998 struct ipaddr
*ip
, bool use_json
)
6002 json_object
*json
= NULL
;
6004 if (!is_evpn_enabled())
6006 zvni
= zvni_lookup(vni
);
6009 vty_out(vty
, "{}\n");
6011 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6014 n
= zvni_neigh_lookup(zvni
, ip
);
6018 "%% Requested neighbor does not exist in VNI %u\n",
6023 json
= json_object_new_object();
6025 zvni_print_neigh(n
, vty
, json
);
6028 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6029 json
, JSON_C_TO_STRING_PRETTY
));
6030 json_object_free(json
);
6035 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6036 * By definition, these are remote neighbors.
6038 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6039 vni_t vni
, struct in_addr vtep_ip
,
6044 struct neigh_walk_ctx wctx
;
6045 json_object
*json
= NULL
;
6047 if (!is_evpn_enabled())
6049 zvni
= zvni_lookup(vni
);
6052 vty_out(vty
, "{}\n");
6054 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6057 num_neigh
= hashcount(zvni
->neigh_table
);
6061 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6064 wctx
.addr_width
= 15;
6065 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6066 wctx
.r_vtep_ip
= vtep_ip
;
6068 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6069 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6072 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6073 json
, JSON_C_TO_STRING_PRETTY
));
6074 json_object_free(json
);
6079 * Display Duplicate detected Neighbors for a VNI
6080 * (VTY command handler).
6082 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6083 struct zebra_vrf
*zvrf
,
6089 struct neigh_walk_ctx wctx
;
6090 json_object
*json
= NULL
;
6092 if (!is_evpn_enabled())
6095 zvni
= zvni_lookup(vni
);
6097 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6101 num_neigh
= hashcount(zvni
->neigh_table
);
6105 num_neigh
= num_dup_detected_neighs(zvni
);
6110 json
= json_object_new_object();
6112 /* Since we have IPv6 addresses to deal with which can vary widely in
6113 * size, we try to be a bit more elegant in display by first computing
6114 * the maximum width.
6116 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6119 wctx
.addr_width
= 15;
6121 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6125 "Number of ARPs (local and remote) known for this VNI: %u\n",
6127 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6128 -wctx
.addr_width
, "IP", "Type",
6129 "State", "MAC", "Remote VTEP");
6131 json_object_int_add(json
, "numArpNd", num_neigh
);
6133 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6136 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6137 json
, JSON_C_TO_STRING_PRETTY
));
6138 json_object_free(json
);
6143 * Display MACs for a VNI (VTY command handler).
6145 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6146 vni_t vni
, bool use_json
)
6150 struct mac_walk_ctx wctx
;
6151 json_object
*json
= NULL
;
6152 json_object
*json_mac
= NULL
;
6154 if (!is_evpn_enabled())
6156 zvni
= zvni_lookup(vni
);
6159 vty_out(vty
, "{}\n");
6161 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6164 num_macs
= num_valid_macs(zvni
);
6169 json
= json_object_new_object();
6170 json_mac
= json_object_new_object();
6173 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6176 wctx
.json
= json_mac
;
6180 "Number of MACs (local and remote) known for this VNI: %u\n",
6182 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6183 "Intf/Remote VTEP", "VLAN");
6185 json_object_int_add(json
, "numMacs", num_macs
);
6187 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6190 json_object_object_add(json
, "macs", json_mac
);
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 MACs for all VNIs (VTY command handler).
6200 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6201 bool print_dup
, bool use_json
)
6203 struct mac_walk_ctx wctx
;
6204 json_object
*json
= NULL
;
6206 if (!is_evpn_enabled()) {
6208 vty_out(vty
, "{}\n");
6212 json
= json_object_new_object();
6214 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6217 wctx
.print_dup
= print_dup
;
6218 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6221 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6222 json
, JSON_C_TO_STRING_PRETTY
));
6223 json_object_free(json
);
6228 * Display MACs in detail for all VNIs (VTY command handler).
6230 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6231 struct zebra_vrf
*zvrf
,
6232 bool print_dup
, bool use_json
)
6234 struct mac_walk_ctx wctx
;
6235 json_object
*json
= NULL
;
6237 if (!is_evpn_enabled()) {
6239 vty_out(vty
, "{}\n");
6243 json
= json_object_new_object();
6245 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6248 wctx
.print_dup
= print_dup
;
6249 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6253 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6254 json
, JSON_C_TO_STRING_PRETTY
));
6255 json_object_free(json
);
6260 * Display MACs for all VNIs (VTY command handler).
6262 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6263 struct zebra_vrf
*zvrf
,
6264 struct in_addr vtep_ip
, bool use_json
)
6266 struct mac_walk_ctx wctx
;
6267 json_object
*json
= NULL
;
6269 if (!is_evpn_enabled())
6273 json
= json_object_new_object();
6275 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6277 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6278 wctx
.r_vtep_ip
= vtep_ip
;
6280 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6283 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6284 json
, JSON_C_TO_STRING_PRETTY
));
6285 json_object_free(json
);
6290 * Display specific MAC for a VNI, if present (VTY command handler).
6292 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6293 vni_t vni
, struct ethaddr
*macaddr
,
6298 json_object
*json
= NULL
;
6300 if (!is_evpn_enabled())
6303 zvni
= zvni_lookup(vni
);
6306 vty_out(vty
, "{}\n");
6308 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6311 mac
= zvni_mac_lookup(zvni
, macaddr
);
6314 vty_out(vty
, "{}\n");
6317 "%% Requested MAC does not exist in VNI %u\n",
6323 json
= json_object_new_object();
6325 zvni_print_mac(mac
, vty
, json
);
6327 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6328 json
, JSON_C_TO_STRING_PRETTY
));
6329 json_object_free(json
);
6333 /* Print Duplicate MACs per VNI */
6334 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6335 struct zebra_vrf
*zvrf
,
6336 vni_t vni
, bool use_json
)
6339 struct mac_walk_ctx wctx
;
6341 json_object
*json
= NULL
;
6342 json_object
*json_mac
= NULL
;
6344 if (!is_evpn_enabled())
6347 zvni
= zvni_lookup(vni
);
6349 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6353 num_macs
= num_valid_macs(zvni
);
6357 num_macs
= num_dup_detected_macs(zvni
);
6362 json
= json_object_new_object();
6363 json_mac
= json_object_new_object();
6366 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6369 wctx
.json
= json_mac
;
6373 "Number of MACs (local and remote) known for this VNI: %u\n",
6375 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6376 "Intf/Remote VTEP", "VLAN");
6378 json_object_int_add(json
, "numMacs", num_macs
);
6380 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6383 json_object_object_add(json
, "macs", json_mac
);
6384 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6385 json
, JSON_C_TO_STRING_PRETTY
));
6386 json_object_free(json
);
6391 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6392 struct zebra_vrf
*zvrf
,
6393 vni_t vni
, struct ethaddr
*macaddr
)
6397 struct listnode
*node
= NULL
;
6398 zebra_neigh_t
*nbr
= NULL
;
6400 if (!is_evpn_enabled())
6403 zvni
= zvni_lookup(vni
);
6405 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6409 mac
= zvni_mac_lookup(zvni
, macaddr
);
6411 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6416 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6417 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6421 /* Remove all IPs as duplicate associcated with this MAC */
6422 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6423 /* For local neigh mark inactive so MACIP update is generated
6424 * to BGP. This is a scenario where MAC update received
6425 * and detected as duplicate which marked neigh as duplicate.
6426 * Later local neigh update did not get a chance to relay
6427 * to BGP. Similarly remote macip update, neigh needs to be
6428 * installed locally.
6430 if (zvrf
->dad_freeze
&&
6431 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6432 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6433 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6434 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6435 zvni_neigh_install(zvni
, nbr
);
6438 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6440 nbr
->detect_start_time
.tv_sec
= 0;
6441 nbr
->dad_dup_detect_time
= 0;
6444 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6446 mac
->detect_start_time
.tv_sec
= 0;
6447 mac
->detect_start_time
.tv_usec
= 0;
6448 mac
->dad_dup_detect_time
= 0;
6449 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6451 /* warn-only action return */
6452 if (!zvrf
->dad_freeze
)
6455 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6456 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6458 if (zvni_mac_send_add_to_client(zvni
->vni
,
6464 /* Process all neighbors associated with this MAC. */
6465 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6467 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6468 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6470 /* Install the entry. */
6471 zvni_mac_install(zvni
, mac
);
6477 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6478 struct zebra_vrf
*zvrf
,
6479 vni_t vni
, struct ipaddr
*ip
)
6484 char buf
[INET6_ADDRSTRLEN
];
6485 char buf2
[ETHER_ADDR_STRLEN
];
6487 if (!is_evpn_enabled())
6490 zvni
= zvni_lookup(vni
);
6492 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6496 nbr
= zvni_neigh_lookup(zvni
, ip
);
6499 "%% Requested host IP does not exist in VNI %u\n",
6504 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6506 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6508 "%% Requsted host IP %s is not duplicate detected\n",
6513 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6515 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6517 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6518 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6519 return CMD_WARNING_CONFIG_FAILED
;
6522 if (IS_ZEBRA_DEBUG_VXLAN
)
6523 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6524 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6527 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6529 nbr
->detect_start_time
.tv_sec
= 0;
6530 nbr
->detect_start_time
.tv_usec
= 0;
6531 nbr
->dad_dup_detect_time
= 0;
6532 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6534 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6535 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6537 nbr
->flags
, nbr
->loc_seq
);
6538 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6539 zvni_neigh_install(zvni
, nbr
);
6545 static void zvni_clear_dup_mac_hash(struct hash_backet
*backet
, void *ctxt
)
6547 struct mac_walk_ctx
*wctx
= ctxt
;
6550 struct listnode
*node
= NULL
;
6551 zebra_neigh_t
*nbr
= NULL
;
6553 mac
= (zebra_mac_t
*)backet
->data
;
6559 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6562 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6564 mac
->detect_start_time
.tv_sec
= 0;
6565 mac
->detect_start_time
.tv_usec
= 0;
6566 mac
->dad_dup_detect_time
= 0;
6567 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6569 /* Remove all IPs as duplicate associcated with this MAC */
6570 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6571 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6573 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6575 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6577 nbr
->detect_start_time
.tv_sec
= 0;
6578 nbr
->dad_dup_detect_time
= 0;
6581 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6582 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6584 if (zvni_mac_send_add_to_client(zvni
->vni
,
6586 mac
->flags
, mac
->loc_seq
))
6589 /* Process all neighbors associated with this MAC. */
6590 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6592 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6593 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6595 /* Install the entry. */
6596 zvni_mac_install(zvni
, mac
);
6600 static void zvni_clear_dup_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
6602 struct neigh_walk_ctx
*wctx
= ctxt
;
6605 char buf
[INET6_ADDRSTRLEN
];
6607 nbr
= (zebra_neigh_t
*)backet
->data
;
6613 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6616 if (IS_ZEBRA_DEBUG_VXLAN
) {
6617 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6619 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6620 __PRETTY_FUNCTION__
, buf
,
6621 nbr
->flags
, nbr
->loc_seq
);
6624 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6626 nbr
->detect_start_time
.tv_sec
= 0;
6627 nbr
->detect_start_time
.tv_usec
= 0;
6628 nbr
->dad_dup_detect_time
= 0;
6629 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6631 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6632 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6634 nbr
->flags
, nbr
->loc_seq
);
6635 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6636 zvni_neigh_install(zvni
, nbr
);
6640 static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet
*backet
,
6645 struct zebra_vrf
*zvrf
;
6646 struct mac_walk_ctx m_wctx
;
6647 struct neigh_walk_ctx n_wctx
;
6649 zvni
= (zebra_vni_t
*)backet
->data
;
6653 vty
= (struct vty
*)args
[0];
6654 zvrf
= (struct zebra_vrf
*)args
[1];
6656 if (hashcount(zvni
->neigh_table
)) {
6657 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6661 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6665 if (num_valid_macs(zvni
)) {
6666 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6670 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6675 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6676 struct zebra_vrf
*zvrf
)
6680 if (!is_evpn_enabled())
6686 hash_iterate(zvrf
->vni_table
,
6687 (void (*)(struct hash_backet
*, void *))
6688 zvni_clear_dup_detect_hash_vni_all
, args
);
6693 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6694 struct zebra_vrf
*zvrf
,
6698 struct mac_walk_ctx m_wctx
;
6699 struct neigh_walk_ctx n_wctx
;
6701 if (!is_evpn_enabled())
6704 zvni
= zvni_lookup(vni
);
6706 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6710 if (hashcount(zvni
->neigh_table
)) {
6711 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6715 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6719 if (num_valid_macs(zvni
)) {
6720 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6724 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6731 * Display MACs for a VNI from specific VTEP (VTY command handler).
6733 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6734 vni_t vni
, struct in_addr vtep_ip
,
6739 struct mac_walk_ctx wctx
;
6740 json_object
*json
= NULL
;
6741 json_object
*json_mac
= NULL
;
6743 if (!is_evpn_enabled())
6745 zvni
= zvni_lookup(vni
);
6748 vty_out(vty
, "{}\n");
6750 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6753 num_macs
= num_valid_macs(zvni
);
6758 json
= json_object_new_object();
6759 json_mac
= json_object_new_object();
6762 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6765 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6766 wctx
.r_vtep_ip
= vtep_ip
;
6767 wctx
.json
= json_mac
;
6768 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6771 json_object_int_add(json
, "numMacs", wctx
.count
);
6773 json_object_object_add(json
, "macs", json_mac
);
6774 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6775 json
, JSON_C_TO_STRING_PRETTY
));
6776 json_object_free(json
);
6782 * Display VNI information (VTY command handler).
6784 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6787 json_object
*json
= NULL
;
6789 zebra_l3vni_t
*zl3vni
= NULL
;
6790 zebra_vni_t
*zvni
= NULL
;
6792 if (!is_evpn_enabled())
6796 json
= json_object_new_object();
6800 zl3vni
= zl3vni_lookup(vni
);
6802 zl3vni_print(zl3vni
, (void *)args
);
6804 zvni
= zvni_lookup(vni
);
6807 vty_out(vty
, "{}\n");
6809 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6813 zvni_print(zvni
, (void *)args
);
6817 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6818 json
, JSON_C_TO_STRING_PRETTY
));
6819 json_object_free(json
);
6823 /* Display all global details for EVPN */
6824 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6829 json_object
*json
= NULL
;
6830 struct zebra_vrf
*zvrf
= NULL
;
6832 if (!is_evpn_enabled())
6835 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6839 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6840 num_l2vnis
= hashcount(zvrf
->vni_table
);
6841 num_vnis
= num_l2vnis
+ num_l3vnis
;
6844 json
= json_object_new_object();
6845 json_object_string_add(json
, "advertiseGatewayMacip",
6846 zvrf
->advertise_gw_macip
? "Yes" : "No");
6847 json_object_int_add(json
, "numVnis", num_vnis
);
6848 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6849 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6850 if (zvrf
->dup_addr_detect
)
6851 json_object_boolean_true_add(json
,
6852 "isDuplicateAddrDetection");
6854 json_object_boolean_false_add(json
,
6855 "isDuplicateAddrDetection");
6856 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6857 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6858 json_object_int_add(json
, "detectionFreezeTime",
6859 zvrf
->dad_freeze_time
);
6862 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6863 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6864 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6865 zvrf
->advertise_gw_macip
? "Yes" : "No");
6866 vty_out(vty
, "Duplicate address detection: %s\n",
6867 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6868 vty_out(vty
, " Detection max-moves %u, time %d\n",
6869 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6870 if (zvrf
->dad_freeze
) {
6871 if (zvrf
->dad_freeze_time
)
6872 vty_out(vty
, " Detection freeze %u\n",
6873 zvrf
->dad_freeze_time
);
6875 vty_out(vty
, " Detection freeze %s\n",
6881 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6882 json
, JSON_C_TO_STRING_PRETTY
));
6883 json_object_free(json
);
6888 * Display VNI hash table (VTY command handler).
6890 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6893 json_object
*json
= NULL
;
6896 if (!is_evpn_enabled())
6900 json
= json_object_new_object();
6902 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6903 "Type", "VxLAN IF", "# MACs", "# ARPs",
6904 "# Remote VTEPs", "Tenant VRF");
6909 /* Display all L2-VNIs */
6910 hash_iterate(zvrf
->vni_table
,
6911 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
6914 /* Display all L3-VNIs */
6915 hash_iterate(zrouter
.l3vni_table
,
6916 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
6920 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6921 json
, JSON_C_TO_STRING_PRETTY
));
6922 json_object_free(json
);
6926 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
6930 uint32_t max_moves
= 0;
6931 uint32_t freeze_time
= 0;
6932 bool dup_addr_detect
= false;
6933 bool freeze
= false;
6936 STREAM_GETL(s
, dup_addr_detect
);
6937 STREAM_GETL(s
, time
);
6938 STREAM_GETL(s
, max_moves
);
6939 STREAM_GETL(s
, freeze
);
6940 STREAM_GETL(s
, freeze_time
);
6942 /* DAD previous state was enabled, and new state is disable,
6943 * clear all duplicate detected addresses.
6945 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
6946 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
6948 zvrf
->dup_addr_detect
= dup_addr_detect
;
6949 zvrf
->dad_time
= time
;
6950 zvrf
->dad_max_moves
= max_moves
;
6951 zvrf
->dad_freeze
= freeze
;
6952 zvrf
->dad_freeze_time
= freeze_time
;
6954 if (IS_ZEBRA_DEBUG_VXLAN
)
6956 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
6957 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
6958 zvrf
->dup_addr_detect
? "enable" : "disable",
6959 zvrf
->dad_max_moves
,
6961 zvrf
->dad_freeze
? "enable" : "disable",
6962 zvrf
->dad_freeze_time
);
6969 * Display VNI hash table in detail(VTY command handler).
6971 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6974 json_object
*json
= NULL
;
6975 struct zebra_ns
*zns
= NULL
;
6976 struct zvni_evpn_show zes
;
6978 if (!is_evpn_enabled())
6981 zns
= zebra_ns_lookup(NS_DEFAULT
);
6987 json
= json_object_new_object();
6993 /* Display all L2-VNIs */
6994 hash_iterate(zvrf
->vni_table
, (void (*)(struct hash_backet
*,
6995 void *))zvni_print_hash_detail
,
6998 /* Display all L3-VNIs */
6999 hash_iterate(zrouter
.l3vni_table
,
7000 (void (*)(struct hash_backet
*,
7001 void *))zl3vni_print_hash_detail
,
7005 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7006 json
, JSON_C_TO_STRING_PRETTY
));
7007 json_object_free(json
);
7012 * Handle neighbor delete notification from the kernel (on a VLAN device
7013 * / L3 interface). This may result in either the neighbor getting deleted
7014 * from our database or being re-added to the kernel (if it is a valid
7017 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7018 struct interface
*link_if
,
7021 char buf
[INET6_ADDRSTRLEN
];
7022 char buf2
[ETHER_ADDR_STRLEN
];
7023 zebra_neigh_t
*n
= NULL
;
7024 zebra_vni_t
*zvni
= NULL
;
7025 zebra_mac_t
*zmac
= NULL
;
7026 zebra_l3vni_t
*zl3vni
= NULL
;
7028 /* check if this is a remote neigh entry corresponding to remote
7031 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7033 return zl3vni_local_nh_del(zl3vni
, ip
);
7035 /* We are only interested in neighbors on an SVI that resides on top
7036 * of a VxLAN bridge.
7038 zvni
= zvni_from_svi(ifp
, link_if
);
7042 if (!zvni
->vxlan_if
) {
7044 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7049 if (IS_ZEBRA_DEBUG_VXLAN
)
7050 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7051 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7052 ifp
->ifindex
, zvni
->vni
);
7054 /* If entry doesn't exist, nothing to do. */
7055 n
= zvni_neigh_lookup(zvni
, ip
);
7059 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7061 if (IS_ZEBRA_DEBUG_VXLAN
)
7063 "Trying to del a neigh %s without a mac %s on VNI %u",
7064 ipaddr2str(ip
, buf
, sizeof(buf
)),
7065 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7071 /* If it is a remote entry, the kernel has aged this out or someone has
7072 * deleted it, it needs to be re-installed as Quagga is the owner.
7074 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7075 zvni_neigh_install(zvni
, n
);
7079 /* Remove neighbor from BGP. */
7080 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
7083 /* Delete this neighbor entry. */
7084 zvni_neigh_del(zvni
, n
);
7086 /* see if the AUTO mac needs to be deleted */
7087 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7088 && !listcount(zmac
->neigh_list
))
7089 zvni_mac_del(zvni
, zmac
);
7095 * Handle neighbor add or update notification from the kernel (on a VLAN
7096 * device / L3 interface). This is typically for a local neighbor but can
7097 * also be for a remote neighbor (e.g., ageout notification). It could
7098 * also be a "move" scenario.
7100 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7101 struct interface
*link_if
,
7103 struct ethaddr
*macaddr
,
7108 char buf
[ETHER_ADDR_STRLEN
];
7109 char buf2
[INET6_ADDRSTRLEN
];
7110 zebra_vni_t
*zvni
= NULL
;
7111 zebra_l3vni_t
*zl3vni
= NULL
;
7113 /* check if this is a remote neigh entry corresponding to remote
7116 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7118 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7120 /* We are only interested in neighbors on an SVI that resides on top
7121 * of a VxLAN bridge.
7123 zvni
= zvni_from_svi(ifp
, link_if
);
7127 if (IS_ZEBRA_DEBUG_VXLAN
)
7129 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7130 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7131 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7132 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7133 is_router
? "router " : "",
7136 /* Is this about a local neighbor or a remote one? */
7138 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7141 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7146 * Handle message from client to delete a remote MACIP for a VNI.
7148 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7152 struct ethaddr macaddr
;
7154 struct in_addr vtep_ip
;
7155 uint16_t l
= 0, ipa_len
;
7156 char buf
[ETHER_ADDR_STRLEN
];
7157 char buf1
[INET6_ADDRSTRLEN
];
7159 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7160 memset(&ip
, 0, sizeof(struct ipaddr
));
7161 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7165 while (l
< hdr
->length
) {
7166 /* Obtain each remote MACIP and process. */
7167 /* Message contains VNI, followed by MAC followed by IP (if any)
7168 * followed by remote VTEP IP.
7170 memset(&ip
, 0, sizeof(ip
));
7171 STREAM_GETL(s
, vni
);
7172 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7173 STREAM_GETL(s
, ipa_len
);
7175 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7177 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7179 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7180 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7181 l
+= IPV4_MAX_BYTELEN
;
7183 if (IS_ZEBRA_DEBUG_VXLAN
)
7185 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7187 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7188 ipa_len
? " IP " : "",
7190 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7192 zebra_route_string(client
->proto
));
7194 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7202 * Handle message from client to add a remote MACIP for a VNI. This
7203 * could be just the add of a MAC address or the add of a neighbor
7206 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7210 struct ethaddr macaddr
;
7212 struct in_addr vtep_ip
;
7213 uint16_t l
= 0, ipa_len
;
7216 char buf
[ETHER_ADDR_STRLEN
];
7217 char buf1
[INET6_ADDRSTRLEN
];
7219 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7220 memset(&ip
, 0, sizeof(struct ipaddr
));
7221 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7223 if (!EVPN_ENABLED(zvrf
)) {
7224 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7230 while (l
< hdr
->length
) {
7231 /* Obtain each remote MACIP and process. */
7232 /* Message contains VNI, followed by MAC followed by IP (if any)
7233 * followed by remote VTEP IP.
7235 memset(&ip
, 0, sizeof(ip
));
7236 STREAM_GETL(s
, vni
);
7237 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7238 STREAM_GETL(s
, ipa_len
);
7240 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7242 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7244 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7245 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7246 l
+= IPV4_MAX_BYTELEN
;
7248 /* Get flags - sticky mac and/or gateway mac */
7249 STREAM_GETC(s
, flags
);
7251 STREAM_GETL(s
, seq
);
7254 if (IS_ZEBRA_DEBUG_VXLAN
)
7256 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7258 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7259 ipa_len
? " IP " : "",
7261 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7262 flags
, seq
, inet_ntoa(vtep_ip
),
7263 zebra_route_string(client
->proto
));
7265 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7266 flags
, seq
, vtep_ip
);
7274 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7275 * us, this must involve a multihoming scenario. Treat this as implicit delete
7276 * of any prior local MAC.
7278 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7279 struct interface
*br_if
,
7280 struct ethaddr
*macaddr
, vlanid_t vid
)
7282 struct zebra_if
*zif
;
7283 struct zebra_l2info_vxlan
*vxl
;
7287 char buf
[ETHER_ADDR_STRLEN
];
7291 vxl
= &zif
->l2info
.vxl
;
7294 /* Check if EVPN is enabled. */
7295 if (!is_evpn_enabled())
7298 /* Locate hash entry; it is expected to exist. */
7299 zvni
= zvni_lookup(vni
);
7303 /* If entry doesn't exist, nothing to do. */
7304 mac
= zvni_mac_lookup(zvni
, macaddr
);
7308 /* Is it a local entry? */
7309 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7312 if (IS_ZEBRA_DEBUG_VXLAN
)
7314 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7315 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7318 /* Remove MAC from BGP. */
7319 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7322 * If there are no neigh associated with the mac delete the mac
7323 * else mark it as AUTO for forward reference
7325 if (!listcount(mac
->neigh_list
)) {
7326 zvni_mac_del(zvni
, mac
);
7328 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7329 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7336 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7337 * This can happen because the remote MAC entries are also added as "dynamic",
7338 * so the kernel can ageout the entry.
7340 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7341 struct interface
*br_if
,
7342 struct ethaddr
*macaddr
, vlanid_t vid
)
7344 struct zebra_if
*zif
= NULL
;
7345 struct zebra_l2info_vxlan
*vxl
= NULL
;
7347 zebra_vni_t
*zvni
= NULL
;
7348 zebra_l3vni_t
*zl3vni
= NULL
;
7349 zebra_mac_t
*mac
= NULL
;
7350 char buf
[ETHER_ADDR_STRLEN
];
7354 vxl
= &zif
->l2info
.vxl
;
7357 /* Check if EVPN is enabled. */
7358 if (!is_evpn_enabled())
7361 /* check if this is a remote RMAC and readd simillar to remote macs */
7362 zl3vni
= zl3vni_lookup(vni
);
7364 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7366 /* Locate hash entry; it is expected to exist. */
7367 zvni
= zvni_lookup(vni
);
7371 /* If entry doesn't exist, nothing to do. */
7372 mac
= zvni_mac_lookup(zvni
, macaddr
);
7376 /* Is it a remote entry? */
7377 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7380 if (IS_ZEBRA_DEBUG_VXLAN
)
7381 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7382 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7385 zvni_mac_install(zvni
, mac
);
7390 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7392 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7393 struct ethaddr
*macaddr
, vlanid_t vid
)
7397 char buf
[ETHER_ADDR_STRLEN
];
7399 /* We are interested in MACs only on ports or (port, VLAN) that
7402 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7405 if (!zvni
->vxlan_if
) {
7407 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7412 if (IS_ZEBRA_DEBUG_VXLAN
)
7413 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7414 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7415 ifp
->ifindex
, vid
, zvni
->vni
);
7417 /* If entry doesn't exist, nothing to do. */
7418 mac
= zvni_mac_lookup(zvni
, macaddr
);
7422 /* Is it a local entry? */
7423 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7426 /* Update all the neigh entries associated with this mac */
7427 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7429 /* Remove MAC from BGP. */
7430 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7433 * If there are no neigh associated with the mac delete the mac
7434 * else mark it as AUTO for forward reference
7436 if (!listcount(mac
->neigh_list
)) {
7437 zvni_mac_del(zvni
, mac
);
7439 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7440 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7447 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7449 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7450 struct interface
*br_if
,
7451 struct ethaddr
*macaddr
, vlanid_t vid
,
7456 struct zebra_vrf
*zvrf
;
7457 char buf
[ETHER_ADDR_STRLEN
];
7458 bool mac_sticky
= false;
7459 bool inform_client
= false;
7460 bool upd_neigh
= false;
7461 bool is_dup_detect
= false;
7462 struct in_addr vtep_ip
= {.s_addr
= 0};
7464 /* We are interested in MACs only on ports or (port, VLAN) that
7467 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7469 if (IS_ZEBRA_DEBUG_VXLAN
)
7471 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7472 sticky
? "sticky " : "",
7473 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7474 ifp
->name
, ifp
->ifindex
, vid
);
7478 if (!zvni
->vxlan_if
) {
7480 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7485 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7489 /* Check if we need to create or update or it is a NO-OP. */
7490 mac
= zvni_mac_lookup(zvni
, macaddr
);
7492 if (IS_ZEBRA_DEBUG_VXLAN
)
7494 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7495 sticky
? "sticky " : "",
7496 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7497 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7499 mac
= zvni_mac_add(zvni
, macaddr
);
7502 EC_ZEBRA_MAC_ADD_FAILED
,
7503 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7504 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7505 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7508 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7509 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7510 mac
->fwd_info
.local
.vid
= vid
;
7512 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7513 inform_client
= true;
7516 if (IS_ZEBRA_DEBUG_VXLAN
)
7518 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7519 sticky
? "sticky " : "",
7520 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7521 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7524 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7525 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7529 * Update any changes and if changes are relevant to
7532 if (mac_sticky
== sticky
7533 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7534 && mac
->fwd_info
.local
.vid
== vid
) {
7535 if (IS_ZEBRA_DEBUG_VXLAN
)
7537 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7538 "entry exists and has not changed ",
7539 sticky
? "sticky " : "",
7540 prefix_mac2str(macaddr
, buf
,
7542 ifp
->name
, ifp
->ifindex
, vid
,
7546 if (mac_sticky
!= sticky
) {
7548 SET_FLAG(mac
->flags
,
7551 UNSET_FLAG(mac
->flags
,
7553 inform_client
= true;
7556 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7557 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7558 mac
->fwd_info
.local
.vid
= vid
;
7560 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7561 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7562 bool do_dad
= false;
7565 * MAC has either moved or was "internally" created due
7566 * to a neighbor learn and is now actually learnt. If
7567 * it was learnt as a remote sticky MAC, this is an
7570 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7572 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7573 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7574 prefix_mac2str(macaddr
, buf
,
7576 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7581 /* If an actual move, compute MAC's seq number */
7582 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7583 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7585 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7586 /* Trigger DAD for remote MAC */
7590 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7591 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7592 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7593 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7594 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7595 mac
->fwd_info
.local
.vid
= vid
;
7597 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7599 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7601 * We have to inform BGP of this MAC as well as process
7604 inform_client
= true;
7607 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7611 if (is_dup_detect
) {
7612 inform_client
= false;
7618 /* Inform BGP if required. */
7619 if (inform_client
) {
7620 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7621 mac
->flags
, mac
->loc_seq
))
7625 /* Process all neighbors associated with this MAC, if required. */
7627 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7633 * Handle message from client to delete a remote VTEP for a VNI.
7635 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7638 unsigned short l
= 0;
7640 struct in_addr vtep_ip
;
7642 zebra_vtep_t
*zvtep
;
7643 struct interface
*ifp
;
7644 struct zebra_if
*zif
;
7646 if (!is_evpn_enabled()) {
7648 "%s: EVPN is not enabled yet we have received a vtep del command",
7649 __PRETTY_FUNCTION__
);
7653 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7654 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7661 while (l
< hdr
->length
) {
7662 /* Obtain each remote VTEP and process. */
7663 STREAM_GETL(s
, vni
);
7665 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7666 l
+= IPV4_MAX_BYTELEN
;
7668 if (IS_ZEBRA_DEBUG_VXLAN
)
7669 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7670 inet_ntoa(vtep_ip
), vni
,
7671 zebra_route_string(client
->proto
));
7673 /* Locate VNI hash entry - expected to exist. */
7674 zvni
= zvni_lookup(vni
);
7676 if (IS_ZEBRA_DEBUG_VXLAN
)
7678 "Failed to locate VNI hash upon remote VTEP DEL, "
7684 ifp
= zvni
->vxlan_if
;
7687 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7693 /* If down or not mapped to a bridge, we're done. */
7694 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7697 /* If the remote VTEP does not exist, there's nothing more to
7699 * Otherwise, uninstall any remote MACs pointing to this VTEP
7701 * then, the VTEP entry itself and remove it.
7703 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7707 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7708 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7709 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7710 zvni_vtep_del(zvni
, zvtep
);
7718 * Handle message from client to add a remote VTEP for a VNI.
7720 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7723 unsigned short l
= 0;
7725 struct in_addr vtep_ip
;
7727 struct interface
*ifp
;
7728 struct zebra_if
*zif
;
7730 if (!is_evpn_enabled()) {
7732 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7733 __PRETTY_FUNCTION__
);
7737 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7738 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7745 while (l
< hdr
->length
) {
7746 /* Obtain each remote VTEP and process. */
7747 STREAM_GETL(s
, vni
);
7749 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7750 l
+= IPV4_MAX_BYTELEN
;
7752 if (IS_ZEBRA_DEBUG_VXLAN
)
7753 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7754 inet_ntoa(vtep_ip
), vni
,
7755 zebra_route_string(client
->proto
));
7757 /* Locate VNI hash entry - expected to exist. */
7758 zvni
= zvni_lookup(vni
);
7761 EC_ZEBRA_VTEP_ADD_FAILED
,
7762 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7767 ifp
= zvni
->vxlan_if
;
7770 EC_ZEBRA_VTEP_ADD_FAILED
,
7771 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7778 /* If down or not mapped to a bridge, we're done. */
7779 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7782 /* If the remote VTEP already exists,
7783 there's nothing more to do. */
7784 if (zvni_vtep_find(zvni
, &vtep_ip
))
7787 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7788 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7789 "Failed to add remote VTEP, VNI %u zvni %p",
7794 zvni_vtep_install(zvni
, &vtep_ip
);
7802 * Add/Del gateway macip to evpn
7804 * 1. SVI interface on a vlan aware bridge
7805 * 2. SVI interface on a vlan unaware bridge
7806 * 3. vrr interface (MACVLAN) associated to a SVI
7807 * We advertise macip routes for an interface if it is associated to VxLan vlan
7809 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7813 struct ethaddr macaddr
;
7814 zebra_vni_t
*zvni
= NULL
;
7816 memset(&ip
, 0, sizeof(struct ipaddr
));
7817 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7819 /* Check if EVPN is enabled. */
7820 if (!is_evpn_enabled())
7823 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7824 struct interface
*svi_if
=
7825 NULL
; /* SVI corresponding to the MACVLAN */
7826 struct zebra_if
*ifp_zif
=
7827 NULL
; /* Zebra daemon specific info for MACVLAN */
7828 struct zebra_if
*svi_if_zif
=
7829 NULL
; /* Zebra daemon specific info for SVI*/
7831 ifp_zif
= ifp
->info
;
7836 * for a MACVLAN interface the link represents the svi_if
7838 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7839 ifp_zif
->link_ifindex
);
7841 zlog_debug("MACVLAN %s(%u) without link information",
7842 ifp
->name
, ifp
->ifindex
);
7846 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7848 * If it is a vlan aware bridge then the link gives the
7849 * bridge information
7851 struct interface
*svi_if_link
= NULL
;
7853 svi_if_zif
= svi_if
->info
;
7855 svi_if_link
= if_lookup_by_index_per_ns(
7856 zebra_ns_lookup(NS_DEFAULT
),
7857 svi_if_zif
->link_ifindex
);
7858 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7860 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7862 * If it is a vlan unaware bridge then svi is the bridge
7865 zvni
= zvni_from_svi(svi_if
, svi_if
);
7867 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7868 struct zebra_if
*svi_if_zif
=
7869 NULL
; /* Zebra daemon specific info for SVI */
7870 struct interface
*svi_if_link
=
7871 NULL
; /* link info for the SVI = bridge info */
7873 svi_if_zif
= ifp
->info
;
7875 svi_if_link
= if_lookup_by_index_per_ns(
7876 zebra_ns_lookup(NS_DEFAULT
),
7877 svi_if_zif
->link_ifindex
);
7879 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7881 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7882 zvni
= zvni_from_svi(ifp
, ifp
);
7888 if (!zvni
->vxlan_if
) {
7889 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
7895 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
7897 if (p
->family
== AF_INET
) {
7898 ip
.ipa_type
= IPADDR_V4
;
7899 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
7900 sizeof(struct in_addr
));
7901 } else if (p
->family
== AF_INET6
) {
7902 ip
.ipa_type
= IPADDR_V6
;
7903 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
7904 sizeof(struct in6_addr
));
7909 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
7911 zvni_gw_macip_del(ifp
, zvni
, &ip
);
7917 * Handle SVI interface going down.
7918 * SVI can be associated to either L3-VNI or L2-VNI.
7919 * For L2-VNI: At this point, this is a NOP since
7920 * the kernel deletes the neighbor entries on this SVI (if any).
7921 * We only need to update the vrf corresponding to zvni.
7922 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
7925 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
7927 zebra_l3vni_t
*zl3vni
= NULL
;
7929 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7932 /* process l3-vni down */
7933 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7935 /* remove association with svi-if */
7936 zl3vni
->svi_if
= NULL
;
7938 zebra_vni_t
*zvni
= NULL
;
7940 /* since we dont have svi corresponding to zvni, we associate it
7941 * to default vrf. Note: the corresponding neigh entries on the
7942 * SVI would have already been deleted */
7943 zvni
= zvni_from_svi(ifp
, link_if
);
7945 zvni
->vrf_id
= VRF_DEFAULT
;
7947 /* update the tenant vrf in BGP */
7948 zvni_send_add_to_client(zvni
);
7955 * Handle SVI interface coming up.
7956 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
7958 * For L2-VNI: we need to install any remote neighbors entried (used for
7960 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
7962 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
7964 zebra_vni_t
*zvni
= NULL
;
7965 zebra_l3vni_t
*zl3vni
= NULL
;
7967 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7970 /* associate with svi */
7971 zl3vni
->svi_if
= ifp
;
7973 /* process oper-up */
7974 if (is_l3vni_oper_up(zl3vni
))
7975 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7978 /* process SVI up for l2-vni */
7979 struct neigh_walk_ctx n_wctx
;
7981 zvni
= zvni_from_svi(ifp
, link_if
);
7985 if (!zvni
->vxlan_if
) {
7987 "VNI %u hash %p doesn't have intf upon SVI up",
7992 if (IS_ZEBRA_DEBUG_VXLAN
)
7994 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
7995 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
7996 vrf_id_to_name(ifp
->vrf_id
));
7998 /* update the vrf information for l2-vni and inform bgp */
7999 zvni
->vrf_id
= ifp
->vrf_id
;
8000 zvni_send_add_to_client(zvni
);
8002 /* Install any remote neighbors for this VNI. */
8003 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8005 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8013 * Handle VxLAN interface down
8015 int zebra_vxlan_if_down(struct interface
*ifp
)
8018 struct zebra_if
*zif
= NULL
;
8019 struct zebra_l2info_vxlan
*vxl
= NULL
;
8020 zebra_l3vni_t
*zl3vni
= NULL
;
8023 /* Check if EVPN is enabled. */
8024 if (!is_evpn_enabled())
8029 vxl
= &zif
->l2info
.vxl
;
8032 zl3vni
= zl3vni_lookup(vni
);
8034 /* process-if-down for l3-vni */
8035 if (IS_ZEBRA_DEBUG_VXLAN
)
8036 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8039 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8041 /* process if-down for l2-vni */
8042 if (IS_ZEBRA_DEBUG_VXLAN
)
8043 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8046 /* Locate hash entry; it is expected to exist. */
8047 zvni
= zvni_lookup(vni
);
8050 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8051 ifp
->name
, ifp
->ifindex
, vni
);
8055 assert(zvni
->vxlan_if
== ifp
);
8057 /* Delete this VNI from BGP. */
8058 zvni_send_del_to_client(zvni
->vni
);
8060 /* Free up all neighbors and MACs, if any. */
8061 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8062 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8064 /* Free up all remote VTEPs, if any. */
8065 zvni_vtep_del_all(zvni
, 1);
8071 * Handle VxLAN interface up - update BGP if required.
8073 int zebra_vxlan_if_up(struct interface
*ifp
)
8076 struct zebra_if
*zif
= NULL
;
8077 struct zebra_l2info_vxlan
*vxl
= NULL
;
8078 zebra_vni_t
*zvni
= NULL
;
8079 zebra_l3vni_t
*zl3vni
= NULL
;
8081 /* Check if EVPN is enabled. */
8082 if (!is_evpn_enabled())
8087 vxl
= &zif
->l2info
.vxl
;
8090 zl3vni
= zl3vni_lookup(vni
);
8093 if (IS_ZEBRA_DEBUG_VXLAN
)
8094 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8097 /* we need to associate with SVI, if any, we can associate with
8098 * svi-if only after association with vxlan-intf is complete
8100 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8102 if (is_l3vni_oper_up(zl3vni
))
8103 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8105 /* Handle L2-VNI add */
8106 struct interface
*vlan_if
= NULL
;
8108 if (IS_ZEBRA_DEBUG_VXLAN
)
8109 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8112 /* Locate hash entry; it is expected to exist. */
8113 zvni
= zvni_lookup(vni
);
8116 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8117 ifp
->name
, ifp
->ifindex
, vni
);
8121 assert(zvni
->vxlan_if
== ifp
);
8122 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8123 zif
->brslave_info
.br_if
);
8125 zvni
->vrf_id
= vlan_if
->vrf_id
;
8126 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8128 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8131 /* If part of a bridge, inform BGP about this VNI. */
8132 /* Also, read and populate local MACs and neighbors. */
8133 if (zif
->brslave_info
.br_if
) {
8134 zvni_send_add_to_client(zvni
);
8135 zvni_read_mac_neigh(zvni
, ifp
);
8143 * Handle VxLAN interface delete. Locate and remove entry in hash table
8144 * and update BGP, if required.
8146 int zebra_vxlan_if_del(struct interface
*ifp
)
8149 struct zebra_if
*zif
= NULL
;
8150 struct zebra_l2info_vxlan
*vxl
= NULL
;
8151 zebra_vni_t
*zvni
= NULL
;
8152 zebra_l3vni_t
*zl3vni
= NULL
;
8154 /* Check if EVPN is enabled. */
8155 if (!is_evpn_enabled())
8160 vxl
= &zif
->l2info
.vxl
;
8163 zl3vni
= zl3vni_lookup(vni
);
8166 if (IS_ZEBRA_DEBUG_VXLAN
)
8167 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8170 /* process oper-down for l3-vni */
8171 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8173 /* remove the association with vxlan_if */
8174 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8175 zl3vni
->vxlan_if
= NULL
;
8178 /* process if-del for l2-vni*/
8179 if (IS_ZEBRA_DEBUG_VXLAN
)
8180 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8183 /* Locate hash entry; it is expected to exist. */
8184 zvni
= zvni_lookup(vni
);
8187 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8188 ifp
->name
, ifp
->ifindex
, vni
);
8192 /* remove from l3-vni list */
8193 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8195 listnode_delete(zl3vni
->l2vnis
, zvni
);
8197 /* Delete VNI from BGP. */
8198 zvni_send_del_to_client(zvni
->vni
);
8200 /* Free up all neighbors and MAC, if any. */
8201 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8202 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8204 /* Free up all remote VTEPs, if any. */
8205 zvni_vtep_del_all(zvni
, 0);
8207 /* Delete the hash entry. */
8208 if (zvni_del(zvni
)) {
8209 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8210 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8211 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8219 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8221 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8224 struct zebra_if
*zif
= NULL
;
8225 struct zebra_l2info_vxlan
*vxl
= NULL
;
8226 zebra_vni_t
*zvni
= NULL
;
8227 zebra_l3vni_t
*zl3vni
= NULL
;
8229 /* Check if EVPN is enabled. */
8230 if (!is_evpn_enabled())
8235 vxl
= &zif
->l2info
.vxl
;
8238 zl3vni
= zl3vni_lookup(vni
);
8241 if (IS_ZEBRA_DEBUG_VXLAN
)
8243 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8244 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8245 inet_ntoa(vxl
->vtep_ip
),
8246 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8248 /* Removed from bridge? Cleanup and return */
8249 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8250 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8251 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8255 /* access-vlan change - process oper down, associate with new
8256 * svi_if and then process oper up again
8258 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8259 if (if_is_operative(ifp
)) {
8260 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8261 zl3vni
->svi_if
= NULL
;
8262 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8263 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8264 if (is_l3vni_oper_up(zl3vni
))
8265 zebra_vxlan_process_l3vni_oper_up(
8271 * local-ip change - process oper down, associate with new
8272 * local-ip and then process oper up again
8274 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8275 if (if_is_operative(ifp
)) {
8276 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8277 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8278 if (is_l3vni_oper_up(zl3vni
))
8279 zebra_vxlan_process_l3vni_oper_up(
8284 /* Update local tunnel IP. */
8285 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8287 /* if we have a valid new master, process l3-vni oper up */
8288 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8289 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8290 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8294 /* Update VNI hash. */
8295 zvni
= zvni_lookup(vni
);
8298 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8299 ifp
->name
, ifp
->ifindex
, vni
);
8303 if (IS_ZEBRA_DEBUG_VXLAN
)
8305 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8306 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8307 inet_ntoa(vxl
->vtep_ip
),
8308 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8310 /* Removed from bridge? Cleanup and return */
8311 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8312 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8313 /* Delete from client, remove all remote VTEPs */
8314 /* Also, free up all MACs and neighbors. */
8315 zvni_send_del_to_client(zvni
->vni
);
8316 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8317 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8318 zvni_vtep_del_all(zvni
, 1);
8322 /* Handle other changes. */
8323 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8324 /* Remove all existing local neigh and MACs for this VNI
8325 * (including from BGP)
8327 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8328 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8331 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8332 zvni
->vxlan_if
= ifp
;
8334 /* Take further actions needed.
8335 * Note that if we are here, there is a change of interest.
8337 /* If down or not mapped to a bridge, we're done. */
8338 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8341 /* Inform BGP, if there is a change of interest. */
8343 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8344 zvni_send_add_to_client(zvni
);
8346 /* If there is a valid new master or a VLAN mapping change,
8347 * read and populate local MACs and neighbors.
8348 * Also, reinstall any remote MACs and neighbors
8349 * for this VNI (based on new VLAN).
8351 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8352 zvni_read_mac_neigh(zvni
, ifp
);
8353 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8354 struct mac_walk_ctx m_wctx
;
8355 struct neigh_walk_ctx n_wctx
;
8357 zvni_read_mac_neigh(zvni
, ifp
);
8359 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8361 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8364 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8366 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8375 * Handle VxLAN interface add.
8377 int zebra_vxlan_if_add(struct interface
*ifp
)
8380 struct zebra_if
*zif
= NULL
;
8381 struct zebra_l2info_vxlan
*vxl
= NULL
;
8382 zebra_vni_t
*zvni
= NULL
;
8383 zebra_l3vni_t
*zl3vni
= NULL
;
8385 /* Check if EVPN is enabled. */
8386 if (!is_evpn_enabled())
8391 vxl
= &zif
->l2info
.vxl
;
8394 zl3vni
= zl3vni_lookup(vni
);
8397 /* process if-add for l3-vni*/
8398 if (IS_ZEBRA_DEBUG_VXLAN
)
8400 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8401 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8402 inet_ntoa(vxl
->vtep_ip
),
8403 zif
->brslave_info
.bridge_ifindex
);
8405 /* associate with vxlan_if */
8406 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8407 zl3vni
->vxlan_if
= ifp
;
8409 /* Associate with SVI, if any. We can associate with svi-if only
8410 * after association with vxlan_if is complete */
8411 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8413 if (is_l3vni_oper_up(zl3vni
))
8414 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8417 /* process if-add for l2-vni */
8418 struct interface
*vlan_if
= NULL
;
8420 /* Create or update VNI hash. */
8421 zvni
= zvni_lookup(vni
);
8423 zvni
= zvni_add(vni
);
8426 EC_ZEBRA_VNI_ADD_FAILED
,
8427 "Failed to add VNI hash, IF %s(%u) VNI %u",
8428 ifp
->name
, ifp
->ifindex
, vni
);
8433 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8434 zvni
->vxlan_if
= ifp
;
8435 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8436 zif
->brslave_info
.br_if
);
8438 zvni
->vrf_id
= vlan_if
->vrf_id
;
8439 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8441 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8444 if (IS_ZEBRA_DEBUG_VXLAN
)
8446 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8448 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8450 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8451 inet_ntoa(vxl
->vtep_ip
),
8452 zif
->brslave_info
.bridge_ifindex
);
8454 /* If down or not mapped to a bridge, we're done. */
8455 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8459 zvni_send_add_to_client(zvni
);
8461 /* Read and populate local MACs and neighbors */
8462 zvni_read_mac_neigh(zvni
, ifp
);
8468 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8469 char *err
, int err_str_sz
, int filter
,
8472 zebra_l3vni_t
*zl3vni
= NULL
;
8473 struct zebra_vrf
*zvrf_default
= NULL
;
8475 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8479 if (IS_ZEBRA_DEBUG_VXLAN
)
8480 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8481 add
? "ADD" : "DEL");
8485 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8487 /* check if the vni is already present under zvrf */
8489 snprintf(err
, err_str_sz
,
8490 "VNI is already configured under the vrf");
8494 /* check if this VNI is already present in the system */
8495 zl3vni
= zl3vni_lookup(vni
);
8497 snprintf(err
, err_str_sz
,
8498 "VNI is already configured as L3-VNI");
8502 /* add the L3-VNI to the global table */
8503 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8505 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8509 /* associate the vrf with vni */
8512 /* set the filter in l3vni to denote if we are using l3vni only
8516 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8518 /* associate with vxlan-intf;
8519 * we need to associate with the vxlan-intf first
8521 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8523 /* associate with corresponding SVI interface, we can associate
8524 * with svi-if only after vxlan interface association is
8527 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8529 /* formulate l2vni list */
8530 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8533 if (is_l3vni_oper_up(zl3vni
))
8534 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8537 zl3vni
= zl3vni_lookup(vni
);
8539 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8543 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8544 snprintf(err
, ERR_STR_SZ
,
8545 "prefix-routes-only is not set for the vni");
8549 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8551 /* delete and uninstall all rmacs */
8552 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8555 /* delete and uninstall all next-hops */
8556 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8562 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8567 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8569 zebra_l3vni_t
*zl3vni
= NULL
;
8572 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8576 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8577 if (is_l3vni_oper_up(zl3vni
))
8578 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8582 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8584 zebra_l3vni_t
*zl3vni
= NULL
;
8587 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8591 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8592 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8596 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8598 zebra_l3vni_t
*zl3vni
= NULL
;
8602 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8608 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8614 * Handle message from client to specify the flooding mechanism for
8615 * BUM packets. The default is to do head-end (ingress) replication
8616 * and the other supported option is to disable it. This applies to
8617 * all BUM traffic and disabling it applies to both the transmit and
8618 * receive direction.
8620 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8623 enum vxlan_flood_control flood_ctrl
;
8625 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8626 zlog_err("EVPN flood control for non-default VRF %u",
8632 STREAM_GETC(s
, flood_ctrl
);
8634 if (IS_ZEBRA_DEBUG_VXLAN
)
8635 zlog_debug("EVPN flood control %u, currently %u",
8636 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8638 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8641 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8643 /* Install or uninstall flood entries corresponding to
8646 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8654 * Handle message from client to enable/disable advertisement of g/w macip
8657 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8662 zebra_vni_t
*zvni
= NULL
;
8663 struct interface
*ifp
= NULL
;
8664 struct zebra_if
*zif
= NULL
;
8665 struct zebra_l2info_vxlan zl2_info
;
8666 struct interface
*vlan_if
= NULL
;
8668 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8669 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8675 STREAM_GETC(s
, advertise
);
8676 vni
= stream_get3(s
);
8678 zvni
= zvni_lookup(vni
);
8682 if (zvni
->advertise_subnet
== advertise
)
8685 if (IS_ZEBRA_DEBUG_VXLAN
)
8686 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8687 advertise
? "enabled" : "disabled", vni
,
8688 zvni
->advertise_subnet
? "enabled" : "disabled");
8691 zvni
->advertise_subnet
= advertise
;
8693 ifp
= zvni
->vxlan_if
;
8699 /* If down or not mapped to a bridge, we're done. */
8700 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8703 zl2_info
= zif
->l2info
.vxl
;
8706 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8710 if (zvni
->advertise_subnet
)
8711 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8713 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8720 * Handle message from client to enable/disable advertisement of g/w macip
8723 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8728 zebra_vni_t
*zvni
= NULL
;
8729 struct interface
*ifp
= NULL
;
8731 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8732 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8738 STREAM_GETC(s
, advertise
);
8739 STREAM_GETL(s
, vni
);
8742 if (IS_ZEBRA_DEBUG_VXLAN
)
8743 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8744 advertise
? "enabled" : "disabled",
8745 advertise_gw_macip_enabled(NULL
)
8749 if (zvrf
->advertise_gw_macip
== advertise
)
8752 zvrf
->advertise_gw_macip
= advertise
;
8754 if (advertise_gw_macip_enabled(zvni
))
8755 hash_iterate(zvrf
->vni_table
,
8756 zvni_gw_macip_add_for_vni_hash
, NULL
);
8758 hash_iterate(zvrf
->vni_table
,
8759 zvni_gw_macip_del_for_vni_hash
, NULL
);
8762 struct zebra_if
*zif
= NULL
;
8763 struct zebra_l2info_vxlan zl2_info
;
8764 struct interface
*vlan_if
= NULL
;
8765 struct interface
*vrr_if
= NULL
;
8767 zvni
= zvni_lookup(vni
);
8771 if (IS_ZEBRA_DEBUG_VXLAN
)
8773 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8774 advertise
? "enabled" : "disabled", vni
,
8775 advertise_gw_macip_enabled(zvni
) ? "enabled"
8778 if (zvni
->advertise_gw_macip
== advertise
)
8781 zvni
->advertise_gw_macip
= advertise
;
8783 ifp
= zvni
->vxlan_if
;
8789 /* If down or not mapped to a bridge, we're done. */
8790 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8793 zl2_info
= zif
->l2info
.vxl
;
8795 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8796 zif
->brslave_info
.br_if
);
8800 if (advertise_gw_macip_enabled(zvni
)) {
8801 /* Add primary SVI MAC-IP */
8802 zvni_add_macip_for_intf(vlan_if
, zvni
);
8804 /* Add VRR MAC-IP - if any*/
8805 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8807 zvni_add_macip_for_intf(vrr_if
, zvni
);
8809 /* Del primary MAC-IP */
8810 zvni_del_macip_for_intf(vlan_if
, zvni
);
8812 /* Del VRR MAC-IP - if any*/
8813 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8815 zvni_del_macip_for_intf(vrr_if
, zvni
);
8825 * Handle message from client to learn (or stop learning) about VNIs and MACs.
8826 * When enabled, the VNI hash table will be built and MAC FDB table read;
8827 * when disabled, the entries should be deleted and remote VTEPs and MACs
8828 * uninstalled from the kernel.
8829 * This also informs the setting for BUM handling at the time this change
8830 * occurs; it is relevant only when specifying "learn".
8832 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
8834 struct stream
*s
= NULL
;
8836 enum vxlan_flood_control flood_ctrl
;
8838 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8839 zlog_debug("EVPN VNI Adv for non-default VRF %u",
8845 STREAM_GETC(s
, advertise
);
8846 STREAM_GETC(s
, flood_ctrl
);
8848 if (IS_ZEBRA_DEBUG_VXLAN
)
8849 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
8850 advertise
? "enabled" : "disabled",
8851 is_evpn_enabled() ? "enabled" : "disabled",
8854 if (zvrf
->advertise_all_vni
== advertise
)
8857 zvrf
->advertise_all_vni
= advertise
;
8858 if (is_evpn_enabled()) {
8859 /* Note BUM handling */
8860 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8862 /* Build VNI hash table and inform BGP. */
8863 zvni_build_hash_table();
8865 /* Add all SVI (L3 GW) MACs to BGP*/
8866 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
8869 /* Read the MAC FDB */
8870 macfdb_read(zvrf
->zns
);
8872 /* Read neighbors */
8873 neigh_read(zvrf
->zns
);
8875 /* Cleanup VTEPs for all VNIs - uninstall from
8876 * kernel and free entries.
8878 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8880 /* cleanup all l3vnis */
8881 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
8889 * Allocate VNI hash table for this VRF and do other initialization.
8890 * NOTE: Currently supported only for default VRF.
8892 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
8896 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
8897 "Zebra VRF VNI Table");
8900 /* Cleanup VNI info, but don't free the table. */
8901 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
8905 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8908 /* Close all VNI handling */
8909 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
8913 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8914 hash_free(zvrf
->vni_table
);
8917 /* init the l3vni table */
8918 void zebra_vxlan_init(void)
8920 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
8921 "Zebra VRF L3 VNI table");
8924 /* free l3vni table */
8925 void zebra_vxlan_disable(void)
8927 hash_free(zrouter
.l3vni_table
);
8930 /* get the l3vni svi ifindex */
8931 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
8933 zebra_l3vni_t
*zl3vni
= NULL
;
8935 zl3vni
= zl3vni_from_vrf(vrf_id
);
8936 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
8939 return zl3vni
->svi_if
->ifindex
;
8942 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
8944 struct zebra_vrf
*zvrf
= NULL
;
8945 zebra_neigh_t
*nbr
= NULL
;
8946 zebra_vni_t
*zvni
= NULL
;
8947 char buf1
[INET6_ADDRSTRLEN
];
8948 char buf2
[ETHER_ADDR_STRLEN
];
8950 nbr
= THREAD_ARG(t
);
8952 /* since this is asynchronous we need sanity checks*/
8953 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
8957 zvni
= zvni_lookup(nbr
->zvni
->vni
);
8961 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
8965 if (IS_ZEBRA_DEBUG_VXLAN
)
8966 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
8967 __PRETTY_FUNCTION__
,
8968 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
8969 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
8971 nbr
->dad_count
, zvni
->vni
);
8973 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8975 nbr
->detect_start_time
.tv_sec
= 0;
8976 nbr
->detect_start_time
.tv_usec
= 0;
8977 nbr
->dad_dup_detect_time
= 0;
8978 nbr
->dad_ip_auto_recovery_timer
= NULL
;
8981 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8982 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
8983 nbr
->flags
, nbr
->loc_seq
);
8984 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8985 zvni_neigh_install(zvni
, nbr
);
8991 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
8993 struct zebra_vrf
*zvrf
= NULL
;
8994 zebra_mac_t
*mac
= NULL
;
8995 zebra_vni_t
*zvni
= NULL
;
8996 struct listnode
*node
= NULL
;
8997 zebra_neigh_t
*nbr
= NULL
;
8998 char buf
[ETHER_ADDR_STRLEN
];
9000 mac
= THREAD_ARG(t
);
9002 /* since this is asynchronous we need sanity checks*/
9003 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9007 zvni
= zvni_lookup(mac
->zvni
->vni
);
9011 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
9015 if (IS_ZEBRA_DEBUG_VXLAN
)
9016 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9017 __PRETTY_FUNCTION__
,
9018 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9021 listcount(mac
->neigh_list
));
9023 /* Remove all IPs as duplicate associcated with this MAC */
9024 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9025 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9026 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9027 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9028 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9029 zvni_neigh_install(zvni
, nbr
);
9032 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9034 nbr
->detect_start_time
.tv_sec
= 0;
9035 nbr
->dad_dup_detect_time
= 0;
9038 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9040 mac
->detect_start_time
.tv_sec
= 0;
9041 mac
->detect_start_time
.tv_usec
= 0;
9042 mac
->dad_dup_detect_time
= 0;
9043 mac
->dad_mac_auto_recovery_timer
= NULL
;
9045 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9047 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9048 mac
->flags
, mac
->loc_seq
))
9051 /* Process all neighbors associated with this MAC. */
9052 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9054 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9055 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9057 /* Install the entry. */
9058 zvni_mac_install(zvni
, mac
);