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
, 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
,
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();
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
= false;
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 zlog_debug("%s: MAC DAD %s dad_count %u ",
469 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
472 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
473 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
474 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
476 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
477 is_local
? "local update, last" :
478 "remote update, from", inet_ntoa(vtep_ip
));
480 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
482 /* Capture Duplicate detection time */
483 mac
->dad_dup_detect_time
= monotime(NULL
);
485 /* Mark all IPs/Neighs as duplicate
486 * associcated with this MAC
488 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
490 /* Ony Mark IPs which are Local */
491 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
494 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
496 nbr
->dad_dup_detect_time
= monotime(NULL
);
498 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
499 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
501 prefix_mac2str(&mac
->macaddr
,
503 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
504 is_local
? "local" : "remote");
507 /* Start auto recovery timer for this MAC */
508 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
509 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
510 if (IS_ZEBRA_DEBUG_VXLAN
)
512 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
513 , __PRETTY_FUNCTION__
,
514 prefix_mac2str(&mac
->macaddr
, buf
,
516 mac
->flags
, zvrf
->dad_freeze_time
);
518 thread_add_timer(zebrad
.master
,
519 zebra_vxlan_dad_mac_auto_recovery_exp
,
520 mac
, zvrf
->dad_freeze_time
,
521 &mac
->dad_mac_auto_recovery_timer
);
524 /* Do not inform to client (BGPd),
525 * upd_neigh for neigh sequence change.
527 if (zvrf
->dad_freeze
)
528 *is_dup_detect
= false;
532 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
534 struct in_addr vtep_ip
,
540 struct timeval elapsed
= {0, 0};
541 char buf
[ETHER_ADDR_STRLEN
];
542 char buf1
[INET6_ADDRSTRLEN
];
543 bool reset_params
= false;
545 if (!zvrf
->dup_addr_detect
)
548 /* IP is detected as duplicate or inherit dup
549 * state, hold on to install as remote entry
550 * only if freeze is enabled.
552 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
553 if (IS_ZEBRA_DEBUG_VXLAN
)
555 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
557 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
558 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
559 nbr
->flags
, nbr
->dad_count
,
560 zvrf
->dad_freeze_time
);
562 if (zvrf
->dad_freeze
)
563 *is_dup_detect
= true;
564 /* warn-only action, neigh will be installed.
565 * freeze action, it wil not be installed.
573 /* Check if detection time (M-secs) expired.
574 * Reset learn count and detection start time.
575 * During remote mac add, count should already be 1
576 * via local learning.
578 monotime_since(&nbr
->detect_start_time
, &elapsed
);
579 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
581 if (is_local
&& !reset_params
) {
582 /* RFC-7432: A PE/VTEP that detects a MAC mobility
583 * event via LOCAL learning starts an M-second timer.
585 * NOTE: This is the START of the probe with count is
586 * 0 during LOCAL learn event.
588 reset_params
= !nbr
->dad_count
;
592 if (IS_ZEBRA_DEBUG_VXLAN
)
594 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
596 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
597 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
598 nbr
->flags
, nbr
->dad_count
);
599 /* Reset learn count but do not start detection
600 * during REMOTE learn event.
603 /* Start dup. addr detection (DAD) start time,
604 * ONLY during LOCAL learn.
607 monotime(&nbr
->detect_start_time
);
609 } else if (!is_local
) {
610 /* For REMOTE IP/Neigh, increment detection count
611 * ONLY while in probe window, once window passed,
612 * next local learn event should trigger DAD.
617 /* For LOCAL IP/Neigh learn event, once count is reset above via either
618 * initial/start detection time or passed the probe time, the count
619 * needs to be incremented.
624 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
625 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
626 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
628 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
629 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
630 is_local
? "local update, last" :
631 "remote update, from",
634 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
636 /* Capture Duplicate detection time */
637 nbr
->dad_dup_detect_time
= monotime(NULL
);
639 /* Start auto recovery timer for this IP */
640 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
641 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
642 if (IS_ZEBRA_DEBUG_VXLAN
)
644 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
646 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
647 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
648 nbr
->flags
, zvrf
->dad_freeze_time
);
650 thread_add_timer(zebrad
.master
,
651 zebra_vxlan_dad_ip_auto_recovery_exp
,
652 nbr
, zvrf
->dad_freeze_time
,
653 &nbr
->dad_ip_auto_recovery_timer
);
655 if (zvrf
->dad_freeze
)
656 *is_dup_detect
= true;
661 * Helper function to determine maximum width of neighbor IP address for
662 * display - just because we're dealing with IPv6 addresses that can
665 static void zvni_find_neigh_addr_width(struct hash_backet
*backet
, void *ctxt
)
668 char buf
[INET6_ADDRSTRLEN
];
669 struct neigh_walk_ctx
*wctx
= ctxt
;
672 n
= (zebra_neigh_t
*)backet
->data
;
674 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
676 if (width
> wctx
->addr_width
)
677 wctx
->addr_width
= width
;
682 * Print a specific neighbor entry.
684 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
687 char buf1
[ETHER_ADDR_STRLEN
];
688 char buf2
[INET6_ADDRSTRLEN
];
689 const char *type_str
;
690 const char *state_str
;
691 bool flags_present
= false;
692 struct zebra_vrf
*zvrf
= NULL
;
693 struct timeval detect_start_time
= {0, 0};
695 zvrf
= zebra_vrf_lookup_by_id(n
->zvni
->vrf_id
);
699 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
700 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
701 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
703 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
704 vty
= (struct vty
*)ctxt
;
706 vty_out(vty
, "IP: %s\n",
707 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
708 vty_out(vty
, " Type: %s\n", type_str
);
709 vty_out(vty
, " State: %s\n", state_str
);
710 vty_out(vty
, " MAC: %s\n",
711 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
713 json_object_string_add(json
, "ip", buf2
);
714 json_object_string_add(json
, "type", type_str
);
715 json_object_string_add(json
, "state", state_str
);
716 json_object_string_add(json
, "mac", buf1
);
718 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
720 vty_out(vty
, " Remote VTEP: %s\n",
721 inet_ntoa(n
->r_vtep_ip
));
723 json_object_string_add(json
, "remoteVtep",
724 inet_ntoa(n
->r_vtep_ip
));
726 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
728 vty_out(vty
, " Flags: Default-gateway");
729 flags_present
= true;
731 json_object_boolean_true_add(json
, "defaultGateway");
733 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
736 flags_present
? " ,Router" : " Flags: Router");
737 flags_present
= true;
743 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
744 n
->loc_seq
, n
->rem_seq
);
746 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
747 vty_out(vty
, " Duplicate, detected at %s",
748 time_to_string(n
->dad_dup_detect_time
));
749 } else if (n
->dad_count
) {
750 monotime_since(&n
->detect_start_time
,
752 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
753 char *buf
= time_to_string(
754 n
->detect_start_time
.tv_sec
);
757 memset(tmp_buf
, 0, 30);
758 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
760 " Duplicate detection started at %s, detection count %u\n",
761 tmp_buf
, n
->dad_count
);
765 json_object_int_add(json
, "localSequence", n
->loc_seq
);
766 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
767 json_object_int_add(json
, "detectionCount",
769 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
770 json_object_boolean_true_add(json
, "isDuplicate");
772 json_object_boolean_false_add(json
, "isDuplicate");
779 * Print neighbor hash entry - called for display of all neighbors.
781 static void zvni_print_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
784 json_object
*json_vni
= NULL
, *json_row
= NULL
;
786 char buf1
[ETHER_ADDR_STRLEN
];
787 char buf2
[INET6_ADDRSTRLEN
];
788 struct neigh_walk_ctx
*wctx
= ctxt
;
789 const char *state_str
;
792 json_vni
= wctx
->json
;
793 n
= (zebra_neigh_t
*)backet
->data
;
796 json_row
= json_object_new_object();
798 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
799 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
800 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
801 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
802 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
805 if (json_vni
== NULL
) {
806 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
807 -wctx
->addr_width
, buf2
, "local",
810 json_object_string_add(json_row
, "type", "local");
811 json_object_string_add(json_row
, "state", state_str
);
812 json_object_string_add(json_row
, "mac", buf1
);
813 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
814 json_object_boolean_true_add(
815 json_row
, "defaultGateway");
816 json_object_int_add(json_row
, "localSequence",
818 json_object_int_add(json_row
, "remoteSequence",
820 json_object_int_add(json_row
, "detectionCount",
822 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
823 json_object_boolean_true_add(json_row
,
826 json_object_boolean_false_add(json_row
,
830 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
831 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
832 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
835 if (json_vni
== NULL
) {
836 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
839 "%*s %-6s %-8s %-17s %-21s\n",
840 -wctx
->addr_width
, "Neighbor", "Type",
841 "State", "MAC", "Remote VTEP");
842 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
843 -wctx
->addr_width
, buf2
, "remote", state_str
,
844 buf1
, inet_ntoa(n
->r_vtep_ip
));
846 json_object_string_add(json_row
, "type", "remote");
847 json_object_string_add(json_row
, "state", state_str
);
848 json_object_string_add(json_row
, "mac", buf1
);
849 json_object_string_add(json_row
, "remoteVtep",
850 inet_ntoa(n
->r_vtep_ip
));
851 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
852 json_object_boolean_true_add(json_row
,
854 json_object_int_add(json_row
, "localSequence",
856 json_object_int_add(json_row
, "remoteSequence",
858 json_object_int_add(json_row
, "detectionCount",
860 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
861 json_object_boolean_true_add(json_row
,
864 json_object_boolean_false_add(json_row
,
871 json_object_object_add(json_vni
, buf2
, json_row
);
875 * Print neighbor hash entry in detail - called for display of all neighbors.
877 static void zvni_print_neigh_hash_detail(struct hash_backet
*backet
, void *ctxt
)
880 json_object
*json_vni
= NULL
, *json_row
= NULL
;
882 char buf
[INET6_ADDRSTRLEN
];
883 struct neigh_walk_ctx
*wctx
= ctxt
;
886 json_vni
= wctx
->json
;
887 n
= (zebra_neigh_t
*)backet
->data
;
891 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
893 json_row
= json_object_new_object();
895 zvni_print_neigh(n
, vty
, json_row
);
898 json_object_object_add(json_vni
, buf
, json_row
);
902 * Print neighbors for all VNI.
904 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
908 json_object
*json
= NULL
, *json_vni
= NULL
;
911 struct neigh_walk_ctx wctx
;
912 char vni_str
[VNI_STR_LEN
];
915 vty
= (struct vty
*)args
[0];
916 json
= (json_object
*)args
[1];
917 print_dup
= (uint32_t)(uintptr_t)args
[2];
919 zvni
= (zebra_vni_t
*)backet
->data
;
921 num_neigh
= hashcount(zvni
->neigh_table
);
924 num_neigh
= num_dup_detected_neighs(zvni
);
928 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
929 zvni
->vni
, num_neigh
);
931 json_vni
= json_object_new_object();
932 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
933 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
938 json_object_object_add(json
, vni_str
, json_vni
);
942 /* Since we have IPv6 addresses to deal with which can vary widely in
943 * size, we try to be a bit more elegant in display by first computing
946 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
949 wctx
.addr_width
= 15;
950 wctx
.json
= json_vni
;
951 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
954 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
955 -wctx
.addr_width
, "IP", "Type",
956 "State", "MAC", "Remote VTEP");
959 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
962 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
965 json_object_object_add(json
, vni_str
, json_vni
);
968 static void zvni_print_dad_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
972 nbr
= (zebra_neigh_t
*)backet
->data
;
976 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
977 zvni_print_neigh_hash(backet
, ctxt
);
980 static void zvni_print_dad_neigh_hash_detail(struct hash_backet
*backet
,
985 nbr
= (zebra_neigh_t
*)backet
->data
;
989 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
990 zvni_print_neigh_hash_detail(backet
, ctxt
);
994 * Print neighbors for all VNIs in detail.
996 static void zvni_print_neigh_hash_all_vni_detail(struct hash_backet
*backet
,
1000 json_object
*json
= NULL
, *json_vni
= NULL
;
1003 struct neigh_walk_ctx wctx
;
1004 char vni_str
[VNI_STR_LEN
];
1007 vty
= (struct vty
*)args
[0];
1008 json
= (json_object
*)args
[1];
1009 print_dup
= (uint32_t)(uintptr_t)args
[2];
1011 zvni
= (zebra_vni_t
*)backet
->data
;
1014 vty_out(vty
, "{}\n");
1017 num_neigh
= hashcount(zvni
->neigh_table
);
1019 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1024 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1025 zvni
->vni
, num_neigh
);
1027 json_vni
= json_object_new_object();
1028 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1029 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1033 json_object_object_add(json
, vni_str
, json_vni
);
1037 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1040 wctx
.addr_width
= 15;
1041 wctx
.json
= json_vni
;
1044 hash_iterate(zvni
->neigh_table
,
1045 zvni_print_dad_neigh_hash_detail
, &wctx
);
1047 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1051 json_object_object_add(json
, vni_str
, json_vni
);
1054 /* print a specific next hop for an l3vni */
1055 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1058 char buf1
[ETHER_ADDR_STRLEN
];
1059 char buf2
[INET6_ADDRSTRLEN
];
1060 json_object
*json_hosts
= NULL
;
1061 struct host_rb_entry
*hle
;
1064 vty_out(vty
, "Ip: %s\n",
1065 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1066 vty_out(vty
, " RMAC: %s\n",
1067 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1068 vty_out(vty
, " Refcount: %d\n",
1069 rb_host_count(&n
->host_rb
));
1070 vty_out(vty
, " Prefixes:\n");
1071 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1072 vty_out(vty
, " %s\n",
1073 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1075 json_hosts
= json_object_new_array();
1076 json_object_string_add(
1077 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1078 json_object_string_add(
1080 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1081 json_object_int_add(json
, "refCount",
1082 rb_host_count(&n
->host_rb
));
1083 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1084 json_object_array_add(json_hosts
,
1085 json_object_new_string(prefix2str(
1086 &hle
->p
, buf2
, sizeof(buf2
))));
1087 json_object_object_add(json
, "prefixList", json_hosts
);
1091 /* Print a specific RMAC entry */
1092 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1095 char buf1
[ETHER_ADDR_STRLEN
];
1096 char buf2
[PREFIX_STRLEN
];
1097 json_object
*json_hosts
= NULL
;
1098 struct host_rb_entry
*hle
;
1101 vty_out(vty
, "MAC: %s\n",
1102 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1103 vty_out(vty
, " Remote VTEP: %s\n",
1104 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1105 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1106 vty_out(vty
, " Prefixes:\n");
1107 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1108 vty_out(vty
, " %s\n",
1109 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1111 json_hosts
= json_object_new_array();
1112 json_object_string_add(
1114 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1115 json_object_string_add(json
, "vtepIp",
1116 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1117 json_object_int_add(json
, "refCount",
1118 rb_host_count(&zrmac
->host_rb
));
1119 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1120 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1121 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1122 json_object_array_add(
1124 json_object_new_string(prefix2str(
1125 &hle
->p
, buf2
, sizeof(buf2
))));
1126 json_object_object_add(json
, "prefixList", json_hosts
);
1131 * Print a specific MAC entry.
1133 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1136 zebra_neigh_t
*n
= NULL
;
1137 struct listnode
*node
= NULL
;
1139 char buf2
[INET6_ADDRSTRLEN
];
1140 struct zebra_vrf
*zvrf
;
1141 struct timeval detect_start_time
= {0, 0};
1143 zvrf
= zebra_vrf_lookup_by_id(mac
->zvni
->vrf_id
);
1145 vty
= (struct vty
*)ctxt
;
1146 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1149 json_object
*json_mac
= json_object_new_object();
1151 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1152 struct zebra_ns
*zns
;
1153 struct interface
*ifp
;
1156 ifindex
= mac
->fwd_info
.local
.ifindex
;
1157 zns
= zebra_ns_lookup(NS_DEFAULT
);
1158 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1161 json_object_string_add(json_mac
, "type", "local");
1162 json_object_string_add(json_mac
, "intf", ifp
->name
);
1163 json_object_int_add(json_mac
, "ifindex", ifindex
);
1164 if (mac
->fwd_info
.local
.vid
)
1165 json_object_int_add(json_mac
, "vlan",
1166 mac
->fwd_info
.local
.vid
);
1167 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1168 json_object_string_add(json_mac
, "type", "remote");
1169 json_object_string_add(
1170 json_mac
, "remoteVtep",
1171 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1172 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1173 json_object_string_add(json_mac
, "type", "auto");
1175 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1176 json_object_boolean_true_add(json_mac
, "stickyMac");
1178 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1179 json_object_boolean_true_add(json_mac
,
1182 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1183 json_object_boolean_true_add(json_mac
,
1184 "remoteGatewayMac");
1186 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1187 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1189 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1190 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1191 json_object_boolean_true_add(json_mac
, "isDuplicate");
1193 json_object_boolean_false_add(json_mac
, "isDuplicate");
1195 /* print all the associated neigh */
1196 if (!listcount(mac
->neigh_list
))
1197 json_object_string_add(json_mac
, "neighbors", "none");
1199 json_object
*json_active_nbrs
= json_object_new_array();
1200 json_object
*json_inactive_nbrs
=
1201 json_object_new_array();
1202 json_object
*json_nbrs
= json_object_new_object();
1204 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1205 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1206 json_object_array_add(
1208 json_object_new_string(
1213 json_object_array_add(
1215 json_object_new_string(
1221 json_object_object_add(json_nbrs
, "active",
1223 json_object_object_add(json_nbrs
, "inactive",
1224 json_inactive_nbrs
);
1225 json_object_object_add(json_mac
, "neighbors",
1229 json_object_object_add(json
, buf1
, json_mac
);
1231 vty_out(vty
, "MAC: %s\n", buf1
);
1233 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1234 struct zebra_ns
*zns
;
1235 struct interface
*ifp
;
1238 ifindex
= mac
->fwd_info
.local
.ifindex
;
1239 zns
= zebra_ns_lookup(NS_DEFAULT
);
1240 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1243 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1244 if (mac
->fwd_info
.local
.vid
)
1245 vty_out(vty
, " VLAN: %u",
1246 mac
->fwd_info
.local
.vid
);
1247 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1248 vty_out(vty
, " Remote VTEP: %s",
1249 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1250 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1251 vty_out(vty
, " Auto Mac ");
1254 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1255 vty_out(vty
, " Sticky Mac ");
1257 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1258 vty_out(vty
, " Default-gateway Mac ");
1260 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1261 vty_out(vty
, " Remote-gateway Mac ");
1264 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1268 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1269 vty_out(vty
, " Duplicate, detected at %s",
1270 time_to_string(mac
->dad_dup_detect_time
));
1271 } else if (mac
->dad_count
) {
1272 monotime_since(&mac
->detect_start_time
,
1273 &detect_start_time
);
1274 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1275 char *buf
= time_to_string(
1276 mac
->detect_start_time
.tv_sec
);
1279 memset(tmp_buf
, 0, 30);
1280 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
1282 " Duplicate detection started at %s, detection count %u\n",
1283 tmp_buf
, mac
->dad_count
);
1287 /* print all the associated neigh */
1288 vty_out(vty
, " Neighbors:\n");
1289 if (!listcount(mac
->neigh_list
))
1290 vty_out(vty
, " No Neighbors\n");
1292 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1293 vty_out(vty
, " %s %s\n",
1294 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1295 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1306 * Print MAC hash entry - called for display of all MACs.
1308 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1311 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1314 struct mac_walk_ctx
*wctx
= ctxt
;
1317 json_mac_hdr
= wctx
->json
;
1318 mac
= (zebra_mac_t
*)backet
->data
;
1320 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1323 json_mac
= json_object_new_object();
1325 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1326 struct zebra_ns
*zns
;
1328 struct interface
*ifp
;
1331 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1334 zns
= zebra_ns_lookup(NS_DEFAULT
);
1335 ifindex
= mac
->fwd_info
.local
.ifindex
;
1336 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1337 if (!ifp
) // unexpected
1339 vid
= mac
->fwd_info
.local
.vid
;
1340 if (json_mac_hdr
== NULL
)
1341 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1344 json_object_string_add(json_mac
, "type", "local");
1345 json_object_string_add(json_mac
, "intf", ifp
->name
);
1348 if (json_mac_hdr
== NULL
)
1349 vty_out(vty
, " %-5u", vid
);
1351 json_object_int_add(json_mac
, "vlan", vid
);
1353 if (json_mac_hdr
== NULL
) {
1356 json_object_int_add(json_mac
, "localSequence",
1358 json_object_int_add(json_mac
, "remoteSequence",
1360 json_object_int_add(json_mac
, "detectionCount",
1362 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1363 json_object_boolean_true_add(json_mac
,
1366 json_object_boolean_false_add(json_mac
,
1368 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1373 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1375 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1376 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1380 if (json_mac_hdr
== NULL
) {
1381 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1382 (wctx
->count
== 0)) {
1383 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1384 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1385 "Type", "Intf/Remote VTEP", "VLAN");
1387 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1388 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1390 json_object_string_add(json_mac
, "type", "remote");
1391 json_object_string_add(json_mac
, "remoteVtep",
1392 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1393 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1394 json_object_int_add(json_mac
, "localSequence",
1396 json_object_int_add(json_mac
, "remoteSequence",
1398 json_object_int_add(json_mac
, "detectionCount",
1400 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1401 json_object_boolean_true_add(json_mac
,
1404 json_object_boolean_false_add(json_mac
,
1413 /* Print Duplicate MAC */
1414 static void zvni_print_dad_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1418 mac
= (zebra_mac_t
*)backet
->data
;
1422 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1423 zvni_print_mac_hash(backet
, ctxt
);
1427 * Print MAC hash entry in detail - called for display of all MACs.
1429 static void zvni_print_mac_hash_detail(struct hash_backet
*backet
, void *ctxt
)
1432 json_object
*json_mac_hdr
= NULL
;
1434 struct mac_walk_ctx
*wctx
= ctxt
;
1438 json_mac_hdr
= wctx
->json
;
1439 mac
= (zebra_mac_t
*)backet
->data
;
1444 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1446 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1449 /* Print Duplicate MAC in detail */
1450 static void zvni_print_dad_mac_hash_detail(struct hash_backet
*backet
,
1455 mac
= (zebra_mac_t
*)backet
->data
;
1459 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1460 zvni_print_mac_hash_detail(backet
, ctxt
);
1464 * Print MACs for all VNI.
1466 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
1469 json_object
*json
= NULL
, *json_vni
= NULL
;
1470 json_object
*json_mac
= NULL
;
1473 struct mac_walk_ctx
*wctx
= ctxt
;
1474 char vni_str
[VNI_STR_LEN
];
1476 vty
= (struct vty
*)wctx
->vty
;
1477 json
= (struct json_object
*)wctx
->json
;
1479 zvni
= (zebra_vni_t
*)backet
->data
;
1482 /*We are iterating over a new VNI, set the count to 0*/
1485 num_macs
= num_valid_macs(zvni
);
1489 if (wctx
->print_dup
)
1490 num_macs
= num_dup_detected_macs(zvni
);
1493 json_vni
= json_object_new_object();
1494 json_mac
= json_object_new_object();
1495 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1498 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1500 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1501 zvni
->vni
, num_macs
);
1502 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1503 "Intf/Remote VTEP", "VLAN");
1505 json_object_int_add(json_vni
, "numMacs", num_macs
);
1510 json_object_int_add(json_vni
, "numMacs", num_macs
);
1511 json_object_object_add(json
, vni_str
, json_vni
);
1516 /* assign per-vni to wctx->json object to fill macs
1517 * under the vni. Re-assign primary json object to fill
1518 * next vni information.
1520 wctx
->json
= json_mac
;
1521 if (wctx
->print_dup
)
1522 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1524 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1528 json_object_object_add(json_vni
, "macs", json_mac
);
1529 json_object_object_add(json
, vni_str
, json_vni
);
1534 * Print MACs in detail for all VNI.
1536 static void zvni_print_mac_hash_all_vni_detail(struct hash_backet
*backet
,
1540 json_object
*json
= NULL
, *json_vni
= NULL
;
1541 json_object
*json_mac
= NULL
;
1544 struct mac_walk_ctx
*wctx
= ctxt
;
1545 char vni_str
[VNI_STR_LEN
];
1547 vty
= (struct vty
*)wctx
->vty
;
1548 json
= (struct json_object
*)wctx
->json
;
1550 zvni
= (zebra_vni_t
*)backet
->data
;
1553 vty_out(vty
, "{}\n");
1558 /*We are iterating over a new VNI, set the count to 0*/
1561 num_macs
= num_valid_macs(zvni
);
1565 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1569 json_vni
= json_object_new_object();
1570 json_mac
= json_object_new_object();
1571 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1574 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1576 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1577 zvni
->vni
, num_macs
);
1579 json_object_int_add(json_vni
, "numMacs", num_macs
);
1581 /* assign per-vni to wctx->json object to fill macs
1582 * under the vni. Re-assign primary json object to fill
1583 * next vni information.
1585 wctx
->json
= json_mac
;
1586 if (wctx
->print_dup
)
1587 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1590 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1594 json_object_object_add(json_vni
, "macs", json_mac
);
1595 json_object_object_add(json
, vni_str
, json_vni
);
1599 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
1601 struct nh_walk_ctx
*wctx
= NULL
;
1602 struct vty
*vty
= NULL
;
1603 struct json_object
*json_vni
= NULL
;
1604 struct json_object
*json_nh
= NULL
;
1605 zebra_neigh_t
*n
= NULL
;
1606 char buf1
[ETHER_ADDR_STRLEN
];
1607 char buf2
[INET6_ADDRSTRLEN
];
1609 wctx
= (struct nh_walk_ctx
*)ctx
;
1611 json_vni
= wctx
->json
;
1613 json_nh
= json_object_new_object();
1614 n
= (zebra_neigh_t
*)backet
->data
;
1617 vty_out(vty
, "%-15s %-17s\n",
1618 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1619 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1621 json_object_string_add(json_nh
, "nexthopIp",
1622 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1623 json_object_string_add(
1624 json_nh
, "routerMac",
1625 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1626 json_object_object_add(json_vni
,
1627 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1632 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
1635 struct vty
*vty
= NULL
;
1636 json_object
*json
= NULL
;
1637 json_object
*json_vni
= NULL
;
1638 zebra_l3vni_t
*zl3vni
= NULL
;
1639 uint32_t num_nh
= 0;
1640 struct nh_walk_ctx wctx
;
1641 char vni_str
[VNI_STR_LEN
];
1643 vty
= (struct vty
*)args
[0];
1644 json
= (struct json_object
*)args
[1];
1646 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1648 num_nh
= hashcount(zl3vni
->nh_table
);
1653 json_vni
= json_object_new_object();
1654 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1658 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1659 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1661 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1663 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1665 wctx
.json
= json_vni
;
1666 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1668 json_object_object_add(json
, vni_str
, json_vni
);
1671 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
1674 struct vty
*vty
= NULL
;
1675 json_object
*json
= NULL
;
1676 json_object
*json_vni
= NULL
;
1677 zebra_l3vni_t
*zl3vni
= NULL
;
1679 struct rmac_walk_ctx wctx
;
1680 char vni_str
[VNI_STR_LEN
];
1682 vty
= (struct vty
*)args
[0];
1683 json
= (struct json_object
*)args
[1];
1685 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1687 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1692 json_vni
= json_object_new_object();
1693 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1697 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1698 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1700 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1702 /* assign per-vni to wctx->json object to fill macs
1703 * under the vni. Re-assign primary json object to fill
1704 * next vni information.
1706 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1708 wctx
.json
= json_vni
;
1709 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1711 json_object_object_add(json
, vni_str
, json_vni
);
1714 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
1716 zebra_mac_t
*zrmac
= NULL
;
1717 struct rmac_walk_ctx
*wctx
= NULL
;
1718 struct vty
*vty
= NULL
;
1719 struct json_object
*json
= NULL
;
1720 struct json_object
*json_rmac
= NULL
;
1721 char buf
[ETHER_ADDR_STRLEN
];
1723 wctx
= (struct rmac_walk_ctx
*)ctx
;
1727 json_rmac
= json_object_new_object();
1728 zrmac
= (zebra_mac_t
*)backet
->data
;
1731 vty_out(vty
, "%-17s %-21s\n",
1732 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1733 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1735 json_object_string_add(
1736 json_rmac
, "routerMac",
1737 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1738 json_object_string_add(json_rmac
, "vtepIp",
1739 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1740 json_object_object_add(
1741 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1746 /* print a specific L3 VNI entry */
1747 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1749 char buf
[ETHER_ADDR_STRLEN
];
1750 struct vty
*vty
= NULL
;
1751 json_object
*json
= NULL
;
1752 zebra_vni_t
*zvni
= NULL
;
1753 json_object
*json_vni_list
= NULL
;
1754 struct listnode
*node
= NULL
, *nnode
= NULL
;
1760 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1761 vty_out(vty
, " Type: %s\n", "L3");
1762 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1763 vty_out(vty
, " Local Vtep Ip: %s\n",
1764 inet_ntoa(zl3vni
->local_vtep_ip
));
1765 vty_out(vty
, " Vxlan-Intf: %s\n",
1766 zl3vni_vxlan_if_name(zl3vni
));
1767 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1768 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1769 vty_out(vty
, " VNI Filter: %s\n",
1770 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1771 ? "prefix-routes-only"
1773 vty_out(vty
, " Router MAC: %s\n",
1774 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1775 vty_out(vty
, " L2 VNIs: ");
1776 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1777 vty_out(vty
, "%u ", zvni
->vni
);
1780 json_vni_list
= json_object_new_array();
1781 json_object_int_add(json
, "vni", zl3vni
->vni
);
1782 json_object_string_add(json
, "type", "L3");
1783 json_object_string_add(json
, "localVtepIp",
1784 inet_ntoa(zl3vni
->local_vtep_ip
));
1785 json_object_string_add(json
, "vxlanIntf",
1786 zl3vni_vxlan_if_name(zl3vni
));
1787 json_object_string_add(json
, "sviIntf",
1788 zl3vni_svi_if_name(zl3vni
));
1789 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1790 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1791 json_object_string_add(
1793 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1794 json_object_string_add(
1796 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1797 ? "prefix-routes-only"
1799 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1800 json_object_array_add(json_vni_list
,
1801 json_object_new_int(zvni
->vni
));
1803 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1808 * Print a specific VNI entry.
1810 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1813 zebra_vtep_t
*zvtep
;
1816 json_object
*json
= NULL
;
1817 json_object
*json_vtep_list
= NULL
;
1818 json_object
*json_ip_str
= NULL
;
1824 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1825 vty_out(vty
, " Type: %s\n", "L2");
1826 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1828 json_object_int_add(json
, "vni", zvni
->vni
);
1829 json_object_string_add(json
, "type", "L2");
1830 json_object_string_add(json
, "vrf",
1831 vrf_id_to_name(zvni
->vrf_id
));
1834 if (!zvni
->vxlan_if
) { // unexpected
1836 vty_out(vty
, " VxLAN interface: unknown\n");
1839 num_macs
= num_valid_macs(zvni
);
1840 num_neigh
= hashcount(zvni
->neigh_table
);
1842 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1843 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1844 vty_out(vty
, " Local VTEP IP: %s\n",
1845 inet_ntoa(zvni
->local_vtep_ip
));
1847 json_object_string_add(json
, "vxlanInterface",
1848 zvni
->vxlan_if
->name
);
1849 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1850 json_object_string_add(json
, "vtepIp",
1851 inet_ntoa(zvni
->local_vtep_ip
));
1852 json_object_string_add(json
, "advertiseGatewayMacip",
1853 zvni
->advertise_gw_macip
? "Yes" : "No");
1854 json_object_int_add(json
, "numMacs", num_macs
);
1855 json_object_int_add(json
, "numArpNd", num_neigh
);
1859 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1862 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1864 json_vtep_list
= json_object_new_array();
1865 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1867 vty_out(vty
, " %s\n",
1868 inet_ntoa(zvtep
->vtep_ip
));
1870 json_ip_str
= json_object_new_string(
1871 inet_ntoa(zvtep
->vtep_ip
));
1872 json_object_array_add(json_vtep_list
,
1877 json_object_object_add(json
, "numRemoteVteps",
1882 " Number of MACs (local and remote) known for this VNI: %u\n",
1885 " Number of ARPs (IPv4 and IPv6, local and remote) "
1886 "known for this VNI: %u\n",
1888 vty_out(vty
, " Advertise-gw-macip: %s\n",
1889 zvni
->advertise_gw_macip
? "Yes" : "No");
1893 /* print a L3 VNI hash entry */
1894 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1896 struct vty
*vty
= NULL
;
1897 json_object
*json
= NULL
;
1898 json_object
*json_vni
= NULL
;
1899 zebra_l3vni_t
*zl3vni
= NULL
;
1901 vty
= (struct vty
*)ctx
[0];
1902 json
= (json_object
*)ctx
[1];
1904 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1907 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1908 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1909 hashcount(zl3vni
->rmac_table
),
1910 hashcount(zl3vni
->nh_table
), "n/a",
1911 zl3vni_vrf_name(zl3vni
));
1913 char vni_str
[VNI_STR_LEN
];
1915 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1916 json_vni
= json_object_new_object();
1917 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1918 json_object_string_add(json_vni
, "vxlanIf",
1919 zl3vni_vxlan_if_name(zl3vni
));
1920 json_object_int_add(json_vni
, "numMacs",
1921 hashcount(zl3vni
->rmac_table
));
1922 json_object_int_add(json_vni
, "numArpNd",
1923 hashcount(zl3vni
->nh_table
));
1924 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1925 json_object_string_add(json_vni
, "type", "L3");
1926 json_object_string_add(json_vni
, "tenantVrf",
1927 zl3vni_vrf_name(zl3vni
));
1928 json_object_object_add(json
, vni_str
, json_vni
);
1932 /* Private Structure to pass callback data for hash iterator */
1933 struct zvni_evpn_show
{
1936 struct zebra_vrf
*zvrf
;
1939 /* print a L3 VNI hash entry in detail*/
1940 static void zl3vni_print_hash_detail(struct hash_backet
*backet
, void *data
)
1942 struct vty
*vty
= NULL
;
1943 zebra_l3vni_t
*zl3vni
= NULL
;
1944 json_object
*json
= NULL
;
1945 bool use_json
= false;
1946 struct zvni_evpn_show
*zes
= data
;
1954 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1956 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1962 * Print a VNI hash entry - called for display of all VNIs.
1964 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1968 zebra_vtep_t
*zvtep
;
1969 uint32_t num_vteps
= 0;
1970 uint32_t num_macs
= 0;
1971 uint32_t num_neigh
= 0;
1972 json_object
*json
= NULL
;
1973 json_object
*json_vni
= NULL
;
1974 json_object
*json_ip_str
= NULL
;
1975 json_object
*json_vtep_list
= NULL
;
1980 zvni
= (zebra_vni_t
*)backet
->data
;
1982 zvtep
= zvni
->vteps
;
1985 zvtep
= zvtep
->next
;
1988 num_macs
= num_valid_macs(zvni
);
1989 num_neigh
= hashcount(zvni
->neigh_table
);
1991 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1993 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1994 num_macs
, num_neigh
, num_vteps
,
1995 vrf_id_to_name(zvni
->vrf_id
));
1997 char vni_str
[VNI_STR_LEN
];
1998 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1999 json_vni
= json_object_new_object();
2000 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2001 json_object_string_add(json_vni
, "type", "L2");
2002 json_object_string_add(json_vni
, "vxlanIf",
2003 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2005 json_object_int_add(json_vni
, "numMacs", num_macs
);
2006 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2007 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2008 json_object_string_add(json_vni
, "tenantVrf",
2009 vrf_id_to_name(zvni
->vrf_id
));
2011 json_vtep_list
= json_object_new_array();
2012 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2013 json_ip_str
= json_object_new_string(
2014 inet_ntoa(zvtep
->vtep_ip
));
2015 json_object_array_add(json_vtep_list
,
2018 json_object_object_add(json_vni
, "remoteVteps",
2021 json_object_object_add(json
, vni_str
, json_vni
);
2026 * Print a VNI hash entry in detail - called for display of all VNIs.
2028 static void zvni_print_hash_detail(struct hash_backet
*backet
, void *data
)
2032 json_object
*json
= NULL
;
2033 bool use_json
= false;
2034 struct zvni_evpn_show
*zes
= data
;
2042 zvni
= (zebra_vni_t
*)backet
->data
;
2044 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2049 * Inform BGP about local MACIP.
2051 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2052 struct ipaddr
*ip
, uint8_t flags
,
2053 uint32_t seq
, uint16_t cmd
)
2055 char buf
[ETHER_ADDR_STRLEN
];
2056 char buf2
[INET6_ADDRSTRLEN
];
2058 struct zserv
*client
= NULL
;
2059 struct stream
*s
= NULL
;
2061 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2062 /* BGP may not be running. */
2066 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2068 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
2069 stream_putl(s
, vni
);
2070 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2073 if (IS_IPADDR_V4(ip
))
2074 ipa_len
= IPV4_MAX_BYTELEN
;
2075 else if (IS_IPADDR_V6(ip
))
2076 ipa_len
= IPV6_MAX_BYTELEN
;
2078 stream_putl(s
, ipa_len
); /* IP address length */
2080 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2082 stream_putl(s
, 0); /* Just MAC. */
2084 if (cmd
== ZEBRA_MACIP_ADD
) {
2085 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2086 stream_putl(s
, seq
); /* sequence number */
2090 /* Write packet size. */
2091 stream_putw_at(s
, 0, stream_get_endp(s
));
2093 if (IS_ZEBRA_DEBUG_VXLAN
)
2095 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2096 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2097 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2098 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2099 zebra_route_string(client
->proto
));
2101 if (cmd
== ZEBRA_MACIP_ADD
)
2102 client
->macipadd_cnt
++;
2104 client
->macipdel_cnt
++;
2106 return zserv_send_message(client
, s
);
2110 * Make hash key for neighbors.
2112 static unsigned int neigh_hash_keymake(void *p
)
2114 zebra_neigh_t
*n
= p
;
2115 struct ipaddr
*ip
= &n
->ip
;
2117 if (IS_IPADDR_V4(ip
))
2118 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2120 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2121 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2125 * Compare two neighbor hash structures.
2127 static bool neigh_cmp(const void *p1
, const void *p2
)
2129 const zebra_neigh_t
*n1
= p1
;
2130 const zebra_neigh_t
*n2
= p2
;
2132 if (n1
== NULL
&& n2
== NULL
)
2135 if (n1
== NULL
|| n2
== NULL
)
2138 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2141 static int neigh_list_cmp(void *p1
, void *p2
)
2143 const zebra_neigh_t
*n1
= p1
;
2144 const zebra_neigh_t
*n2
= p2
;
2146 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2150 * Callback to allocate neighbor hash entry.
2152 static void *zvni_neigh_alloc(void *p
)
2154 const zebra_neigh_t
*tmp_n
= p
;
2157 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2164 * Add neighbor entry.
2166 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2167 struct ethaddr
*mac
)
2169 zebra_neigh_t tmp_n
;
2170 zebra_neigh_t
*n
= NULL
;
2171 zebra_mac_t
*zmac
= NULL
;
2173 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2174 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2175 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2178 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2179 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2181 /* Associate the neigh to mac */
2182 zmac
= zvni_mac_lookup(zvni
, mac
);
2184 listnode_add_sort(zmac
->neigh_list
, n
);
2190 * Delete neighbor entry.
2192 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2194 zebra_neigh_t
*tmp_n
;
2195 zebra_mac_t
*zmac
= NULL
;
2197 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2199 listnode_delete(zmac
->neigh_list
, n
);
2201 /* Free the VNI hash entry and allocated memory. */
2202 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2204 XFREE(MTYPE_NEIGH
, tmp_n
);
2210 * Free neighbor hash entry (callback)
2212 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2214 struct neigh_walk_ctx
*wctx
= arg
;
2215 zebra_neigh_t
*n
= backet
->data
;
2217 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2218 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2219 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2220 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2221 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2222 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2223 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2224 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2227 if (wctx
->uninstall
)
2228 zvni_neigh_uninstall(wctx
->zvni
, n
);
2230 zvni_neigh_del(wctx
->zvni
, n
);
2237 * Delete all neighbor entries from specific VTEP for a particular VNI.
2239 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2240 struct in_addr
*r_vtep_ip
)
2242 struct neigh_walk_ctx wctx
;
2244 if (!zvni
->neigh_table
)
2247 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2249 wctx
.uninstall
= uninstall
;
2250 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2251 wctx
.r_vtep_ip
= *r_vtep_ip
;
2253 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2257 * Delete all neighbor entries for this VNI.
2259 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2262 struct neigh_walk_ctx wctx
;
2264 if (!zvni
->neigh_table
)
2267 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2269 wctx
.uninstall
= uninstall
;
2270 wctx
.upd_client
= upd_client
;
2273 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2277 * Look up neighbor hash entry.
2279 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2284 memset(&tmp
, 0, sizeof(tmp
));
2285 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2286 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2292 * Process all neighbors associated with a MAC upon the MAC being learnt
2293 * locally or undergoing any other change (such as sequence number).
2295 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2299 zebra_neigh_t
*n
= NULL
;
2300 struct listnode
*node
= NULL
;
2301 struct zebra_vrf
*zvrf
= NULL
;
2302 char buf
[ETHER_ADDR_STRLEN
];
2304 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2306 if (IS_ZEBRA_DEBUG_VXLAN
)
2307 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2308 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2309 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2311 /* Walk all neighbors and mark any inactive local neighbors as
2312 * active and/or update sequence number upon a move, and inform BGP.
2313 * The action for remote neighbors is TBD.
2314 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2315 * accidentally end up deleting a just-learnt local neighbor.
2317 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2318 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2319 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2320 ZEBRA_NEIGH_SET_ACTIVE(n
);
2321 n
->loc_seq
= zmac
->loc_seq
;
2322 if (!(zvrf
->dup_addr_detect
&&
2323 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2324 ZEBRA_NEIGH_DUPLICATE
)))
2325 zvni_neigh_send_add_to_client(
2326 zvni
->vni
, &n
->ip
, &n
->emac
,
2327 n
->flags
, n
->loc_seq
);
2334 * Process all neighbors associated with a local MAC upon the MAC being
2337 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2340 zebra_neigh_t
*n
= NULL
;
2341 struct listnode
*node
= NULL
;
2342 char buf
[ETHER_ADDR_STRLEN
];
2344 if (IS_ZEBRA_DEBUG_VXLAN
)
2345 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2346 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2349 /* Walk all local neighbors and mark as inactive and inform
2351 * TBD: There is currently no handling for remote neighbors. We
2352 * don't expect them to exist, if they do, do we install the MAC
2353 * as a remote MAC and the neighbor as remote?
2355 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2356 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2357 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2358 ZEBRA_NEIGH_SET_INACTIVE(n
);
2360 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2368 * Process all neighbors associated with a MAC upon the MAC being remotely
2371 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2374 zebra_neigh_t
*n
= NULL
;
2375 struct listnode
*node
= NULL
;
2376 char buf
[ETHER_ADDR_STRLEN
];
2378 if (IS_ZEBRA_DEBUG_VXLAN
)
2379 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2380 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2383 /* Walk all local neighbors and mark as inactive and inform
2386 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2387 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2388 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2389 ZEBRA_NEIGH_SET_INACTIVE(n
);
2391 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2399 * Process all neighbors associated with a remote MAC upon the MAC being
2402 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2405 /* NOTE: Currently a NO-OP. */
2409 * Inform BGP about local neighbor addition.
2411 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2412 struct ethaddr
*macaddr
,
2413 uint8_t neigh_flags
,
2418 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2419 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2420 /* Set router flag (R-bit) based on local neigh entry add */
2421 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2422 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2424 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2425 seq
, ZEBRA_MACIP_ADD
);
2429 * Inform BGP about local neighbor deletion.
2431 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2432 struct ethaddr
*macaddr
, uint8_t flags
)
2434 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2435 0, ZEBRA_MACIP_DEL
);
2439 * Install remote neighbor into the kernel.
2441 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2443 struct zebra_if
*zif
;
2444 struct zebra_l2info_vxlan
*vxl
;
2445 struct interface
*vlan_if
;
2451 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2454 zif
= zvni
->vxlan_if
->info
;
2457 vxl
= &zif
->l2info
.vxl
;
2459 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2463 flags
= NTF_EXT_LEARNED
;
2464 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2465 flags
|= NTF_ROUTER
;
2466 ZEBRA_NEIGH_SET_ACTIVE(n
);
2467 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2473 * Uninstall remote neighbor from the kernel.
2475 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2477 struct zebra_if
*zif
;
2478 struct zebra_l2info_vxlan
*vxl
;
2479 struct interface
*vlan_if
;
2481 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2484 if (!zvni
->vxlan_if
) {
2485 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2490 zif
= zvni
->vxlan_if
->info
;
2493 vxl
= &zif
->l2info
.vxl
;
2494 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2498 ZEBRA_NEIGH_SET_INACTIVE(n
);
2500 return kernel_del_neigh(vlan_if
, &n
->ip
);
2504 * Install neighbor hash entry - called upon access VLAN change.
2506 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
2509 struct neigh_walk_ctx
*wctx
= ctxt
;
2511 n
= (zebra_neigh_t
*)backet
->data
;
2513 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2514 zvni_neigh_install(wctx
->zvni
, n
);
2517 /* Get the VRR interface for SVI if any */
2518 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2520 struct zebra_vrf
*zvrf
= NULL
;
2521 struct interface
*tmp_if
= NULL
;
2522 struct zebra_if
*zif
= NULL
;
2524 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2527 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2532 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2535 if (zif
->link
== ifp
)
2542 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2544 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2545 struct connected
*c
= NULL
;
2546 struct ethaddr macaddr
;
2548 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2550 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2553 memset(&ip
, 0, sizeof(struct ipaddr
));
2554 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2557 if (c
->address
->family
== AF_INET
) {
2558 ip
.ipa_type
= IPADDR_V4
;
2559 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2560 sizeof(struct in_addr
));
2561 } else if (c
->address
->family
== AF_INET6
) {
2562 ip
.ipa_type
= IPADDR_V6
;
2563 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2564 sizeof(struct in6_addr
));
2569 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2575 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2577 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2578 struct connected
*c
= NULL
;
2579 struct ethaddr macaddr
;
2581 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2583 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2586 memset(&ip
, 0, sizeof(struct ipaddr
));
2587 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2590 if (c
->address
->family
== AF_INET
) {
2591 ip
.ipa_type
= IPADDR_V4
;
2592 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2593 sizeof(struct in_addr
));
2594 } else if (c
->address
->family
== AF_INET6
) {
2595 ip
.ipa_type
= IPADDR_V6
;
2596 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2597 sizeof(struct in6_addr
));
2602 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2608 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2611 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2612 struct connected
*c
= NULL
;
2613 struct ethaddr macaddr
;
2615 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2617 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2620 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2622 /* skip link local address */
2623 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2628 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2629 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2631 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2632 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2638 * zvni_gw_macip_add_to_client
2640 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2641 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2643 char buf
[ETHER_ADDR_STRLEN
];
2644 char buf2
[INET6_ADDRSTRLEN
];
2645 zebra_neigh_t
*n
= NULL
;
2646 zebra_mac_t
*mac
= NULL
;
2647 struct zebra_if
*zif
= NULL
;
2648 struct zebra_l2info_vxlan
*vxl
= NULL
;
2650 zif
= zvni
->vxlan_if
->info
;
2654 vxl
= &zif
->l2info
.vxl
;
2656 mac
= zvni_mac_lookup(zvni
, macaddr
);
2658 mac
= zvni_mac_add(zvni
, macaddr
);
2660 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2661 "Failed to add MAC %s intf %s(%u) VID %u",
2662 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2663 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2668 /* Set "local" forwarding info. */
2669 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2670 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2671 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2672 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2673 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2674 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2676 n
= zvni_neigh_lookup(zvni
, ip
);
2678 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2681 EC_ZEBRA_MAC_ADD_FAILED
,
2682 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2683 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2684 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2685 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2690 /* Set "local" forwarding info. */
2691 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2692 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2693 ZEBRA_NEIGH_SET_ACTIVE(n
);
2694 /* Set Router flag (R-bit) */
2695 if (ip
->ipa_type
== IPADDR_V6
)
2696 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2697 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2698 n
->ifindex
= ifp
->ifindex
;
2700 /* Only advertise in BGP if the knob is enabled */
2701 if (!advertise_gw_macip_enabled(zvni
))
2704 if (IS_ZEBRA_DEBUG_VXLAN
)
2706 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2707 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2708 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2709 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2711 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2712 n
->flags
, n
->loc_seq
);
2718 * zvni_gw_macip_del_from_client
2720 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2723 char buf1
[ETHER_ADDR_STRLEN
];
2724 char buf2
[INET6_ADDRSTRLEN
];
2725 zebra_neigh_t
*n
= NULL
;
2726 zebra_mac_t
*mac
= NULL
;
2728 /* If the neigh entry is not present nothing to do*/
2729 n
= zvni_neigh_lookup(zvni
, ip
);
2733 /* mac entry should be present */
2734 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2736 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2737 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2738 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2742 /* If the entry is not local nothing to do*/
2743 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2746 /* only need to delete the entry from bgp if we sent it before */
2747 if (IS_ZEBRA_DEBUG_VXLAN
)
2749 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2750 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2751 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2752 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2754 /* Remove neighbor from BGP. */
2755 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2756 ZEBRA_MACIP_TYPE_GW
);
2758 /* Delete this neighbor entry. */
2759 zvni_neigh_del(zvni
, n
);
2761 /* see if the mac needs to be deleted as well*/
2763 zvni_deref_ip2mac(zvni
, mac
);
2768 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
2771 zebra_vni_t
*zvni
= NULL
;
2772 struct zebra_if
*zif
= NULL
;
2773 struct zebra_l2info_vxlan zl2_info
;
2774 struct interface
*vlan_if
= NULL
;
2775 struct interface
*vrr_if
= NULL
;
2776 struct interface
*ifp
;
2778 /* Add primary SVI MAC*/
2779 zvni
= (zebra_vni_t
*)backet
->data
;
2781 ifp
= zvni
->vxlan_if
;
2786 /* If down or not mapped to a bridge, we're done. */
2787 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2790 zl2_info
= zif
->l2info
.vxl
;
2793 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2797 /* Del primary MAC-IP */
2798 zvni_del_macip_for_intf(vlan_if
, zvni
);
2800 /* Del VRR MAC-IP - if any*/
2801 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2803 zvni_del_macip_for_intf(vrr_if
, zvni
);
2808 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2811 zebra_vni_t
*zvni
= NULL
;
2812 struct zebra_if
*zif
= NULL
;
2813 struct zebra_l2info_vxlan zl2_info
;
2814 struct interface
*vlan_if
= NULL
;
2815 struct interface
*vrr_if
= NULL
;
2816 struct interface
*ifp
= NULL
;
2818 zvni
= (zebra_vni_t
*)backet
->data
;
2820 ifp
= zvni
->vxlan_if
;
2825 /* If down or not mapped to a bridge, we're done. */
2826 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2828 zl2_info
= zif
->l2info
.vxl
;
2831 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2835 /* Add primary SVI MAC-IP */
2836 zvni_add_macip_for_intf(vlan_if
, zvni
);
2838 /* Add VRR MAC-IP - if any*/
2839 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2841 zvni_add_macip_for_intf(vrr_if
, zvni
);
2846 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2847 struct interface
*ifp
,
2849 struct ethaddr
*macaddr
,
2852 char buf
[ETHER_ADDR_STRLEN
];
2853 char buf2
[INET6_ADDRSTRLEN
];
2854 struct zebra_vrf
*zvrf
;
2855 zebra_neigh_t
*n
= NULL
;
2856 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2857 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2858 bool upd_mac_seq
= false;
2859 bool neigh_mac_change
= false;
2860 bool neigh_on_hold
= false;
2861 bool neigh_was_remote
= false;
2862 bool do_dad
= false;
2863 struct in_addr vtep_ip
= {.s_addr
= 0};
2865 /* Check if the MAC exists. */
2866 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2868 /* create a dummy MAC if the MAC is not already present */
2869 if (IS_ZEBRA_DEBUG_VXLAN
)
2871 "AUTO MAC %s created for neigh %s on VNI %u",
2872 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2873 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2875 zmac
= zvni_mac_add(zvni
, macaddr
);
2877 zlog_debug("Failed to add MAC %s VNI %u",
2878 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2883 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2884 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2885 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2887 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2889 * We don't change the MAC to local upon a neighbor
2890 * learn event, we wait for the explicit local MAC
2891 * learn. However, we have to compute its sequence
2892 * number in preparation for when it actually turns
2899 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2903 /* Check if the neighbor exists. */
2904 n
= zvni_neigh_lookup(zvni
, ip
);
2906 /* New neighbor - create */
2907 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2910 EC_ZEBRA_MAC_ADD_FAILED
,
2911 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2912 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2913 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2914 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2917 /* Set "local" forwarding info. */
2918 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2919 n
->ifindex
= ifp
->ifindex
;
2921 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2925 /* Note any changes and see if of interest to BGP. */
2926 mac_different
= (memcmp(n
->emac
.octet
,
2927 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2928 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2929 ZEBRA_NEIGH_ROUTER_FLAG
);
2930 if (!mac_different
&& is_router
== cur_is_router
) {
2931 n
->ifindex
= ifp
->ifindex
;
2935 if (!mac_different
) {
2936 bool is_neigh_freezed
= false;
2938 /* Only the router flag has changed. */
2941 ZEBRA_NEIGH_ROUTER_FLAG
);
2943 UNSET_FLAG(n
->flags
,
2944 ZEBRA_NEIGH_ROUTER_FLAG
);
2946 /* Neigh is in freeze state and freeze action
2947 * is enabled, do not send update to client.
2949 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
2951 CHECK_FLAG(n
->flags
,
2952 ZEBRA_NEIGH_DUPLICATE
));
2954 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
2956 return zvni_neigh_send_add_to_client(
2957 zvni
->vni
, ip
, macaddr
,
2958 n
->flags
, n
->loc_seq
);
2962 /* The MAC has changed, need to issue a delete
2963 * first as this means a different MACIP route.
2964 * Also, need to do some unlinking/relinking.
2965 * We also need to update the MAC's sequence number
2966 * in different situations.
2968 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2969 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2971 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2973 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2975 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2976 neigh_mac_change
= upd_mac_seq
= true;
2977 listnode_delete(old_zmac
->neigh_list
, n
);
2978 zvni_deref_ip2mac(zvni
, old_zmac
);
2981 /* Update the forwarding info. */
2982 n
->ifindex
= ifp
->ifindex
;
2983 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2985 /* Link to new MAC */
2986 listnode_add_sort(zmac
->neigh_list
, n
);
2987 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2989 * Neighbor has moved from remote to local. Its
2990 * MAC could have also changed as part of the move.
2992 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2994 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2996 old_mac_seq
= CHECK_FLAG(
3001 neigh_mac_change
= upd_mac_seq
= true;
3002 listnode_delete(old_zmac
->neigh_list
,
3004 zvni_deref_ip2mac(zvni
, old_zmac
);
3007 /* Link to new MAC */
3008 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3009 listnode_add_sort(zmac
->neigh_list
, n
);
3011 /* Based on Mobility event Scenario-B from the
3012 * draft, neigh's previous state was remote treat this
3015 neigh_was_remote
= true;
3016 vtep_ip
= n
->r_vtep_ip
;
3017 /* Mark appropriately */
3018 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3019 n
->r_vtep_ip
.s_addr
= 0;
3020 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3021 n
->ifindex
= ifp
->ifindex
;
3025 /* If MAC was previously remote, or the neighbor had a different
3026 * MAC earlier, recompute the sequence number.
3029 uint32_t seq1
, seq2
;
3031 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3032 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3033 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3034 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3035 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3038 /* Mark Router flag (R-bit) */
3040 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3042 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3044 /* Check old and/or new MAC detected as duplicate mark
3045 * the neigh as duplicate
3047 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3048 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3049 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3051 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3052 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3055 /* For IP Duplicate Address Detection (DAD) is trigger,
3056 * when the event is extended mobility based on scenario-B
3057 * from the draft, IP/Neigh's MAC binding changed and
3058 * neigh's previous state was remote.
3060 if (neigh_mac_change
&& neigh_was_remote
)
3063 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3064 &neigh_on_hold
, true);
3066 /* Before we program this in BGP, we need to check if MAC is locally
3067 * learnt. If not, force neighbor to be inactive and reset its seq.
3069 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3070 ZEBRA_NEIGH_SET_INACTIVE(n
);
3072 zmac
->loc_seq
= mac_new_seq
;
3076 /* If the MAC's sequence number has changed, inform the MAC and all
3077 * neighbors associated with the MAC to BGP, else just inform this
3080 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3081 if (IS_ZEBRA_DEBUG_VXLAN
)
3082 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3083 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3084 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3085 zmac
->loc_seq
= mac_new_seq
;
3086 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3087 zmac
->flags
, zmac
->loc_seq
))
3089 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3093 ZEBRA_NEIGH_SET_ACTIVE(n
);
3094 n
->loc_seq
= zmac
->loc_seq
;
3097 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3098 n
->flags
, n
->loc_seq
);
3102 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3103 struct interface
*ifp
,
3105 struct ethaddr
*macaddr
,
3108 char buf
[ETHER_ADDR_STRLEN
];
3109 char buf2
[INET6_ADDRSTRLEN
];
3110 zebra_neigh_t
*n
= NULL
;
3111 zebra_mac_t
*zmac
= NULL
;
3113 /* If the neighbor is unknown, there is no further action. */
3114 n
= zvni_neigh_lookup(zvni
, ip
);
3118 /* If a remote entry, see if it needs to be refreshed */
3119 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3121 if (state
& NUD_STALE
)
3122 zvni_neigh_install(zvni
, n
);
3125 /* We got a "remote" neighbor notification for an entry
3126 * we think is local. This can happen in a multihoming
3127 * scenario - but only if the MAC is already "remote".
3128 * Just mark our entry as "remote".
3130 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3131 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3133 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3134 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3135 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3140 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3141 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3142 ZEBRA_NEIGH_SET_ACTIVE(n
);
3143 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3150 * Make hash key for MAC.
3152 static unsigned int mac_hash_keymake(void *p
)
3154 zebra_mac_t
*pmac
= p
;
3155 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3157 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3161 * Compare two MAC addresses.
3163 static bool mac_cmp(const void *p1
, const void *p2
)
3165 const zebra_mac_t
*pmac1
= p1
;
3166 const zebra_mac_t
*pmac2
= p2
;
3168 if (pmac1
== NULL
&& pmac2
== NULL
)
3171 if (pmac1
== NULL
|| pmac2
== NULL
)
3174 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3179 * Callback to allocate MAC hash entry.
3181 static void *zvni_mac_alloc(void *p
)
3183 const zebra_mac_t
*tmp_mac
= p
;
3186 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3189 return ((void *)mac
);
3195 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3197 zebra_mac_t tmp_mac
;
3198 zebra_mac_t
*mac
= NULL
;
3200 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3201 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3202 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3205 mac
->neigh_list
= list_new();
3206 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3214 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3216 zebra_mac_t
*tmp_mac
;
3218 list_delete(&mac
->neigh_list
);
3220 /* Free the VNI hash entry and allocated memory. */
3221 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3223 XFREE(MTYPE_MAC
, tmp_mac
);
3229 * Free MAC hash entry (callback)
3231 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
3233 struct mac_walk_ctx
*wctx
= arg
;
3234 zebra_mac_t
*mac
= backet
->data
;
3236 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3237 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3238 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3239 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3240 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3241 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3242 &wctx
->r_vtep_ip
))) {
3243 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3244 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3248 if (wctx
->uninstall
)
3249 zvni_mac_uninstall(wctx
->zvni
, mac
);
3251 zvni_mac_del(wctx
->zvni
, mac
);
3258 * Delete all MAC entries from specific VTEP for a particular VNI.
3260 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3261 struct in_addr
*r_vtep_ip
)
3263 struct mac_walk_ctx wctx
;
3265 if (!zvni
->mac_table
)
3268 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3270 wctx
.uninstall
= uninstall
;
3271 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3272 wctx
.r_vtep_ip
= *r_vtep_ip
;
3274 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3278 * Delete all MAC entries for this VNI.
3280 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3283 struct mac_walk_ctx wctx
;
3285 if (!zvni
->mac_table
)
3288 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3290 wctx
.uninstall
= uninstall
;
3291 wctx
.upd_client
= upd_client
;
3294 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3298 * Look up MAC hash entry.
3300 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3305 memset(&tmp
, 0, sizeof(tmp
));
3306 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3307 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3313 * Inform BGP about local MAC addition.
3315 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3316 uint8_t mac_flags
, uint32_t seq
)
3320 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3321 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3322 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3323 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3325 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3326 seq
, ZEBRA_MACIP_ADD
);
3330 * Inform BGP about local MAC deletion.
3332 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3334 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3335 0 /* seq */, ZEBRA_MACIP_DEL
);
3339 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3340 * notifications, to see if they are of interest.
3342 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3343 struct interface
*br_if
, vlanid_t vid
)
3345 struct zebra_ns
*zns
;
3346 struct route_node
*rn
;
3347 struct interface
*tmp_if
= NULL
;
3348 struct zebra_if
*zif
;
3349 struct zebra_l2info_bridge
*br
;
3350 struct zebra_l2info_vxlan
*vxl
= NULL
;
3351 uint8_t bridge_vlan_aware
;
3355 /* Determine if bridge is VLAN-aware or not */
3358 br
= &zif
->l2info
.br
;
3359 bridge_vlan_aware
= br
->vlan_aware
;
3361 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3362 /* TODO: Optimize with a hash. */
3363 zns
= zebra_ns_lookup(NS_DEFAULT
);
3364 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3365 tmp_if
= (struct interface
*)rn
->info
;
3369 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3371 if (!if_is_operative(tmp_if
))
3373 vxl
= &zif
->l2info
.vxl
;
3375 if (zif
->brslave_info
.br_if
!= br_if
)
3378 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3387 zvni
= zvni_lookup(vxl
->vni
);
3392 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3393 * neighbor notifications, to see if they are of interest.
3395 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3396 struct interface
*br_if
)
3398 struct zebra_ns
*zns
;
3399 struct route_node
*rn
;
3400 struct interface
*tmp_if
= NULL
;
3401 struct zebra_if
*zif
;
3402 struct zebra_l2info_bridge
*br
;
3403 struct zebra_l2info_vxlan
*vxl
= NULL
;
3404 uint8_t bridge_vlan_aware
;
3412 /* Make sure the linked interface is a bridge. */
3413 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3416 /* Determine if bridge is VLAN-aware or not */
3419 br
= &zif
->l2info
.br
;
3420 bridge_vlan_aware
= br
->vlan_aware
;
3421 if (bridge_vlan_aware
) {
3422 struct zebra_l2info_vlan
*vl
;
3424 if (!IS_ZEBRA_IF_VLAN(ifp
))
3429 vl
= &zif
->l2info
.vl
;
3433 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3434 /* TODO: Optimize with a hash. */
3435 zns
= zebra_ns_lookup(NS_DEFAULT
);
3436 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3437 tmp_if
= (struct interface
*)rn
->info
;
3441 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3443 if (!if_is_operative(tmp_if
))
3445 vxl
= &zif
->l2info
.vxl
;
3447 if (zif
->brslave_info
.br_if
!= br_if
)
3450 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3459 zvni
= zvni_lookup(vxl
->vni
);
3463 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3465 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3466 * linked to the bridge
3467 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3470 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3472 struct zebra_ns
*zns
;
3473 struct route_node
*rn
;
3474 struct interface
*tmp_if
= NULL
;
3475 struct zebra_if
*zif
;
3476 struct zebra_l2info_bridge
*br
;
3477 struct zebra_l2info_vlan
*vl
;
3478 uint8_t bridge_vlan_aware
;
3481 /* Defensive check, caller expected to invoke only with valid bridge. */
3485 /* Determine if bridge is VLAN-aware or not */
3488 br
= &zif
->l2info
.br
;
3489 bridge_vlan_aware
= br
->vlan_aware
;
3491 /* Check oper status of the SVI. */
3492 if (!bridge_vlan_aware
)
3493 return if_is_operative(br_if
) ? br_if
: NULL
;
3495 /* Identify corresponding VLAN interface. */
3496 /* TODO: Optimize with a hash. */
3497 zns
= zebra_ns_lookup(NS_DEFAULT
);
3498 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3499 tmp_if
= (struct interface
*)rn
->info
;
3500 /* Check oper status of the SVI. */
3501 if (!tmp_if
|| !if_is_operative(tmp_if
))
3504 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3505 || zif
->link
!= br_if
)
3507 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3509 if (vl
->vid
== vid
) {
3515 return found
? tmp_if
: NULL
;
3519 * Install remote MAC into the kernel.
3521 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3523 struct zebra_if
*zif
;
3524 struct zebra_l2info_vxlan
*vxl
;
3527 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3530 zif
= zvni
->vxlan_if
->info
;
3533 vxl
= &zif
->l2info
.vxl
;
3535 sticky
= !!CHECK_FLAG(mac
->flags
,
3536 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3538 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3539 mac
->fwd_info
.r_vtep_ip
, sticky
);
3543 * Uninstall remote MAC from the kernel.
3545 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3547 struct zebra_if
*zif
;
3548 struct zebra_l2info_vxlan
*vxl
;
3549 struct in_addr vtep_ip
;
3550 struct interface
*ifp
;
3552 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3555 if (!zvni
->vxlan_if
) {
3556 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3561 zif
= zvni
->vxlan_if
->info
;
3564 vxl
= &zif
->l2info
.vxl
;
3566 ifp
= zvni
->vxlan_if
;
3567 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3569 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3573 * Install MAC hash entry - called upon access VLAN change.
3575 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
3578 struct mac_walk_ctx
*wctx
= ctxt
;
3580 mac
= (zebra_mac_t
*)backet
->data
;
3582 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3583 zvni_mac_install(wctx
->zvni
, mac
);
3587 * Count of remote neighbors referencing this MAC.
3589 static int remote_neigh_count(zebra_mac_t
*zmac
)
3591 zebra_neigh_t
*n
= NULL
;
3592 struct listnode
*node
= NULL
;
3595 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3596 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3604 * Decrement neighbor refcount of MAC; uninstall and free it if
3607 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3609 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3612 /* If all remote neighbors referencing a remote MAC go away,
3613 * we need to uninstall the MAC.
3615 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3616 remote_neigh_count(mac
) == 0) {
3617 zvni_mac_uninstall(zvni
, mac
);
3618 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3621 /* If no neighbors, delete the MAC. */
3622 if (list_isempty(mac
->neigh_list
))
3623 zvni_mac_del(zvni
, mac
);
3627 * Read and populate local MACs and neighbors corresponding to this VNI.
3629 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3631 struct zebra_ns
*zns
;
3632 struct zebra_if
*zif
;
3633 struct interface
*vlan_if
;
3634 struct zebra_l2info_vxlan
*vxl
;
3635 struct interface
*vrr_if
;
3638 vxl
= &zif
->l2info
.vxl
;
3639 zns
= zebra_ns_lookup(NS_DEFAULT
);
3641 if (IS_ZEBRA_DEBUG_VXLAN
)
3643 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3644 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3645 zif
->brslave_info
.bridge_ifindex
);
3647 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3648 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3651 /* Add SVI MAC-IP */
3652 zvni_add_macip_for_intf(vlan_if
, zvni
);
3654 /* Add VRR MAC-IP - if any*/
3655 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3657 zvni_add_macip_for_intf(vrr_if
, zvni
);
3659 neigh_read_for_vlan(zns
, vlan_if
);
3664 * Hash function for VNI.
3666 static unsigned int vni_hash_keymake(void *p
)
3668 const zebra_vni_t
*zvni
= p
;
3670 return (jhash_1word(zvni
->vni
, 0));
3674 * Compare 2 VNI hash entries.
3676 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3678 const zebra_vni_t
*zvni1
= p1
;
3679 const zebra_vni_t
*zvni2
= p2
;
3681 return (zvni1
->vni
== zvni2
->vni
);
3684 static int vni_list_cmp(void *p1
, void *p2
)
3686 const zebra_vni_t
*zvni1
= p1
;
3687 const zebra_vni_t
*zvni2
= p2
;
3689 if (zvni1
->vni
== zvni2
->vni
)
3691 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3695 * Callback to allocate VNI hash entry.
3697 static void *zvni_alloc(void *p
)
3699 const zebra_vni_t
*tmp_vni
= p
;
3702 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3703 zvni
->vni
= tmp_vni
->vni
;
3704 return ((void *)zvni
);
3708 * Look up VNI hash entry.
3710 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3712 struct zebra_vrf
*zvrf
;
3713 zebra_vni_t tmp_vni
;
3714 zebra_vni_t
*zvni
= NULL
;
3716 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3718 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3720 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3726 * Add VNI hash entry.
3728 static zebra_vni_t
*zvni_add(vni_t vni
)
3730 struct zebra_vrf
*zvrf
;
3731 zebra_vni_t tmp_zvni
;
3732 zebra_vni_t
*zvni
= NULL
;
3734 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3736 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3738 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3741 /* Create hash table for MAC */
3743 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3745 /* Create hash table for neighbors */
3746 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3747 "Zebra VNI Neighbor Table");
3753 * Delete VNI hash entry.
3755 static int zvni_del(zebra_vni_t
*zvni
)
3757 struct zebra_vrf
*zvrf
;
3758 zebra_vni_t
*tmp_zvni
;
3760 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3763 zvni
->vxlan_if
= NULL
;
3765 /* Free the neighbor hash table. */
3766 hash_free(zvni
->neigh_table
);
3767 zvni
->neigh_table
= NULL
;
3769 /* Free the MAC hash table. */
3770 hash_free(zvni
->mac_table
);
3771 zvni
->mac_table
= NULL
;
3773 /* Free the VNI hash entry and allocated memory. */
3774 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3776 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3782 * Inform BGP about local VNI addition.
3784 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3786 struct zserv
*client
;
3789 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3790 /* BGP may not be running. */
3794 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3796 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3797 stream_putl(s
, zvni
->vni
);
3798 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3799 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3801 /* Write packet size. */
3802 stream_putw_at(s
, 0, stream_get_endp(s
));
3804 if (IS_ZEBRA_DEBUG_VXLAN
)
3805 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3806 inet_ntoa(zvni
->local_vtep_ip
),
3807 vrf_id_to_name(zvni
->vrf_id
),
3808 zebra_route_string(client
->proto
));
3810 client
->vniadd_cnt
++;
3811 return zserv_send_message(client
, s
);
3815 * Inform BGP about local VNI deletion.
3817 static int zvni_send_del_to_client(vni_t vni
)
3819 struct zserv
*client
;
3822 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3823 /* BGP may not be running. */
3827 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3830 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3831 stream_putl(s
, vni
);
3833 /* Write packet size. */
3834 stream_putw_at(s
, 0, stream_get_endp(s
));
3836 if (IS_ZEBRA_DEBUG_VXLAN
)
3837 zlog_debug("Send VNI_DEL %u to %s", vni
,
3838 zebra_route_string(client
->proto
));
3840 client
->vnidel_cnt
++;
3841 return zserv_send_message(client
, s
);
3845 * Build the VNI hash table by going over the VxLAN interfaces. This
3846 * is called when EVPN (advertise-all-vni) is enabled.
3848 static void zvni_build_hash_table()
3850 struct zebra_ns
*zns
;
3851 struct route_node
*rn
;
3852 struct interface
*ifp
;
3854 /* Walk VxLAN interfaces and create VNI hash. */
3855 zns
= zebra_ns_lookup(NS_DEFAULT
);
3856 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3858 zebra_vni_t
*zvni
= NULL
;
3859 zebra_l3vni_t
*zl3vni
= NULL
;
3860 struct zebra_if
*zif
;
3861 struct zebra_l2info_vxlan
*vxl
;
3863 ifp
= (struct interface
*)rn
->info
;
3867 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3870 vxl
= &zif
->l2info
.vxl
;
3873 /* L3-VNI and L2-VNI are handled seperately */
3874 zl3vni
= zl3vni_lookup(vni
);
3877 if (IS_ZEBRA_DEBUG_VXLAN
)
3879 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3880 ifp
->name
, ifp
->ifindex
, vni
);
3882 /* associate with vxlan_if */
3883 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3884 zl3vni
->vxlan_if
= ifp
;
3887 * we need to associate with SVI.
3888 * we can associate with svi-if only after association
3889 * with vxlan-intf is complete
3891 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3893 if (is_l3vni_oper_up(zl3vni
))
3894 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3897 struct interface
*vlan_if
= NULL
;
3899 if (IS_ZEBRA_DEBUG_VXLAN
)
3901 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3902 ifp
->name
, ifp
->ifindex
, vni
,
3903 inet_ntoa(vxl
->vtep_ip
));
3905 /* VNI hash entry is not expected to exist. */
3906 zvni
= zvni_lookup(vni
);
3909 "VNI hash already present for IF %s(%u) L2-VNI %u",
3910 ifp
->name
, ifp
->ifindex
, vni
);
3914 zvni
= zvni_add(vni
);
3917 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3918 ifp
->name
, ifp
->ifindex
, vni
);
3922 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3923 zvni
->vxlan_if
= ifp
;
3924 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3925 zif
->brslave_info
.br_if
);
3927 zvni
->vrf_id
= vlan_if
->vrf_id
;
3928 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3930 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3934 /* Inform BGP if intf is up and mapped to bridge. */
3935 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3936 zvni_send_add_to_client(zvni
);
3942 * See if remote VTEP matches with prefix.
3944 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3946 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3950 * Locate remote VTEP in VNI hash table.
3952 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3954 zebra_vtep_t
*zvtep
;
3959 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3960 if (zvni_vtep_match(vtep_ip
, zvtep
))
3968 * Add remote VTEP to VNI hash table.
3970 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3972 zebra_vtep_t
*zvtep
;
3974 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3976 zvtep
->vtep_ip
= *vtep_ip
;
3979 zvni
->vteps
->prev
= zvtep
;
3980 zvtep
->next
= zvni
->vteps
;
3981 zvni
->vteps
= zvtep
;
3987 * Remove remote VTEP from VNI hash table.
3989 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3992 zvtep
->next
->prev
= zvtep
->prev
;
3994 zvtep
->prev
->next
= zvtep
->next
;
3996 zvni
->vteps
= zvtep
->next
;
3998 zvtep
->prev
= zvtep
->next
= NULL
;
3999 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4005 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4006 * uninstall from kernel if asked to.
4008 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4010 zebra_vtep_t
*zvtep
, *zvtep_next
;
4015 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4016 zvtep_next
= zvtep
->next
;
4018 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4019 zvni_vtep_del(zvni
, zvtep
);
4026 * Install remote VTEP into the kernel.
4028 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4030 if (is_vxlan_flooding_head_end())
4031 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4036 * Uninstall remote VTEP from the kernel.
4038 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4040 if (!zvni
->vxlan_if
) {
4041 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4046 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4050 * Install or uninstall flood entries in the kernel corresponding to
4051 * remote VTEPs. This is invoked upon change to BUM handling.
4053 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
4057 zebra_vtep_t
*zvtep
;
4059 zvni
= (zebra_vni_t
*)backet
->data
;
4063 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4064 if (is_vxlan_flooding_head_end())
4065 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4067 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4072 * Cleanup VNI/VTEP and update kernel
4074 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
4076 zebra_vni_t
*zvni
= NULL
;
4077 zebra_l3vni_t
*zl3vni
= NULL
;
4078 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4080 zvni
= (zebra_vni_t
*)backet
->data
;
4082 /* remove from l3-vni list */
4084 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4086 listnode_delete(zl3vni
->l2vnis
, zvni
);
4088 /* Free up all neighbors and MACs, if any. */
4089 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4090 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4092 /* Free up all remote VTEPs, if any. */
4093 zvni_vtep_del_all(zvni
, 1);
4095 /* Delete the hash entry. */
4100 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
4102 zebra_l3vni_t
*zl3vni
= NULL
;
4104 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
4106 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4109 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4110 struct prefix
*host
)
4112 struct host_rb_entry lookup
;
4113 struct host_rb_entry
*hle
;
4115 memset(&lookup
, 0, sizeof(lookup
));
4116 memcpy(&lookup
.p
, host
, sizeof(*host
));
4118 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4122 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4123 memcpy(hle
, &lookup
, sizeof(lookup
));
4125 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4128 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4130 struct host_rb_entry lookup
;
4131 struct host_rb_entry
*hle
;
4133 memset(&lookup
, 0, sizeof(lookup
));
4134 memcpy(&lookup
.p
, host
, sizeof(*host
));
4136 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4138 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4139 XFREE(MTYPE_HOST_PREFIX
, hle
);
4146 * Look up MAC hash entry.
4148 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4149 struct ethaddr
*rmac
)
4154 memset(&tmp
, 0, sizeof(tmp
));
4155 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4156 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4162 * Callback to allocate RMAC hash entry.
4164 static void *zl3vni_rmac_alloc(void *p
)
4166 const zebra_mac_t
*tmp_rmac
= p
;
4169 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4172 return ((void *)zrmac
);
4176 * Add RMAC entry to l3-vni
4178 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4180 zebra_mac_t tmp_rmac
;
4181 zebra_mac_t
*zrmac
= NULL
;
4183 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4184 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4185 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4188 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4190 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4191 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4199 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4201 zebra_mac_t
*tmp_rmac
;
4202 struct host_rb_entry
*hle
;
4204 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4205 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4207 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4208 XFREE(MTYPE_HOST_PREFIX
, hle
);
4211 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4213 XFREE(MTYPE_MAC
, tmp_rmac
);
4219 * Install remote RMAC into the kernel.
4221 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4223 struct zebra_if
*zif
= NULL
;
4224 struct zebra_l2info_vxlan
*vxl
= NULL
;
4226 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4227 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4230 zif
= zl3vni
->vxlan_if
->info
;
4234 vxl
= &zif
->l2info
.vxl
;
4236 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4237 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4241 * Uninstall remote RMAC from the kernel.
4243 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4245 char buf
[ETHER_ADDR_STRLEN
];
4246 struct zebra_if
*zif
= NULL
;
4247 struct zebra_l2info_vxlan
*vxl
= NULL
;
4249 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4250 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4253 if (!zl3vni
->vxlan_if
) {
4255 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4256 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4257 zl3vni
->vni
, zl3vni
);
4261 zif
= zl3vni
->vxlan_if
->info
;
4265 vxl
= &zif
->l2info
.vxl
;
4267 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4268 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4271 /* handle rmac add */
4272 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4273 struct ipaddr
*vtep_ip
,
4274 struct prefix
*host_prefix
)
4276 char buf
[ETHER_ADDR_STRLEN
];
4277 char buf1
[INET6_ADDRSTRLEN
];
4278 zebra_mac_t
*zrmac
= NULL
;
4280 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4283 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4286 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4287 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4289 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4292 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4293 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4295 /* install rmac in kernel */
4296 zl3vni_rmac_install(zl3vni
, zrmac
);
4299 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4305 /* handle rmac delete */
4306 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4307 struct prefix
*host_prefix
)
4309 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4311 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4312 /* uninstall from kernel */
4313 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4315 /* del the rmac entry */
4316 zl3vni_rmac_del(zl3vni
, zrmac
);
4321 * Look up nh hash entry on a l3-vni.
4323 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4328 memset(&tmp
, 0, sizeof(tmp
));
4329 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4330 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4337 * Callback to allocate NH hash entry on L3-VNI.
4339 static void *zl3vni_nh_alloc(void *p
)
4341 const zebra_neigh_t
*tmp_n
= p
;
4344 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4351 * Add neighbor entry.
4353 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4354 struct ethaddr
*mac
)
4356 zebra_neigh_t tmp_n
;
4357 zebra_neigh_t
*n
= NULL
;
4359 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4360 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4361 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4364 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4366 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4367 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4368 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4374 * Delete neighbor entry.
4376 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4378 zebra_neigh_t
*tmp_n
;
4379 struct host_rb_entry
*hle
;
4381 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4382 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4384 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4385 XFREE(MTYPE_HOST_PREFIX
, hle
);
4388 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4390 XFREE(MTYPE_NEIGH
, tmp_n
);
4396 * Install remote nh as neigh into the kernel.
4398 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4405 if (!is_l3vni_oper_up(zl3vni
))
4408 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4409 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4412 flags
= NTF_EXT_LEARNED
;
4413 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4414 flags
|= NTF_ROUTER
;
4415 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4421 * Uninstall remote nh from the kernel.
4423 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4425 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4426 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4429 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4432 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4435 /* add remote vtep as a neigh entry */
4436 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4437 struct ethaddr
*rmac
,
4438 struct prefix
*host_prefix
)
4440 char buf
[ETHER_ADDR_STRLEN
];
4441 char buf1
[INET6_ADDRSTRLEN
];
4442 zebra_neigh_t
*nh
= NULL
;
4444 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4446 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4450 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4451 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4452 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4457 /* install the nh neigh in kernel */
4458 zl3vni_nh_install(zl3vni
, nh
);
4461 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4466 /* handle nh neigh delete */
4467 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4468 struct prefix
*host_prefix
)
4470 rb_delete_host(&nh
->host_rb
, host_prefix
);
4472 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4473 /* uninstall from kernel */
4474 zl3vni_nh_uninstall(zl3vni
, nh
);
4476 /* delete the nh entry */
4477 zl3vni_nh_del(zl3vni
, nh
);
4481 /* handle neigh update from kernel - the only thing of interest is to
4482 * readd stale entries.
4484 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4488 zebra_neigh_t
*n
= NULL
;
4490 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4494 /* all next hop neigh are remote and installed by frr.
4495 * If the kernel has aged this entry, re-install.
4497 if (state
& NUD_STALE
)
4498 zl3vni_nh_install(zl3vni
, n
);
4503 /* handle neigh delete from kernel */
4504 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4506 zebra_neigh_t
*n
= NULL
;
4508 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4512 /* all next hop neigh are remote and installed by frr.
4513 * If we get an age out notification for these neigh entries, we have to
4516 zl3vni_nh_install(zl3vni
, n
);
4522 * Hash function for L3 VNI.
4524 static unsigned int l3vni_hash_keymake(void *p
)
4526 const zebra_l3vni_t
*zl3vni
= p
;
4528 return jhash_1word(zl3vni
->vni
, 0);
4532 * Compare 2 L3 VNI hash entries.
4534 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4536 const zebra_l3vni_t
*zl3vni1
= p1
;
4537 const zebra_l3vni_t
*zl3vni2
= p2
;
4539 return (zl3vni1
->vni
== zl3vni2
->vni
);
4543 * Callback to allocate L3 VNI hash entry.
4545 static void *zl3vni_alloc(void *p
)
4547 zebra_l3vni_t
*zl3vni
= NULL
;
4548 const zebra_l3vni_t
*tmp_l3vni
= p
;
4550 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4551 zl3vni
->vni
= tmp_l3vni
->vni
;
4552 return ((void *)zl3vni
);
4556 * Look up L3 VNI hash entry.
4558 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4560 zebra_l3vni_t tmp_l3vni
;
4561 zebra_l3vni_t
*zl3vni
= NULL
;
4563 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4564 tmp_l3vni
.vni
= vni
;
4565 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4571 * Add L3 VNI hash entry.
4573 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4575 zebra_l3vni_t tmp_zl3vni
;
4576 zebra_l3vni_t
*zl3vni
= NULL
;
4578 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4579 tmp_zl3vni
.vni
= vni
;
4581 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4584 zl3vni
->vrf_id
= vrf_id
;
4585 zl3vni
->svi_if
= NULL
;
4586 zl3vni
->vxlan_if
= NULL
;
4587 zl3vni
->l2vnis
= list_new();
4588 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4590 /* Create hash table for remote RMAC */
4591 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4592 "Zebra L3-VNI RMAC-Table");
4594 /* Create hash table for neighbors */
4595 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4596 "Zebra L3-VNI next-hop table");
4602 * Delete L3 VNI hash entry.
4604 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4606 zebra_l3vni_t
*tmp_zl3vni
;
4608 /* free the list of l2vnis */
4609 list_delete(&zl3vni
->l2vnis
);
4610 zl3vni
->l2vnis
= NULL
;
4612 /* Free the rmac table */
4613 hash_free(zl3vni
->rmac_table
);
4614 zl3vni
->rmac_table
= NULL
;
4616 /* Free the nh table */
4617 hash_free(zl3vni
->nh_table
);
4618 zl3vni
->nh_table
= NULL
;
4620 /* Free the VNI hash entry and allocated memory. */
4621 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4623 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4628 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4630 struct zebra_ns
*zns
= NULL
;
4631 struct route_node
*rn
= NULL
;
4632 struct interface
*ifp
= NULL
;
4634 /* loop through all vxlan-interface */
4635 zns
= zebra_ns_lookup(NS_DEFAULT
);
4636 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4638 struct zebra_if
*zif
= NULL
;
4639 struct zebra_l2info_vxlan
*vxl
= NULL
;
4641 ifp
= (struct interface
*)rn
->info
;
4646 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4649 vxl
= &zif
->l2info
.vxl
;
4650 if (vxl
->vni
== zl3vni
->vni
) {
4651 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4659 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4661 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4662 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4667 if (!zl3vni
->vxlan_if
)
4670 zif
= zl3vni
->vxlan_if
->info
;
4674 vxl
= &zif
->l2info
.vxl
;
4676 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4679 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4681 struct zebra_vrf
*zvrf
= NULL
;
4683 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4687 return zl3vni_lookup(zvrf
->l3vni
);
4691 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4692 * neighbor notifications, to see if they are of interest.
4694 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4695 struct interface
*br_if
)
4699 uint8_t bridge_vlan_aware
= 0;
4700 zebra_l3vni_t
*zl3vni
= NULL
;
4701 struct zebra_ns
*zns
= NULL
;
4702 struct route_node
*rn
= NULL
;
4703 struct zebra_if
*zif
= NULL
;
4704 struct interface
*tmp_if
= NULL
;
4705 struct zebra_l2info_bridge
*br
= NULL
;
4706 struct zebra_l2info_vxlan
*vxl
= NULL
;
4711 /* Make sure the linked interface is a bridge. */
4712 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4715 /* Determine if bridge is VLAN-aware or not */
4718 br
= &zif
->l2info
.br
;
4719 bridge_vlan_aware
= br
->vlan_aware
;
4720 if (bridge_vlan_aware
) {
4721 struct zebra_l2info_vlan
*vl
;
4723 if (!IS_ZEBRA_IF_VLAN(ifp
))
4728 vl
= &zif
->l2info
.vl
;
4732 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4733 /* TODO: Optimize with a hash. */
4734 zns
= zebra_ns_lookup(NS_DEFAULT
);
4735 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4736 tmp_if
= (struct interface
*)rn
->info
;
4740 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4742 if (!if_is_operative(tmp_if
))
4744 vxl
= &zif
->l2info
.vxl
;
4746 if (zif
->brslave_info
.br_if
!= br_if
)
4749 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4758 zl3vni
= zl3vni_lookup(vxl
->vni
);
4763 * Inform BGP about l3-vni.
4765 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4767 struct stream
*s
= NULL
;
4768 struct zserv
*client
= NULL
;
4769 struct ethaddr rmac
;
4770 char buf
[ETHER_ADDR_STRLEN
];
4772 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4773 /* BGP may not be running. */
4778 memset(&rmac
, 0, sizeof(struct ethaddr
));
4779 zl3vni_get_rmac(zl3vni
, &rmac
);
4781 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4783 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4784 stream_putl(s
, zl3vni
->vni
);
4785 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4786 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4787 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4789 /* Write packet size. */
4790 stream_putw_at(s
, 0, stream_get_endp(s
));
4792 if (IS_ZEBRA_DEBUG_VXLAN
)
4794 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4795 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4796 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4797 inet_ntoa(zl3vni
->local_vtep_ip
),
4798 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4799 ? "prefix-routes-only"
4801 zebra_route_string(client
->proto
));
4803 client
->l3vniadd_cnt
++;
4804 return zserv_send_message(client
, s
);
4808 * Inform BGP about local l3-VNI deletion.
4810 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4812 struct stream
*s
= NULL
;
4813 struct zserv
*client
= NULL
;
4815 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4816 /* BGP may not be running. */
4820 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4822 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4823 stream_putl(s
, zl3vni
->vni
);
4825 /* Write packet size. */
4826 stream_putw_at(s
, 0, stream_get_endp(s
));
4828 if (IS_ZEBRA_DEBUG_VXLAN
)
4829 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4830 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4831 zebra_route_string(client
->proto
));
4833 client
->l3vnidel_cnt
++;
4834 return zserv_send_message(client
, s
);
4837 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4842 /* send l3vni add to BGP */
4843 zl3vni_send_add_to_client(zl3vni
);
4846 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4851 /* send l3-vni del to BGP*/
4852 zl3vni_send_del_to_client(zl3vni
);
4855 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4857 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4858 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4860 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4861 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4865 * handle transition of vni from l2 to l3 and vice versa
4867 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4870 zebra_vni_t
*zvni
= NULL
;
4872 /* There is a possibility that VNI notification was already received
4873 * from kernel and we programmed it as L2-VNI
4874 * In such a case we need to delete this L2-VNI first, so
4875 * that it can be reprogrammed as L3-VNI in the system. It is also
4876 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4877 * interface is still present in kernel. In this case to keep it
4878 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4881 /* Locate hash entry */
4882 zvni
= zvni_lookup(vni
);
4886 if (IS_ZEBRA_DEBUG_VXLAN
)
4887 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4889 /* Delete VNI from BGP. */
4890 zvni_send_del_to_client(zvni
->vni
);
4892 /* Free up all neighbors and MAC, if any. */
4893 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4894 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4896 /* Free up all remote VTEPs, if any. */
4897 zvni_vtep_del_all(zvni
, 0);
4899 /* Delete the hash entry. */
4900 if (zvni_del(zvni
)) {
4901 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4902 "Failed to del VNI hash %p, VNI %u", zvni
,
4907 /* TODO_MITESH: This needs to be thought through. We don't have
4908 * enough information at this point to reprogram the vni as
4909 * l2-vni. One way is to store the required info in l3-vni and
4910 * used it solely for this purpose
4917 /* delete and uninstall rmac hash entry */
4918 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4920 zebra_mac_t
*zrmac
= NULL
;
4921 zebra_l3vni_t
*zl3vni
= NULL
;
4923 zrmac
= (zebra_mac_t
*)backet
->data
;
4924 zl3vni
= (zebra_l3vni_t
*)ctx
;
4925 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4926 zl3vni_rmac_del(zl3vni
, zrmac
);
4929 /* delete and uninstall nh hash entry */
4930 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4932 zebra_neigh_t
*n
= NULL
;
4933 zebra_l3vni_t
*zl3vni
= NULL
;
4935 n
= (zebra_neigh_t
*)backet
->data
;
4936 zl3vni
= (zebra_l3vni_t
*)ctx
;
4937 zl3vni_nh_uninstall(zl3vni
, n
);
4938 zl3vni_nh_del(zl3vni
, n
);
4941 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4944 struct zserv
*client
= NULL
;
4945 struct stream
*s
= NULL
;
4946 char buf
[PREFIX_STRLEN
];
4948 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4949 /* BGP may not be running. */
4953 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4955 zclient_create_header(s
, cmd
, vrf_id
);
4956 stream_put(s
, p
, sizeof(struct prefix
));
4958 /* Write packet size. */
4959 stream_putw_at(s
, 0, stream_get_endp(s
));
4961 if (IS_ZEBRA_DEBUG_VXLAN
)
4962 zlog_debug("Send ip prefix %s %s on vrf %s",
4963 prefix2str(p
, buf
, sizeof(buf
)),
4964 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4965 vrf_id_to_name(vrf_id
));
4967 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4968 client
->prefixadd_cnt
++;
4970 client
->prefixdel_cnt
++;
4972 return zserv_send_message(client
, s
);
4975 /* re-add remote rmac if needed */
4976 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4977 struct ethaddr
*rmac
)
4979 char buf
[ETHER_ADDR_STRLEN
];
4980 zebra_mac_t
*zrmac
= NULL
;
4982 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4986 if (IS_ZEBRA_DEBUG_VXLAN
)
4987 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4988 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4990 zl3vni_rmac_install(zl3vni
, zrmac
);
4994 /* Process a remote MACIP add from BGP. */
4995 static void process_remote_macip_add(vni_t vni
,
4996 struct ethaddr
*macaddr
,
4998 struct ipaddr
*ipaddr
,
5001 struct in_addr vtep_ip
)
5004 zebra_vtep_t
*zvtep
;
5005 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5006 zebra_neigh_t
*n
= NULL
;
5007 int update_mac
= 0, update_neigh
= 0;
5008 char buf
[ETHER_ADDR_STRLEN
];
5009 char buf1
[INET6_ADDRSTRLEN
];
5010 struct interface
*ifp
= NULL
;
5011 struct zebra_if
*zif
= NULL
;
5012 struct zebra_vrf
*zvrf
;
5017 bool do_dad
= false;
5018 bool is_dup_detect
= false;
5020 /* Locate VNI hash entry - expected to exist. */
5021 zvni
= zvni_lookup(vni
);
5023 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5027 ifp
= zvni
->vxlan_if
;
5031 !if_is_operative(ifp
) ||
5033 !zif
->brslave_info
.br_if
) {
5034 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5039 /* The remote VTEP specified should normally exist, but it is
5040 * possible that when peering comes up, peer may advertise MACIP
5041 * routes before advertising type-3 routes.
5043 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5045 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5047 EC_ZEBRA_VTEP_ADD_FAILED
,
5048 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5053 zvni_vtep_install(zvni
, &vtep_ip
);
5056 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5057 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5058 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5060 mac
= zvni_mac_lookup(zvni
, macaddr
);
5062 /* Ignore if the mac is already present as a gateway mac */
5064 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5065 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5066 if (IS_ZEBRA_DEBUG_VXLAN
)
5067 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5069 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5070 ipa_len
? " IP " : "",
5072 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5076 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5080 /* check if the remote MAC is unknown or has a change.
5081 * If so, that needs to be updated first. Note that client could
5082 * install MAC and MACIP separately or just install the latter.
5085 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5086 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5087 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5088 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5089 || seq
!= mac
->rem_seq
)
5094 mac
= zvni_mac_add(zvni
, macaddr
);
5097 "Failed to add MAC %s VNI %u Remote VTEP %s",
5098 prefix_mac2str(macaddr
, buf
,
5100 vni
, inet_ntoa(vtep_ip
));
5104 /* Is this MAC created for a MACIP? */
5106 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5108 const char *mac_type
;
5110 /* When host moves but changes its (MAC,IP)
5111 * binding, BGP may install a MACIP entry that
5112 * corresponds to "older" location of the host
5113 * in transient situations (because {IP1,M1}
5114 * is a different route from {IP1,M2}). Check
5115 * the sequence number and ignore this update
5118 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5119 tmp_seq
= mac
->loc_seq
;
5122 tmp_seq
= mac
->rem_seq
;
5123 mac_type
= "remote";
5125 if (seq
< tmp_seq
) {
5126 if (IS_ZEBRA_DEBUG_VXLAN
)
5127 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5129 prefix_mac2str(macaddr
,
5131 ipa_len
? " IP " : "",
5134 buf1
, sizeof(buf1
)) : "",
5141 /* Check MAC's curent state is local (this is the case
5142 * where MAC has moved from L->R) and check previous
5143 * detection started via local learning.
5144 * RFC-7432: A PE/VTEP that detects a MAC mobility
5145 * event via local learning starts an M-second timer.
5147 * VTEP-IP or seq. change along is not considered
5148 * for dup. detection.
5150 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) &&
5154 /* Remove local MAC from BGP. */
5155 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5156 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5158 /* Set "auto" and "remote" forwarding info. */
5159 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5160 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5161 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5162 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5165 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5167 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5170 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5172 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5174 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5175 mac
->fwd_info
.r_vtep_ip
,
5176 do_dad
, &is_dup_detect
,
5179 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5181 /* Install the entry. */
5183 zvni_mac_install(zvni
, mac
);
5186 /* Update seq number. */
5189 /* If there is no IP, return after clearing AUTO flag of MAC. */
5191 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5198 /* Check if the remote neighbor itself is unknown or has a
5199 * change. If so, create or update and then install the entry.
5201 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5203 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5204 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5205 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5206 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5207 || seq
!= n
->rem_seq
)
5212 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5215 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5216 ipaddr2str(ipaddr
, buf1
,
5218 prefix_mac2str(macaddr
, buf
,
5220 vni
, inet_ntoa(vtep_ip
));
5227 /* When host moves but changes its (MAC,IP)
5228 * binding, BGP may install a MACIP entry that
5229 * corresponds to "older" location of the host
5230 * in transient situations (because {IP1,M1}
5231 * is a different route from {IP1,M2}). Check
5232 * the sequence number and ignore this update
5235 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5236 tmp_seq
= n
->loc_seq
;
5239 tmp_seq
= n
->rem_seq
;
5242 if (seq
< tmp_seq
) {
5243 if (IS_ZEBRA_DEBUG_VXLAN
)
5244 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5246 prefix_mac2str(macaddr
,
5249 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5254 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5255 /* MAC change, send a delete for old
5256 * neigh if learnt locally.
5258 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5259 IS_ZEBRA_NEIGH_ACTIVE(n
))
5260 zvni_neigh_send_del_to_client(
5264 /* update neigh list for macs */
5265 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5267 listnode_delete(old_mac
->neigh_list
, n
);
5268 zvni_deref_ip2mac(zvni
, old_mac
);
5270 listnode_add_sort(mac
->neigh_list
, n
);
5271 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5273 /* Check Neigh's curent state is local
5274 * (this is the case where neigh/host has moved
5275 * from L->R) and check previous detction
5276 * started via local learning.
5278 * RFC-7432: A PE/VTEP that detects a MAC
5279 * mobilit event via local learning starts
5280 * an M-second timer.
5281 * VTEP-IP or seq. change along is not
5282 * considered for dup. detection.
5284 * Mobilty event scenario-B IP-MAC binding
5287 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5294 /* Set "remote" forwarding info. */
5295 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5296 n
->r_vtep_ip
= vtep_ip
;
5297 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5299 /* Set router flag (R-bit) to this Neighbor entry */
5300 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5301 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5303 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5305 /* Check old or new MAC detected as duplicate,
5306 * inherit duplicate flag to this neigh.
5308 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5310 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5311 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5313 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5314 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5317 /* Check duplicate address detection for IP */
5318 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5323 /* Install the entry. */
5325 zvni_neigh_install(zvni
, n
);
5328 /* Update seq number. */
5332 /* Process a remote MACIP delete from BGP. */
5333 static void process_remote_macip_del(vni_t vni
,
5334 struct ethaddr
*macaddr
,
5336 struct ipaddr
*ipaddr
,
5337 struct in_addr vtep_ip
)
5340 zebra_mac_t
*mac
= NULL
;
5341 zebra_neigh_t
*n
= NULL
;
5342 struct interface
*ifp
= NULL
;
5343 struct zebra_if
*zif
= NULL
;
5344 char buf
[ETHER_ADDR_STRLEN
];
5345 char buf1
[INET6_ADDRSTRLEN
];
5347 /* Locate VNI hash entry - expected to exist. */
5348 zvni
= zvni_lookup(vni
);
5350 if (IS_ZEBRA_DEBUG_VXLAN
)
5351 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5355 ifp
= zvni
->vxlan_if
;
5359 !if_is_operative(ifp
) ||
5361 !zif
->brslave_info
.br_if
) {
5362 if (IS_ZEBRA_DEBUG_VXLAN
)
5363 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5368 /* The remote VTEP specified is normally expected to exist, but
5369 * it is possible that the peer may delete the VTEP before deleting
5370 * any MACs referring to the VTEP, in which case the handler (see
5371 * remote_vtep_del) would have already deleted the MACs.
5373 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5376 mac
= zvni_mac_lookup(zvni
, macaddr
);
5378 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5381 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5382 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5383 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5387 /* If the remote mac or neighbor doesn't exist there is nothing
5388 * more to do. Otherwise, uninstall the entry and then remove it.
5393 /* Ignore the delete if this mac is a gateway mac-ip */
5395 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5396 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5398 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5400 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5401 ipa_len
? " IP " : "",
5403 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5407 /* Uninstall remote neighbor or MAC. */
5409 /* When the MAC changes for an IP, it is possible the
5410 * client may update the new MAC before trying to delete the
5411 * "old" neighbor (as these are two different MACIP routes).
5412 * Do the delete only if the MAC matches.
5414 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5415 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5416 zvni_neigh_uninstall(zvni
, n
);
5417 zvni_neigh_del(zvni
, n
);
5418 zvni_deref_ip2mac(zvni
, mac
);
5421 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5422 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5424 * the remote sequence number in the auto mac entry
5425 * needs to be reset to 0 as the mac entry may have
5426 * been removed on all VTEPs (including
5427 * the originating one)
5431 /* If all remote neighbors referencing a remote MAC
5432 * go away, we need to uninstall the MAC.
5434 if (remote_neigh_count(mac
) == 0) {
5435 zvni_mac_uninstall(zvni
, mac
);
5436 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5438 if (list_isempty(mac
->neigh_list
))
5439 zvni_mac_del(zvni
, mac
);
5441 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5447 /* Public functions */
5449 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5451 zebra_l3vni_t
*zl3vni
= NULL
;
5453 zl3vni
= zl3vni_lookup(vni
);
5457 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5460 /* handle evpn route in vrf table */
5461 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5462 struct ipaddr
*vtep_ip
,
5463 struct prefix
*host_prefix
)
5465 zebra_l3vni_t
*zl3vni
= NULL
;
5466 struct ipaddr ipv4_vtep
;
5468 zl3vni
= zl3vni_from_vrf(vrf_id
);
5469 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5473 * add the next hop neighbor -
5474 * neigh to be installed is the ipv6 nexthop neigh
5476 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5479 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5480 * address. Rmac is programmed against the ipv4 vtep because we only
5481 * support ipv4 tunnels in the h/w right now
5483 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5484 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5485 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5486 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5487 &(ipv4_vtep
.ipaddr_v4
));
5489 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5490 sizeof(struct in_addr
));
5493 * add the rmac - remote rmac to be installed is against the ipv4
5496 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5499 /* handle evpn vrf route delete */
5500 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5501 struct ipaddr
*vtep_ip
,
5502 struct prefix
*host_prefix
)
5504 zebra_l3vni_t
*zl3vni
= NULL
;
5505 zebra_neigh_t
*nh
= NULL
;
5506 zebra_mac_t
*zrmac
= NULL
;
5508 zl3vni
= zl3vni_from_vrf(vrf_id
);
5512 /* find the next hop entry and rmac entry */
5513 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5516 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5518 /* delete the next hop entry */
5519 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5521 /* delete the rmac entry */
5523 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5527 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5528 struct ethaddr
*rmac
, bool use_json
)
5530 zebra_l3vni_t
*zl3vni
= NULL
;
5531 zebra_mac_t
*zrmac
= NULL
;
5532 json_object
*json
= NULL
;
5534 if (!is_evpn_enabled()) {
5536 vty_out(vty
, "{}\n");
5541 json
= json_object_new_object();
5543 zl3vni
= zl3vni_lookup(l3vni
);
5546 vty_out(vty
, "{}\n");
5548 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5552 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5555 vty_out(vty
, "{}\n");
5558 "%% Requested RMAC doesn't exist in L3-VNI %u",
5563 zl3vni_print_rmac(zrmac
, vty
, json
);
5566 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5567 json
, JSON_C_TO_STRING_PRETTY
));
5568 json_object_free(json
);
5572 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5574 zebra_l3vni_t
*zl3vni
;
5576 struct rmac_walk_ctx wctx
;
5577 json_object
*json
= NULL
;
5579 if (!is_evpn_enabled())
5582 zl3vni
= zl3vni_lookup(l3vni
);
5585 vty_out(vty
, "{}\n");
5587 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5590 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5595 json
= json_object_new_object();
5597 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5601 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5603 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5605 json_object_int_add(json
, "numRmacs", num_rmacs
);
5607 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5610 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5611 json
, JSON_C_TO_STRING_PRETTY
));
5612 json_object_free(json
);
5616 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5618 json_object
*json
= NULL
;
5621 if (!is_evpn_enabled()) {
5623 vty_out(vty
, "{}\n");
5628 json
= json_object_new_object();
5632 hash_iterate(zrouter
.l3vni_table
,
5633 (void (*)(struct hash_backet
*,
5634 void *))zl3vni_print_rmac_hash_all_vni
,
5638 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5639 json
, JSON_C_TO_STRING_PRETTY
));
5640 json_object_free(json
);
5644 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5645 struct ipaddr
*ip
, bool use_json
)
5647 zebra_l3vni_t
*zl3vni
= NULL
;
5648 zebra_neigh_t
*n
= NULL
;
5649 json_object
*json
= NULL
;
5651 if (!is_evpn_enabled()) {
5653 vty_out(vty
, "{}\n");
5658 json
= json_object_new_object();
5660 zl3vni
= zl3vni_lookup(l3vni
);
5663 vty_out(vty
, "{}\n");
5665 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5669 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5672 vty_out(vty
, "{}\n");
5675 "%% Requested next-hop not present for L3-VNI %u",
5680 zl3vni_print_nh(n
, vty
, json
);
5683 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5684 json
, JSON_C_TO_STRING_PRETTY
));
5685 json_object_free(json
);
5689 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5692 struct nh_walk_ctx wctx
;
5693 json_object
*json
= NULL
;
5694 zebra_l3vni_t
*zl3vni
= NULL
;
5696 if (!is_evpn_enabled())
5699 zl3vni
= zl3vni_lookup(l3vni
);
5702 vty_out(vty
, "{}\n");
5704 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5708 num_nh
= hashcount(zl3vni
->nh_table
);
5713 json
= json_object_new_object();
5718 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5720 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5722 json_object_int_add(json
, "numNextHops", num_nh
);
5724 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5727 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5728 json
, JSON_C_TO_STRING_PRETTY
));
5729 json_object_free(json
);
5733 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5735 json_object
*json
= NULL
;
5738 if (!is_evpn_enabled()) {
5740 vty_out(vty
, "{}\n");
5745 json
= json_object_new_object();
5749 hash_iterate(zrouter
.l3vni_table
,
5750 (void (*)(struct hash_backet
*,
5751 void *))zl3vni_print_nh_hash_all_vni
,
5755 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5756 json
, JSON_C_TO_STRING_PRETTY
));
5757 json_object_free(json
);
5762 * Display L3 VNI information (VTY command handler).
5764 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5767 json_object
*json
= NULL
;
5768 zebra_l3vni_t
*zl3vni
= NULL
;
5770 if (!is_evpn_enabled()) {
5772 vty_out(vty
, "{}\n");
5776 zl3vni
= zl3vni_lookup(vni
);
5779 vty_out(vty
, "{}\n");
5781 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5786 json
= json_object_new_object();
5790 zl3vni_print(zl3vni
, (void *)args
);
5793 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5794 json
, JSON_C_TO_STRING_PRETTY
));
5795 json_object_free(json
);
5799 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5800 json_object
*json_vrfs
)
5802 char buf
[ETHER_ADDR_STRLEN
];
5803 zebra_l3vni_t
*zl3vni
= NULL
;
5805 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5810 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5811 zvrf_name(zvrf
), zl3vni
->vni
,
5812 zl3vni_vxlan_if_name(zl3vni
),
5813 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5814 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5816 json_object
*json_vrf
= NULL
;
5818 json_vrf
= json_object_new_object();
5819 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5820 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5821 json_object_string_add(json_vrf
, "vxlanIntf",
5822 zl3vni_vxlan_if_name(zl3vni
));
5823 json_object_string_add(json_vrf
, "sviIntf",
5824 zl3vni_svi_if_name(zl3vni
));
5825 json_object_string_add(json_vrf
, "state",
5826 zl3vni_state2str(zl3vni
));
5827 json_object_string_add(
5828 json_vrf
, "routerMac",
5829 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5830 json_object_array_add(json_vrfs
, json_vrf
);
5835 * Display Neighbors for a VNI (VTY command handler).
5837 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5838 vni_t vni
, bool use_json
)
5842 struct neigh_walk_ctx wctx
;
5843 json_object
*json
= NULL
;
5845 if (!is_evpn_enabled())
5847 zvni
= zvni_lookup(vni
);
5850 vty_out(vty
, "{}\n");
5852 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5855 num_neigh
= hashcount(zvni
->neigh_table
);
5860 json
= json_object_new_object();
5862 /* Since we have IPv6 addresses to deal with which can vary widely in
5863 * size, we try to be a bit more elegant in display by first computing
5864 * the maximum width.
5866 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5869 wctx
.addr_width
= 15;
5871 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5875 "Number of ARPs (local and remote) known for this VNI: %u\n",
5877 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5878 -wctx
.addr_width
, "IP", "Type",
5879 "State", "MAC", "Remote VTEP");
5881 json_object_int_add(json
, "numArpNd", num_neigh
);
5883 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5885 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5886 json
, JSON_C_TO_STRING_PRETTY
));
5887 json_object_free(json
);
5892 * Display neighbors across all VNIs (VTY command handler).
5894 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5895 bool print_dup
, bool use_json
)
5897 json_object
*json
= NULL
;
5900 if (!is_evpn_enabled())
5904 json
= json_object_new_object();
5908 args
[2] = (void *)(ptrdiff_t)print_dup
;
5910 hash_iterate(zvrf
->vni_table
,
5911 (void (*)(struct hash_backet
*,
5912 void *))zvni_print_neigh_hash_all_vni
,
5915 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5916 json
, JSON_C_TO_STRING_PRETTY
));
5917 json_object_free(json
);
5922 * Display neighbors across all VNIs in detail(VTY command handler).
5924 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
5925 struct zebra_vrf
*zvrf
,
5926 bool print_dup
, bool use_json
)
5928 json_object
*json
= NULL
;
5931 if (!is_evpn_enabled())
5935 json
= json_object_new_object();
5939 args
[2] = (void *)(ptrdiff_t)print_dup
;
5941 hash_iterate(zvrf
->vni_table
,
5942 (void (*)(struct hash_backet
*,
5943 void *))zvni_print_neigh_hash_all_vni_detail
,
5946 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5947 json
, JSON_C_TO_STRING_PRETTY
));
5948 json_object_free(json
);
5953 * Display specific neighbor for a VNI, if present (VTY command handler).
5955 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5956 struct zebra_vrf
*zvrf
, vni_t vni
,
5957 struct ipaddr
*ip
, bool use_json
)
5961 json_object
*json
= NULL
;
5963 if (!is_evpn_enabled())
5965 zvni
= zvni_lookup(vni
);
5968 vty_out(vty
, "{}\n");
5970 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5973 n
= zvni_neigh_lookup(zvni
, ip
);
5977 "%% Requested neighbor does not exist in VNI %u\n",
5982 json
= json_object_new_object();
5984 zvni_print_neigh(n
, vty
, json
);
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 neighbors for a VNI from specific VTEP (VTY command handler).
5995 * By definition, these are remote neighbors.
5997 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5998 vni_t vni
, struct in_addr vtep_ip
,
6003 struct neigh_walk_ctx wctx
;
6004 json_object
*json
= NULL
;
6006 if (!is_evpn_enabled())
6008 zvni
= zvni_lookup(vni
);
6011 vty_out(vty
, "{}\n");
6013 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6016 num_neigh
= hashcount(zvni
->neigh_table
);
6020 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6023 wctx
.addr_width
= 15;
6024 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6025 wctx
.r_vtep_ip
= vtep_ip
;
6027 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6028 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6031 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6032 json
, JSON_C_TO_STRING_PRETTY
));
6033 json_object_free(json
);
6038 * Display Duplicate detected Neighbors for a VNI
6039 * (VTY command handler).
6041 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6042 struct zebra_vrf
*zvrf
,
6048 struct neigh_walk_ctx wctx
;
6049 json_object
*json
= NULL
;
6051 if (!is_evpn_enabled())
6054 zvni
= zvni_lookup(vni
);
6056 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6060 num_neigh
= hashcount(zvni
->neigh_table
);
6064 num_neigh
= num_dup_detected_neighs(zvni
);
6069 json
= json_object_new_object();
6071 /* Since we have IPv6 addresses to deal with which can vary widely in
6072 * size, we try to be a bit more elegant in display by first computing
6073 * the maximum width.
6075 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6078 wctx
.addr_width
= 15;
6080 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6084 "Number of ARPs (local and remote) known for this VNI: %u\n",
6086 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6087 -wctx
.addr_width
, "IP", "Type",
6088 "State", "MAC", "Remote VTEP");
6090 json_object_int_add(json
, "numArpNd", num_neigh
);
6092 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6095 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6096 json
, JSON_C_TO_STRING_PRETTY
));
6097 json_object_free(json
);
6102 * Display MACs for a VNI (VTY command handler).
6104 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6105 vni_t vni
, bool use_json
)
6109 struct mac_walk_ctx wctx
;
6110 json_object
*json
= NULL
;
6111 json_object
*json_mac
= NULL
;
6113 if (!is_evpn_enabled())
6115 zvni
= zvni_lookup(vni
);
6118 vty_out(vty
, "{}\n");
6120 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6123 num_macs
= num_valid_macs(zvni
);
6128 json
= json_object_new_object();
6129 json_mac
= json_object_new_object();
6132 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6135 wctx
.json
= json_mac
;
6139 "Number of MACs (local and remote) known for this VNI: %u\n",
6141 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6142 "Intf/Remote VTEP", "VLAN");
6144 json_object_int_add(json
, "numMacs", num_macs
);
6146 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6149 json_object_object_add(json
, "macs", json_mac
);
6150 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6151 json
, JSON_C_TO_STRING_PRETTY
));
6152 json_object_free(json
);
6157 * Display MACs for all VNIs (VTY command handler).
6159 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6160 bool print_dup
, bool use_json
)
6162 struct mac_walk_ctx wctx
;
6163 json_object
*json
= NULL
;
6165 if (!is_evpn_enabled()) {
6167 vty_out(vty
, "{}\n");
6171 json
= json_object_new_object();
6173 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6176 wctx
.print_dup
= print_dup
;
6177 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6180 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6181 json
, JSON_C_TO_STRING_PRETTY
));
6182 json_object_free(json
);
6187 * Display MACs in detail for all VNIs (VTY command handler).
6189 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6190 struct zebra_vrf
*zvrf
,
6191 bool print_dup
, bool use_json
)
6193 struct mac_walk_ctx wctx
;
6194 json_object
*json
= NULL
;
6196 if (!is_evpn_enabled()) {
6198 vty_out(vty
, "{}\n");
6202 json
= json_object_new_object();
6204 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6207 wctx
.print_dup
= print_dup
;
6208 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6212 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6213 json
, JSON_C_TO_STRING_PRETTY
));
6214 json_object_free(json
);
6219 * Display MACs for all VNIs (VTY command handler).
6221 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6222 struct zebra_vrf
*zvrf
,
6223 struct in_addr vtep_ip
, bool use_json
)
6225 struct mac_walk_ctx wctx
;
6226 json_object
*json
= NULL
;
6228 if (!is_evpn_enabled())
6232 json
= json_object_new_object();
6234 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6236 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6237 wctx
.r_vtep_ip
= vtep_ip
;
6239 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6242 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6243 json
, JSON_C_TO_STRING_PRETTY
));
6244 json_object_free(json
);
6249 * Display specific MAC for a VNI, if present (VTY command handler).
6251 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6252 vni_t vni
, struct ethaddr
*macaddr
,
6257 json_object
*json
= NULL
;
6259 if (!is_evpn_enabled())
6262 zvni
= zvni_lookup(vni
);
6265 vty_out(vty
, "{}\n");
6267 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6270 mac
= zvni_mac_lookup(zvni
, macaddr
);
6273 vty_out(vty
, "{}\n");
6276 "%% Requested MAC does not exist in VNI %u\n",
6282 json
= json_object_new_object();
6284 zvni_print_mac(mac
, vty
, json
);
6286 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6287 json
, JSON_C_TO_STRING_PRETTY
));
6288 json_object_free(json
);
6292 /* Print Duplicate MACs per VNI */
6293 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6294 struct zebra_vrf
*zvrf
,
6295 vni_t vni
, bool use_json
)
6298 struct mac_walk_ctx wctx
;
6300 json_object
*json
= NULL
;
6301 json_object
*json_mac
= NULL
;
6303 if (!is_evpn_enabled())
6306 zvni
= zvni_lookup(vni
);
6308 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6312 num_macs
= num_valid_macs(zvni
);
6316 num_macs
= num_dup_detected_macs(zvni
);
6321 json
= json_object_new_object();
6322 json_mac
= json_object_new_object();
6325 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6328 wctx
.json
= json_mac
;
6332 "Number of MACs (local and remote) known for this VNI: %u\n",
6334 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6335 "Intf/Remote VTEP", "VLAN");
6337 json_object_int_add(json
, "numMacs", num_macs
);
6339 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6342 json_object_object_add(json
, "macs", json_mac
);
6343 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6344 json
, JSON_C_TO_STRING_PRETTY
));
6345 json_object_free(json
);
6350 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6351 struct zebra_vrf
*zvrf
,
6352 vni_t vni
, struct ethaddr
*macaddr
)
6356 struct listnode
*node
= NULL
;
6357 zebra_neigh_t
*nbr
= NULL
;
6359 if (!is_evpn_enabled())
6362 zvni
= zvni_lookup(vni
);
6364 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6368 mac
= zvni_mac_lookup(zvni
, macaddr
);
6370 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6375 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6376 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6380 /* Remove all IPs as duplicate associcated with this MAC */
6381 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6382 /* For local neigh mark inactive so MACIP update is generated
6383 * to BGP. This is a scenario where MAC update received
6384 * and detected as duplicate which marked neigh as duplicate.
6385 * Later local neigh update did not get a chance to relay
6386 * to BGP. Similarly remote macip update, neigh needs to be
6387 * installed locally.
6389 if (nbr
->dad_count
) {
6390 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6391 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6392 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6393 zvni_neigh_install(zvni
, nbr
);
6396 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6398 nbr
->detect_start_time
.tv_sec
= 0;
6399 nbr
->dad_dup_detect_time
= 0;
6402 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6404 mac
->detect_start_time
.tv_sec
= 0;
6405 mac
->detect_start_time
.tv_usec
= 0;
6406 mac
->dad_dup_detect_time
= 0;
6407 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6409 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6410 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6412 if (zvni_mac_send_add_to_client(zvni
->vni
,
6418 /* Process all neighbors associated with this MAC. */
6419 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6421 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6422 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6424 /* Install the entry. */
6425 zvni_mac_install(zvni
, mac
);
6431 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6432 struct zebra_vrf
*zvrf
,
6433 vni_t vni
, struct ipaddr
*ip
)
6438 char buf
[INET6_ADDRSTRLEN
];
6439 char buf2
[ETHER_ADDR_STRLEN
];
6441 if (!is_evpn_enabled())
6444 zvni
= zvni_lookup(vni
);
6446 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6450 nbr
= zvni_neigh_lookup(zvni
, ip
);
6453 "%% Requested host IP does not exist in VNI %u\n",
6458 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6460 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6462 "%% Requsted host IP %s is not duplicate detected\n",
6467 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6469 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6471 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6472 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6473 return CMD_WARNING_CONFIG_FAILED
;
6476 if (IS_ZEBRA_DEBUG_VXLAN
)
6477 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6478 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6481 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6483 nbr
->detect_start_time
.tv_sec
= 0;
6484 nbr
->detect_start_time
.tv_usec
= 0;
6485 nbr
->dad_dup_detect_time
= 0;
6486 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6488 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6489 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6491 nbr
->flags
, nbr
->loc_seq
);
6492 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6493 zvni_neigh_install(zvni
, nbr
);
6499 static void zvni_clear_dup_mac_hash(struct hash_backet
*backet
, void *ctxt
)
6501 struct mac_walk_ctx
*wctx
= ctxt
;
6504 struct listnode
*node
= NULL
;
6505 zebra_neigh_t
*nbr
= NULL
;
6507 mac
= (zebra_mac_t
*)backet
->data
;
6513 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6516 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6518 mac
->detect_start_time
.tv_sec
= 0;
6519 mac
->detect_start_time
.tv_usec
= 0;
6520 mac
->dad_dup_detect_time
= 0;
6521 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6523 /* Remove all IPs as duplicate associcated with this MAC */
6524 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6525 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6527 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6529 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6531 nbr
->detect_start_time
.tv_sec
= 0;
6532 nbr
->dad_dup_detect_time
= 0;
6535 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6536 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6538 if (zvni_mac_send_add_to_client(zvni
->vni
,
6540 mac
->flags
, mac
->loc_seq
))
6543 /* Process all neighbors associated with this MAC. */
6544 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6546 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6547 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6549 /* Install the entry. */
6550 zvni_mac_install(zvni
, mac
);
6554 static void zvni_clear_dup_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
6556 struct neigh_walk_ctx
*wctx
= ctxt
;
6559 char buf
[INET6_ADDRSTRLEN
];
6561 nbr
= (zebra_neigh_t
*)backet
->data
;
6567 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6570 if (IS_ZEBRA_DEBUG_VXLAN
) {
6571 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6573 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6574 __PRETTY_FUNCTION__
, buf
,
6575 nbr
->flags
, nbr
->loc_seq
);
6578 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6580 nbr
->detect_start_time
.tv_sec
= 0;
6581 nbr
->detect_start_time
.tv_usec
= 0;
6582 nbr
->dad_dup_detect_time
= 0;
6583 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6585 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6586 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6588 nbr
->flags
, nbr
->loc_seq
);
6589 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6590 zvni_neigh_install(zvni
, nbr
);
6594 static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet
*backet
,
6599 struct zebra_vrf
*zvrf
;
6600 struct mac_walk_ctx m_wctx
;
6601 struct neigh_walk_ctx n_wctx
;
6603 zvni
= (zebra_vni_t
*)backet
->data
;
6607 vty
= (struct vty
*)args
[0];
6608 zvrf
= (struct zebra_vrf
*)args
[1];
6610 if (hashcount(zvni
->neigh_table
)) {
6611 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6615 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6619 if (num_valid_macs(zvni
)) {
6620 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6624 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6629 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6630 struct zebra_vrf
*zvrf
)
6634 if (!is_evpn_enabled())
6640 hash_iterate(zvrf
->vni_table
,
6641 (void (*)(struct hash_backet
*, void *))
6642 zvni_clear_dup_detect_hash_vni_all
, args
);
6647 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6648 struct zebra_vrf
*zvrf
,
6652 struct mac_walk_ctx m_wctx
;
6653 struct neigh_walk_ctx n_wctx
;
6655 if (!is_evpn_enabled())
6658 zvni
= zvni_lookup(vni
);
6660 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6664 if (hashcount(zvni
->neigh_table
)) {
6665 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6669 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6673 if (num_valid_macs(zvni
)) {
6674 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6678 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6685 * Display MACs for a VNI from specific VTEP (VTY command handler).
6687 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6688 vni_t vni
, struct in_addr vtep_ip
,
6693 struct mac_walk_ctx wctx
;
6694 json_object
*json
= NULL
;
6695 json_object
*json_mac
= NULL
;
6697 if (!is_evpn_enabled())
6699 zvni
= zvni_lookup(vni
);
6702 vty_out(vty
, "{}\n");
6704 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6707 num_macs
= num_valid_macs(zvni
);
6712 json
= json_object_new_object();
6713 json_mac
= json_object_new_object();
6716 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6719 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6720 wctx
.r_vtep_ip
= vtep_ip
;
6721 wctx
.json
= json_mac
;
6722 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6725 json_object_int_add(json
, "numMacs", wctx
.count
);
6727 json_object_object_add(json
, "macs", json_mac
);
6728 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6729 json
, JSON_C_TO_STRING_PRETTY
));
6730 json_object_free(json
);
6736 * Display VNI information (VTY command handler).
6738 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6741 json_object
*json
= NULL
;
6743 zebra_l3vni_t
*zl3vni
= NULL
;
6744 zebra_vni_t
*zvni
= NULL
;
6746 if (!is_evpn_enabled())
6750 json
= json_object_new_object();
6754 zl3vni
= zl3vni_lookup(vni
);
6756 zl3vni_print(zl3vni
, (void *)args
);
6758 zvni
= zvni_lookup(vni
);
6761 vty_out(vty
, "{}\n");
6763 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6767 zvni_print(zvni
, (void *)args
);
6771 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6772 json
, JSON_C_TO_STRING_PRETTY
));
6773 json_object_free(json
);
6777 /* Display all global details for EVPN */
6778 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6783 json_object
*json
= NULL
;
6784 struct zebra_vrf
*zvrf
= NULL
;
6786 if (!is_evpn_enabled())
6789 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6793 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6794 num_l2vnis
= hashcount(zvrf
->vni_table
);
6795 num_vnis
= num_l2vnis
+ num_l3vnis
;
6798 json
= json_object_new_object();
6799 json_object_string_add(json
, "advertiseGatewayMacip",
6800 zvrf
->advertise_gw_macip
? "Yes" : "No");
6801 json_object_int_add(json
, "numVnis", num_vnis
);
6802 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6803 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6804 if (zvrf
->dup_addr_detect
)
6805 json_object_boolean_true_add(json
,
6806 "isDuplicateAddrDetection");
6808 json_object_boolean_false_add(json
,
6809 "isDuplicateAddrDetection");
6810 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6811 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6812 json_object_int_add(json
, "detectionFreezeTime",
6813 zvrf
->dad_freeze_time
);
6816 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6817 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6818 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6819 zvrf
->advertise_gw_macip
? "Yes" : "No");
6820 vty_out(vty
, "Duplicate address detection: %s\n",
6821 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6822 vty_out(vty
, " Detection max-moves %u, time %d\n",
6823 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6824 if (zvrf
->dad_freeze
) {
6825 if (zvrf
->dad_freeze_time
)
6826 vty_out(vty
, " Detection freeze %u\n",
6827 zvrf
->dad_freeze_time
);
6829 vty_out(vty
, " Detection freeze %s\n",
6835 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6836 json
, JSON_C_TO_STRING_PRETTY
));
6837 json_object_free(json
);
6842 * Display VNI hash table (VTY command handler).
6844 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6847 json_object
*json
= NULL
;
6850 if (!is_evpn_enabled())
6854 json
= json_object_new_object();
6856 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6857 "Type", "VxLAN IF", "# MACs", "# ARPs",
6858 "# Remote VTEPs", "Tenant VRF");
6863 /* Display all L2-VNIs */
6864 hash_iterate(zvrf
->vni_table
,
6865 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
6868 /* Display all L3-VNIs */
6869 hash_iterate(zrouter
.l3vni_table
,
6870 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
6874 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6875 json
, JSON_C_TO_STRING_PRETTY
));
6876 json_object_free(json
);
6880 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
6884 uint32_t max_moves
= 0;
6885 uint32_t freeze_time
= 0;
6886 bool dup_addr_detect
= false;
6887 bool freeze
= false;
6890 STREAM_GETL(s
, dup_addr_detect
);
6891 STREAM_GETL(s
, time
);
6892 STREAM_GETL(s
, max_moves
);
6893 STREAM_GETL(s
, freeze
);
6894 STREAM_GETL(s
, freeze_time
);
6896 /* DAD previous state was enabled, and new state is disable,
6897 * clear all duplicate detected addresses.
6899 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
6900 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
6902 zvrf
->dup_addr_detect
= dup_addr_detect
;
6903 zvrf
->dad_time
= time
;
6904 zvrf
->dad_max_moves
= max_moves
;
6905 zvrf
->dad_freeze
= freeze
;
6906 zvrf
->dad_freeze_time
= freeze_time
;
6908 if (IS_ZEBRA_DEBUG_VXLAN
)
6910 "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
6911 __PRETTY_FUNCTION__
,
6912 zvrf
->dup_addr_detect
? "enable" : "disable",
6913 zvrf
->dad_max_moves
,
6915 zvrf
->dad_freeze
? "enable" : "disable",
6916 zvrf
->dad_freeze_time
);
6923 * Display VNI hash table in detail(VTY command handler).
6925 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6928 json_object
*json
= NULL
;
6929 struct zebra_ns
*zns
= NULL
;
6930 struct zvni_evpn_show zes
;
6932 if (!is_evpn_enabled())
6935 zns
= zebra_ns_lookup(NS_DEFAULT
);
6941 json
= json_object_new_object();
6947 /* Display all L2-VNIs */
6948 hash_iterate(zvrf
->vni_table
, (void (*)(struct hash_backet
*,
6949 void *))zvni_print_hash_detail
,
6952 /* Display all L3-VNIs */
6953 hash_iterate(zrouter
.l3vni_table
,
6954 (void (*)(struct hash_backet
*,
6955 void *))zl3vni_print_hash_detail
,
6959 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6960 json
, JSON_C_TO_STRING_PRETTY
));
6961 json_object_free(json
);
6966 * Handle neighbor delete notification from the kernel (on a VLAN device
6967 * / L3 interface). This may result in either the neighbor getting deleted
6968 * from our database or being re-added to the kernel (if it is a valid
6971 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
6972 struct interface
*link_if
,
6975 char buf
[INET6_ADDRSTRLEN
];
6976 char buf2
[ETHER_ADDR_STRLEN
];
6977 zebra_neigh_t
*n
= NULL
;
6978 zebra_vni_t
*zvni
= NULL
;
6979 zebra_mac_t
*zmac
= NULL
;
6980 zebra_l3vni_t
*zl3vni
= NULL
;
6982 /* check if this is a remote neigh entry corresponding to remote
6985 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6987 return zl3vni_local_nh_del(zl3vni
, ip
);
6989 /* We are only interested in neighbors on an SVI that resides on top
6990 * of a VxLAN bridge.
6992 zvni
= zvni_from_svi(ifp
, link_if
);
6996 if (!zvni
->vxlan_if
) {
6998 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7003 if (IS_ZEBRA_DEBUG_VXLAN
)
7004 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7005 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7006 ifp
->ifindex
, zvni
->vni
);
7008 /* If entry doesn't exist, nothing to do. */
7009 n
= zvni_neigh_lookup(zvni
, ip
);
7013 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7015 if (IS_ZEBRA_DEBUG_VXLAN
)
7017 "Trying to del a neigh %s without a mac %s on VNI %u",
7018 ipaddr2str(ip
, buf
, sizeof(buf
)),
7019 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7025 /* If it is a remote entry, the kernel has aged this out or someone has
7026 * deleted it, it needs to be re-installed as Quagga is the owner.
7028 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7029 zvni_neigh_install(zvni
, n
);
7033 /* Remove neighbor from BGP. */
7034 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
7035 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
7037 /* Delete this neighbor entry. */
7038 zvni_neigh_del(zvni
, n
);
7040 /* see if the AUTO mac needs to be deleted */
7041 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7042 && !listcount(zmac
->neigh_list
))
7043 zvni_mac_del(zvni
, zmac
);
7049 * Handle neighbor add or update notification from the kernel (on a VLAN
7050 * device / L3 interface). This is typically for a local neighbor but can
7051 * also be for a remote neighbor (e.g., ageout notification). It could
7052 * also be a "move" scenario.
7054 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7055 struct interface
*link_if
,
7057 struct ethaddr
*macaddr
,
7062 char buf
[ETHER_ADDR_STRLEN
];
7063 char buf2
[INET6_ADDRSTRLEN
];
7064 zebra_vni_t
*zvni
= NULL
;
7065 zebra_l3vni_t
*zl3vni
= NULL
;
7067 /* check if this is a remote neigh entry corresponding to remote
7070 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7072 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7074 /* We are only interested in neighbors on an SVI that resides on top
7075 * of a VxLAN bridge.
7077 zvni
= zvni_from_svi(ifp
, link_if
);
7081 if (IS_ZEBRA_DEBUG_VXLAN
)
7083 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7084 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7085 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7086 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7087 is_router
? "router " : "",
7090 /* Is this about a local neighbor or a remote one? */
7092 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7095 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7100 * Handle message from client to delete a remote MACIP for a VNI.
7102 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7106 struct ethaddr macaddr
;
7108 struct in_addr vtep_ip
;
7109 uint16_t l
= 0, ipa_len
;
7110 char buf
[ETHER_ADDR_STRLEN
];
7111 char buf1
[INET6_ADDRSTRLEN
];
7113 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7114 memset(&ip
, 0, sizeof(struct ipaddr
));
7115 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7119 while (l
< hdr
->length
) {
7120 /* Obtain each remote MACIP and process. */
7121 /* Message contains VNI, followed by MAC followed by IP (if any)
7122 * followed by remote VTEP IP.
7124 memset(&ip
, 0, sizeof(ip
));
7125 STREAM_GETL(s
, vni
);
7126 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7127 STREAM_GETL(s
, ipa_len
);
7129 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7131 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7133 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7134 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7135 l
+= IPV4_MAX_BYTELEN
;
7137 if (IS_ZEBRA_DEBUG_VXLAN
)
7139 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7141 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7142 ipa_len
? " IP " : "",
7144 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7146 zebra_route_string(client
->proto
));
7148 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7156 * Handle message from client to add a remote MACIP for a VNI. This
7157 * could be just the add of a MAC address or the add of a neighbor
7160 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7164 struct ethaddr macaddr
;
7166 struct in_addr vtep_ip
;
7167 uint16_t l
= 0, ipa_len
;
7170 char buf
[ETHER_ADDR_STRLEN
];
7171 char buf1
[INET6_ADDRSTRLEN
];
7173 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7174 memset(&ip
, 0, sizeof(struct ipaddr
));
7175 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7177 if (!EVPN_ENABLED(zvrf
)) {
7178 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7184 while (l
< hdr
->length
) {
7185 /* Obtain each remote MACIP and process. */
7186 /* Message contains VNI, followed by MAC followed by IP (if any)
7187 * followed by remote VTEP IP.
7189 memset(&ip
, 0, sizeof(ip
));
7190 STREAM_GETL(s
, vni
);
7191 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7192 STREAM_GETL(s
, ipa_len
);
7194 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7196 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7198 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7199 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7200 l
+= IPV4_MAX_BYTELEN
;
7202 /* Get flags - sticky mac and/or gateway mac */
7203 STREAM_GETC(s
, flags
);
7205 STREAM_GETL(s
, seq
);
7208 if (IS_ZEBRA_DEBUG_VXLAN
)
7210 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7212 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7213 ipa_len
? " IP " : "",
7215 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7216 flags
, seq
, inet_ntoa(vtep_ip
),
7217 zebra_route_string(client
->proto
));
7219 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7220 flags
, seq
, vtep_ip
);
7228 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7229 * us, this must involve a multihoming scenario. Treat this as implicit delete
7230 * of any prior local MAC.
7232 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7233 struct interface
*br_if
,
7234 struct ethaddr
*macaddr
, vlanid_t vid
)
7236 struct zebra_if
*zif
;
7237 struct zebra_l2info_vxlan
*vxl
;
7241 char buf
[ETHER_ADDR_STRLEN
];
7245 vxl
= &zif
->l2info
.vxl
;
7248 /* Check if EVPN is enabled. */
7249 if (!is_evpn_enabled())
7252 /* Locate hash entry; it is expected to exist. */
7253 zvni
= zvni_lookup(vni
);
7257 /* If entry doesn't exist, nothing to do. */
7258 mac
= zvni_mac_lookup(zvni
, macaddr
);
7262 /* Is it a local entry? */
7263 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7266 if (IS_ZEBRA_DEBUG_VXLAN
)
7268 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7269 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7272 /* Remove MAC from BGP. */
7273 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7276 * If there are no neigh associated with the mac delete the mac
7277 * else mark it as AUTO for forward reference
7279 if (!listcount(mac
->neigh_list
)) {
7280 zvni_mac_del(zvni
, mac
);
7282 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7283 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7290 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7291 * This can happen because the remote MAC entries are also added as "dynamic",
7292 * so the kernel can ageout the entry.
7294 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7295 struct interface
*br_if
,
7296 struct ethaddr
*macaddr
, vlanid_t vid
)
7298 struct zebra_if
*zif
= NULL
;
7299 struct zebra_l2info_vxlan
*vxl
= NULL
;
7301 zebra_vni_t
*zvni
= NULL
;
7302 zebra_l3vni_t
*zl3vni
= NULL
;
7303 zebra_mac_t
*mac
= NULL
;
7304 char buf
[ETHER_ADDR_STRLEN
];
7308 vxl
= &zif
->l2info
.vxl
;
7311 /* Check if EVPN is enabled. */
7312 if (!is_evpn_enabled())
7315 /* check if this is a remote RMAC and readd simillar to remote macs */
7316 zl3vni
= zl3vni_lookup(vni
);
7318 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7320 /* Locate hash entry; it is expected to exist. */
7321 zvni
= zvni_lookup(vni
);
7325 /* If entry doesn't exist, nothing to do. */
7326 mac
= zvni_mac_lookup(zvni
, macaddr
);
7330 /* Is it a remote entry? */
7331 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7334 if (IS_ZEBRA_DEBUG_VXLAN
)
7335 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7336 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7339 zvni_mac_install(zvni
, mac
);
7344 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7346 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7347 struct ethaddr
*macaddr
, vlanid_t vid
)
7351 char buf
[ETHER_ADDR_STRLEN
];
7353 /* We are interested in MACs only on ports or (port, VLAN) that
7356 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7359 if (!zvni
->vxlan_if
) {
7361 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7366 if (IS_ZEBRA_DEBUG_VXLAN
)
7367 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7368 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7369 ifp
->ifindex
, vid
, zvni
->vni
);
7371 /* If entry doesn't exist, nothing to do. */
7372 mac
= zvni_mac_lookup(zvni
, macaddr
);
7376 /* Is it a local entry? */
7377 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7380 /* Update all the neigh entries associated with this mac */
7381 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7383 /* Remove MAC from BGP. */
7384 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7387 * If there are no neigh associated with the mac delete the mac
7388 * else mark it as AUTO for forward reference
7390 if (!listcount(mac
->neigh_list
)) {
7391 zvni_mac_del(zvni
, mac
);
7393 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7394 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7401 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7403 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7404 struct interface
*br_if
,
7405 struct ethaddr
*macaddr
, vlanid_t vid
,
7410 struct zebra_vrf
*zvrf
;
7411 char buf
[ETHER_ADDR_STRLEN
];
7412 bool mac_sticky
= false;
7413 bool inform_client
= false;
7414 bool upd_neigh
= false;
7415 struct in_addr vtep_ip
= {.s_addr
= 0};
7417 /* We are interested in MACs only on ports or (port, VLAN) that
7420 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7422 if (IS_ZEBRA_DEBUG_VXLAN
)
7424 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7425 sticky
? "sticky " : "",
7426 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7427 ifp
->name
, ifp
->ifindex
, vid
);
7431 if (!zvni
->vxlan_if
) {
7433 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7438 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7442 /* Check if we need to create or update or it is a NO-OP. */
7443 mac
= zvni_mac_lookup(zvni
, macaddr
);
7445 if (IS_ZEBRA_DEBUG_VXLAN
)
7447 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7448 sticky
? "sticky " : "",
7449 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7450 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7452 mac
= zvni_mac_add(zvni
, macaddr
);
7455 EC_ZEBRA_MAC_ADD_FAILED
,
7456 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7457 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7458 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7461 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7462 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7463 mac
->fwd_info
.local
.vid
= vid
;
7465 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7466 inform_client
= true;
7469 if (IS_ZEBRA_DEBUG_VXLAN
)
7471 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7472 sticky
? "sticky " : "",
7473 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7474 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7477 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7478 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7482 * Update any changes and if changes are relevant to
7485 if (mac_sticky
== sticky
7486 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7487 && mac
->fwd_info
.local
.vid
== vid
) {
7488 if (IS_ZEBRA_DEBUG_VXLAN
)
7490 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7491 "entry exists and has not changed ",
7492 sticky
? "sticky " : "",
7493 prefix_mac2str(macaddr
, buf
,
7495 ifp
->name
, ifp
->ifindex
, vid
,
7499 if (mac_sticky
!= sticky
) {
7501 SET_FLAG(mac
->flags
,
7504 UNSET_FLAG(mac
->flags
,
7506 inform_client
= true;
7509 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7510 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7511 mac
->fwd_info
.local
.vid
= vid
;
7513 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7514 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7515 bool do_dad
= false;
7518 * MAC has either moved or was "internally" created due
7519 * to a neighbor learn and is now actually learnt. If
7520 * it was learnt as a remote sticky MAC, this is an
7523 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7525 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7526 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7527 prefix_mac2str(macaddr
, buf
,
7529 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7534 /* If an actual move, compute MAC's seq number */
7535 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7536 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7538 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7539 /* Trigger DAD for remote MAC */
7543 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7544 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7545 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7546 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7547 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7548 mac
->fwd_info
.local
.vid
= vid
;
7550 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7552 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7554 * We have to inform BGP of this MAC as well as process
7557 inform_client
= true;
7560 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7567 /* Inform BGP if required. */
7568 if (inform_client
) {
7569 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7570 mac
->flags
, mac
->loc_seq
))
7574 /* Process all neighbors associated with this MAC, if required. */
7576 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7582 * Handle message from client to delete a remote VTEP for a VNI.
7584 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7587 unsigned short l
= 0;
7589 struct in_addr vtep_ip
;
7591 zebra_vtep_t
*zvtep
;
7592 struct interface
*ifp
;
7593 struct zebra_if
*zif
;
7595 if (!is_evpn_enabled()) {
7597 "%s: EVPN is not enabled yet we have received a vtep del command",
7598 __PRETTY_FUNCTION__
);
7602 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7603 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7610 while (l
< hdr
->length
) {
7611 /* Obtain each remote VTEP and process. */
7612 STREAM_GETL(s
, vni
);
7614 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7615 l
+= IPV4_MAX_BYTELEN
;
7617 if (IS_ZEBRA_DEBUG_VXLAN
)
7618 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7619 inet_ntoa(vtep_ip
), vni
,
7620 zebra_route_string(client
->proto
));
7622 /* Locate VNI hash entry - expected to exist. */
7623 zvni
= zvni_lookup(vni
);
7625 if (IS_ZEBRA_DEBUG_VXLAN
)
7627 "Failed to locate VNI hash upon remote VTEP DEL, "
7633 ifp
= zvni
->vxlan_if
;
7636 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7642 /* If down or not mapped to a bridge, we're done. */
7643 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7646 /* If the remote VTEP does not exist, there's nothing more to
7648 * Otherwise, uninstall any remote MACs pointing to this VTEP
7650 * then, the VTEP entry itself and remove it.
7652 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7656 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7657 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7658 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7659 zvni_vtep_del(zvni
, zvtep
);
7667 * Handle message from client to add a remote VTEP for a VNI.
7669 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7672 unsigned short l
= 0;
7674 struct in_addr vtep_ip
;
7676 struct interface
*ifp
;
7677 struct zebra_if
*zif
;
7679 if (!is_evpn_enabled()) {
7681 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7682 __PRETTY_FUNCTION__
);
7686 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7687 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7694 while (l
< hdr
->length
) {
7695 /* Obtain each remote VTEP and process. */
7696 STREAM_GETL(s
, vni
);
7698 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7699 l
+= IPV4_MAX_BYTELEN
;
7701 if (IS_ZEBRA_DEBUG_VXLAN
)
7702 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7703 inet_ntoa(vtep_ip
), vni
,
7704 zebra_route_string(client
->proto
));
7706 /* Locate VNI hash entry - expected to exist. */
7707 zvni
= zvni_lookup(vni
);
7710 EC_ZEBRA_VTEP_ADD_FAILED
,
7711 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7716 ifp
= zvni
->vxlan_if
;
7719 EC_ZEBRA_VTEP_ADD_FAILED
,
7720 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7727 /* If down or not mapped to a bridge, we're done. */
7728 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7731 /* If the remote VTEP already exists,
7732 there's nothing more to do. */
7733 if (zvni_vtep_find(zvni
, &vtep_ip
))
7736 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7737 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7738 "Failed to add remote VTEP, VNI %u zvni %p",
7743 zvni_vtep_install(zvni
, &vtep_ip
);
7751 * Add/Del gateway macip to evpn
7753 * 1. SVI interface on a vlan aware bridge
7754 * 2. SVI interface on a vlan unaware bridge
7755 * 3. vrr interface (MACVLAN) associated to a SVI
7756 * We advertise macip routes for an interface if it is associated to VxLan vlan
7758 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7762 struct ethaddr macaddr
;
7763 zebra_vni_t
*zvni
= NULL
;
7765 memset(&ip
, 0, sizeof(struct ipaddr
));
7766 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7768 /* Check if EVPN is enabled. */
7769 if (!is_evpn_enabled())
7772 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7773 struct interface
*svi_if
=
7774 NULL
; /* SVI corresponding to the MACVLAN */
7775 struct zebra_if
*ifp_zif
=
7776 NULL
; /* Zebra daemon specific info for MACVLAN */
7777 struct zebra_if
*svi_if_zif
=
7778 NULL
; /* Zebra daemon specific info for SVI*/
7780 ifp_zif
= ifp
->info
;
7785 * for a MACVLAN interface the link represents the svi_if
7787 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7788 ifp_zif
->link_ifindex
);
7790 zlog_debug("MACVLAN %s(%u) without link information",
7791 ifp
->name
, ifp
->ifindex
);
7795 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7797 * If it is a vlan aware bridge then the link gives the
7798 * bridge information
7800 struct interface
*svi_if_link
= NULL
;
7802 svi_if_zif
= svi_if
->info
;
7804 svi_if_link
= if_lookup_by_index_per_ns(
7805 zebra_ns_lookup(NS_DEFAULT
),
7806 svi_if_zif
->link_ifindex
);
7807 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7809 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7811 * If it is a vlan unaware bridge then svi is the bridge
7814 zvni
= zvni_from_svi(svi_if
, svi_if
);
7816 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7817 struct zebra_if
*svi_if_zif
=
7818 NULL
; /* Zebra daemon specific info for SVI */
7819 struct interface
*svi_if_link
=
7820 NULL
; /* link info for the SVI = bridge info */
7822 svi_if_zif
= ifp
->info
;
7824 svi_if_link
= if_lookup_by_index_per_ns(
7825 zebra_ns_lookup(NS_DEFAULT
),
7826 svi_if_zif
->link_ifindex
);
7828 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7830 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7831 zvni
= zvni_from_svi(ifp
, ifp
);
7837 if (!zvni
->vxlan_if
) {
7838 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
7844 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
7846 if (p
->family
== AF_INET
) {
7847 ip
.ipa_type
= IPADDR_V4
;
7848 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
7849 sizeof(struct in_addr
));
7850 } else if (p
->family
== AF_INET6
) {
7851 ip
.ipa_type
= IPADDR_V6
;
7852 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
7853 sizeof(struct in6_addr
));
7858 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
7860 zvni_gw_macip_del(ifp
, zvni
, &ip
);
7866 * Handle SVI interface going down.
7867 * SVI can be associated to either L3-VNI or L2-VNI.
7868 * For L2-VNI: At this point, this is a NOP since
7869 * the kernel deletes the neighbor entries on this SVI (if any).
7870 * We only need to update the vrf corresponding to zvni.
7871 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
7874 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
7876 zebra_l3vni_t
*zl3vni
= NULL
;
7878 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7881 /* process l3-vni down */
7882 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7884 /* remove association with svi-if */
7885 zl3vni
->svi_if
= NULL
;
7887 zebra_vni_t
*zvni
= NULL
;
7889 /* since we dont have svi corresponding to zvni, we associate it
7890 * to default vrf. Note: the corresponding neigh entries on the
7891 * SVI would have already been deleted */
7892 zvni
= zvni_from_svi(ifp
, link_if
);
7894 zvni
->vrf_id
= VRF_DEFAULT
;
7896 /* update the tenant vrf in BGP */
7897 zvni_send_add_to_client(zvni
);
7904 * Handle SVI interface coming up.
7905 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
7907 * For L2-VNI: we need to install any remote neighbors entried (used for
7909 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
7911 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
7913 zebra_vni_t
*zvni
= NULL
;
7914 zebra_l3vni_t
*zl3vni
= NULL
;
7916 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7919 /* associate with svi */
7920 zl3vni
->svi_if
= ifp
;
7922 /* process oper-up */
7923 if (is_l3vni_oper_up(zl3vni
))
7924 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7927 /* process SVI up for l2-vni */
7928 struct neigh_walk_ctx n_wctx
;
7930 zvni
= zvni_from_svi(ifp
, link_if
);
7934 if (!zvni
->vxlan_if
) {
7936 "VNI %u hash %p doesn't have intf upon SVI up",
7941 if (IS_ZEBRA_DEBUG_VXLAN
)
7943 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
7944 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
7945 vrf_id_to_name(ifp
->vrf_id
));
7947 /* update the vrf information for l2-vni and inform bgp */
7948 zvni
->vrf_id
= ifp
->vrf_id
;
7949 zvni_send_add_to_client(zvni
);
7951 /* Install any remote neighbors for this VNI. */
7952 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7954 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
7962 * Handle VxLAN interface down
7964 int zebra_vxlan_if_down(struct interface
*ifp
)
7967 struct zebra_if
*zif
= NULL
;
7968 struct zebra_l2info_vxlan
*vxl
= NULL
;
7969 zebra_l3vni_t
*zl3vni
= NULL
;
7972 /* Check if EVPN is enabled. */
7973 if (!is_evpn_enabled())
7978 vxl
= &zif
->l2info
.vxl
;
7981 zl3vni
= zl3vni_lookup(vni
);
7983 /* process-if-down for l3-vni */
7984 if (IS_ZEBRA_DEBUG_VXLAN
)
7985 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
7988 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7990 /* process if-down for l2-vni */
7991 if (IS_ZEBRA_DEBUG_VXLAN
)
7992 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
7995 /* Locate hash entry; it is expected to exist. */
7996 zvni
= zvni_lookup(vni
);
7999 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8000 ifp
->name
, ifp
->ifindex
, vni
);
8004 assert(zvni
->vxlan_if
== ifp
);
8006 /* Delete this VNI from BGP. */
8007 zvni_send_del_to_client(zvni
->vni
);
8009 /* Free up all neighbors and MACs, if any. */
8010 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8011 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8013 /* Free up all remote VTEPs, if any. */
8014 zvni_vtep_del_all(zvni
, 1);
8020 * Handle VxLAN interface up - update BGP if required.
8022 int zebra_vxlan_if_up(struct interface
*ifp
)
8025 struct zebra_if
*zif
= NULL
;
8026 struct zebra_l2info_vxlan
*vxl
= NULL
;
8027 zebra_vni_t
*zvni
= NULL
;
8028 zebra_l3vni_t
*zl3vni
= NULL
;
8030 /* Check if EVPN is enabled. */
8031 if (!is_evpn_enabled())
8036 vxl
= &zif
->l2info
.vxl
;
8039 zl3vni
= zl3vni_lookup(vni
);
8042 if (IS_ZEBRA_DEBUG_VXLAN
)
8043 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8046 /* we need to associate with SVI, if any, we can associate with
8047 * svi-if only after association with vxlan-intf is complete
8049 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8051 if (is_l3vni_oper_up(zl3vni
))
8052 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8054 /* Handle L2-VNI add */
8055 struct interface
*vlan_if
= NULL
;
8057 if (IS_ZEBRA_DEBUG_VXLAN
)
8058 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8061 /* Locate hash entry; it is expected to exist. */
8062 zvni
= zvni_lookup(vni
);
8065 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8066 ifp
->name
, ifp
->ifindex
, vni
);
8070 assert(zvni
->vxlan_if
== ifp
);
8071 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8072 zif
->brslave_info
.br_if
);
8074 zvni
->vrf_id
= vlan_if
->vrf_id
;
8075 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8077 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8080 /* If part of a bridge, inform BGP about this VNI. */
8081 /* Also, read and populate local MACs and neighbors. */
8082 if (zif
->brslave_info
.br_if
) {
8083 zvni_send_add_to_client(zvni
);
8084 zvni_read_mac_neigh(zvni
, ifp
);
8092 * Handle VxLAN interface delete. Locate and remove entry in hash table
8093 * and update BGP, if required.
8095 int zebra_vxlan_if_del(struct interface
*ifp
)
8098 struct zebra_if
*zif
= NULL
;
8099 struct zebra_l2info_vxlan
*vxl
= NULL
;
8100 zebra_vni_t
*zvni
= NULL
;
8101 zebra_l3vni_t
*zl3vni
= NULL
;
8103 /* Check if EVPN is enabled. */
8104 if (!is_evpn_enabled())
8109 vxl
= &zif
->l2info
.vxl
;
8112 zl3vni
= zl3vni_lookup(vni
);
8115 if (IS_ZEBRA_DEBUG_VXLAN
)
8116 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8119 /* process oper-down for l3-vni */
8120 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8122 /* remove the association with vxlan_if */
8123 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8124 zl3vni
->vxlan_if
= NULL
;
8127 /* process if-del for l2-vni*/
8128 if (IS_ZEBRA_DEBUG_VXLAN
)
8129 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8132 /* Locate hash entry; it is expected to exist. */
8133 zvni
= zvni_lookup(vni
);
8136 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8137 ifp
->name
, ifp
->ifindex
, vni
);
8141 /* remove from l3-vni list */
8142 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8144 listnode_delete(zl3vni
->l2vnis
, zvni
);
8146 /* Delete VNI from BGP. */
8147 zvni_send_del_to_client(zvni
->vni
);
8149 /* Free up all neighbors and MAC, if any. */
8150 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8151 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8153 /* Free up all remote VTEPs, if any. */
8154 zvni_vtep_del_all(zvni
, 0);
8156 /* Delete the hash entry. */
8157 if (zvni_del(zvni
)) {
8158 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8159 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8160 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8168 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8170 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8173 struct zebra_if
*zif
= NULL
;
8174 struct zebra_l2info_vxlan
*vxl
= NULL
;
8175 zebra_vni_t
*zvni
= NULL
;
8176 zebra_l3vni_t
*zl3vni
= NULL
;
8178 /* Check if EVPN is enabled. */
8179 if (!is_evpn_enabled())
8184 vxl
= &zif
->l2info
.vxl
;
8187 zl3vni
= zl3vni_lookup(vni
);
8190 if (IS_ZEBRA_DEBUG_VXLAN
)
8192 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8193 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8194 inet_ntoa(vxl
->vtep_ip
),
8195 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8197 /* Removed from bridge? Cleanup and return */
8198 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8199 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8200 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8204 /* access-vlan change - process oper down, associate with new
8205 * svi_if and then process oper up again
8207 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8208 if (if_is_operative(ifp
)) {
8209 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8210 zl3vni
->svi_if
= NULL
;
8211 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8212 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8213 if (is_l3vni_oper_up(zl3vni
))
8214 zebra_vxlan_process_l3vni_oper_up(
8220 * local-ip change - process oper down, associate with new
8221 * local-ip and then process oper up again
8223 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8224 if (if_is_operative(ifp
)) {
8225 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8226 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8227 if (is_l3vni_oper_up(zl3vni
))
8228 zebra_vxlan_process_l3vni_oper_up(
8233 /* Update local tunnel IP. */
8234 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8236 /* if we have a valid new master, process l3-vni oper up */
8237 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8238 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8239 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8243 /* Update VNI hash. */
8244 zvni
= zvni_lookup(vni
);
8247 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8248 ifp
->name
, ifp
->ifindex
, vni
);
8252 if (IS_ZEBRA_DEBUG_VXLAN
)
8254 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8255 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8256 inet_ntoa(vxl
->vtep_ip
),
8257 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8259 /* Removed from bridge? Cleanup and return */
8260 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8261 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8262 /* Delete from client, remove all remote VTEPs */
8263 /* Also, free up all MACs and neighbors. */
8264 zvni_send_del_to_client(zvni
->vni
);
8265 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8266 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8267 zvni_vtep_del_all(zvni
, 1);
8271 /* Handle other changes. */
8272 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8273 /* Remove all existing local neigh and MACs for this VNI
8274 * (including from BGP)
8276 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8277 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8280 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8281 zvni
->vxlan_if
= ifp
;
8283 /* Take further actions needed.
8284 * Note that if we are here, there is a change of interest.
8286 /* If down or not mapped to a bridge, we're done. */
8287 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8290 /* Inform BGP, if there is a change of interest. */
8292 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8293 zvni_send_add_to_client(zvni
);
8295 /* If there is a valid new master or a VLAN mapping change,
8296 * read and populate local MACs and neighbors.
8297 * Also, reinstall any remote MACs and neighbors
8298 * for this VNI (based on new VLAN).
8300 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8301 zvni_read_mac_neigh(zvni
, ifp
);
8302 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8303 struct mac_walk_ctx m_wctx
;
8304 struct neigh_walk_ctx n_wctx
;
8306 zvni_read_mac_neigh(zvni
, ifp
);
8308 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8310 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8313 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8315 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8324 * Handle VxLAN interface add.
8326 int zebra_vxlan_if_add(struct interface
*ifp
)
8329 struct zebra_if
*zif
= NULL
;
8330 struct zebra_l2info_vxlan
*vxl
= NULL
;
8331 zebra_vni_t
*zvni
= NULL
;
8332 zebra_l3vni_t
*zl3vni
= NULL
;
8334 /* Check if EVPN is enabled. */
8335 if (!is_evpn_enabled())
8340 vxl
= &zif
->l2info
.vxl
;
8343 zl3vni
= zl3vni_lookup(vni
);
8346 /* process if-add for l3-vni*/
8347 if (IS_ZEBRA_DEBUG_VXLAN
)
8349 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8350 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8351 inet_ntoa(vxl
->vtep_ip
),
8352 zif
->brslave_info
.bridge_ifindex
);
8354 /* associate with vxlan_if */
8355 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8356 zl3vni
->vxlan_if
= ifp
;
8358 /* Associate with SVI, if any. We can associate with svi-if only
8359 * after association with vxlan_if is complete */
8360 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8362 if (is_l3vni_oper_up(zl3vni
))
8363 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8366 /* process if-add for l2-vni */
8367 struct interface
*vlan_if
= NULL
;
8369 /* Create or update VNI hash. */
8370 zvni
= zvni_lookup(vni
);
8372 zvni
= zvni_add(vni
);
8375 EC_ZEBRA_VNI_ADD_FAILED
,
8376 "Failed to add VNI hash, IF %s(%u) VNI %u",
8377 ifp
->name
, ifp
->ifindex
, vni
);
8382 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8383 zvni
->vxlan_if
= ifp
;
8384 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8385 zif
->brslave_info
.br_if
);
8387 zvni
->vrf_id
= vlan_if
->vrf_id
;
8388 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8390 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8393 if (IS_ZEBRA_DEBUG_VXLAN
)
8395 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8397 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8399 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8400 inet_ntoa(vxl
->vtep_ip
),
8401 zif
->brslave_info
.bridge_ifindex
);
8403 /* If down or not mapped to a bridge, we're done. */
8404 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8408 zvni_send_add_to_client(zvni
);
8410 /* Read and populate local MACs and neighbors */
8411 zvni_read_mac_neigh(zvni
, ifp
);
8417 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8418 char *err
, int err_str_sz
, int filter
,
8421 zebra_l3vni_t
*zl3vni
= NULL
;
8422 struct zebra_vrf
*zvrf_default
= NULL
;
8424 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8428 if (IS_ZEBRA_DEBUG_VXLAN
)
8429 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8430 add
? "ADD" : "DEL");
8434 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8436 /* check if the vni is already present under zvrf */
8438 snprintf(err
, err_str_sz
,
8439 "VNI is already configured under the vrf");
8443 /* check if this VNI is already present in the system */
8444 zl3vni
= zl3vni_lookup(vni
);
8446 snprintf(err
, err_str_sz
,
8447 "VNI is already configured as L3-VNI");
8451 /* add the L3-VNI to the global table */
8452 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8454 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8458 /* associate the vrf with vni */
8461 /* set the filter in l3vni to denote if we are using l3vni only
8465 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8467 /* associate with vxlan-intf;
8468 * we need to associate with the vxlan-intf first
8470 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8472 /* associate with corresponding SVI interface, we can associate
8473 * with svi-if only after vxlan interface association is
8476 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8478 /* formulate l2vni list */
8479 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8482 if (is_l3vni_oper_up(zl3vni
))
8483 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8486 zl3vni
= zl3vni_lookup(vni
);
8488 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8492 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8493 snprintf(err
, ERR_STR_SZ
,
8494 "prefix-routes-only is not set for the vni");
8498 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8500 /* delete and uninstall all rmacs */
8501 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8504 /* delete and uninstall all next-hops */
8505 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8511 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8516 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8518 zebra_l3vni_t
*zl3vni
= NULL
;
8521 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8525 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8526 if (is_l3vni_oper_up(zl3vni
))
8527 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8531 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8533 zebra_l3vni_t
*zl3vni
= NULL
;
8536 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8540 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8541 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8545 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8547 zebra_l3vni_t
*zl3vni
= NULL
;
8551 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8557 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8563 * Handle message from client to specify the flooding mechanism for
8564 * BUM packets. The default is to do head-end (ingress) replication
8565 * and the other supported option is to disable it. This applies to
8566 * all BUM traffic and disabling it applies to both the transmit and
8567 * receive direction.
8569 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8572 enum vxlan_flood_control flood_ctrl
;
8574 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8575 zlog_err("EVPN flood control for non-default VRF %u",
8581 STREAM_GETC(s
, flood_ctrl
);
8583 if (IS_ZEBRA_DEBUG_VXLAN
)
8584 zlog_debug("EVPN flood control %u, currently %u",
8585 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8587 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8590 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8592 /* Install or uninstall flood entries corresponding to
8595 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8603 * Handle message from client to enable/disable advertisement of g/w macip
8606 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8611 zebra_vni_t
*zvni
= NULL
;
8612 struct interface
*ifp
= NULL
;
8613 struct zebra_if
*zif
= NULL
;
8614 struct zebra_l2info_vxlan zl2_info
;
8615 struct interface
*vlan_if
= NULL
;
8617 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8618 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8624 STREAM_GETC(s
, advertise
);
8625 vni
= stream_get3(s
);
8627 zvni
= zvni_lookup(vni
);
8631 if (zvni
->advertise_subnet
== advertise
)
8634 if (IS_ZEBRA_DEBUG_VXLAN
)
8635 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8636 advertise
? "enabled" : "disabled", vni
,
8637 zvni
->advertise_subnet
? "enabled" : "disabled");
8640 zvni
->advertise_subnet
= advertise
;
8642 ifp
= zvni
->vxlan_if
;
8648 /* If down or not mapped to a bridge, we're done. */
8649 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8652 zl2_info
= zif
->l2info
.vxl
;
8655 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8659 if (zvni
->advertise_subnet
)
8660 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8662 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8669 * Handle message from client to enable/disable advertisement of g/w macip
8672 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8677 zebra_vni_t
*zvni
= NULL
;
8678 struct interface
*ifp
= NULL
;
8680 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8681 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8687 STREAM_GETC(s
, advertise
);
8688 STREAM_GETL(s
, vni
);
8691 if (IS_ZEBRA_DEBUG_VXLAN
)
8692 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8693 advertise
? "enabled" : "disabled",
8694 advertise_gw_macip_enabled(NULL
)
8698 if (zvrf
->advertise_gw_macip
== advertise
)
8701 zvrf
->advertise_gw_macip
= advertise
;
8703 if (advertise_gw_macip_enabled(zvni
))
8704 hash_iterate(zvrf
->vni_table
,
8705 zvni_gw_macip_add_for_vni_hash
, NULL
);
8707 hash_iterate(zvrf
->vni_table
,
8708 zvni_gw_macip_del_for_vni_hash
, NULL
);
8711 struct zebra_if
*zif
= NULL
;
8712 struct zebra_l2info_vxlan zl2_info
;
8713 struct interface
*vlan_if
= NULL
;
8714 struct interface
*vrr_if
= NULL
;
8716 zvni
= zvni_lookup(vni
);
8720 if (IS_ZEBRA_DEBUG_VXLAN
)
8722 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8723 advertise
? "enabled" : "disabled", vni
,
8724 advertise_gw_macip_enabled(zvni
) ? "enabled"
8727 if (zvni
->advertise_gw_macip
== advertise
)
8730 zvni
->advertise_gw_macip
= advertise
;
8732 ifp
= zvni
->vxlan_if
;
8738 /* If down or not mapped to a bridge, we're done. */
8739 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8742 zl2_info
= zif
->l2info
.vxl
;
8744 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8745 zif
->brslave_info
.br_if
);
8749 if (advertise_gw_macip_enabled(zvni
)) {
8750 /* Add primary SVI MAC-IP */
8751 zvni_add_macip_for_intf(vlan_if
, zvni
);
8753 /* Add VRR MAC-IP - if any*/
8754 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8756 zvni_add_macip_for_intf(vrr_if
, zvni
);
8758 /* Del primary MAC-IP */
8759 zvni_del_macip_for_intf(vlan_if
, zvni
);
8761 /* Del VRR MAC-IP - if any*/
8762 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8764 zvni_del_macip_for_intf(vrr_if
, zvni
);
8774 * Handle message from client to learn (or stop learning) about VNIs and MACs.
8775 * When enabled, the VNI hash table will be built and MAC FDB table read;
8776 * when disabled, the entries should be deleted and remote VTEPs and MACs
8777 * uninstalled from the kernel.
8778 * This also informs the setting for BUM handling at the time this change
8779 * occurs; it is relevant only when specifying "learn".
8781 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
8783 struct stream
*s
= NULL
;
8785 enum vxlan_flood_control flood_ctrl
;
8787 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8788 zlog_debug("EVPN VNI Adv for non-default VRF %u",
8794 STREAM_GETC(s
, advertise
);
8795 STREAM_GETC(s
, flood_ctrl
);
8797 if (IS_ZEBRA_DEBUG_VXLAN
)
8798 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
8799 advertise
? "enabled" : "disabled",
8800 is_evpn_enabled() ? "enabled" : "disabled",
8803 if (zvrf
->advertise_all_vni
== advertise
)
8806 zvrf
->advertise_all_vni
= advertise
;
8807 if (is_evpn_enabled()) {
8808 /* Note BUM handling */
8809 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8811 /* Build VNI hash table and inform BGP. */
8812 zvni_build_hash_table();
8814 /* Add all SVI (L3 GW) MACs to BGP*/
8815 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
8818 /* Read the MAC FDB */
8819 macfdb_read(zvrf
->zns
);
8821 /* Read neighbors */
8822 neigh_read(zvrf
->zns
);
8824 /* Cleanup VTEPs for all VNIs - uninstall from
8825 * kernel and free entries.
8827 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8829 /* cleanup all l3vnis */
8830 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
8838 * Allocate VNI hash table for this VRF and do other initialization.
8839 * NOTE: Currently supported only for default VRF.
8841 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
8845 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
8846 "Zebra VRF VNI Table");
8849 /* Cleanup VNI info, but don't free the table. */
8850 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
8854 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8857 /* Close all VNI handling */
8858 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
8862 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8863 hash_free(zvrf
->vni_table
);
8866 /* init the l3vni table */
8867 void zebra_vxlan_init(void)
8869 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
8870 "Zebra VRF L3 VNI table");
8873 /* free l3vni table */
8874 void zebra_vxlan_disable(void)
8876 hash_free(zrouter
.l3vni_table
);
8879 /* get the l3vni svi ifindex */
8880 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
8882 zebra_l3vni_t
*zl3vni
= NULL
;
8884 zl3vni
= zl3vni_from_vrf(vrf_id
);
8885 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
8888 return zl3vni
->svi_if
->ifindex
;
8891 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
8893 struct zebra_vrf
*zvrf
= NULL
;
8894 zebra_neigh_t
*nbr
= NULL
;
8895 zebra_vni_t
*zvni
= NULL
;
8896 char buf1
[INET6_ADDRSTRLEN
];
8897 char buf2
[ETHER_ADDR_STRLEN
];
8899 nbr
= THREAD_ARG(t
);
8901 /* since this is asynchronous we need sanity checks*/
8902 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
8906 zvni
= zvni_lookup(nbr
->zvni
->vni
);
8910 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
8914 if (IS_ZEBRA_DEBUG_VXLAN
)
8915 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
8916 __PRETTY_FUNCTION__
,
8917 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
8918 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
8920 nbr
->dad_count
, zvni
->vni
);
8922 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8924 nbr
->detect_start_time
.tv_sec
= 0;
8925 nbr
->detect_start_time
.tv_usec
= 0;
8926 nbr
->dad_dup_detect_time
= 0;
8927 nbr
->dad_ip_auto_recovery_timer
= NULL
;
8930 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8931 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
8932 nbr
->flags
, nbr
->loc_seq
);
8933 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8934 zvni_neigh_install(zvni
, nbr
);
8940 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
8942 struct zebra_vrf
*zvrf
= NULL
;
8943 zebra_mac_t
*mac
= NULL
;
8944 zebra_vni_t
*zvni
= NULL
;
8945 struct listnode
*node
= NULL
;
8946 zebra_neigh_t
*nbr
= NULL
;
8947 char buf
[ETHER_ADDR_STRLEN
];
8949 mac
= THREAD_ARG(t
);
8951 /* since this is asynchronous we need sanity checks*/
8952 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
8956 zvni
= zvni_lookup(mac
->zvni
->vni
);
8960 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
8964 if (IS_ZEBRA_DEBUG_VXLAN
)
8965 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
8966 __PRETTY_FUNCTION__
,
8967 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
8970 listcount(mac
->neigh_list
));
8972 /* Remove all IPs as duplicate associcated with this MAC */
8973 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
8974 if (nbr
->dad_count
) {
8975 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
8976 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
8977 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
8978 zvni_neigh_install(zvni
, nbr
);
8981 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8983 nbr
->detect_start_time
.tv_sec
= 0;
8984 nbr
->dad_dup_detect_time
= 0;
8987 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
8989 mac
->detect_start_time
.tv_sec
= 0;
8990 mac
->detect_start_time
.tv_usec
= 0;
8991 mac
->dad_dup_detect_time
= 0;
8992 mac
->dad_mac_auto_recovery_timer
= NULL
;
8994 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8996 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
8997 mac
->flags
, mac
->loc_seq
))
9000 /* Process all neighbors associated with this MAC. */
9001 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9003 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9004 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9006 /* Install the entry. */
9007 zvni_mac_install(zvni
, mac
);