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 neighbors for all VNI.
877 static void zvni_print_neigh_hash_all_vni(struct hash_backet
*backet
,
881 json_object
*json
= NULL
, *json_vni
= NULL
;
884 struct neigh_walk_ctx wctx
;
885 char vni_str
[VNI_STR_LEN
];
888 vty
= (struct vty
*)args
[0];
889 json
= (json_object
*)args
[1];
890 print_dup
= (uint32_t)(uintptr_t)args
[2];
892 zvni
= (zebra_vni_t
*)backet
->data
;
894 num_neigh
= hashcount(zvni
->neigh_table
);
897 num_neigh
= num_dup_detected_neighs(zvni
);
901 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
902 zvni
->vni
, num_neigh
);
904 json_vni
= json_object_new_object();
905 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
906 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
911 json_object_object_add(json
, vni_str
, json_vni
);
915 /* Since we have IPv6 addresses to deal with which can vary widely in
916 * size, we try to be a bit more elegant in display by first computing
919 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
922 wctx
.addr_width
= 15;
923 wctx
.json
= json_vni
;
924 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
927 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
928 -wctx
.addr_width
, "IP", "Type",
929 "State", "MAC", "Remote VTEP");
932 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
935 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
938 json_object_object_add(json
, vni_str
, json_vni
);
941 static void zvni_print_dad_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
945 nbr
= (zebra_neigh_t
*)backet
->data
;
949 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
950 zvni_print_neigh_hash(backet
, ctxt
);
953 /* print a specific next hop for an l3vni */
954 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
957 char buf1
[ETHER_ADDR_STRLEN
];
958 char buf2
[INET6_ADDRSTRLEN
];
959 json_object
*json_hosts
= NULL
;
960 struct host_rb_entry
*hle
;
963 vty_out(vty
, "Ip: %s\n",
964 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
965 vty_out(vty
, " RMAC: %s\n",
966 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
967 vty_out(vty
, " Refcount: %d\n",
968 rb_host_count(&n
->host_rb
));
969 vty_out(vty
, " Prefixes:\n");
970 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
971 vty_out(vty
, " %s\n",
972 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
974 json_hosts
= json_object_new_array();
975 json_object_string_add(
976 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
977 json_object_string_add(
979 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
980 json_object_int_add(json
, "refCount",
981 rb_host_count(&n
->host_rb
));
982 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
983 json_object_array_add(json_hosts
,
984 json_object_new_string(prefix2str(
985 &hle
->p
, buf2
, sizeof(buf2
))));
986 json_object_object_add(json
, "prefixList", json_hosts
);
990 /* Print a specific RMAC entry */
991 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
994 char buf1
[ETHER_ADDR_STRLEN
];
995 char buf2
[PREFIX_STRLEN
];
996 json_object
*json_hosts
= NULL
;
997 struct host_rb_entry
*hle
;
1000 vty_out(vty
, "MAC: %s\n",
1001 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1002 vty_out(vty
, " Remote VTEP: %s\n",
1003 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1004 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1005 vty_out(vty
, " Prefixes:\n");
1006 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1007 vty_out(vty
, " %s\n",
1008 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1010 json_hosts
= json_object_new_array();
1011 json_object_string_add(
1013 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1014 json_object_string_add(json
, "vtepIp",
1015 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1016 json_object_int_add(json
, "refCount",
1017 rb_host_count(&zrmac
->host_rb
));
1018 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1019 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1020 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1021 json_object_array_add(
1023 json_object_new_string(prefix2str(
1024 &hle
->p
, buf2
, sizeof(buf2
))));
1025 json_object_object_add(json
, "prefixList", json_hosts
);
1030 * Print a specific MAC entry.
1032 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1035 zebra_neigh_t
*n
= NULL
;
1036 struct listnode
*node
= NULL
;
1038 char buf2
[INET6_ADDRSTRLEN
];
1039 struct zebra_vrf
*zvrf
;
1040 struct timeval detect_start_time
= {0, 0};
1042 zvrf
= zebra_vrf_lookup_by_id(mac
->zvni
->vrf_id
);
1044 vty
= (struct vty
*)ctxt
;
1045 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1048 json_object
*json_mac
= json_object_new_object();
1050 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1051 struct zebra_ns
*zns
;
1052 struct interface
*ifp
;
1055 ifindex
= mac
->fwd_info
.local
.ifindex
;
1056 zns
= zebra_ns_lookup(NS_DEFAULT
);
1057 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1060 json_object_string_add(json_mac
, "type", "local");
1061 json_object_string_add(json_mac
, "intf", ifp
->name
);
1062 json_object_int_add(json_mac
, "ifindex", ifindex
);
1063 if (mac
->fwd_info
.local
.vid
)
1064 json_object_int_add(json_mac
, "vlan",
1065 mac
->fwd_info
.local
.vid
);
1066 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1067 json_object_string_add(json_mac
, "type", "remote");
1068 json_object_string_add(
1069 json_mac
, "remoteVtep",
1070 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1071 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1072 json_object_string_add(json_mac
, "type", "auto");
1074 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1075 json_object_boolean_true_add(json_mac
, "stickyMac");
1077 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1078 json_object_boolean_true_add(json_mac
,
1081 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1082 json_object_boolean_true_add(json_mac
,
1083 "remoteGatewayMac");
1085 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1086 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1088 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1089 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1090 json_object_boolean_true_add(json_mac
, "isDuplicate");
1092 json_object_boolean_false_add(json_mac
, "isDuplicate");
1094 /* print all the associated neigh */
1095 if (!listcount(mac
->neigh_list
))
1096 json_object_string_add(json_mac
, "neighbors", "none");
1098 json_object
*json_active_nbrs
= json_object_new_array();
1099 json_object
*json_inactive_nbrs
=
1100 json_object_new_array();
1101 json_object
*json_nbrs
= json_object_new_object();
1103 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1104 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1105 json_object_array_add(
1107 json_object_new_string(
1112 json_object_array_add(
1114 json_object_new_string(
1120 json_object_object_add(json_nbrs
, "active",
1122 json_object_object_add(json_nbrs
, "inactive",
1123 json_inactive_nbrs
);
1124 json_object_object_add(json_mac
, "neighbors",
1128 json_object_object_add(json
, buf1
, json_mac
);
1129 vty_out(vty
, "%s\n",
1130 json_object_to_json_string_ext(
1131 json
, JSON_C_TO_STRING_PRETTY
));
1132 json_object_free(json
);
1134 vty_out(vty
, "MAC: %s\n", buf1
);
1136 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1137 struct zebra_ns
*zns
;
1138 struct interface
*ifp
;
1141 ifindex
= mac
->fwd_info
.local
.ifindex
;
1142 zns
= zebra_ns_lookup(NS_DEFAULT
);
1143 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1146 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1147 if (mac
->fwd_info
.local
.vid
)
1148 vty_out(vty
, " VLAN: %u",
1149 mac
->fwd_info
.local
.vid
);
1150 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1151 vty_out(vty
, " Remote VTEP: %s",
1152 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1153 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1154 vty_out(vty
, " Auto Mac ");
1157 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1158 vty_out(vty
, " Sticky Mac ");
1160 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1161 vty_out(vty
, " Default-gateway Mac ");
1163 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1164 vty_out(vty
, " Remote-gateway Mac ");
1167 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1171 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1172 vty_out(vty
, " Duplicate, detected at %s",
1173 time_to_string(mac
->dad_dup_detect_time
));
1174 } else if (mac
->dad_count
) {
1175 monotime_since(&mac
->detect_start_time
,
1176 &detect_start_time
);
1177 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1178 char *buf
= time_to_string(
1179 mac
->detect_start_time
.tv_sec
);
1182 memset(tmp_buf
, 0, 30);
1183 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
1185 " Duplicate detection started at %s, detection count %u\n",
1186 tmp_buf
, mac
->dad_count
);
1190 /* print all the associated neigh */
1191 vty_out(vty
, " Neighbors:\n");
1192 if (!listcount(mac
->neigh_list
))
1193 vty_out(vty
, " No Neighbors\n");
1195 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1196 vty_out(vty
, " %s %s\n",
1197 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1198 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1209 * Print MAC hash entry - called for display of all MACs.
1211 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1214 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1217 struct mac_walk_ctx
*wctx
= ctxt
;
1220 json_mac_hdr
= wctx
->json
;
1221 mac
= (zebra_mac_t
*)backet
->data
;
1223 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1226 json_mac
= json_object_new_object();
1228 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1229 struct zebra_ns
*zns
;
1231 struct interface
*ifp
;
1234 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1237 zns
= zebra_ns_lookup(NS_DEFAULT
);
1238 ifindex
= mac
->fwd_info
.local
.ifindex
;
1239 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1240 if (!ifp
) // unexpected
1242 vid
= mac
->fwd_info
.local
.vid
;
1243 if (json_mac_hdr
== NULL
)
1244 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1247 json_object_string_add(json_mac
, "type", "local");
1248 json_object_string_add(json_mac
, "intf", ifp
->name
);
1251 if (json_mac_hdr
== NULL
)
1252 vty_out(vty
, " %-5u", vid
);
1254 json_object_int_add(json_mac
, "vlan", vid
);
1256 if (json_mac_hdr
== NULL
) {
1259 json_object_int_add(json_mac
, "localSequence",
1261 json_object_int_add(json_mac
, "remoteSequence",
1263 json_object_int_add(json_mac
, "detectionCount",
1265 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1266 json_object_boolean_true_add(json_mac
,
1269 json_object_boolean_false_add(json_mac
,
1271 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1276 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1278 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1279 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1283 if (json_mac_hdr
== NULL
) {
1284 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1285 (wctx
->count
== 0)) {
1286 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1287 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1288 "Type", "Intf/Remote VTEP", "VLAN");
1290 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1291 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1293 json_object_string_add(json_mac
, "type", "remote");
1294 json_object_string_add(json_mac
, "remoteVtep",
1295 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1296 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1297 json_object_int_add(json_mac
, "localSequence",
1299 json_object_int_add(json_mac
, "remoteSequence",
1301 json_object_int_add(json_mac
, "detectionCount",
1303 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1304 json_object_boolean_true_add(json_mac
,
1307 json_object_boolean_false_add(json_mac
,
1316 /* Print Duplicate MAC */
1317 static void zvni_print_dad_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1321 mac
= (zebra_mac_t
*)backet
->data
;
1325 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1326 zvni_print_mac_hash(backet
, ctxt
);
1330 * Print MACs for all VNI.
1332 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
1335 json_object
*json
= NULL
, *json_vni
= NULL
;
1336 json_object
*json_mac
= NULL
;
1339 struct mac_walk_ctx
*wctx
= ctxt
;
1340 char vni_str
[VNI_STR_LEN
];
1342 vty
= (struct vty
*)wctx
->vty
;
1343 json
= (struct json_object
*)wctx
->json
;
1345 zvni
= (zebra_vni_t
*)backet
->data
;
1348 /*We are iterating over a new VNI, set the count to 0*/
1351 num_macs
= num_valid_macs(zvni
);
1355 if (wctx
->print_dup
)
1356 num_macs
= num_dup_detected_macs(zvni
);
1359 json_vni
= json_object_new_object();
1360 json_mac
= json_object_new_object();
1361 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1364 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1366 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1367 zvni
->vni
, num_macs
);
1368 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1369 "Intf/Remote VTEP", "VLAN");
1371 json_object_int_add(json_vni
, "numMacs", num_macs
);
1376 json_object_int_add(json_vni
, "numMacs", num_macs
);
1377 json_object_object_add(json
, vni_str
, json_vni
);
1382 /* assign per-vni to wctx->json object to fill macs
1383 * under the vni. Re-assign primary json object to fill
1384 * next vni information.
1386 wctx
->json
= json_mac
;
1387 if (wctx
->print_dup
)
1388 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1390 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1394 json_object_object_add(json_vni
, "macs", json_mac
);
1395 json_object_object_add(json
, vni_str
, json_vni
);
1399 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
1401 struct nh_walk_ctx
*wctx
= NULL
;
1402 struct vty
*vty
= NULL
;
1403 struct json_object
*json_vni
= NULL
;
1404 struct json_object
*json_nh
= NULL
;
1405 zebra_neigh_t
*n
= NULL
;
1406 char buf1
[ETHER_ADDR_STRLEN
];
1407 char buf2
[INET6_ADDRSTRLEN
];
1409 wctx
= (struct nh_walk_ctx
*)ctx
;
1411 json_vni
= wctx
->json
;
1413 json_nh
= json_object_new_object();
1414 n
= (zebra_neigh_t
*)backet
->data
;
1417 vty_out(vty
, "%-15s %-17s\n",
1418 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1419 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1421 json_object_string_add(json_nh
, "nexthopIp",
1422 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1423 json_object_string_add(
1424 json_nh
, "routerMac",
1425 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1426 json_object_object_add(json_vni
,
1427 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1432 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
1435 struct vty
*vty
= NULL
;
1436 json_object
*json
= NULL
;
1437 json_object
*json_vni
= NULL
;
1438 zebra_l3vni_t
*zl3vni
= NULL
;
1439 uint32_t num_nh
= 0;
1440 struct nh_walk_ctx wctx
;
1441 char vni_str
[VNI_STR_LEN
];
1443 vty
= (struct vty
*)args
[0];
1444 json
= (struct json_object
*)args
[1];
1446 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1448 num_nh
= hashcount(zl3vni
->nh_table
);
1453 json_vni
= json_object_new_object();
1454 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1458 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1459 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1461 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1463 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1465 wctx
.json
= json_vni
;
1466 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1468 json_object_object_add(json
, vni_str
, json_vni
);
1471 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
1474 struct vty
*vty
= NULL
;
1475 json_object
*json
= NULL
;
1476 json_object
*json_vni
= NULL
;
1477 zebra_l3vni_t
*zl3vni
= NULL
;
1479 struct rmac_walk_ctx wctx
;
1480 char vni_str
[VNI_STR_LEN
];
1482 vty
= (struct vty
*)args
[0];
1483 json
= (struct json_object
*)args
[1];
1485 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1487 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1492 json_vni
= json_object_new_object();
1493 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1497 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1498 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1500 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1502 /* assign per-vni to wctx->json object to fill macs
1503 * under the vni. Re-assign primary json object to fill
1504 * next vni information.
1506 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1508 wctx
.json
= json_vni
;
1509 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1511 json_object_object_add(json
, vni_str
, json_vni
);
1514 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
1516 zebra_mac_t
*zrmac
= NULL
;
1517 struct rmac_walk_ctx
*wctx
= NULL
;
1518 struct vty
*vty
= NULL
;
1519 struct json_object
*json
= NULL
;
1520 struct json_object
*json_rmac
= NULL
;
1521 char buf
[ETHER_ADDR_STRLEN
];
1523 wctx
= (struct rmac_walk_ctx
*)ctx
;
1527 json_rmac
= json_object_new_object();
1528 zrmac
= (zebra_mac_t
*)backet
->data
;
1531 vty_out(vty
, "%-17s %-21s\n",
1532 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1533 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1535 json_object_string_add(
1536 json_rmac
, "routerMac",
1537 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1538 json_object_string_add(json_rmac
, "vtepIp",
1539 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1540 json_object_object_add(
1541 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1546 /* print a specific L3 VNI entry */
1547 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1549 char buf
[ETHER_ADDR_STRLEN
];
1550 struct vty
*vty
= NULL
;
1551 json_object
*json
= NULL
;
1552 zebra_vni_t
*zvni
= NULL
;
1553 json_object
*json_vni_list
= NULL
;
1554 struct listnode
*node
= NULL
, *nnode
= NULL
;
1560 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1561 vty_out(vty
, " Type: %s\n", "L3");
1562 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1563 vty_out(vty
, " Local Vtep Ip: %s\n",
1564 inet_ntoa(zl3vni
->local_vtep_ip
));
1565 vty_out(vty
, " Vxlan-Intf: %s\n",
1566 zl3vni_vxlan_if_name(zl3vni
));
1567 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1568 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1569 vty_out(vty
, " VNI Filter: %s\n",
1570 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1571 ? "prefix-routes-only"
1573 vty_out(vty
, " Router MAC: %s\n",
1574 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1575 vty_out(vty
, " L2 VNIs: ");
1576 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1577 vty_out(vty
, "%u ", zvni
->vni
);
1580 json_vni_list
= json_object_new_array();
1581 json_object_int_add(json
, "vni", zl3vni
->vni
);
1582 json_object_string_add(json
, "type", "L3");
1583 json_object_string_add(json
, "localVtepIp",
1584 inet_ntoa(zl3vni
->local_vtep_ip
));
1585 json_object_string_add(json
, "vxlanIntf",
1586 zl3vni_vxlan_if_name(zl3vni
));
1587 json_object_string_add(json
, "sviIntf",
1588 zl3vni_svi_if_name(zl3vni
));
1589 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1590 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1591 json_object_string_add(
1593 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1594 json_object_string_add(
1596 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1597 ? "prefix-routes-only"
1599 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1600 json_object_array_add(json_vni_list
,
1601 json_object_new_int(zvni
->vni
));
1603 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1608 * Print a specific VNI entry.
1610 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1613 zebra_vtep_t
*zvtep
;
1616 json_object
*json
= NULL
;
1617 json_object
*json_vtep_list
= NULL
;
1618 json_object
*json_ip_str
= NULL
;
1624 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1625 vty_out(vty
, " Type: %s\n", "L2");
1626 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1628 json_object_int_add(json
, "vni", zvni
->vni
);
1629 json_object_string_add(json
, "type", "L2");
1630 json_object_string_add(json
, "vrf",
1631 vrf_id_to_name(zvni
->vrf_id
));
1634 if (!zvni
->vxlan_if
) { // unexpected
1636 vty_out(vty
, " VxLAN interface: unknown\n");
1639 num_macs
= num_valid_macs(zvni
);
1640 num_neigh
= hashcount(zvni
->neigh_table
);
1642 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1643 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1644 vty_out(vty
, " Local VTEP IP: %s\n",
1645 inet_ntoa(zvni
->local_vtep_ip
));
1647 json_object_string_add(json
, "vxlanInterface",
1648 zvni
->vxlan_if
->name
);
1649 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1650 json_object_string_add(json
, "vtepIp",
1651 inet_ntoa(zvni
->local_vtep_ip
));
1652 json_object_string_add(json
, "advertiseGatewayMacip",
1653 zvni
->advertise_gw_macip
? "Yes" : "No");
1654 json_object_int_add(json
, "numMacs", num_macs
);
1655 json_object_int_add(json
, "numArpNd", num_neigh
);
1659 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1662 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1664 json_vtep_list
= json_object_new_array();
1665 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1667 vty_out(vty
, " %s\n",
1668 inet_ntoa(zvtep
->vtep_ip
));
1670 json_ip_str
= json_object_new_string(
1671 inet_ntoa(zvtep
->vtep_ip
));
1672 json_object_array_add(json_vtep_list
,
1677 json_object_object_add(json
, "numRemoteVteps",
1682 " Number of MACs (local and remote) known for this VNI: %u\n",
1685 " Number of ARPs (IPv4 and IPv6, local and remote) "
1686 "known for this VNI: %u\n",
1688 vty_out(vty
, " Advertise-gw-macip: %s\n",
1689 zvni
->advertise_gw_macip
? "Yes" : "No");
1693 /* print a L3 VNI hash entry */
1694 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1696 struct vty
*vty
= NULL
;
1697 json_object
*json
= NULL
;
1698 json_object
*json_vni
= NULL
;
1699 zebra_l3vni_t
*zl3vni
= NULL
;
1701 vty
= (struct vty
*)ctx
[0];
1702 json
= (json_object
*)ctx
[1];
1704 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1707 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1708 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1709 hashcount(zl3vni
->rmac_table
),
1710 hashcount(zl3vni
->nh_table
), "n/a",
1711 zl3vni_vrf_name(zl3vni
));
1713 char vni_str
[VNI_STR_LEN
];
1715 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1716 json_vni
= json_object_new_object();
1717 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1718 json_object_string_add(json_vni
, "vxlanIf",
1719 zl3vni_vxlan_if_name(zl3vni
));
1720 json_object_int_add(json_vni
, "numMacs",
1721 hashcount(zl3vni
->rmac_table
));
1722 json_object_int_add(json_vni
, "numArpNd",
1723 hashcount(zl3vni
->nh_table
));
1724 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1725 json_object_string_add(json_vni
, "type", "L3");
1726 json_object_string_add(json_vni
, "tenantVrf",
1727 zl3vni_vrf_name(zl3vni
));
1728 json_object_object_add(json
, vni_str
, json_vni
);
1733 * Print a VNI hash entry - called for display of all VNIs.
1735 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1739 zebra_vtep_t
*zvtep
;
1740 uint32_t num_vteps
= 0;
1741 uint32_t num_macs
= 0;
1742 uint32_t num_neigh
= 0;
1743 json_object
*json
= NULL
;
1744 json_object
*json_vni
= NULL
;
1745 json_object
*json_ip_str
= NULL
;
1746 json_object
*json_vtep_list
= NULL
;
1751 zvni
= (zebra_vni_t
*)backet
->data
;
1753 zvtep
= zvni
->vteps
;
1756 zvtep
= zvtep
->next
;
1759 num_macs
= num_valid_macs(zvni
);
1760 num_neigh
= hashcount(zvni
->neigh_table
);
1762 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1764 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1765 num_macs
, num_neigh
, num_vteps
,
1766 vrf_id_to_name(zvni
->vrf_id
));
1768 char vni_str
[VNI_STR_LEN
];
1769 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1770 json_vni
= json_object_new_object();
1771 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1772 json_object_string_add(json_vni
, "type", "L2");
1773 json_object_string_add(json_vni
, "vxlanIf",
1774 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1776 json_object_int_add(json_vni
, "numMacs", num_macs
);
1777 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1778 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1779 json_object_string_add(json_vni
, "tenantVrf",
1780 vrf_id_to_name(zvni
->vrf_id
));
1782 json_vtep_list
= json_object_new_array();
1783 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1784 json_ip_str
= json_object_new_string(
1785 inet_ntoa(zvtep
->vtep_ip
));
1786 json_object_array_add(json_vtep_list
,
1789 json_object_object_add(json_vni
, "remoteVteps",
1792 json_object_object_add(json
, vni_str
, json_vni
);
1797 * Inform BGP about local MACIP.
1799 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1800 struct ipaddr
*ip
, uint8_t flags
,
1801 uint32_t seq
, uint16_t cmd
)
1803 char buf
[ETHER_ADDR_STRLEN
];
1804 char buf2
[INET6_ADDRSTRLEN
];
1806 struct zserv
*client
= NULL
;
1807 struct stream
*s
= NULL
;
1809 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1810 /* BGP may not be running. */
1814 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1816 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1817 stream_putl(s
, vni
);
1818 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1821 if (IS_IPADDR_V4(ip
))
1822 ipa_len
= IPV4_MAX_BYTELEN
;
1823 else if (IS_IPADDR_V6(ip
))
1824 ipa_len
= IPV6_MAX_BYTELEN
;
1826 stream_putl(s
, ipa_len
); /* IP address length */
1828 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1830 stream_putl(s
, 0); /* Just MAC. */
1832 if (cmd
== ZEBRA_MACIP_ADD
) {
1833 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1834 stream_putl(s
, seq
); /* sequence number */
1838 /* Write packet size. */
1839 stream_putw_at(s
, 0, stream_get_endp(s
));
1841 if (IS_ZEBRA_DEBUG_VXLAN
)
1843 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
1844 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1845 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1846 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
1847 zebra_route_string(client
->proto
));
1849 if (cmd
== ZEBRA_MACIP_ADD
)
1850 client
->macipadd_cnt
++;
1852 client
->macipdel_cnt
++;
1854 return zserv_send_message(client
, s
);
1858 * Make hash key for neighbors.
1860 static unsigned int neigh_hash_keymake(void *p
)
1862 zebra_neigh_t
*n
= p
;
1863 struct ipaddr
*ip
= &n
->ip
;
1865 if (IS_IPADDR_V4(ip
))
1866 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1868 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1869 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1873 * Compare two neighbor hash structures.
1875 static bool neigh_cmp(const void *p1
, const void *p2
)
1877 const zebra_neigh_t
*n1
= p1
;
1878 const zebra_neigh_t
*n2
= p2
;
1880 if (n1
== NULL
&& n2
== NULL
)
1883 if (n1
== NULL
|| n2
== NULL
)
1886 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1889 static int neigh_list_cmp(void *p1
, void *p2
)
1891 const zebra_neigh_t
*n1
= p1
;
1892 const zebra_neigh_t
*n2
= p2
;
1894 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
1898 * Callback to allocate neighbor hash entry.
1900 static void *zvni_neigh_alloc(void *p
)
1902 const zebra_neigh_t
*tmp_n
= p
;
1905 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
1912 * Add neighbor entry.
1914 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
1915 struct ethaddr
*mac
)
1917 zebra_neigh_t tmp_n
;
1918 zebra_neigh_t
*n
= NULL
;
1919 zebra_mac_t
*zmac
= NULL
;
1921 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
1922 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
1923 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
1926 memcpy(&n
->emac
, mac
, ETH_ALEN
);
1927 n
->state
= ZEBRA_NEIGH_INACTIVE
;
1929 /* Associate the neigh to mac */
1930 zmac
= zvni_mac_lookup(zvni
, mac
);
1932 listnode_add_sort(zmac
->neigh_list
, n
);
1938 * Delete neighbor entry.
1940 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
1942 zebra_neigh_t
*tmp_n
;
1943 zebra_mac_t
*zmac
= NULL
;
1945 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
1947 listnode_delete(zmac
->neigh_list
, n
);
1949 /* Free the VNI hash entry and allocated memory. */
1950 tmp_n
= hash_release(zvni
->neigh_table
, n
);
1952 XFREE(MTYPE_NEIGH
, tmp_n
);
1958 * Free neighbor hash entry (callback)
1960 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
1962 struct neigh_walk_ctx
*wctx
= arg
;
1963 zebra_neigh_t
*n
= backet
->data
;
1965 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1966 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
1967 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
1968 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
1969 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
1970 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
1971 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
1972 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
1975 if (wctx
->uninstall
)
1976 zvni_neigh_uninstall(wctx
->zvni
, n
);
1978 zvni_neigh_del(wctx
->zvni
, n
);
1985 * Delete all neighbor entries from specific VTEP for a particular VNI.
1987 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
1988 struct in_addr
*r_vtep_ip
)
1990 struct neigh_walk_ctx wctx
;
1992 if (!zvni
->neigh_table
)
1995 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1997 wctx
.uninstall
= uninstall
;
1998 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
1999 wctx
.r_vtep_ip
= *r_vtep_ip
;
2001 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2005 * Delete all neighbor entries for this VNI.
2007 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2010 struct neigh_walk_ctx wctx
;
2012 if (!zvni
->neigh_table
)
2015 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2017 wctx
.uninstall
= uninstall
;
2018 wctx
.upd_client
= upd_client
;
2021 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2025 * Look up neighbor hash entry.
2027 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2032 memset(&tmp
, 0, sizeof(tmp
));
2033 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2034 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2040 * Process all neighbors associated with a MAC upon the MAC being learnt
2041 * locally or undergoing any other change (such as sequence number).
2043 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2047 zebra_neigh_t
*n
= NULL
;
2048 struct listnode
*node
= NULL
;
2049 struct zebra_vrf
*zvrf
= NULL
;
2050 char buf
[ETHER_ADDR_STRLEN
];
2052 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2054 if (IS_ZEBRA_DEBUG_VXLAN
)
2055 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2056 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2057 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2059 /* Walk all neighbors and mark any inactive local neighbors as
2060 * active and/or update sequence number upon a move, and inform BGP.
2061 * The action for remote neighbors is TBD.
2062 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2063 * accidentally end up deleting a just-learnt local neighbor.
2065 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2066 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2067 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2068 ZEBRA_NEIGH_SET_ACTIVE(n
);
2069 n
->loc_seq
= zmac
->loc_seq
;
2070 if (!(zvrf
->dup_addr_detect
&&
2071 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2072 ZEBRA_NEIGH_DUPLICATE
)))
2073 zvni_neigh_send_add_to_client(
2074 zvni
->vni
, &n
->ip
, &n
->emac
,
2075 n
->flags
, n
->loc_seq
);
2082 * Process all neighbors associated with a local MAC upon the MAC being
2085 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2088 zebra_neigh_t
*n
= NULL
;
2089 struct listnode
*node
= NULL
;
2090 char buf
[ETHER_ADDR_STRLEN
];
2092 if (IS_ZEBRA_DEBUG_VXLAN
)
2093 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2094 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2097 /* Walk all local neighbors and mark as inactive and inform
2099 * TBD: There is currently no handling for remote neighbors. We
2100 * don't expect them to exist, if they do, do we install the MAC
2101 * as a remote MAC and the neighbor as remote?
2103 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2104 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2105 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2106 ZEBRA_NEIGH_SET_INACTIVE(n
);
2108 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2116 * Process all neighbors associated with a MAC upon the MAC being remotely
2119 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2122 zebra_neigh_t
*n
= NULL
;
2123 struct listnode
*node
= NULL
;
2124 char buf
[ETHER_ADDR_STRLEN
];
2126 if (IS_ZEBRA_DEBUG_VXLAN
)
2127 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2128 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2131 /* Walk all local neighbors and mark as inactive and inform
2134 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2135 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2136 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2137 ZEBRA_NEIGH_SET_INACTIVE(n
);
2139 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2147 * Process all neighbors associated with a remote MAC upon the MAC being
2150 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2153 /* NOTE: Currently a NO-OP. */
2157 * Inform BGP about local neighbor addition.
2159 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2160 struct ethaddr
*macaddr
,
2161 uint8_t neigh_flags
,
2166 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2167 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2168 /* Set router flag (R-bit) based on local neigh entry add */
2169 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2170 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2172 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2173 seq
, ZEBRA_MACIP_ADD
);
2177 * Inform BGP about local neighbor deletion.
2179 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2180 struct ethaddr
*macaddr
, uint8_t flags
)
2182 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2183 0, ZEBRA_MACIP_DEL
);
2187 * Install remote neighbor into the kernel.
2189 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2191 struct zebra_if
*zif
;
2192 struct zebra_l2info_vxlan
*vxl
;
2193 struct interface
*vlan_if
;
2199 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2202 zif
= zvni
->vxlan_if
->info
;
2205 vxl
= &zif
->l2info
.vxl
;
2207 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2211 flags
= NTF_EXT_LEARNED
;
2212 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2213 flags
|= NTF_ROUTER
;
2214 ZEBRA_NEIGH_SET_ACTIVE(n
);
2215 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2221 * Uninstall remote neighbor from the kernel.
2223 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2225 struct zebra_if
*zif
;
2226 struct zebra_l2info_vxlan
*vxl
;
2227 struct interface
*vlan_if
;
2229 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2232 if (!zvni
->vxlan_if
) {
2233 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2238 zif
= zvni
->vxlan_if
->info
;
2241 vxl
= &zif
->l2info
.vxl
;
2242 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2246 ZEBRA_NEIGH_SET_INACTIVE(n
);
2248 return kernel_del_neigh(vlan_if
, &n
->ip
);
2252 * Install neighbor hash entry - called upon access VLAN change.
2254 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
2257 struct neigh_walk_ctx
*wctx
= ctxt
;
2259 n
= (zebra_neigh_t
*)backet
->data
;
2261 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2262 zvni_neigh_install(wctx
->zvni
, n
);
2265 /* Get the VRR interface for SVI if any */
2266 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2268 struct zebra_vrf
*zvrf
= NULL
;
2269 struct interface
*tmp_if
= NULL
;
2270 struct zebra_if
*zif
= NULL
;
2272 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2275 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2280 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2283 if (zif
->link
== ifp
)
2290 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2292 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2293 struct connected
*c
= NULL
;
2294 struct ethaddr macaddr
;
2296 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2298 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2301 memset(&ip
, 0, sizeof(struct ipaddr
));
2302 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2305 if (c
->address
->family
== AF_INET
) {
2306 ip
.ipa_type
= IPADDR_V4
;
2307 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2308 sizeof(struct in_addr
));
2309 } else if (c
->address
->family
== AF_INET6
) {
2310 ip
.ipa_type
= IPADDR_V6
;
2311 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2312 sizeof(struct in6_addr
));
2317 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2323 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2325 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2326 struct connected
*c
= NULL
;
2327 struct ethaddr macaddr
;
2329 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2331 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2334 memset(&ip
, 0, sizeof(struct ipaddr
));
2335 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2338 if (c
->address
->family
== AF_INET
) {
2339 ip
.ipa_type
= IPADDR_V4
;
2340 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2341 sizeof(struct in_addr
));
2342 } else if (c
->address
->family
== AF_INET6
) {
2343 ip
.ipa_type
= IPADDR_V6
;
2344 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2345 sizeof(struct in6_addr
));
2350 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2356 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2359 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2360 struct connected
*c
= NULL
;
2361 struct ethaddr macaddr
;
2363 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2365 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2368 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2370 /* skip link local address */
2371 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2376 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2377 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2379 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2380 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2386 * zvni_gw_macip_add_to_client
2388 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2389 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2391 char buf
[ETHER_ADDR_STRLEN
];
2392 char buf2
[INET6_ADDRSTRLEN
];
2393 zebra_neigh_t
*n
= NULL
;
2394 zebra_mac_t
*mac
= NULL
;
2395 struct zebra_if
*zif
= NULL
;
2396 struct zebra_l2info_vxlan
*vxl
= NULL
;
2398 zif
= zvni
->vxlan_if
->info
;
2402 vxl
= &zif
->l2info
.vxl
;
2404 mac
= zvni_mac_lookup(zvni
, macaddr
);
2406 mac
= zvni_mac_add(zvni
, macaddr
);
2408 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2409 "Failed to add MAC %s intf %s(%u) VID %u",
2410 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2411 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2416 /* Set "local" forwarding info. */
2417 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2418 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2419 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2420 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2421 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2422 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2424 n
= zvni_neigh_lookup(zvni
, ip
);
2426 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2429 EC_ZEBRA_MAC_ADD_FAILED
,
2430 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2431 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2432 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2433 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2438 /* Set "local" forwarding info. */
2439 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2440 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2441 ZEBRA_NEIGH_SET_ACTIVE(n
);
2442 /* Set Router flag (R-bit) */
2443 if (ip
->ipa_type
== IPADDR_V6
)
2444 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2445 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2446 n
->ifindex
= ifp
->ifindex
;
2448 /* Only advertise in BGP if the knob is enabled */
2449 if (!advertise_gw_macip_enabled(zvni
))
2452 if (IS_ZEBRA_DEBUG_VXLAN
)
2454 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2455 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2456 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2457 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2459 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2460 n
->flags
, n
->loc_seq
);
2466 * zvni_gw_macip_del_from_client
2468 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2471 char buf1
[ETHER_ADDR_STRLEN
];
2472 char buf2
[INET6_ADDRSTRLEN
];
2473 zebra_neigh_t
*n
= NULL
;
2474 zebra_mac_t
*mac
= NULL
;
2476 /* If the neigh entry is not present nothing to do*/
2477 n
= zvni_neigh_lookup(zvni
, ip
);
2481 /* mac entry should be present */
2482 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2484 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2485 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2486 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2490 /* If the entry is not local nothing to do*/
2491 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2494 /* only need to delete the entry from bgp if we sent it before */
2495 if (IS_ZEBRA_DEBUG_VXLAN
)
2497 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2498 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2499 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2500 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2502 /* Remove neighbor from BGP. */
2503 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2504 ZEBRA_MACIP_TYPE_GW
);
2506 /* Delete this neighbor entry. */
2507 zvni_neigh_del(zvni
, n
);
2509 /* see if the mac needs to be deleted as well*/
2511 zvni_deref_ip2mac(zvni
, mac
);
2516 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
2519 zebra_vni_t
*zvni
= NULL
;
2520 struct zebra_if
*zif
= NULL
;
2521 struct zebra_l2info_vxlan zl2_info
;
2522 struct interface
*vlan_if
= NULL
;
2523 struct interface
*vrr_if
= NULL
;
2524 struct interface
*ifp
;
2526 /* Add primary SVI MAC*/
2527 zvni
= (zebra_vni_t
*)backet
->data
;
2529 ifp
= zvni
->vxlan_if
;
2534 /* If down or not mapped to a bridge, we're done. */
2535 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2538 zl2_info
= zif
->l2info
.vxl
;
2541 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2545 /* Del primary MAC-IP */
2546 zvni_del_macip_for_intf(vlan_if
, zvni
);
2548 /* Del VRR MAC-IP - if any*/
2549 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2551 zvni_del_macip_for_intf(vrr_if
, zvni
);
2556 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2559 zebra_vni_t
*zvni
= NULL
;
2560 struct zebra_if
*zif
= NULL
;
2561 struct zebra_l2info_vxlan zl2_info
;
2562 struct interface
*vlan_if
= NULL
;
2563 struct interface
*vrr_if
= NULL
;
2564 struct interface
*ifp
= NULL
;
2566 zvni
= (zebra_vni_t
*)backet
->data
;
2568 ifp
= zvni
->vxlan_if
;
2573 /* If down or not mapped to a bridge, we're done. */
2574 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2576 zl2_info
= zif
->l2info
.vxl
;
2579 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2583 /* Add primary SVI MAC-IP */
2584 zvni_add_macip_for_intf(vlan_if
, zvni
);
2586 /* Add VRR MAC-IP - if any*/
2587 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2589 zvni_add_macip_for_intf(vrr_if
, zvni
);
2594 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2595 struct interface
*ifp
,
2597 struct ethaddr
*macaddr
,
2600 char buf
[ETHER_ADDR_STRLEN
];
2601 char buf2
[INET6_ADDRSTRLEN
];
2602 struct zebra_vrf
*zvrf
;
2603 zebra_neigh_t
*n
= NULL
;
2604 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2605 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2606 bool upd_mac_seq
= false;
2607 bool neigh_mac_change
= false;
2608 bool neigh_on_hold
= false;
2609 bool neigh_was_remote
= false;
2610 bool do_dad
= false;
2611 struct in_addr vtep_ip
= {.s_addr
= 0};
2613 /* Check if the MAC exists. */
2614 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2616 /* create a dummy MAC if the MAC is not already present */
2617 if (IS_ZEBRA_DEBUG_VXLAN
)
2619 "AUTO MAC %s created for neigh %s on VNI %u",
2620 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2621 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2623 zmac
= zvni_mac_add(zvni
, macaddr
);
2625 zlog_debug("Failed to add MAC %s VNI %u",
2626 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2631 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2632 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2633 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2635 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2637 * We don't change the MAC to local upon a neighbor
2638 * learn event, we wait for the explicit local MAC
2639 * learn. However, we have to compute its sequence
2640 * number in preparation for when it actually turns
2647 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2651 /* Check if the neighbor exists. */
2652 n
= zvni_neigh_lookup(zvni
, ip
);
2654 /* New neighbor - create */
2655 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2658 EC_ZEBRA_MAC_ADD_FAILED
,
2659 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2660 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2661 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2662 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2665 /* Set "local" forwarding info. */
2666 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2667 n
->ifindex
= ifp
->ifindex
;
2669 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2673 /* Note any changes and see if of interest to BGP. */
2674 mac_different
= (memcmp(n
->emac
.octet
,
2675 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2676 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2677 ZEBRA_NEIGH_ROUTER_FLAG
);
2678 if (!mac_different
&& is_router
== cur_is_router
) {
2679 n
->ifindex
= ifp
->ifindex
;
2683 if (!mac_different
) {
2684 bool is_neigh_freezed
= false;
2686 /* Only the router flag has changed. */
2689 ZEBRA_NEIGH_ROUTER_FLAG
);
2691 UNSET_FLAG(n
->flags
,
2692 ZEBRA_NEIGH_ROUTER_FLAG
);
2694 /* Neigh is in freeze state and freeze action
2695 * is enabled, do not send update to client.
2697 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
2699 CHECK_FLAG(n
->flags
,
2700 ZEBRA_NEIGH_DUPLICATE
));
2702 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
2704 return zvni_neigh_send_add_to_client(
2705 zvni
->vni
, ip
, macaddr
,
2706 n
->flags
, n
->loc_seq
);
2710 /* The MAC has changed, need to issue a delete
2711 * first as this means a different MACIP route.
2712 * Also, need to do some unlinking/relinking.
2713 * We also need to update the MAC's sequence number
2714 * in different situations.
2716 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2717 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2719 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2721 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2723 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2724 neigh_mac_change
= upd_mac_seq
= true;
2725 listnode_delete(old_zmac
->neigh_list
, n
);
2726 zvni_deref_ip2mac(zvni
, old_zmac
);
2729 /* Update the forwarding info. */
2730 n
->ifindex
= ifp
->ifindex
;
2731 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2733 /* Link to new MAC */
2734 listnode_add_sort(zmac
->neigh_list
, n
);
2735 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2737 * Neighbor has moved from remote to local. Its
2738 * MAC could have also changed as part of the move.
2740 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2742 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2744 old_mac_seq
= CHECK_FLAG(
2749 neigh_mac_change
= upd_mac_seq
= true;
2750 listnode_delete(old_zmac
->neigh_list
,
2752 zvni_deref_ip2mac(zvni
, old_zmac
);
2755 /* Link to new MAC */
2756 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2757 listnode_add_sort(zmac
->neigh_list
, n
);
2759 /* Based on Mobility event Scenario-B from the
2760 * draft, neigh's previous state was remote treat this
2763 neigh_was_remote
= true;
2764 vtep_ip
= n
->r_vtep_ip
;
2765 /* Mark appropriately */
2766 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2767 n
->r_vtep_ip
.s_addr
= 0;
2768 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2769 n
->ifindex
= ifp
->ifindex
;
2773 /* If MAC was previously remote, or the neighbor had a different
2774 * MAC earlier, recompute the sequence number.
2777 uint32_t seq1
, seq2
;
2779 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
2780 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
2781 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
2782 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
2783 MAX(seq1
, seq2
) : zmac
->loc_seq
;
2786 /* Mark Router flag (R-bit) */
2788 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2790 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2792 /* Check old and/or new MAC detected as duplicate mark
2793 * the neigh as duplicate
2795 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
2796 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
2797 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
2799 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2800 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
2803 /* For IP Duplicate Address Detection (DAD) is trigger,
2804 * when the event is extended mobility based on scenario-B
2805 * from the draft, IP/Neigh's MAC binding changed and
2806 * neigh's previous state was remote.
2808 if (neigh_mac_change
&& neigh_was_remote
)
2811 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
2812 &neigh_on_hold
, true);
2814 /* Before we program this in BGP, we need to check if MAC is locally
2815 * learnt. If not, force neighbor to be inactive and reset its seq.
2817 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2818 ZEBRA_NEIGH_SET_INACTIVE(n
);
2820 zmac
->loc_seq
= mac_new_seq
;
2824 /* If the MAC's sequence number has changed, inform the MAC and all
2825 * neighbors associated with the MAC to BGP, else just inform this
2828 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
2829 if (IS_ZEBRA_DEBUG_VXLAN
)
2830 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
2831 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2832 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
2833 zmac
->loc_seq
= mac_new_seq
;
2834 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
2835 zmac
->flags
, zmac
->loc_seq
))
2837 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
2841 ZEBRA_NEIGH_SET_ACTIVE(n
);
2842 n
->loc_seq
= zmac
->loc_seq
;
2845 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2846 n
->flags
, n
->loc_seq
);
2850 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2851 struct interface
*ifp
,
2853 struct ethaddr
*macaddr
,
2856 char buf
[ETHER_ADDR_STRLEN
];
2857 char buf2
[INET6_ADDRSTRLEN
];
2858 zebra_neigh_t
*n
= NULL
;
2859 zebra_mac_t
*zmac
= NULL
;
2861 /* If the neighbor is unknown, there is no further action. */
2862 n
= zvni_neigh_lookup(zvni
, ip
);
2866 /* If a remote entry, see if it needs to be refreshed */
2867 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2869 if (state
& NUD_STALE
)
2870 zvni_neigh_install(zvni
, n
);
2873 /* We got a "remote" neighbor notification for an entry
2874 * we think is local. This can happen in a multihoming
2875 * scenario - but only if the MAC is already "remote".
2876 * Just mark our entry as "remote".
2878 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2879 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2881 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2882 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2883 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2888 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2889 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2890 ZEBRA_NEIGH_SET_ACTIVE(n
);
2891 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2898 * Make hash key for MAC.
2900 static unsigned int mac_hash_keymake(void *p
)
2902 zebra_mac_t
*pmac
= p
;
2903 const void *pnt
= (void *)pmac
->macaddr
.octet
;
2905 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
2909 * Compare two MAC addresses.
2911 static bool mac_cmp(const void *p1
, const void *p2
)
2913 const zebra_mac_t
*pmac1
= p1
;
2914 const zebra_mac_t
*pmac2
= p2
;
2916 if (pmac1
== NULL
&& pmac2
== NULL
)
2919 if (pmac1
== NULL
|| pmac2
== NULL
)
2922 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
2927 * Callback to allocate MAC hash entry.
2929 static void *zvni_mac_alloc(void *p
)
2931 const zebra_mac_t
*tmp_mac
= p
;
2934 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
2937 return ((void *)mac
);
2943 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
2945 zebra_mac_t tmp_mac
;
2946 zebra_mac_t
*mac
= NULL
;
2948 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
2949 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
2950 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
2953 mac
->neigh_list
= list_new();
2954 mac
->neigh_list
->cmp
= neigh_list_cmp
;
2962 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
2964 zebra_mac_t
*tmp_mac
;
2966 list_delete(&mac
->neigh_list
);
2968 /* Free the VNI hash entry and allocated memory. */
2969 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
2971 XFREE(MTYPE_MAC
, tmp_mac
);
2977 * Free MAC hash entry (callback)
2979 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2981 struct mac_walk_ctx
*wctx
= arg
;
2982 zebra_mac_t
*mac
= backet
->data
;
2984 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
2985 || ((wctx
->flags
& DEL_REMOTE_MAC
)
2986 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
2987 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
2988 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
2989 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
2990 &wctx
->r_vtep_ip
))) {
2991 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
2992 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
2996 if (wctx
->uninstall
)
2997 zvni_mac_uninstall(wctx
->zvni
, mac
);
2999 zvni_mac_del(wctx
->zvni
, mac
);
3006 * Delete all MAC entries from specific VTEP for a particular VNI.
3008 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3009 struct in_addr
*r_vtep_ip
)
3011 struct mac_walk_ctx wctx
;
3013 if (!zvni
->mac_table
)
3016 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3018 wctx
.uninstall
= uninstall
;
3019 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3020 wctx
.r_vtep_ip
= *r_vtep_ip
;
3022 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3026 * Delete all MAC entries for this VNI.
3028 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3031 struct mac_walk_ctx wctx
;
3033 if (!zvni
->mac_table
)
3036 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3038 wctx
.uninstall
= uninstall
;
3039 wctx
.upd_client
= upd_client
;
3042 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3046 * Look up MAC hash entry.
3048 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3053 memset(&tmp
, 0, sizeof(tmp
));
3054 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3055 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3061 * Inform BGP about local MAC addition.
3063 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3064 uint8_t mac_flags
, uint32_t seq
)
3068 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3069 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3070 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3071 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3073 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3074 seq
, ZEBRA_MACIP_ADD
);
3078 * Inform BGP about local MAC deletion.
3080 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3082 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3083 0 /* seq */, ZEBRA_MACIP_DEL
);
3087 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3088 * notifications, to see if they are of interest.
3090 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3091 struct interface
*br_if
, vlanid_t vid
)
3093 struct zebra_ns
*zns
;
3094 struct route_node
*rn
;
3095 struct interface
*tmp_if
= NULL
;
3096 struct zebra_if
*zif
;
3097 struct zebra_l2info_bridge
*br
;
3098 struct zebra_l2info_vxlan
*vxl
= NULL
;
3099 uint8_t bridge_vlan_aware
;
3103 /* Determine if bridge is VLAN-aware or not */
3106 br
= &zif
->l2info
.br
;
3107 bridge_vlan_aware
= br
->vlan_aware
;
3109 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3110 /* TODO: Optimize with a hash. */
3111 zns
= zebra_ns_lookup(NS_DEFAULT
);
3112 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3113 tmp_if
= (struct interface
*)rn
->info
;
3117 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3119 if (!if_is_operative(tmp_if
))
3121 vxl
= &zif
->l2info
.vxl
;
3123 if (zif
->brslave_info
.br_if
!= br_if
)
3126 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3135 zvni
= zvni_lookup(vxl
->vni
);
3140 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3141 * neighbor notifications, to see if they are of interest.
3143 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3144 struct interface
*br_if
)
3146 struct zebra_ns
*zns
;
3147 struct route_node
*rn
;
3148 struct interface
*tmp_if
= NULL
;
3149 struct zebra_if
*zif
;
3150 struct zebra_l2info_bridge
*br
;
3151 struct zebra_l2info_vxlan
*vxl
= NULL
;
3152 uint8_t bridge_vlan_aware
;
3160 /* Make sure the linked interface is a bridge. */
3161 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3164 /* Determine if bridge is VLAN-aware or not */
3167 br
= &zif
->l2info
.br
;
3168 bridge_vlan_aware
= br
->vlan_aware
;
3169 if (bridge_vlan_aware
) {
3170 struct zebra_l2info_vlan
*vl
;
3172 if (!IS_ZEBRA_IF_VLAN(ifp
))
3177 vl
= &zif
->l2info
.vl
;
3181 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3182 /* TODO: Optimize with a hash. */
3183 zns
= zebra_ns_lookup(NS_DEFAULT
);
3184 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3185 tmp_if
= (struct interface
*)rn
->info
;
3189 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3191 if (!if_is_operative(tmp_if
))
3193 vxl
= &zif
->l2info
.vxl
;
3195 if (zif
->brslave_info
.br_if
!= br_if
)
3198 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3207 zvni
= zvni_lookup(vxl
->vni
);
3211 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3213 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3214 * linked to the bridge
3215 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3218 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3220 struct zebra_ns
*zns
;
3221 struct route_node
*rn
;
3222 struct interface
*tmp_if
= NULL
;
3223 struct zebra_if
*zif
;
3224 struct zebra_l2info_bridge
*br
;
3225 struct zebra_l2info_vlan
*vl
;
3226 uint8_t bridge_vlan_aware
;
3229 /* Defensive check, caller expected to invoke only with valid bridge. */
3233 /* Determine if bridge is VLAN-aware or not */
3236 br
= &zif
->l2info
.br
;
3237 bridge_vlan_aware
= br
->vlan_aware
;
3239 /* Check oper status of the SVI. */
3240 if (!bridge_vlan_aware
)
3241 return if_is_operative(br_if
) ? br_if
: NULL
;
3243 /* Identify corresponding VLAN interface. */
3244 /* TODO: Optimize with a hash. */
3245 zns
= zebra_ns_lookup(NS_DEFAULT
);
3246 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3247 tmp_if
= (struct interface
*)rn
->info
;
3248 /* Check oper status of the SVI. */
3249 if (!tmp_if
|| !if_is_operative(tmp_if
))
3252 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3253 || zif
->link
!= br_if
)
3255 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3257 if (vl
->vid
== vid
) {
3263 return found
? tmp_if
: NULL
;
3267 * Install remote MAC into the kernel.
3269 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3271 struct zebra_if
*zif
;
3272 struct zebra_l2info_vxlan
*vxl
;
3275 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3278 zif
= zvni
->vxlan_if
->info
;
3281 vxl
= &zif
->l2info
.vxl
;
3283 sticky
= !!CHECK_FLAG(mac
->flags
,
3284 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3286 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3287 mac
->fwd_info
.r_vtep_ip
, sticky
);
3291 * Uninstall remote MAC from the kernel.
3293 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3295 struct zebra_if
*zif
;
3296 struct zebra_l2info_vxlan
*vxl
;
3297 struct in_addr vtep_ip
;
3298 struct interface
*ifp
;
3300 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3303 if (!zvni
->vxlan_if
) {
3304 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3309 zif
= zvni
->vxlan_if
->info
;
3312 vxl
= &zif
->l2info
.vxl
;
3314 ifp
= zvni
->vxlan_if
;
3315 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3317 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3321 * Install MAC hash entry - called upon access VLAN change.
3323 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
3326 struct mac_walk_ctx
*wctx
= ctxt
;
3328 mac
= (zebra_mac_t
*)backet
->data
;
3330 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3331 zvni_mac_install(wctx
->zvni
, mac
);
3335 * Count of remote neighbors referencing this MAC.
3337 static int remote_neigh_count(zebra_mac_t
*zmac
)
3339 zebra_neigh_t
*n
= NULL
;
3340 struct listnode
*node
= NULL
;
3343 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3344 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3352 * Decrement neighbor refcount of MAC; uninstall and free it if
3355 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3357 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3360 /* If all remote neighbors referencing a remote MAC go away,
3361 * we need to uninstall the MAC.
3363 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3364 remote_neigh_count(mac
) == 0) {
3365 zvni_mac_uninstall(zvni
, mac
);
3366 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3369 /* If no neighbors, delete the MAC. */
3370 if (list_isempty(mac
->neigh_list
))
3371 zvni_mac_del(zvni
, mac
);
3375 * Read and populate local MACs and neighbors corresponding to this VNI.
3377 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3379 struct zebra_ns
*zns
;
3380 struct zebra_if
*zif
;
3381 struct interface
*vlan_if
;
3382 struct zebra_l2info_vxlan
*vxl
;
3383 struct interface
*vrr_if
;
3386 vxl
= &zif
->l2info
.vxl
;
3387 zns
= zebra_ns_lookup(NS_DEFAULT
);
3389 if (IS_ZEBRA_DEBUG_VXLAN
)
3391 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3392 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3393 zif
->brslave_info
.bridge_ifindex
);
3395 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3396 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3399 /* Add SVI MAC-IP */
3400 zvni_add_macip_for_intf(vlan_if
, zvni
);
3402 /* Add VRR MAC-IP - if any*/
3403 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3405 zvni_add_macip_for_intf(vrr_if
, zvni
);
3407 neigh_read_for_vlan(zns
, vlan_if
);
3412 * Hash function for VNI.
3414 static unsigned int vni_hash_keymake(void *p
)
3416 const zebra_vni_t
*zvni
= p
;
3418 return (jhash_1word(zvni
->vni
, 0));
3422 * Compare 2 VNI hash entries.
3424 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3426 const zebra_vni_t
*zvni1
= p1
;
3427 const zebra_vni_t
*zvni2
= p2
;
3429 return (zvni1
->vni
== zvni2
->vni
);
3432 static int vni_list_cmp(void *p1
, void *p2
)
3434 const zebra_vni_t
*zvni1
= p1
;
3435 const zebra_vni_t
*zvni2
= p2
;
3437 if (zvni1
->vni
== zvni2
->vni
)
3439 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3443 * Callback to allocate VNI hash entry.
3445 static void *zvni_alloc(void *p
)
3447 const zebra_vni_t
*tmp_vni
= p
;
3450 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3451 zvni
->vni
= tmp_vni
->vni
;
3452 return ((void *)zvni
);
3456 * Look up VNI hash entry.
3458 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3460 struct zebra_vrf
*zvrf
;
3461 zebra_vni_t tmp_vni
;
3462 zebra_vni_t
*zvni
= NULL
;
3464 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3466 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3468 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3474 * Add VNI hash entry.
3476 static zebra_vni_t
*zvni_add(vni_t vni
)
3478 struct zebra_vrf
*zvrf
;
3479 zebra_vni_t tmp_zvni
;
3480 zebra_vni_t
*zvni
= NULL
;
3482 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3484 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3486 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3489 /* Create hash table for MAC */
3491 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3493 /* Create hash table for neighbors */
3494 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3495 "Zebra VNI Neighbor Table");
3501 * Delete VNI hash entry.
3503 static int zvni_del(zebra_vni_t
*zvni
)
3505 struct zebra_vrf
*zvrf
;
3506 zebra_vni_t
*tmp_zvni
;
3508 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3511 zvni
->vxlan_if
= NULL
;
3513 /* Free the neighbor hash table. */
3514 hash_free(zvni
->neigh_table
);
3515 zvni
->neigh_table
= NULL
;
3517 /* Free the MAC hash table. */
3518 hash_free(zvni
->mac_table
);
3519 zvni
->mac_table
= NULL
;
3521 /* Free the VNI hash entry and allocated memory. */
3522 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3524 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3530 * Inform BGP about local VNI addition.
3532 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3534 struct zserv
*client
;
3537 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3538 /* BGP may not be running. */
3542 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3544 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3545 stream_putl(s
, zvni
->vni
);
3546 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3547 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3549 /* Write packet size. */
3550 stream_putw_at(s
, 0, stream_get_endp(s
));
3552 if (IS_ZEBRA_DEBUG_VXLAN
)
3553 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3554 inet_ntoa(zvni
->local_vtep_ip
),
3555 vrf_id_to_name(zvni
->vrf_id
),
3556 zebra_route_string(client
->proto
));
3558 client
->vniadd_cnt
++;
3559 return zserv_send_message(client
, s
);
3563 * Inform BGP about local VNI deletion.
3565 static int zvni_send_del_to_client(vni_t vni
)
3567 struct zserv
*client
;
3570 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3571 /* BGP may not be running. */
3575 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3578 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3579 stream_putl(s
, vni
);
3581 /* Write packet size. */
3582 stream_putw_at(s
, 0, stream_get_endp(s
));
3584 if (IS_ZEBRA_DEBUG_VXLAN
)
3585 zlog_debug("Send VNI_DEL %u to %s", vni
,
3586 zebra_route_string(client
->proto
));
3588 client
->vnidel_cnt
++;
3589 return zserv_send_message(client
, s
);
3593 * Build the VNI hash table by going over the VxLAN interfaces. This
3594 * is called when EVPN (advertise-all-vni) is enabled.
3596 static void zvni_build_hash_table()
3598 struct zebra_ns
*zns
;
3599 struct route_node
*rn
;
3600 struct interface
*ifp
;
3602 /* Walk VxLAN interfaces and create VNI hash. */
3603 zns
= zebra_ns_lookup(NS_DEFAULT
);
3604 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3606 zebra_vni_t
*zvni
= NULL
;
3607 zebra_l3vni_t
*zl3vni
= NULL
;
3608 struct zebra_if
*zif
;
3609 struct zebra_l2info_vxlan
*vxl
;
3611 ifp
= (struct interface
*)rn
->info
;
3615 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3618 vxl
= &zif
->l2info
.vxl
;
3621 /* L3-VNI and L2-VNI are handled seperately */
3622 zl3vni
= zl3vni_lookup(vni
);
3625 if (IS_ZEBRA_DEBUG_VXLAN
)
3627 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3628 ifp
->name
, ifp
->ifindex
, vni
);
3630 /* associate with vxlan_if */
3631 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3632 zl3vni
->vxlan_if
= ifp
;
3635 * we need to associate with SVI.
3636 * we can associate with svi-if only after association
3637 * with vxlan-intf is complete
3639 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3641 if (is_l3vni_oper_up(zl3vni
))
3642 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3645 struct interface
*vlan_if
= NULL
;
3647 if (IS_ZEBRA_DEBUG_VXLAN
)
3649 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3650 ifp
->name
, ifp
->ifindex
, vni
,
3651 inet_ntoa(vxl
->vtep_ip
));
3653 /* VNI hash entry is not expected to exist. */
3654 zvni
= zvni_lookup(vni
);
3657 "VNI hash already present for IF %s(%u) L2-VNI %u",
3658 ifp
->name
, ifp
->ifindex
, vni
);
3662 zvni
= zvni_add(vni
);
3665 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3666 ifp
->name
, ifp
->ifindex
, vni
);
3670 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3671 zvni
->vxlan_if
= ifp
;
3672 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3673 zif
->brslave_info
.br_if
);
3675 zvni
->vrf_id
= vlan_if
->vrf_id
;
3676 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3678 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3682 /* Inform BGP if intf is up and mapped to bridge. */
3683 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3684 zvni_send_add_to_client(zvni
);
3690 * See if remote VTEP matches with prefix.
3692 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3694 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3698 * Locate remote VTEP in VNI hash table.
3700 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3702 zebra_vtep_t
*zvtep
;
3707 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3708 if (zvni_vtep_match(vtep_ip
, zvtep
))
3716 * Add remote VTEP to VNI hash table.
3718 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3720 zebra_vtep_t
*zvtep
;
3722 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3724 zvtep
->vtep_ip
= *vtep_ip
;
3727 zvni
->vteps
->prev
= zvtep
;
3728 zvtep
->next
= zvni
->vteps
;
3729 zvni
->vteps
= zvtep
;
3735 * Remove remote VTEP from VNI hash table.
3737 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3740 zvtep
->next
->prev
= zvtep
->prev
;
3742 zvtep
->prev
->next
= zvtep
->next
;
3744 zvni
->vteps
= zvtep
->next
;
3746 zvtep
->prev
= zvtep
->next
= NULL
;
3747 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3753 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3754 * uninstall from kernel if asked to.
3756 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3758 zebra_vtep_t
*zvtep
, *zvtep_next
;
3763 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3764 zvtep_next
= zvtep
->next
;
3766 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3767 zvni_vtep_del(zvni
, zvtep
);
3774 * Install remote VTEP into the kernel.
3776 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3778 if (is_vxlan_flooding_head_end())
3779 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3784 * Uninstall remote VTEP from the kernel.
3786 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3788 if (!zvni
->vxlan_if
) {
3789 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3794 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3798 * Install or uninstall flood entries in the kernel corresponding to
3799 * remote VTEPs. This is invoked upon change to BUM handling.
3801 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
3805 zebra_vtep_t
*zvtep
;
3807 zvni
= (zebra_vni_t
*)backet
->data
;
3811 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3812 if (is_vxlan_flooding_head_end())
3813 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
3815 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3820 * Cleanup VNI/VTEP and update kernel
3822 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3824 zebra_vni_t
*zvni
= NULL
;
3825 zebra_l3vni_t
*zl3vni
= NULL
;
3826 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3828 zvni
= (zebra_vni_t
*)backet
->data
;
3830 /* remove from l3-vni list */
3832 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3834 listnode_delete(zl3vni
->l2vnis
, zvni
);
3836 /* Free up all neighbors and MACs, if any. */
3837 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3838 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3840 /* Free up all remote VTEPs, if any. */
3841 zvni_vtep_del_all(zvni
, 1);
3843 /* Delete the hash entry. */
3848 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3850 zebra_l3vni_t
*zl3vni
= NULL
;
3852 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3854 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3857 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3858 struct prefix
*host
)
3860 struct host_rb_entry lookup
;
3861 struct host_rb_entry
*hle
;
3863 memset(&lookup
, 0, sizeof(lookup
));
3864 memcpy(&lookup
.p
, host
, sizeof(*host
));
3866 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3870 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3871 memcpy(hle
, &lookup
, sizeof(lookup
));
3873 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3876 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3878 struct host_rb_entry lookup
;
3879 struct host_rb_entry
*hle
;
3881 memset(&lookup
, 0, sizeof(lookup
));
3882 memcpy(&lookup
.p
, host
, sizeof(*host
));
3884 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3886 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3887 XFREE(MTYPE_HOST_PREFIX
, hle
);
3894 * Look up MAC hash entry.
3896 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3897 struct ethaddr
*rmac
)
3902 memset(&tmp
, 0, sizeof(tmp
));
3903 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
3904 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
3910 * Callback to allocate RMAC hash entry.
3912 static void *zl3vni_rmac_alloc(void *p
)
3914 const zebra_mac_t
*tmp_rmac
= p
;
3917 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3920 return ((void *)zrmac
);
3924 * Add RMAC entry to l3-vni
3926 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
3928 zebra_mac_t tmp_rmac
;
3929 zebra_mac_t
*zrmac
= NULL
;
3931 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
3932 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
3933 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
3936 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
3938 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
3939 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
3947 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3949 zebra_mac_t
*tmp_rmac
;
3950 struct host_rb_entry
*hle
;
3952 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
3953 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
3955 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
3956 XFREE(MTYPE_HOST_PREFIX
, hle
);
3959 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
3961 XFREE(MTYPE_MAC
, tmp_rmac
);
3967 * Install remote RMAC into the kernel.
3969 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3971 struct zebra_if
*zif
= NULL
;
3972 struct zebra_l2info_vxlan
*vxl
= NULL
;
3974 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3975 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
3978 zif
= zl3vni
->vxlan_if
->info
;
3982 vxl
= &zif
->l2info
.vxl
;
3984 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
3985 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
3989 * Uninstall remote RMAC from the kernel.
3991 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
3993 char buf
[ETHER_ADDR_STRLEN
];
3994 struct zebra_if
*zif
= NULL
;
3995 struct zebra_l2info_vxlan
*vxl
= NULL
;
3997 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
3998 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4001 if (!zl3vni
->vxlan_if
) {
4003 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4004 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4005 zl3vni
->vni
, zl3vni
);
4009 zif
= zl3vni
->vxlan_if
->info
;
4013 vxl
= &zif
->l2info
.vxl
;
4015 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4016 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4019 /* handle rmac add */
4020 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4021 struct ipaddr
*vtep_ip
,
4022 struct prefix
*host_prefix
)
4024 char buf
[ETHER_ADDR_STRLEN
];
4025 char buf1
[INET6_ADDRSTRLEN
];
4026 zebra_mac_t
*zrmac
= NULL
;
4028 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4031 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4034 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4035 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4037 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4040 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4041 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4043 /* install rmac in kernel */
4044 zl3vni_rmac_install(zl3vni
, zrmac
);
4047 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4053 /* handle rmac delete */
4054 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4055 struct prefix
*host_prefix
)
4057 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4059 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4060 /* uninstall from kernel */
4061 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4063 /* del the rmac entry */
4064 zl3vni_rmac_del(zl3vni
, zrmac
);
4069 * Look up nh hash entry on a l3-vni.
4071 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4076 memset(&tmp
, 0, sizeof(tmp
));
4077 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4078 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4085 * Callback to allocate NH hash entry on L3-VNI.
4087 static void *zl3vni_nh_alloc(void *p
)
4089 const zebra_neigh_t
*tmp_n
= p
;
4092 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4099 * Add neighbor entry.
4101 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4102 struct ethaddr
*mac
)
4104 zebra_neigh_t tmp_n
;
4105 zebra_neigh_t
*n
= NULL
;
4107 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4108 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4109 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4112 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4114 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4115 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4116 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4122 * Delete neighbor entry.
4124 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4126 zebra_neigh_t
*tmp_n
;
4127 struct host_rb_entry
*hle
;
4129 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4130 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4132 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4133 XFREE(MTYPE_HOST_PREFIX
, hle
);
4136 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4138 XFREE(MTYPE_NEIGH
, tmp_n
);
4144 * Install remote nh as neigh into the kernel.
4146 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4153 if (!is_l3vni_oper_up(zl3vni
))
4156 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4157 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4160 flags
= NTF_EXT_LEARNED
;
4161 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4162 flags
|= NTF_ROUTER
;
4163 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4169 * Uninstall remote nh from the kernel.
4171 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4173 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4174 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4177 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4180 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4183 /* add remote vtep as a neigh entry */
4184 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4185 struct ethaddr
*rmac
,
4186 struct prefix
*host_prefix
)
4188 char buf
[ETHER_ADDR_STRLEN
];
4189 char buf1
[INET6_ADDRSTRLEN
];
4190 zebra_neigh_t
*nh
= NULL
;
4192 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4194 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4198 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4199 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4200 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4205 /* install the nh neigh in kernel */
4206 zl3vni_nh_install(zl3vni
, nh
);
4209 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4214 /* handle nh neigh delete */
4215 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4216 struct prefix
*host_prefix
)
4218 rb_delete_host(&nh
->host_rb
, host_prefix
);
4220 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4221 /* uninstall from kernel */
4222 zl3vni_nh_uninstall(zl3vni
, nh
);
4224 /* delete the nh entry */
4225 zl3vni_nh_del(zl3vni
, nh
);
4229 /* handle neigh update from kernel - the only thing of interest is to
4230 * readd stale entries.
4232 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4236 zebra_neigh_t
*n
= NULL
;
4238 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4242 /* all next hop neigh are remote and installed by frr.
4243 * If the kernel has aged this entry, re-install.
4245 if (state
& NUD_STALE
)
4246 zl3vni_nh_install(zl3vni
, n
);
4251 /* handle neigh delete from kernel */
4252 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4254 zebra_neigh_t
*n
= NULL
;
4256 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4260 /* all next hop neigh are remote and installed by frr.
4261 * If we get an age out notification for these neigh entries, we have to
4264 zl3vni_nh_install(zl3vni
, n
);
4270 * Hash function for L3 VNI.
4272 static unsigned int l3vni_hash_keymake(void *p
)
4274 const zebra_l3vni_t
*zl3vni
= p
;
4276 return jhash_1word(zl3vni
->vni
, 0);
4280 * Compare 2 L3 VNI hash entries.
4282 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4284 const zebra_l3vni_t
*zl3vni1
= p1
;
4285 const zebra_l3vni_t
*zl3vni2
= p2
;
4287 return (zl3vni1
->vni
== zl3vni2
->vni
);
4291 * Callback to allocate L3 VNI hash entry.
4293 static void *zl3vni_alloc(void *p
)
4295 zebra_l3vni_t
*zl3vni
= NULL
;
4296 const zebra_l3vni_t
*tmp_l3vni
= p
;
4298 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4299 zl3vni
->vni
= tmp_l3vni
->vni
;
4300 return ((void *)zl3vni
);
4304 * Look up L3 VNI hash entry.
4306 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4308 zebra_l3vni_t tmp_l3vni
;
4309 zebra_l3vni_t
*zl3vni
= NULL
;
4311 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4312 tmp_l3vni
.vni
= vni
;
4313 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4319 * Add L3 VNI hash entry.
4321 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4323 zebra_l3vni_t tmp_zl3vni
;
4324 zebra_l3vni_t
*zl3vni
= NULL
;
4326 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4327 tmp_zl3vni
.vni
= vni
;
4329 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4332 zl3vni
->vrf_id
= vrf_id
;
4333 zl3vni
->svi_if
= NULL
;
4334 zl3vni
->vxlan_if
= NULL
;
4335 zl3vni
->l2vnis
= list_new();
4336 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4338 /* Create hash table for remote RMAC */
4339 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4340 "Zebra L3-VNI RMAC-Table");
4342 /* Create hash table for neighbors */
4343 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4344 "Zebra L3-VNI next-hop table");
4350 * Delete L3 VNI hash entry.
4352 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4354 zebra_l3vni_t
*tmp_zl3vni
;
4356 /* free the list of l2vnis */
4357 list_delete(&zl3vni
->l2vnis
);
4358 zl3vni
->l2vnis
= NULL
;
4360 /* Free the rmac table */
4361 hash_free(zl3vni
->rmac_table
);
4362 zl3vni
->rmac_table
= NULL
;
4364 /* Free the nh table */
4365 hash_free(zl3vni
->nh_table
);
4366 zl3vni
->nh_table
= NULL
;
4368 /* Free the VNI hash entry and allocated memory. */
4369 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4371 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4376 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4378 struct zebra_ns
*zns
= NULL
;
4379 struct route_node
*rn
= NULL
;
4380 struct interface
*ifp
= NULL
;
4382 /* loop through all vxlan-interface */
4383 zns
= zebra_ns_lookup(NS_DEFAULT
);
4384 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4386 struct zebra_if
*zif
= NULL
;
4387 struct zebra_l2info_vxlan
*vxl
= NULL
;
4389 ifp
= (struct interface
*)rn
->info
;
4394 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4397 vxl
= &zif
->l2info
.vxl
;
4398 if (vxl
->vni
== zl3vni
->vni
) {
4399 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4407 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4409 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4410 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4415 if (!zl3vni
->vxlan_if
)
4418 zif
= zl3vni
->vxlan_if
->info
;
4422 vxl
= &zif
->l2info
.vxl
;
4424 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4427 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4429 struct zebra_vrf
*zvrf
= NULL
;
4431 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4435 return zl3vni_lookup(zvrf
->l3vni
);
4439 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4440 * neighbor notifications, to see if they are of interest.
4442 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4443 struct interface
*br_if
)
4447 uint8_t bridge_vlan_aware
= 0;
4448 zebra_l3vni_t
*zl3vni
= NULL
;
4449 struct zebra_ns
*zns
= NULL
;
4450 struct route_node
*rn
= NULL
;
4451 struct zebra_if
*zif
= NULL
;
4452 struct interface
*tmp_if
= NULL
;
4453 struct zebra_l2info_bridge
*br
= NULL
;
4454 struct zebra_l2info_vxlan
*vxl
= NULL
;
4459 /* Make sure the linked interface is a bridge. */
4460 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4463 /* Determine if bridge is VLAN-aware or not */
4466 br
= &zif
->l2info
.br
;
4467 bridge_vlan_aware
= br
->vlan_aware
;
4468 if (bridge_vlan_aware
) {
4469 struct zebra_l2info_vlan
*vl
;
4471 if (!IS_ZEBRA_IF_VLAN(ifp
))
4476 vl
= &zif
->l2info
.vl
;
4480 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4481 /* TODO: Optimize with a hash. */
4482 zns
= zebra_ns_lookup(NS_DEFAULT
);
4483 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4484 tmp_if
= (struct interface
*)rn
->info
;
4488 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4490 if (!if_is_operative(tmp_if
))
4492 vxl
= &zif
->l2info
.vxl
;
4494 if (zif
->brslave_info
.br_if
!= br_if
)
4497 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4506 zl3vni
= zl3vni_lookup(vxl
->vni
);
4511 * Inform BGP about l3-vni.
4513 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4515 struct stream
*s
= NULL
;
4516 struct zserv
*client
= NULL
;
4517 struct ethaddr rmac
;
4518 char buf
[ETHER_ADDR_STRLEN
];
4520 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4521 /* BGP may not be running. */
4526 memset(&rmac
, 0, sizeof(struct ethaddr
));
4527 zl3vni_get_rmac(zl3vni
, &rmac
);
4529 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4531 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4532 stream_putl(s
, zl3vni
->vni
);
4533 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4534 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4535 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4537 /* Write packet size. */
4538 stream_putw_at(s
, 0, stream_get_endp(s
));
4540 if (IS_ZEBRA_DEBUG_VXLAN
)
4542 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4543 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4544 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4545 inet_ntoa(zl3vni
->local_vtep_ip
),
4546 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4547 ? "prefix-routes-only"
4549 zebra_route_string(client
->proto
));
4551 client
->l3vniadd_cnt
++;
4552 return zserv_send_message(client
, s
);
4556 * Inform BGP about local l3-VNI deletion.
4558 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4560 struct stream
*s
= NULL
;
4561 struct zserv
*client
= NULL
;
4563 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4564 /* BGP may not be running. */
4568 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4570 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4571 stream_putl(s
, zl3vni
->vni
);
4573 /* Write packet size. */
4574 stream_putw_at(s
, 0, stream_get_endp(s
));
4576 if (IS_ZEBRA_DEBUG_VXLAN
)
4577 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4578 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4579 zebra_route_string(client
->proto
));
4581 client
->l3vnidel_cnt
++;
4582 return zserv_send_message(client
, s
);
4585 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4590 /* send l3vni add to BGP */
4591 zl3vni_send_add_to_client(zl3vni
);
4594 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4599 /* send l3-vni del to BGP*/
4600 zl3vni_send_del_to_client(zl3vni
);
4603 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4605 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4606 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4608 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4609 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4613 * handle transition of vni from l2 to l3 and vice versa
4615 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4618 zebra_vni_t
*zvni
= NULL
;
4620 /* There is a possibility that VNI notification was already received
4621 * from kernel and we programmed it as L2-VNI
4622 * In such a case we need to delete this L2-VNI first, so
4623 * that it can be reprogrammed as L3-VNI in the system. It is also
4624 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4625 * interface is still present in kernel. In this case to keep it
4626 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4629 /* Locate hash entry */
4630 zvni
= zvni_lookup(vni
);
4634 if (IS_ZEBRA_DEBUG_VXLAN
)
4635 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4637 /* Delete VNI from BGP. */
4638 zvni_send_del_to_client(zvni
->vni
);
4640 /* Free up all neighbors and MAC, if any. */
4641 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4642 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4644 /* Free up all remote VTEPs, if any. */
4645 zvni_vtep_del_all(zvni
, 0);
4647 /* Delete the hash entry. */
4648 if (zvni_del(zvni
)) {
4649 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4650 "Failed to del VNI hash %p, VNI %u", zvni
,
4655 /* TODO_MITESH: This needs to be thought through. We don't have
4656 * enough information at this point to reprogram the vni as
4657 * l2-vni. One way is to store the required info in l3-vni and
4658 * used it solely for this purpose
4665 /* delete and uninstall rmac hash entry */
4666 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4668 zebra_mac_t
*zrmac
= NULL
;
4669 zebra_l3vni_t
*zl3vni
= NULL
;
4671 zrmac
= (zebra_mac_t
*)backet
->data
;
4672 zl3vni
= (zebra_l3vni_t
*)ctx
;
4673 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4674 zl3vni_rmac_del(zl3vni
, zrmac
);
4677 /* delete and uninstall nh hash entry */
4678 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4680 zebra_neigh_t
*n
= NULL
;
4681 zebra_l3vni_t
*zl3vni
= NULL
;
4683 n
= (zebra_neigh_t
*)backet
->data
;
4684 zl3vni
= (zebra_l3vni_t
*)ctx
;
4685 zl3vni_nh_uninstall(zl3vni
, n
);
4686 zl3vni_nh_del(zl3vni
, n
);
4689 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4692 struct zserv
*client
= NULL
;
4693 struct stream
*s
= NULL
;
4694 char buf
[PREFIX_STRLEN
];
4696 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4697 /* BGP may not be running. */
4701 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4703 zclient_create_header(s
, cmd
, vrf_id
);
4704 stream_put(s
, p
, sizeof(struct prefix
));
4706 /* Write packet size. */
4707 stream_putw_at(s
, 0, stream_get_endp(s
));
4709 if (IS_ZEBRA_DEBUG_VXLAN
)
4710 zlog_debug("Send ip prefix %s %s on vrf %s",
4711 prefix2str(p
, buf
, sizeof(buf
)),
4712 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4713 vrf_id_to_name(vrf_id
));
4715 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4716 client
->prefixadd_cnt
++;
4718 client
->prefixdel_cnt
++;
4720 return zserv_send_message(client
, s
);
4723 /* re-add remote rmac if needed */
4724 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4725 struct ethaddr
*rmac
)
4727 char buf
[ETHER_ADDR_STRLEN
];
4728 zebra_mac_t
*zrmac
= NULL
;
4730 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4734 if (IS_ZEBRA_DEBUG_VXLAN
)
4735 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4736 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4738 zl3vni_rmac_install(zl3vni
, zrmac
);
4742 /* Process a remote MACIP add from BGP. */
4743 static void process_remote_macip_add(vni_t vni
,
4744 struct ethaddr
*macaddr
,
4746 struct ipaddr
*ipaddr
,
4749 struct in_addr vtep_ip
)
4752 zebra_vtep_t
*zvtep
;
4753 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
4754 zebra_neigh_t
*n
= NULL
;
4755 int update_mac
= 0, update_neigh
= 0;
4756 char buf
[ETHER_ADDR_STRLEN
];
4757 char buf1
[INET6_ADDRSTRLEN
];
4758 struct interface
*ifp
= NULL
;
4759 struct zebra_if
*zif
= NULL
;
4760 struct zebra_vrf
*zvrf
;
4765 bool do_dad
= false;
4766 bool is_dup_detect
= false;
4768 /* Locate VNI hash entry - expected to exist. */
4769 zvni
= zvni_lookup(vni
);
4771 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
4775 ifp
= zvni
->vxlan_if
;
4779 !if_is_operative(ifp
) ||
4781 !zif
->brslave_info
.br_if
) {
4782 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
4787 /* The remote VTEP specified should normally exist, but it is
4788 * possible that when peering comes up, peer may advertise MACIP
4789 * routes before advertising type-3 routes.
4791 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
4793 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
4795 EC_ZEBRA_VTEP_ADD_FAILED
,
4796 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
4801 zvni_vtep_install(zvni
, &vtep_ip
);
4804 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
4805 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
4806 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
4808 mac
= zvni_mac_lookup(zvni
, macaddr
);
4810 /* Ignore if the mac is already present as a gateway mac */
4812 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
4813 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
4814 if (IS_ZEBRA_DEBUG_VXLAN
)
4815 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4817 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4818 ipa_len
? " IP " : "",
4820 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4824 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
4828 /* check if the remote MAC is unknown or has a change.
4829 * If so, that needs to be updated first. Note that client could
4830 * install MAC and MACIP separately or just install the latter.
4833 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
4834 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
4835 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
4836 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
4837 || seq
!= mac
->rem_seq
)
4842 mac
= zvni_mac_add(zvni
, macaddr
);
4845 "Failed to add MAC %s VNI %u Remote VTEP %s",
4846 prefix_mac2str(macaddr
, buf
,
4848 vni
, inet_ntoa(vtep_ip
));
4852 /* Is this MAC created for a MACIP? */
4854 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4856 const char *mac_type
;
4858 /* When host moves but changes its (MAC,IP)
4859 * binding, BGP may install a MACIP entry that
4860 * corresponds to "older" location of the host
4861 * in transient situations (because {IP1,M1}
4862 * is a different route from {IP1,M2}). Check
4863 * the sequence number and ignore this update
4866 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
4867 tmp_seq
= mac
->loc_seq
;
4870 tmp_seq
= mac
->rem_seq
;
4871 mac_type
= "remote";
4873 if (seq
< tmp_seq
) {
4874 if (IS_ZEBRA_DEBUG_VXLAN
)
4875 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
4877 prefix_mac2str(macaddr
,
4879 ipa_len
? " IP " : "",
4882 buf1
, sizeof(buf1
)) : "",
4889 /* Check MAC's curent state is local (this is the case
4890 * where MAC has moved from L->R) and check previous
4891 * detection started via local learning.
4892 * RFC-7432: A PE/VTEP that detects a MAC mobility
4893 * event via local learning starts an M-second timer.
4895 * VTEP-IP or seq. change along is not considered
4896 * for dup. detection.
4898 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) &&
4902 /* Remove local MAC from BGP. */
4903 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
4904 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
4906 /* Set "auto" and "remote" forwarding info. */
4907 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
4908 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
4909 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4910 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
4913 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4915 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
4918 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4920 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
4922 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
4923 mac
->fwd_info
.r_vtep_ip
,
4924 do_dad
, &is_dup_detect
,
4927 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
4929 /* Install the entry. */
4931 zvni_mac_install(zvni
, mac
);
4934 /* Update seq number. */
4937 /* If there is no IP, return after clearing AUTO flag of MAC. */
4939 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4946 /* Check if the remote neighbor itself is unknown or has a
4947 * change. If so, create or update and then install the entry.
4949 n
= zvni_neigh_lookup(zvni
, ipaddr
);
4951 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
4952 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
4953 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
4954 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
4955 || seq
!= n
->rem_seq
)
4960 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
4963 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
4964 ipaddr2str(ipaddr
, buf1
,
4966 prefix_mac2str(macaddr
, buf
,
4968 vni
, inet_ntoa(vtep_ip
));
4975 /* When host moves but changes its (MAC,IP)
4976 * binding, BGP may install a MACIP entry that
4977 * corresponds to "older" location of the host
4978 * in transient situations (because {IP1,M1}
4979 * is a different route from {IP1,M2}). Check
4980 * the sequence number and ignore this update
4983 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
4984 tmp_seq
= n
->loc_seq
;
4987 tmp_seq
= n
->rem_seq
;
4990 if (seq
< tmp_seq
) {
4991 if (IS_ZEBRA_DEBUG_VXLAN
)
4992 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
4994 prefix_mac2str(macaddr
,
4997 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5002 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5003 /* MAC change, send a delete for old
5004 * neigh if learnt locally.
5006 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5007 IS_ZEBRA_NEIGH_ACTIVE(n
))
5008 zvni_neigh_send_del_to_client(
5012 /* update neigh list for macs */
5013 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5015 listnode_delete(old_mac
->neigh_list
, n
);
5016 zvni_deref_ip2mac(zvni
, old_mac
);
5018 listnode_add_sort(mac
->neigh_list
, n
);
5019 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5021 /* Check Neigh's curent state is local
5022 * (this is the case where neigh/host has moved
5023 * from L->R) and check previous detction
5024 * started via local learning.
5026 * RFC-7432: A PE/VTEP that detects a MAC
5027 * mobilit event via local learning starts
5028 * an M-second timer.
5029 * VTEP-IP or seq. change along is not
5030 * considered for dup. detection.
5032 * Mobilty event scenario-B IP-MAC binding
5035 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5042 /* Set "remote" forwarding info. */
5043 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5044 n
->r_vtep_ip
= vtep_ip
;
5045 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5047 /* Set router flag (R-bit) to this Neighbor entry */
5048 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5049 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5051 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5053 /* Check old or new MAC detected as duplicate,
5054 * inherit duplicate flag to this neigh.
5056 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5058 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5059 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5061 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5062 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5065 /* Check duplicate address detection for IP */
5066 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5071 /* Install the entry. */
5073 zvni_neigh_install(zvni
, n
);
5076 /* Update seq number. */
5080 /* Process a remote MACIP delete from BGP. */
5081 static void process_remote_macip_del(vni_t vni
,
5082 struct ethaddr
*macaddr
,
5084 struct ipaddr
*ipaddr
,
5085 struct in_addr vtep_ip
)
5088 zebra_mac_t
*mac
= NULL
;
5089 zebra_neigh_t
*n
= NULL
;
5090 struct interface
*ifp
= NULL
;
5091 struct zebra_if
*zif
= NULL
;
5092 char buf
[ETHER_ADDR_STRLEN
];
5093 char buf1
[INET6_ADDRSTRLEN
];
5095 /* Locate VNI hash entry - expected to exist. */
5096 zvni
= zvni_lookup(vni
);
5098 if (IS_ZEBRA_DEBUG_VXLAN
)
5099 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5103 ifp
= zvni
->vxlan_if
;
5107 !if_is_operative(ifp
) ||
5109 !zif
->brslave_info
.br_if
) {
5110 if (IS_ZEBRA_DEBUG_VXLAN
)
5111 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5116 /* The remote VTEP specified is normally expected to exist, but
5117 * it is possible that the peer may delete the VTEP before deleting
5118 * any MACs referring to the VTEP, in which case the handler (see
5119 * remote_vtep_del) would have already deleted the MACs.
5121 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5124 mac
= zvni_mac_lookup(zvni
, macaddr
);
5126 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5129 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5130 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5131 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5135 /* If the remote mac or neighbor doesn't exist there is nothing
5136 * more to do. Otherwise, uninstall the entry and then remove it.
5141 /* Ignore the delete if this mac is a gateway mac-ip */
5143 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5144 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5146 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5148 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5149 ipa_len
? " IP " : "",
5151 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5155 /* Uninstall remote neighbor or MAC. */
5157 /* When the MAC changes for an IP, it is possible the
5158 * client may update the new MAC before trying to delete the
5159 * "old" neighbor (as these are two different MACIP routes).
5160 * Do the delete only if the MAC matches.
5162 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5163 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5164 zvni_neigh_uninstall(zvni
, n
);
5165 zvni_neigh_del(zvni
, n
);
5166 zvni_deref_ip2mac(zvni
, mac
);
5169 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5170 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5172 * the remote sequence number in the auto mac entry
5173 * needs to be reset to 0 as the mac entry may have
5174 * been removed on all VTEPs (including
5175 * the originating one)
5179 /* If all remote neighbors referencing a remote MAC
5180 * go away, we need to uninstall the MAC.
5182 if (remote_neigh_count(mac
) == 0) {
5183 zvni_mac_uninstall(zvni
, mac
);
5184 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5186 if (list_isempty(mac
->neigh_list
))
5187 zvni_mac_del(zvni
, mac
);
5189 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5195 /* Public functions */
5197 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5199 zebra_l3vni_t
*zl3vni
= NULL
;
5201 zl3vni
= zl3vni_lookup(vni
);
5205 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5208 /* handle evpn route in vrf table */
5209 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5210 struct ipaddr
*vtep_ip
,
5211 struct prefix
*host_prefix
)
5213 zebra_l3vni_t
*zl3vni
= NULL
;
5214 struct ipaddr ipv4_vtep
;
5216 zl3vni
= zl3vni_from_vrf(vrf_id
);
5217 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5221 * add the next hop neighbor -
5222 * neigh to be installed is the ipv6 nexthop neigh
5224 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5227 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5228 * address. Rmac is programmed against the ipv4 vtep because we only
5229 * support ipv4 tunnels in the h/w right now
5231 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5232 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5233 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5234 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5235 &(ipv4_vtep
.ipaddr_v4
));
5237 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5238 sizeof(struct in_addr
));
5241 * add the rmac - remote rmac to be installed is against the ipv4
5244 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5247 /* handle evpn vrf route delete */
5248 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5249 struct ipaddr
*vtep_ip
,
5250 struct prefix
*host_prefix
)
5252 zebra_l3vni_t
*zl3vni
= NULL
;
5253 zebra_neigh_t
*nh
= NULL
;
5254 zebra_mac_t
*zrmac
= NULL
;
5256 zl3vni
= zl3vni_from_vrf(vrf_id
);
5260 /* find the next hop entry and rmac entry */
5261 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5264 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5266 /* delete the next hop entry */
5267 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5269 /* delete the rmac entry */
5271 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5275 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5276 struct ethaddr
*rmac
, bool use_json
)
5278 zebra_l3vni_t
*zl3vni
= NULL
;
5279 zebra_mac_t
*zrmac
= NULL
;
5280 json_object
*json
= NULL
;
5282 if (!is_evpn_enabled()) {
5284 vty_out(vty
, "{}\n");
5289 json
= json_object_new_object();
5291 zl3vni
= zl3vni_lookup(l3vni
);
5294 vty_out(vty
, "{}\n");
5296 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5300 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5303 vty_out(vty
, "{}\n");
5306 "%% Requested RMAC doesn't exist in L3-VNI %u",
5311 zl3vni_print_rmac(zrmac
, vty
, json
);
5314 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5315 json
, JSON_C_TO_STRING_PRETTY
));
5316 json_object_free(json
);
5320 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5322 zebra_l3vni_t
*zl3vni
;
5324 struct rmac_walk_ctx wctx
;
5325 json_object
*json
= NULL
;
5327 if (!is_evpn_enabled())
5330 zl3vni
= zl3vni_lookup(l3vni
);
5333 vty_out(vty
, "{}\n");
5335 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5338 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5343 json
= json_object_new_object();
5345 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5349 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5351 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5353 json_object_int_add(json
, "numRmacs", num_rmacs
);
5355 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5358 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5359 json
, JSON_C_TO_STRING_PRETTY
));
5360 json_object_free(json
);
5364 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5366 json_object
*json
= NULL
;
5369 if (!is_evpn_enabled()) {
5371 vty_out(vty
, "{}\n");
5376 json
= json_object_new_object();
5380 hash_iterate(zrouter
.l3vni_table
,
5381 (void (*)(struct hash_backet
*,
5382 void *))zl3vni_print_rmac_hash_all_vni
,
5386 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5387 json
, JSON_C_TO_STRING_PRETTY
));
5388 json_object_free(json
);
5392 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5393 struct ipaddr
*ip
, bool use_json
)
5395 zebra_l3vni_t
*zl3vni
= NULL
;
5396 zebra_neigh_t
*n
= NULL
;
5397 json_object
*json
= NULL
;
5399 if (!is_evpn_enabled()) {
5401 vty_out(vty
, "{}\n");
5406 json
= json_object_new_object();
5408 zl3vni
= zl3vni_lookup(l3vni
);
5411 vty_out(vty
, "{}\n");
5413 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5417 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5420 vty_out(vty
, "{}\n");
5423 "%% Requested next-hop not present for L3-VNI %u",
5428 zl3vni_print_nh(n
, vty
, json
);
5431 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5432 json
, JSON_C_TO_STRING_PRETTY
));
5433 json_object_free(json
);
5437 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5440 struct nh_walk_ctx wctx
;
5441 json_object
*json
= NULL
;
5442 zebra_l3vni_t
*zl3vni
= NULL
;
5444 if (!is_evpn_enabled())
5447 zl3vni
= zl3vni_lookup(l3vni
);
5450 vty_out(vty
, "{}\n");
5452 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5456 num_nh
= hashcount(zl3vni
->nh_table
);
5461 json
= json_object_new_object();
5466 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5468 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5470 json_object_int_add(json
, "numNextHops", num_nh
);
5472 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5475 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5476 json
, JSON_C_TO_STRING_PRETTY
));
5477 json_object_free(json
);
5481 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5483 json_object
*json
= NULL
;
5486 if (!is_evpn_enabled()) {
5488 vty_out(vty
, "{}\n");
5493 json
= json_object_new_object();
5497 hash_iterate(zrouter
.l3vni_table
,
5498 (void (*)(struct hash_backet
*,
5499 void *))zl3vni_print_nh_hash_all_vni
,
5503 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5504 json
, JSON_C_TO_STRING_PRETTY
));
5505 json_object_free(json
);
5510 * Display L3 VNI information (VTY command handler).
5512 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5515 json_object
*json
= NULL
;
5516 zebra_l3vni_t
*zl3vni
= NULL
;
5518 if (!is_evpn_enabled()) {
5520 vty_out(vty
, "{}\n");
5524 zl3vni
= zl3vni_lookup(vni
);
5527 vty_out(vty
, "{}\n");
5529 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5534 json
= json_object_new_object();
5538 zl3vni_print(zl3vni
, (void *)args
);
5541 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5542 json
, JSON_C_TO_STRING_PRETTY
));
5543 json_object_free(json
);
5547 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5548 json_object
*json_vrfs
)
5550 char buf
[ETHER_ADDR_STRLEN
];
5551 zebra_l3vni_t
*zl3vni
= NULL
;
5553 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5558 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5559 zvrf_name(zvrf
), zl3vni
->vni
,
5560 zl3vni_vxlan_if_name(zl3vni
),
5561 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5562 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5564 json_object
*json_vrf
= NULL
;
5566 json_vrf
= json_object_new_object();
5567 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5568 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5569 json_object_string_add(json_vrf
, "vxlanIntf",
5570 zl3vni_vxlan_if_name(zl3vni
));
5571 json_object_string_add(json_vrf
, "sviIntf",
5572 zl3vni_svi_if_name(zl3vni
));
5573 json_object_string_add(json_vrf
, "state",
5574 zl3vni_state2str(zl3vni
));
5575 json_object_string_add(
5576 json_vrf
, "routerMac",
5577 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5578 json_object_array_add(json_vrfs
, json_vrf
);
5583 * Display Neighbors for a VNI (VTY command handler).
5585 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5586 vni_t vni
, bool use_json
)
5590 struct neigh_walk_ctx wctx
;
5591 json_object
*json
= NULL
;
5593 if (!is_evpn_enabled())
5595 zvni
= zvni_lookup(vni
);
5598 vty_out(vty
, "{}\n");
5600 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5603 num_neigh
= hashcount(zvni
->neigh_table
);
5608 json
= json_object_new_object();
5610 /* Since we have IPv6 addresses to deal with which can vary widely in
5611 * size, we try to be a bit more elegant in display by first computing
5612 * the maximum width.
5614 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5617 wctx
.addr_width
= 15;
5619 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5623 "Number of ARPs (local and remote) known for this VNI: %u\n",
5625 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5626 -wctx
.addr_width
, "IP", "Type",
5627 "State", "MAC", "Remote VTEP");
5629 json_object_int_add(json
, "numArpNd", num_neigh
);
5631 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5633 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5634 json
, JSON_C_TO_STRING_PRETTY
));
5635 json_object_free(json
);
5640 * Display neighbors across all VNIs (VTY command handler).
5642 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5643 bool print_dup
, bool use_json
)
5645 json_object
*json
= NULL
;
5648 if (!is_evpn_enabled())
5652 json
= json_object_new_object();
5656 args
[2] = (void *)(ptrdiff_t)print_dup
;
5658 hash_iterate(zvrf
->vni_table
,
5659 (void (*)(struct hash_backet
*,
5660 void *))zvni_print_neigh_hash_all_vni
,
5663 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5664 json
, JSON_C_TO_STRING_PRETTY
));
5665 json_object_free(json
);
5670 * Display specific neighbor for a VNI, if present (VTY command handler).
5672 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5673 struct zebra_vrf
*zvrf
, vni_t vni
,
5674 struct ipaddr
*ip
, bool use_json
)
5678 json_object
*json
= NULL
;
5680 if (!is_evpn_enabled())
5682 zvni
= zvni_lookup(vni
);
5685 vty_out(vty
, "{}\n");
5687 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5690 n
= zvni_neigh_lookup(zvni
, ip
);
5694 "%% Requested neighbor does not exist in VNI %u\n",
5699 json
= json_object_new_object();
5701 zvni_print_neigh(n
, vty
, json
);
5704 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5705 json
, JSON_C_TO_STRING_PRETTY
));
5706 json_object_free(json
);
5711 * Display neighbors for a VNI from specific VTEP (VTY command handler).
5712 * By definition, these are remote neighbors.
5714 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5715 vni_t vni
, struct in_addr vtep_ip
,
5720 struct neigh_walk_ctx wctx
;
5721 json_object
*json
= NULL
;
5723 if (!is_evpn_enabled())
5725 zvni
= zvni_lookup(vni
);
5728 vty_out(vty
, "{}\n");
5730 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5733 num_neigh
= hashcount(zvni
->neigh_table
);
5737 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5740 wctx
.addr_width
= 15;
5741 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
5742 wctx
.r_vtep_ip
= vtep_ip
;
5744 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5745 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5748 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5749 json
, JSON_C_TO_STRING_PRETTY
));
5750 json_object_free(json
);
5755 * Display Duplicate detected Neighbors for a VNI
5756 * (VTY command handler).
5758 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
5759 struct zebra_vrf
*zvrf
,
5765 struct neigh_walk_ctx wctx
;
5766 json_object
*json
= NULL
;
5768 if (!is_evpn_enabled())
5771 zvni
= zvni_lookup(vni
);
5773 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5777 num_neigh
= hashcount(zvni
->neigh_table
);
5781 num_neigh
= num_dup_detected_neighs(zvni
);
5786 json
= json_object_new_object();
5788 /* Since we have IPv6 addresses to deal with which can vary widely in
5789 * size, we try to be a bit more elegant in display by first computing
5790 * the maximum width.
5792 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5795 wctx
.addr_width
= 15;
5797 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5801 "Number of ARPs (local and remote) known for this VNI: %u\n",
5803 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5804 -wctx
.addr_width
, "IP", "Type",
5805 "State", "MAC", "Remote VTEP");
5807 json_object_int_add(json
, "numArpNd", num_neigh
);
5809 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
5812 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5813 json
, JSON_C_TO_STRING_PRETTY
));
5814 json_object_free(json
);
5819 * Display MACs for a VNI (VTY command handler).
5821 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5822 vni_t vni
, bool use_json
)
5826 struct mac_walk_ctx wctx
;
5827 json_object
*json
= NULL
;
5828 json_object
*json_mac
= NULL
;
5830 if (!is_evpn_enabled())
5832 zvni
= zvni_lookup(vni
);
5835 vty_out(vty
, "{}\n");
5837 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5840 num_macs
= num_valid_macs(zvni
);
5845 json
= json_object_new_object();
5846 json_mac
= json_object_new_object();
5849 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5852 wctx
.json
= json_mac
;
5856 "Number of MACs (local and remote) known for this VNI: %u\n",
5858 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
5859 "Intf/Remote VTEP", "VLAN");
5861 json_object_int_add(json
, "numMacs", num_macs
);
5863 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5866 json_object_object_add(json
, "macs", json_mac
);
5867 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5868 json
, JSON_C_TO_STRING_PRETTY
));
5869 json_object_free(json
);
5874 * Display MACs for all VNIs (VTY command handler).
5876 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5877 bool print_dup
, bool use_json
)
5879 struct mac_walk_ctx wctx
;
5880 json_object
*json
= NULL
;
5882 if (!is_evpn_enabled()) {
5884 vty_out(vty
, "{}\n");
5888 json
= json_object_new_object();
5890 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5893 wctx
.print_dup
= print_dup
;
5894 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5897 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5898 json
, JSON_C_TO_STRING_PRETTY
));
5899 json_object_free(json
);
5904 * Display MACs for all VNIs (VTY command handler).
5906 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
5907 struct zebra_vrf
*zvrf
,
5908 struct in_addr vtep_ip
, bool use_json
)
5910 struct mac_walk_ctx wctx
;
5911 json_object
*json
= NULL
;
5913 if (!is_evpn_enabled())
5917 json
= json_object_new_object();
5919 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5921 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
5922 wctx
.r_vtep_ip
= vtep_ip
;
5924 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5927 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5928 json
, JSON_C_TO_STRING_PRETTY
));
5929 json_object_free(json
);
5934 * Display specific MAC for a VNI, if present (VTY command handler).
5936 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5937 vni_t vni
, struct ethaddr
*macaddr
,
5942 json_object
*json
= NULL
;
5944 if (!is_evpn_enabled())
5947 zvni
= zvni_lookup(vni
);
5950 vty_out(vty
, "{}\n");
5952 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5955 mac
= zvni_mac_lookup(zvni
, macaddr
);
5958 vty_out(vty
, "{}\n");
5961 "%% Requested MAC does not exist in VNI %u\n",
5967 json
= json_object_new_object();
5969 zvni_print_mac(mac
, vty
, json
);
5972 /* Print Duplicate MACs per VNI */
5973 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
5974 struct zebra_vrf
*zvrf
,
5975 vni_t vni
, bool use_json
)
5978 struct mac_walk_ctx wctx
;
5980 json_object
*json
= NULL
;
5981 json_object
*json_mac
= NULL
;
5983 if (!is_evpn_enabled())
5986 zvni
= zvni_lookup(vni
);
5988 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5992 num_macs
= num_valid_macs(zvni
);
5996 num_macs
= num_dup_detected_macs(zvni
);
6001 json
= json_object_new_object();
6002 json_mac
= json_object_new_object();
6005 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6008 wctx
.json
= json_mac
;
6012 "Number of MACs (local and remote) known for this VNI: %u\n",
6014 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6015 "Intf/Remote VTEP", "VLAN");
6017 json_object_int_add(json
, "numMacs", num_macs
);
6019 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6022 json_object_object_add(json
, "macs", json_mac
);
6023 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6024 json
, JSON_C_TO_STRING_PRETTY
));
6025 json_object_free(json
);
6030 void zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6031 struct zebra_vrf
*zvrf
,
6032 vni_t vni
, struct ethaddr
*macaddr
)
6036 struct listnode
*node
= NULL
;
6037 zebra_neigh_t
*nbr
= NULL
;
6039 if (!is_evpn_enabled())
6041 zvni
= zvni_lookup(vni
);
6043 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6047 mac
= zvni_mac_lookup(zvni
, macaddr
);
6049 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6054 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6055 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6059 /* Remove all IPs as duplicate associcated with this MAC */
6060 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6061 /* For local neigh mark inactive so MACIP update is generated
6062 * to BGP. This is a scenario where MAC update received
6063 * and detected as duplicate which marked neigh as duplicate.
6064 * Later local neigh update did not get a chance to relay
6065 * to BGP. Similarly remote macip update, neigh needs to be
6066 * installed locally.
6068 if (nbr
->dad_count
) {
6069 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6070 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6071 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6072 zvni_neigh_install(zvni
, nbr
);
6075 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6077 nbr
->detect_start_time
.tv_sec
= 0;
6078 nbr
->dad_dup_detect_time
= 0;
6081 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6083 mac
->detect_start_time
.tv_sec
= 0;
6084 mac
->detect_start_time
.tv_usec
= 0;
6085 mac
->dad_dup_detect_time
= 0;
6086 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6088 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6089 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6091 if (zvni_mac_send_add_to_client(zvni
->vni
,
6097 /* Process all neighbors associated with this MAC. */
6098 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6100 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6101 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6103 /* Install the entry. */
6104 zvni_mac_install(zvni
, mac
);
6109 void zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6110 struct zebra_vrf
*zvrf
,
6111 vni_t vni
, struct ipaddr
*ip
)
6116 char buf
[INET6_ADDRSTRLEN
];
6117 char buf2
[ETHER_ADDR_STRLEN
];
6119 if (!is_evpn_enabled())
6122 zvni
= zvni_lookup(vni
);
6124 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6128 nbr
= zvni_neigh_lookup(zvni
, ip
);
6131 "%% Requested host IP does not exist in VNI %u\n",
6136 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6138 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6140 "%% Requsted host IP %s is not duplicate detected\n",
6145 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6147 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6149 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6150 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6154 if (IS_ZEBRA_DEBUG_VXLAN
)
6155 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6156 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6159 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6161 nbr
->detect_start_time
.tv_sec
= 0;
6162 nbr
->detect_start_time
.tv_usec
= 0;
6163 nbr
->dad_dup_detect_time
= 0;
6164 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6166 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6167 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6169 nbr
->flags
, nbr
->loc_seq
);
6170 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6171 zvni_neigh_install(zvni
, nbr
);
6176 static void zvni_clear_dup_mac_hash(struct hash_backet
*backet
, void *ctxt
)
6178 struct mac_walk_ctx
*wctx
= ctxt
;
6181 struct listnode
*node
= NULL
;
6182 zebra_neigh_t
*nbr
= NULL
;
6184 mac
= (zebra_mac_t
*)backet
->data
;
6190 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6193 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6195 mac
->detect_start_time
.tv_sec
= 0;
6196 mac
->detect_start_time
.tv_usec
= 0;
6197 mac
->dad_dup_detect_time
= 0;
6198 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6200 /* Remove all IPs as duplicate associcated with this MAC */
6201 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6202 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6204 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6206 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6208 nbr
->detect_start_time
.tv_sec
= 0;
6209 nbr
->dad_dup_detect_time
= 0;
6212 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6213 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6215 if (zvni_mac_send_add_to_client(zvni
->vni
,
6217 mac
->flags
, mac
->loc_seq
))
6220 /* Process all neighbors associated with this MAC. */
6221 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6223 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6224 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6226 /* Install the entry. */
6227 zvni_mac_install(zvni
, mac
);
6231 static void zvni_clear_dup_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
6233 struct neigh_walk_ctx
*wctx
= ctxt
;
6236 char buf
[INET6_ADDRSTRLEN
];
6238 nbr
= (zebra_neigh_t
*)backet
->data
;
6244 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6247 if (IS_ZEBRA_DEBUG_VXLAN
) {
6248 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6250 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6251 __PRETTY_FUNCTION__
, buf
,
6252 nbr
->flags
, nbr
->loc_seq
);
6255 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6257 nbr
->detect_start_time
.tv_sec
= 0;
6258 nbr
->detect_start_time
.tv_usec
= 0;
6259 nbr
->dad_dup_detect_time
= 0;
6260 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6262 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6263 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6265 nbr
->flags
, nbr
->loc_seq
);
6266 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6267 zvni_neigh_install(zvni
, nbr
);
6271 static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet
*backet
,
6276 struct zebra_vrf
*zvrf
;
6277 struct mac_walk_ctx m_wctx
;
6278 struct neigh_walk_ctx n_wctx
;
6280 zvni
= (zebra_vni_t
*)backet
->data
;
6284 vty
= (struct vty
*)args
[0];
6285 zvrf
= (struct zebra_vrf
*)args
[1];
6287 if (hashcount(zvni
->neigh_table
)) {
6288 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6292 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6296 if (num_valid_macs(zvni
)) {
6297 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6301 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6306 void zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6307 struct zebra_vrf
*zvrf
)
6311 if (!is_evpn_enabled())
6317 hash_iterate(zvrf
->vni_table
,
6318 (void (*)(struct hash_backet
*, void *))
6319 zvni_clear_dup_detect_hash_vni_all
, args
);
6323 void zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6324 struct zebra_vrf
*zvrf
,
6328 struct mac_walk_ctx m_wctx
;
6329 struct neigh_walk_ctx n_wctx
;
6331 if (!is_evpn_enabled())
6334 zvni
= zvni_lookup(vni
);
6336 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6340 if (hashcount(zvni
->neigh_table
)) {
6341 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6345 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6349 if (num_valid_macs(zvni
)) {
6350 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6354 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6360 * Display MACs for a VNI from specific VTEP (VTY command handler).
6362 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6363 vni_t vni
, struct in_addr vtep_ip
,
6368 struct mac_walk_ctx wctx
;
6369 json_object
*json
= NULL
;
6370 json_object
*json_mac
= NULL
;
6372 if (!is_evpn_enabled())
6374 zvni
= zvni_lookup(vni
);
6377 vty_out(vty
, "{}\n");
6379 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6382 num_macs
= num_valid_macs(zvni
);
6387 json
= json_object_new_object();
6388 json_mac
= json_object_new_object();
6391 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6394 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6395 wctx
.r_vtep_ip
= vtep_ip
;
6396 wctx
.json
= json_mac
;
6397 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6400 json_object_int_add(json
, "numMacs", wctx
.count
);
6402 json_object_object_add(json
, "macs", json_mac
);
6403 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6404 json
, JSON_C_TO_STRING_PRETTY
));
6405 json_object_free(json
);
6411 * Display VNI information (VTY command handler).
6413 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6416 json_object
*json
= NULL
;
6418 zebra_l3vni_t
*zl3vni
= NULL
;
6419 zebra_vni_t
*zvni
= NULL
;
6421 if (!is_evpn_enabled())
6425 json
= json_object_new_object();
6429 zl3vni
= zl3vni_lookup(vni
);
6431 zl3vni_print(zl3vni
, (void *)args
);
6433 zvni
= zvni_lookup(vni
);
6436 vty_out(vty
, "{}\n");
6438 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6442 zvni_print(zvni
, (void *)args
);
6446 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6447 json
, JSON_C_TO_STRING_PRETTY
));
6448 json_object_free(json
);
6452 /* Display all global details for EVPN */
6453 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6458 json_object
*json
= NULL
;
6459 struct zebra_vrf
*zvrf
= NULL
;
6461 if (!is_evpn_enabled())
6464 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6468 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6469 num_l2vnis
= hashcount(zvrf
->vni_table
);
6470 num_vnis
= num_l2vnis
+ num_l3vnis
;
6473 json
= json_object_new_object();
6474 json_object_string_add(json
, "advertiseGatewayMacip",
6475 zvrf
->advertise_gw_macip
? "Yes" : "No");
6476 json_object_int_add(json
, "numVnis", num_vnis
);
6477 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6478 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6479 if (zvrf
->dup_addr_detect
)
6480 json_object_boolean_true_add(json
,
6481 "isDuplicateAddrDetection");
6483 json_object_boolean_false_add(json
,
6484 "isDuplicateAddrDetection");
6485 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6486 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6487 json_object_int_add(json
, "detectionFreezeTime",
6488 zvrf
->dad_freeze_time
);
6491 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6492 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6493 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6494 zvrf
->advertise_gw_macip
? "Yes" : "No");
6495 vty_out(vty
, "Duplicate address detection: %s\n",
6496 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6497 vty_out(vty
, " Detection max-moves %u, time %d\n",
6498 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6499 if (zvrf
->dad_freeze
) {
6500 if (zvrf
->dad_freeze_time
)
6501 vty_out(vty
, " Detection freeze %u\n",
6502 zvrf
->dad_freeze_time
);
6504 vty_out(vty
, " Detection freeze %s\n",
6510 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6511 json
, JSON_C_TO_STRING_PRETTY
));
6512 json_object_free(json
);
6517 * Display VNI hash table (VTY command handler).
6519 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6522 json_object
*json
= NULL
;
6525 if (!is_evpn_enabled())
6529 json
= json_object_new_object();
6531 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6532 "Type", "VxLAN IF", "# MACs", "# ARPs",
6533 "# Remote VTEPs", "Tenant VRF");
6538 /* Display all L2-VNIs */
6539 hash_iterate(zvrf
->vni_table
,
6540 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
6543 /* Display all L3-VNIs */
6544 hash_iterate(zrouter
.l3vni_table
,
6545 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
6549 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6550 json
, JSON_C_TO_STRING_PRETTY
));
6551 json_object_free(json
);
6555 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
6559 uint32_t max_moves
= 0;
6560 uint32_t freeze_time
= 0;
6561 bool dup_addr_detect
= false;
6562 bool freeze
= false;
6565 STREAM_GETL(s
, dup_addr_detect
);
6566 STREAM_GETL(s
, time
);
6567 STREAM_GETL(s
, max_moves
);
6568 STREAM_GETL(s
, freeze
);
6569 STREAM_GETL(s
, freeze_time
);
6571 /* DAD previous state was enabled, and new state is disable,
6572 * clear all duplicate detected addresses.
6574 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
6575 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
6577 zvrf
->dup_addr_detect
= dup_addr_detect
;
6578 zvrf
->dad_time
= time
;
6579 zvrf
->dad_max_moves
= max_moves
;
6580 zvrf
->dad_freeze
= freeze
;
6581 zvrf
->dad_freeze_time
= freeze_time
;
6583 if (IS_ZEBRA_DEBUG_VXLAN
)
6585 "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
6586 __PRETTY_FUNCTION__
,
6587 zvrf
->dup_addr_detect
? "enable" : "disable",
6588 zvrf
->dad_max_moves
,
6590 zvrf
->dad_freeze
? "enable" : "disable",
6591 zvrf
->dad_freeze_time
);
6598 * Handle neighbor delete notification from the kernel (on a VLAN device
6599 * / L3 interface). This may result in either the neighbor getting deleted
6600 * from our database or being re-added to the kernel (if it is a valid
6603 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
6604 struct interface
*link_if
,
6607 char buf
[INET6_ADDRSTRLEN
];
6608 char buf2
[ETHER_ADDR_STRLEN
];
6609 zebra_neigh_t
*n
= NULL
;
6610 zebra_vni_t
*zvni
= NULL
;
6611 zebra_mac_t
*zmac
= NULL
;
6612 zebra_l3vni_t
*zl3vni
= NULL
;
6614 /* check if this is a remote neigh entry corresponding to remote
6617 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6619 return zl3vni_local_nh_del(zl3vni
, ip
);
6621 /* We are only interested in neighbors on an SVI that resides on top
6622 * of a VxLAN bridge.
6624 zvni
= zvni_from_svi(ifp
, link_if
);
6628 if (!zvni
->vxlan_if
) {
6630 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
6635 if (IS_ZEBRA_DEBUG_VXLAN
)
6636 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
6637 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
6638 ifp
->ifindex
, zvni
->vni
);
6640 /* If entry doesn't exist, nothing to do. */
6641 n
= zvni_neigh_lookup(zvni
, ip
);
6645 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
6647 if (IS_ZEBRA_DEBUG_VXLAN
)
6649 "Trying to del a neigh %s without a mac %s on VNI %u",
6650 ipaddr2str(ip
, buf
, sizeof(buf
)),
6651 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
6657 /* If it is a remote entry, the kernel has aged this out or someone has
6658 * deleted it, it needs to be re-installed as Quagga is the owner.
6660 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6661 zvni_neigh_install(zvni
, n
);
6665 /* Remove neighbor from BGP. */
6666 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
6667 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
6669 /* Delete this neighbor entry. */
6670 zvni_neigh_del(zvni
, n
);
6672 /* see if the AUTO mac needs to be deleted */
6673 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
6674 && !listcount(zmac
->neigh_list
))
6675 zvni_mac_del(zvni
, zmac
);
6681 * Handle neighbor add or update notification from the kernel (on a VLAN
6682 * device / L3 interface). This is typically for a local neighbor but can
6683 * also be for a remote neighbor (e.g., ageout notification). It could
6684 * also be a "move" scenario.
6686 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
6687 struct interface
*link_if
,
6689 struct ethaddr
*macaddr
,
6694 char buf
[ETHER_ADDR_STRLEN
];
6695 char buf2
[INET6_ADDRSTRLEN
];
6696 zebra_vni_t
*zvni
= NULL
;
6697 zebra_l3vni_t
*zl3vni
= NULL
;
6699 /* check if this is a remote neigh entry corresponding to remote
6702 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6704 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
6706 /* We are only interested in neighbors on an SVI that resides on top
6707 * of a VxLAN bridge.
6709 zvni
= zvni_from_svi(ifp
, link_if
);
6713 if (IS_ZEBRA_DEBUG_VXLAN
)
6715 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
6716 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
6717 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
6718 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
6719 is_router
? "router " : "",
6722 /* Is this about a local neighbor or a remote one? */
6724 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
6727 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
6732 * Handle message from client to delete a remote MACIP for a VNI.
6734 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
6738 struct ethaddr macaddr
;
6740 struct in_addr vtep_ip
;
6741 uint16_t l
= 0, ipa_len
;
6742 char buf
[ETHER_ADDR_STRLEN
];
6743 char buf1
[INET6_ADDRSTRLEN
];
6745 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6746 memset(&ip
, 0, sizeof(struct ipaddr
));
6747 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
6751 while (l
< hdr
->length
) {
6752 /* Obtain each remote MACIP and process. */
6753 /* Message contains VNI, followed by MAC followed by IP (if any)
6754 * followed by remote VTEP IP.
6756 memset(&ip
, 0, sizeof(ip
));
6757 STREAM_GETL(s
, vni
);
6758 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
6759 STREAM_GETL(s
, ipa_len
);
6761 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
6763 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
6765 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
6766 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6767 l
+= IPV4_MAX_BYTELEN
;
6769 if (IS_ZEBRA_DEBUG_VXLAN
)
6771 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
6773 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
6774 ipa_len
? " IP " : "",
6776 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
6778 zebra_route_string(client
->proto
));
6780 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
6788 * Handle message from client to add a remote MACIP for a VNI. This
6789 * could be just the add of a MAC address or the add of a neighbor
6792 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
6796 struct ethaddr macaddr
;
6798 struct in_addr vtep_ip
;
6799 uint16_t l
= 0, ipa_len
;
6802 char buf
[ETHER_ADDR_STRLEN
];
6803 char buf1
[INET6_ADDRSTRLEN
];
6805 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6806 memset(&ip
, 0, sizeof(struct ipaddr
));
6807 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
6809 if (!EVPN_ENABLED(zvrf
)) {
6810 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
6816 while (l
< hdr
->length
) {
6817 /* Obtain each remote MACIP and process. */
6818 /* Message contains VNI, followed by MAC followed by IP (if any)
6819 * followed by remote VTEP IP.
6821 memset(&ip
, 0, sizeof(ip
));
6822 STREAM_GETL(s
, vni
);
6823 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
6824 STREAM_GETL(s
, ipa_len
);
6826 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
6828 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
6830 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
6831 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6832 l
+= IPV4_MAX_BYTELEN
;
6834 /* Get flags - sticky mac and/or gateway mac */
6835 STREAM_GETC(s
, flags
);
6837 STREAM_GETL(s
, seq
);
6840 if (IS_ZEBRA_DEBUG_VXLAN
)
6842 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
6844 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
6845 ipa_len
? " IP " : "",
6847 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
6848 flags
, seq
, inet_ntoa(vtep_ip
),
6849 zebra_route_string(client
->proto
));
6851 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
6852 flags
, seq
, vtep_ip
);
6860 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
6861 * us, this must involve a multihoming scenario. Treat this as implicit delete
6862 * of any prior local MAC.
6864 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
6865 struct interface
*br_if
,
6866 struct ethaddr
*macaddr
, vlanid_t vid
)
6868 struct zebra_if
*zif
;
6869 struct zebra_l2info_vxlan
*vxl
;
6873 char buf
[ETHER_ADDR_STRLEN
];
6877 vxl
= &zif
->l2info
.vxl
;
6880 /* Check if EVPN is enabled. */
6881 if (!is_evpn_enabled())
6884 /* Locate hash entry; it is expected to exist. */
6885 zvni
= zvni_lookup(vni
);
6889 /* If entry doesn't exist, nothing to do. */
6890 mac
= zvni_mac_lookup(zvni
, macaddr
);
6894 /* Is it a local entry? */
6895 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
6898 if (IS_ZEBRA_DEBUG_VXLAN
)
6900 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
6901 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
6904 /* Remove MAC from BGP. */
6905 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
6908 * If there are no neigh associated with the mac delete the mac
6909 * else mark it as AUTO for forward reference
6911 if (!listcount(mac
->neigh_list
)) {
6912 zvni_mac_del(zvni
, mac
);
6914 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
6915 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
6922 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
6923 * This can happen because the remote MAC entries are also added as "dynamic",
6924 * so the kernel can ageout the entry.
6926 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
6927 struct interface
*br_if
,
6928 struct ethaddr
*macaddr
, vlanid_t vid
)
6930 struct zebra_if
*zif
= NULL
;
6931 struct zebra_l2info_vxlan
*vxl
= NULL
;
6933 zebra_vni_t
*zvni
= NULL
;
6934 zebra_l3vni_t
*zl3vni
= NULL
;
6935 zebra_mac_t
*mac
= NULL
;
6936 char buf
[ETHER_ADDR_STRLEN
];
6940 vxl
= &zif
->l2info
.vxl
;
6943 /* Check if EVPN is enabled. */
6944 if (!is_evpn_enabled())
6947 /* check if this is a remote RMAC and readd simillar to remote macs */
6948 zl3vni
= zl3vni_lookup(vni
);
6950 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
6952 /* Locate hash entry; it is expected to exist. */
6953 zvni
= zvni_lookup(vni
);
6957 /* If entry doesn't exist, nothing to do. */
6958 mac
= zvni_mac_lookup(zvni
, macaddr
);
6962 /* Is it a remote entry? */
6963 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
6966 if (IS_ZEBRA_DEBUG_VXLAN
)
6967 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
6968 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
6971 zvni_mac_install(zvni
, mac
);
6976 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
6978 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
6979 struct ethaddr
*macaddr
, vlanid_t vid
)
6983 char buf
[ETHER_ADDR_STRLEN
];
6985 /* We are interested in MACs only on ports or (port, VLAN) that
6988 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
6991 if (!zvni
->vxlan_if
) {
6993 "VNI %u hash %p doesn't have intf upon local MAC DEL",
6998 if (IS_ZEBRA_DEBUG_VXLAN
)
6999 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7000 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7001 ifp
->ifindex
, vid
, zvni
->vni
);
7003 /* If entry doesn't exist, nothing to do. */
7004 mac
= zvni_mac_lookup(zvni
, macaddr
);
7008 /* Is it a local entry? */
7009 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7012 /* Update all the neigh entries associated with this mac */
7013 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7015 /* Remove MAC from BGP. */
7016 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7019 * If there are no neigh associated with the mac delete the mac
7020 * else mark it as AUTO for forward reference
7022 if (!listcount(mac
->neigh_list
)) {
7023 zvni_mac_del(zvni
, mac
);
7025 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7026 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7033 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7035 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7036 struct interface
*br_if
,
7037 struct ethaddr
*macaddr
, vlanid_t vid
,
7042 struct zebra_vrf
*zvrf
;
7043 char buf
[ETHER_ADDR_STRLEN
];
7044 bool mac_sticky
= false;
7045 bool inform_client
= false;
7046 bool upd_neigh
= false;
7047 struct in_addr vtep_ip
= {.s_addr
= 0};
7049 /* We are interested in MACs only on ports or (port, VLAN) that
7052 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7054 if (IS_ZEBRA_DEBUG_VXLAN
)
7056 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7057 sticky
? "sticky " : "",
7058 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7059 ifp
->name
, ifp
->ifindex
, vid
);
7063 if (!zvni
->vxlan_if
) {
7065 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7070 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7074 /* Check if we need to create or update or it is a NO-OP. */
7075 mac
= zvni_mac_lookup(zvni
, macaddr
);
7077 if (IS_ZEBRA_DEBUG_VXLAN
)
7079 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7080 sticky
? "sticky " : "",
7081 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7082 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7084 mac
= zvni_mac_add(zvni
, macaddr
);
7087 EC_ZEBRA_MAC_ADD_FAILED
,
7088 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7089 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7090 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7093 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7094 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7095 mac
->fwd_info
.local
.vid
= vid
;
7097 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7098 inform_client
= true;
7101 if (IS_ZEBRA_DEBUG_VXLAN
)
7103 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7104 sticky
? "sticky " : "",
7105 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7106 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7109 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7110 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7114 * Update any changes and if changes are relevant to
7117 if (mac_sticky
== sticky
7118 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7119 && mac
->fwd_info
.local
.vid
== vid
) {
7120 if (IS_ZEBRA_DEBUG_VXLAN
)
7122 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7123 "entry exists and has not changed ",
7124 sticky
? "sticky " : "",
7125 prefix_mac2str(macaddr
, buf
,
7127 ifp
->name
, ifp
->ifindex
, vid
,
7131 if (mac_sticky
!= sticky
) {
7133 SET_FLAG(mac
->flags
,
7136 UNSET_FLAG(mac
->flags
,
7138 inform_client
= true;
7141 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7142 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7143 mac
->fwd_info
.local
.vid
= vid
;
7145 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7146 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7147 bool do_dad
= false;
7150 * MAC has either moved or was "internally" created due
7151 * to a neighbor learn and is now actually learnt. If
7152 * it was learnt as a remote sticky MAC, this is an
7155 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7157 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7158 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7159 prefix_mac2str(macaddr
, buf
,
7161 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7166 /* If an actual move, compute MAC's seq number */
7167 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7168 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7170 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7171 /* Trigger DAD for remote MAC */
7175 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7176 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7177 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7178 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7179 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7180 mac
->fwd_info
.local
.vid
= vid
;
7182 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7184 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7186 * We have to inform BGP of this MAC as well as process
7189 inform_client
= true;
7192 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7199 /* Inform BGP if required. */
7200 if (inform_client
) {
7201 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7202 mac
->flags
, mac
->loc_seq
))
7206 /* Process all neighbors associated with this MAC, if required. */
7208 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7214 * Handle message from client to delete a remote VTEP for a VNI.
7216 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7219 unsigned short l
= 0;
7221 struct in_addr vtep_ip
;
7223 zebra_vtep_t
*zvtep
;
7224 struct interface
*ifp
;
7225 struct zebra_if
*zif
;
7227 if (!is_evpn_enabled()) {
7229 "%s: EVPN is not enabled yet we have received a vtep del command",
7230 __PRETTY_FUNCTION__
);
7234 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7235 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7242 while (l
< hdr
->length
) {
7243 /* Obtain each remote VTEP and process. */
7244 STREAM_GETL(s
, vni
);
7246 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7247 l
+= IPV4_MAX_BYTELEN
;
7249 if (IS_ZEBRA_DEBUG_VXLAN
)
7250 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7251 inet_ntoa(vtep_ip
), vni
,
7252 zebra_route_string(client
->proto
));
7254 /* Locate VNI hash entry - expected to exist. */
7255 zvni
= zvni_lookup(vni
);
7257 if (IS_ZEBRA_DEBUG_VXLAN
)
7259 "Failed to locate VNI hash upon remote VTEP DEL, "
7265 ifp
= zvni
->vxlan_if
;
7268 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7274 /* If down or not mapped to a bridge, we're done. */
7275 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7278 /* If the remote VTEP does not exist, there's nothing more to
7280 * Otherwise, uninstall any remote MACs pointing to this VTEP
7282 * then, the VTEP entry itself and remove it.
7284 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7288 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7289 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7290 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7291 zvni_vtep_del(zvni
, zvtep
);
7299 * Handle message from client to add a remote VTEP for a VNI.
7301 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7304 unsigned short l
= 0;
7306 struct in_addr vtep_ip
;
7308 struct interface
*ifp
;
7309 struct zebra_if
*zif
;
7311 if (!is_evpn_enabled()) {
7313 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7314 __PRETTY_FUNCTION__
);
7318 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7319 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7326 while (l
< hdr
->length
) {
7327 /* Obtain each remote VTEP and process. */
7328 STREAM_GETL(s
, vni
);
7330 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7331 l
+= IPV4_MAX_BYTELEN
;
7333 if (IS_ZEBRA_DEBUG_VXLAN
)
7334 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7335 inet_ntoa(vtep_ip
), vni
,
7336 zebra_route_string(client
->proto
));
7338 /* Locate VNI hash entry - expected to exist. */
7339 zvni
= zvni_lookup(vni
);
7342 EC_ZEBRA_VTEP_ADD_FAILED
,
7343 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7348 ifp
= zvni
->vxlan_if
;
7351 EC_ZEBRA_VTEP_ADD_FAILED
,
7352 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7359 /* If down or not mapped to a bridge, we're done. */
7360 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7363 /* If the remote VTEP already exists,
7364 there's nothing more to do. */
7365 if (zvni_vtep_find(zvni
, &vtep_ip
))
7368 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7369 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7370 "Failed to add remote VTEP, VNI %u zvni %p",
7375 zvni_vtep_install(zvni
, &vtep_ip
);
7383 * Add/Del gateway macip to evpn
7385 * 1. SVI interface on a vlan aware bridge
7386 * 2. SVI interface on a vlan unaware bridge
7387 * 3. vrr interface (MACVLAN) associated to a SVI
7388 * We advertise macip routes for an interface if it is associated to VxLan vlan
7390 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7394 struct ethaddr macaddr
;
7395 zebra_vni_t
*zvni
= NULL
;
7397 memset(&ip
, 0, sizeof(struct ipaddr
));
7398 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7400 /* Check if EVPN is enabled. */
7401 if (!is_evpn_enabled())
7404 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7405 struct interface
*svi_if
=
7406 NULL
; /* SVI corresponding to the MACVLAN */
7407 struct zebra_if
*ifp_zif
=
7408 NULL
; /* Zebra daemon specific info for MACVLAN */
7409 struct zebra_if
*svi_if_zif
=
7410 NULL
; /* Zebra daemon specific info for SVI*/
7412 ifp_zif
= ifp
->info
;
7417 * for a MACVLAN interface the link represents the svi_if
7419 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7420 ifp_zif
->link_ifindex
);
7422 zlog_debug("MACVLAN %s(%u) without link information",
7423 ifp
->name
, ifp
->ifindex
);
7427 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7429 * If it is a vlan aware bridge then the link gives the
7430 * bridge information
7432 struct interface
*svi_if_link
= NULL
;
7434 svi_if_zif
= svi_if
->info
;
7436 svi_if_link
= if_lookup_by_index_per_ns(
7437 zebra_ns_lookup(NS_DEFAULT
),
7438 svi_if_zif
->link_ifindex
);
7439 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7441 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7443 * If it is a vlan unaware bridge then svi is the bridge
7446 zvni
= zvni_from_svi(svi_if
, svi_if
);
7448 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7449 struct zebra_if
*svi_if_zif
=
7450 NULL
; /* Zebra daemon specific info for SVI */
7451 struct interface
*svi_if_link
=
7452 NULL
; /* link info for the SVI = bridge info */
7454 svi_if_zif
= ifp
->info
;
7456 svi_if_link
= if_lookup_by_index_per_ns(
7457 zebra_ns_lookup(NS_DEFAULT
),
7458 svi_if_zif
->link_ifindex
);
7460 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7462 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7463 zvni
= zvni_from_svi(ifp
, ifp
);
7469 if (!zvni
->vxlan_if
) {
7470 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
7476 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
7478 if (p
->family
== AF_INET
) {
7479 ip
.ipa_type
= IPADDR_V4
;
7480 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
7481 sizeof(struct in_addr
));
7482 } else if (p
->family
== AF_INET6
) {
7483 ip
.ipa_type
= IPADDR_V6
;
7484 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
7485 sizeof(struct in6_addr
));
7490 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
7492 zvni_gw_macip_del(ifp
, zvni
, &ip
);
7498 * Handle SVI interface going down.
7499 * SVI can be associated to either L3-VNI or L2-VNI.
7500 * For L2-VNI: At this point, this is a NOP since
7501 * the kernel deletes the neighbor entries on this SVI (if any).
7502 * We only need to update the vrf corresponding to zvni.
7503 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
7506 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
7508 zebra_l3vni_t
*zl3vni
= NULL
;
7510 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7513 /* process l3-vni down */
7514 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7516 /* remove association with svi-if */
7517 zl3vni
->svi_if
= NULL
;
7519 zebra_vni_t
*zvni
= NULL
;
7521 /* since we dont have svi corresponding to zvni, we associate it
7522 * to default vrf. Note: the corresponding neigh entries on the
7523 * SVI would have already been deleted */
7524 zvni
= zvni_from_svi(ifp
, link_if
);
7526 zvni
->vrf_id
= VRF_DEFAULT
;
7528 /* update the tenant vrf in BGP */
7529 zvni_send_add_to_client(zvni
);
7536 * Handle SVI interface coming up.
7537 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
7539 * For L2-VNI: we need to install any remote neighbors entried (used for
7541 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
7543 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
7545 zebra_vni_t
*zvni
= NULL
;
7546 zebra_l3vni_t
*zl3vni
= NULL
;
7548 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7551 /* associate with svi */
7552 zl3vni
->svi_if
= ifp
;
7554 /* process oper-up */
7555 if (is_l3vni_oper_up(zl3vni
))
7556 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7559 /* process SVI up for l2-vni */
7560 struct neigh_walk_ctx n_wctx
;
7562 zvni
= zvni_from_svi(ifp
, link_if
);
7566 if (!zvni
->vxlan_if
) {
7568 "VNI %u hash %p doesn't have intf upon SVI up",
7573 if (IS_ZEBRA_DEBUG_VXLAN
)
7575 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
7576 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
7577 vrf_id_to_name(ifp
->vrf_id
));
7579 /* update the vrf information for l2-vni and inform bgp */
7580 zvni
->vrf_id
= ifp
->vrf_id
;
7581 zvni_send_add_to_client(zvni
);
7583 /* Install any remote neighbors for this VNI. */
7584 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7586 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
7594 * Handle VxLAN interface down
7596 int zebra_vxlan_if_down(struct interface
*ifp
)
7599 struct zebra_if
*zif
= NULL
;
7600 struct zebra_l2info_vxlan
*vxl
= NULL
;
7601 zebra_l3vni_t
*zl3vni
= NULL
;
7604 /* Check if EVPN is enabled. */
7605 if (!is_evpn_enabled())
7610 vxl
= &zif
->l2info
.vxl
;
7613 zl3vni
= zl3vni_lookup(vni
);
7615 /* process-if-down for l3-vni */
7616 if (IS_ZEBRA_DEBUG_VXLAN
)
7617 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
7620 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7622 /* process if-down for l2-vni */
7623 if (IS_ZEBRA_DEBUG_VXLAN
)
7624 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
7627 /* Locate hash entry; it is expected to exist. */
7628 zvni
= zvni_lookup(vni
);
7631 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
7632 ifp
->name
, ifp
->ifindex
, vni
);
7636 assert(zvni
->vxlan_if
== ifp
);
7638 /* Delete this VNI from BGP. */
7639 zvni_send_del_to_client(zvni
->vni
);
7641 /* Free up all neighbors and MACs, if any. */
7642 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
7643 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
7645 /* Free up all remote VTEPs, if any. */
7646 zvni_vtep_del_all(zvni
, 1);
7652 * Handle VxLAN interface up - update BGP if required.
7654 int zebra_vxlan_if_up(struct interface
*ifp
)
7657 struct zebra_if
*zif
= NULL
;
7658 struct zebra_l2info_vxlan
*vxl
= NULL
;
7659 zebra_vni_t
*zvni
= NULL
;
7660 zebra_l3vni_t
*zl3vni
= NULL
;
7662 /* Check if EVPN is enabled. */
7663 if (!is_evpn_enabled())
7668 vxl
= &zif
->l2info
.vxl
;
7671 zl3vni
= zl3vni_lookup(vni
);
7674 if (IS_ZEBRA_DEBUG_VXLAN
)
7675 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
7678 /* we need to associate with SVI, if any, we can associate with
7679 * svi-if only after association with vxlan-intf is complete
7681 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7683 if (is_l3vni_oper_up(zl3vni
))
7684 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7686 /* Handle L2-VNI add */
7687 struct interface
*vlan_if
= NULL
;
7689 if (IS_ZEBRA_DEBUG_VXLAN
)
7690 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
7693 /* Locate hash entry; it is expected to exist. */
7694 zvni
= zvni_lookup(vni
);
7697 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
7698 ifp
->name
, ifp
->ifindex
, vni
);
7702 assert(zvni
->vxlan_if
== ifp
);
7703 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
7704 zif
->brslave_info
.br_if
);
7706 zvni
->vrf_id
= vlan_if
->vrf_id
;
7707 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
7709 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
7712 /* If part of a bridge, inform BGP about this VNI. */
7713 /* Also, read and populate local MACs and neighbors. */
7714 if (zif
->brslave_info
.br_if
) {
7715 zvni_send_add_to_client(zvni
);
7716 zvni_read_mac_neigh(zvni
, ifp
);
7724 * Handle VxLAN interface delete. Locate and remove entry in hash table
7725 * and update BGP, if required.
7727 int zebra_vxlan_if_del(struct interface
*ifp
)
7730 struct zebra_if
*zif
= NULL
;
7731 struct zebra_l2info_vxlan
*vxl
= NULL
;
7732 zebra_vni_t
*zvni
= NULL
;
7733 zebra_l3vni_t
*zl3vni
= NULL
;
7735 /* Check if EVPN is enabled. */
7736 if (!is_evpn_enabled())
7741 vxl
= &zif
->l2info
.vxl
;
7744 zl3vni
= zl3vni_lookup(vni
);
7747 if (IS_ZEBRA_DEBUG_VXLAN
)
7748 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
7751 /* process oper-down for l3-vni */
7752 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7754 /* remove the association with vxlan_if */
7755 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
7756 zl3vni
->vxlan_if
= NULL
;
7759 /* process if-del for l2-vni*/
7760 if (IS_ZEBRA_DEBUG_VXLAN
)
7761 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
7764 /* Locate hash entry; it is expected to exist. */
7765 zvni
= zvni_lookup(vni
);
7768 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
7769 ifp
->name
, ifp
->ifindex
, vni
);
7773 /* remove from l3-vni list */
7774 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
7776 listnode_delete(zl3vni
->l2vnis
, zvni
);
7778 /* Delete VNI from BGP. */
7779 zvni_send_del_to_client(zvni
->vni
);
7781 /* Free up all neighbors and MAC, if any. */
7782 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
7783 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
7785 /* Free up all remote VTEPs, if any. */
7786 zvni_vtep_del_all(zvni
, 0);
7788 /* Delete the hash entry. */
7789 if (zvni_del(zvni
)) {
7790 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
7791 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
7792 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
7800 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
7802 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
7805 struct zebra_if
*zif
= NULL
;
7806 struct zebra_l2info_vxlan
*vxl
= NULL
;
7807 zebra_vni_t
*zvni
= NULL
;
7808 zebra_l3vni_t
*zl3vni
= NULL
;
7810 /* Check if EVPN is enabled. */
7811 if (!is_evpn_enabled())
7816 vxl
= &zif
->l2info
.vxl
;
7819 zl3vni
= zl3vni_lookup(vni
);
7822 if (IS_ZEBRA_DEBUG_VXLAN
)
7824 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
7825 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
7826 inet_ntoa(vxl
->vtep_ip
),
7827 zif
->brslave_info
.bridge_ifindex
, chgflags
);
7829 /* Removed from bridge? Cleanup and return */
7830 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
7831 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
7832 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7836 /* access-vlan change - process oper down, associate with new
7837 * svi_if and then process oper up again
7839 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
7840 if (if_is_operative(ifp
)) {
7841 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7842 zl3vni
->svi_if
= NULL
;
7843 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7844 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7845 if (is_l3vni_oper_up(zl3vni
))
7846 zebra_vxlan_process_l3vni_oper_up(
7852 * local-ip change - process oper down, associate with new
7853 * local-ip and then process oper up again
7855 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
7856 if (if_is_operative(ifp
)) {
7857 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7858 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7859 if (is_l3vni_oper_up(zl3vni
))
7860 zebra_vxlan_process_l3vni_oper_up(
7865 /* Update local tunnel IP. */
7866 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7868 /* if we have a valid new master, process l3-vni oper up */
7869 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
7870 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
7871 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7875 /* Update VNI hash. */
7876 zvni
= zvni_lookup(vni
);
7879 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
7880 ifp
->name
, ifp
->ifindex
, vni
);
7884 if (IS_ZEBRA_DEBUG_VXLAN
)
7886 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
7887 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
7888 inet_ntoa(vxl
->vtep_ip
),
7889 zif
->brslave_info
.bridge_ifindex
, chgflags
);
7891 /* Removed from bridge? Cleanup and return */
7892 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
7893 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
7894 /* Delete from client, remove all remote VTEPs */
7895 /* Also, free up all MACs and neighbors. */
7896 zvni_send_del_to_client(zvni
->vni
);
7897 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
7898 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
7899 zvni_vtep_del_all(zvni
, 1);
7903 /* Handle other changes. */
7904 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
7905 /* Remove all existing local neigh and MACs for this VNI
7906 * (including from BGP)
7908 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
7909 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
7912 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
7913 zvni
->vxlan_if
= ifp
;
7915 /* Take further actions needed.
7916 * Note that if we are here, there is a change of interest.
7918 /* If down or not mapped to a bridge, we're done. */
7919 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7922 /* Inform BGP, if there is a change of interest. */
7924 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
7925 zvni_send_add_to_client(zvni
);
7927 /* If there is a valid new master or a VLAN mapping change,
7928 * read and populate local MACs and neighbors.
7929 * Also, reinstall any remote MACs and neighbors
7930 * for this VNI (based on new VLAN).
7932 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
7933 zvni_read_mac_neigh(zvni
, ifp
);
7934 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
7935 struct mac_walk_ctx m_wctx
;
7936 struct neigh_walk_ctx n_wctx
;
7938 zvni_read_mac_neigh(zvni
, ifp
);
7940 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7942 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
7945 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7947 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
7956 * Handle VxLAN interface add.
7958 int zebra_vxlan_if_add(struct interface
*ifp
)
7961 struct zebra_if
*zif
= NULL
;
7962 struct zebra_l2info_vxlan
*vxl
= NULL
;
7963 zebra_vni_t
*zvni
= NULL
;
7964 zebra_l3vni_t
*zl3vni
= NULL
;
7966 /* Check if EVPN is enabled. */
7967 if (!is_evpn_enabled())
7972 vxl
= &zif
->l2info
.vxl
;
7975 zl3vni
= zl3vni_lookup(vni
);
7978 /* process if-add for l3-vni*/
7979 if (IS_ZEBRA_DEBUG_VXLAN
)
7981 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
7982 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
7983 inet_ntoa(vxl
->vtep_ip
),
7984 zif
->brslave_info
.bridge_ifindex
);
7986 /* associate with vxlan_if */
7987 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7988 zl3vni
->vxlan_if
= ifp
;
7990 /* Associate with SVI, if any. We can associate with svi-if only
7991 * after association with vxlan_if is complete */
7992 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7994 if (is_l3vni_oper_up(zl3vni
))
7995 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7998 /* process if-add for l2-vni */
7999 struct interface
*vlan_if
= NULL
;
8001 /* Create or update VNI hash. */
8002 zvni
= zvni_lookup(vni
);
8004 zvni
= zvni_add(vni
);
8007 EC_ZEBRA_VNI_ADD_FAILED
,
8008 "Failed to add VNI hash, IF %s(%u) VNI %u",
8009 ifp
->name
, ifp
->ifindex
, vni
);
8014 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8015 zvni
->vxlan_if
= ifp
;
8016 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8017 zif
->brslave_info
.br_if
);
8019 zvni
->vrf_id
= vlan_if
->vrf_id
;
8020 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8022 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8025 if (IS_ZEBRA_DEBUG_VXLAN
)
8027 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8029 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8031 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8032 inet_ntoa(vxl
->vtep_ip
),
8033 zif
->brslave_info
.bridge_ifindex
);
8035 /* If down or not mapped to a bridge, we're done. */
8036 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8040 zvni_send_add_to_client(zvni
);
8042 /* Read and populate local MACs and neighbors */
8043 zvni_read_mac_neigh(zvni
, ifp
);
8049 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8050 char *err
, int err_str_sz
, int filter
,
8053 zebra_l3vni_t
*zl3vni
= NULL
;
8054 struct zebra_vrf
*zvrf_default
= NULL
;
8056 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8060 if (IS_ZEBRA_DEBUG_VXLAN
)
8061 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8062 add
? "ADD" : "DEL");
8066 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8068 /* check if the vni is already present under zvrf */
8070 snprintf(err
, err_str_sz
,
8071 "VNI is already configured under the vrf");
8075 /* check if this VNI is already present in the system */
8076 zl3vni
= zl3vni_lookup(vni
);
8078 snprintf(err
, err_str_sz
,
8079 "VNI is already configured as L3-VNI");
8083 /* add the L3-VNI to the global table */
8084 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8086 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8090 /* associate the vrf with vni */
8093 /* set the filter in l3vni to denote if we are using l3vni only
8097 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8099 /* associate with vxlan-intf;
8100 * we need to associate with the vxlan-intf first
8102 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8104 /* associate with corresponding SVI interface, we can associate
8105 * with svi-if only after vxlan interface association is
8108 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8110 /* formulate l2vni list */
8111 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8114 if (is_l3vni_oper_up(zl3vni
))
8115 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8118 zl3vni
= zl3vni_lookup(vni
);
8120 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8124 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8125 snprintf(err
, ERR_STR_SZ
,
8126 "prefix-routes-only is not set for the vni");
8130 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8132 /* delete and uninstall all rmacs */
8133 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8136 /* delete and uninstall all next-hops */
8137 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8143 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8148 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8150 zebra_l3vni_t
*zl3vni
= NULL
;
8153 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8157 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8158 if (is_l3vni_oper_up(zl3vni
))
8159 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8163 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8165 zebra_l3vni_t
*zl3vni
= NULL
;
8168 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8172 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8173 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8177 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8179 zebra_l3vni_t
*zl3vni
= NULL
;
8183 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8189 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8195 * Handle message from client to specify the flooding mechanism for
8196 * BUM packets. The default is to do head-end (ingress) replication
8197 * and the other supported option is to disable it. This applies to
8198 * all BUM traffic and disabling it applies to both the transmit and
8199 * receive direction.
8201 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8204 enum vxlan_flood_control flood_ctrl
;
8206 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8207 zlog_err("EVPN flood control for non-default VRF %u",
8213 STREAM_GETC(s
, flood_ctrl
);
8215 if (IS_ZEBRA_DEBUG_VXLAN
)
8216 zlog_debug("EVPN flood control %u, currently %u",
8217 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8219 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8222 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8224 /* Install or uninstall flood entries corresponding to
8227 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8235 * Handle message from client to enable/disable advertisement of g/w macip
8238 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8243 zebra_vni_t
*zvni
= NULL
;
8244 struct interface
*ifp
= NULL
;
8245 struct zebra_if
*zif
= NULL
;
8246 struct zebra_l2info_vxlan zl2_info
;
8247 struct interface
*vlan_if
= NULL
;
8249 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8250 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8256 STREAM_GETC(s
, advertise
);
8257 vni
= stream_get3(s
);
8259 zvni
= zvni_lookup(vni
);
8263 if (zvni
->advertise_subnet
== advertise
)
8266 if (IS_ZEBRA_DEBUG_VXLAN
)
8267 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8268 advertise
? "enabled" : "disabled", vni
,
8269 zvni
->advertise_subnet
? "enabled" : "disabled");
8272 zvni
->advertise_subnet
= advertise
;
8274 ifp
= zvni
->vxlan_if
;
8280 /* If down or not mapped to a bridge, we're done. */
8281 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8284 zl2_info
= zif
->l2info
.vxl
;
8287 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8291 if (zvni
->advertise_subnet
)
8292 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8294 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8301 * Handle message from client to enable/disable advertisement of g/w macip
8304 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8309 zebra_vni_t
*zvni
= NULL
;
8310 struct interface
*ifp
= NULL
;
8312 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8313 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8319 STREAM_GETC(s
, advertise
);
8320 STREAM_GETL(s
, vni
);
8323 if (IS_ZEBRA_DEBUG_VXLAN
)
8324 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8325 advertise
? "enabled" : "disabled",
8326 advertise_gw_macip_enabled(NULL
)
8330 if (zvrf
->advertise_gw_macip
== advertise
)
8333 zvrf
->advertise_gw_macip
= advertise
;
8335 if (advertise_gw_macip_enabled(zvni
))
8336 hash_iterate(zvrf
->vni_table
,
8337 zvni_gw_macip_add_for_vni_hash
, NULL
);
8339 hash_iterate(zvrf
->vni_table
,
8340 zvni_gw_macip_del_for_vni_hash
, NULL
);
8343 struct zebra_if
*zif
= NULL
;
8344 struct zebra_l2info_vxlan zl2_info
;
8345 struct interface
*vlan_if
= NULL
;
8346 struct interface
*vrr_if
= NULL
;
8348 zvni
= zvni_lookup(vni
);
8352 if (IS_ZEBRA_DEBUG_VXLAN
)
8354 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8355 advertise
? "enabled" : "disabled", vni
,
8356 advertise_gw_macip_enabled(zvni
) ? "enabled"
8359 if (zvni
->advertise_gw_macip
== advertise
)
8362 zvni
->advertise_gw_macip
= advertise
;
8364 ifp
= zvni
->vxlan_if
;
8370 /* If down or not mapped to a bridge, we're done. */
8371 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8374 zl2_info
= zif
->l2info
.vxl
;
8376 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8377 zif
->brslave_info
.br_if
);
8381 if (advertise_gw_macip_enabled(zvni
)) {
8382 /* Add primary SVI MAC-IP */
8383 zvni_add_macip_for_intf(vlan_if
, zvni
);
8385 /* Add VRR MAC-IP - if any*/
8386 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8388 zvni_add_macip_for_intf(vrr_if
, zvni
);
8390 /* Del primary MAC-IP */
8391 zvni_del_macip_for_intf(vlan_if
, zvni
);
8393 /* Del VRR MAC-IP - if any*/
8394 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8396 zvni_del_macip_for_intf(vrr_if
, zvni
);
8406 * Handle message from client to learn (or stop learning) about VNIs and MACs.
8407 * When enabled, the VNI hash table will be built and MAC FDB table read;
8408 * when disabled, the entries should be deleted and remote VTEPs and MACs
8409 * uninstalled from the kernel.
8410 * This also informs the setting for BUM handling at the time this change
8411 * occurs; it is relevant only when specifying "learn".
8413 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
8415 struct stream
*s
= NULL
;
8417 enum vxlan_flood_control flood_ctrl
;
8419 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8420 zlog_debug("EVPN VNI Adv for non-default VRF %u",
8426 STREAM_GETC(s
, advertise
);
8427 STREAM_GETC(s
, flood_ctrl
);
8429 if (IS_ZEBRA_DEBUG_VXLAN
)
8430 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
8431 advertise
? "enabled" : "disabled",
8432 is_evpn_enabled() ? "enabled" : "disabled",
8435 if (zvrf
->advertise_all_vni
== advertise
)
8438 zvrf
->advertise_all_vni
= advertise
;
8439 if (is_evpn_enabled()) {
8440 /* Note BUM handling */
8441 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8443 /* Build VNI hash table and inform BGP. */
8444 zvni_build_hash_table();
8446 /* Add all SVI (L3 GW) MACs to BGP*/
8447 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
8450 /* Read the MAC FDB */
8451 macfdb_read(zvrf
->zns
);
8453 /* Read neighbors */
8454 neigh_read(zvrf
->zns
);
8456 /* Cleanup VTEPs for all VNIs - uninstall from
8457 * kernel and free entries.
8459 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8461 /* cleanup all l3vnis */
8462 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
8470 * Allocate VNI hash table for this VRF and do other initialization.
8471 * NOTE: Currently supported only for default VRF.
8473 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
8477 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
8478 "Zebra VRF VNI Table");
8481 /* Cleanup VNI info, but don't free the table. */
8482 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
8486 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8489 /* Close all VNI handling */
8490 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
8494 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8495 hash_free(zvrf
->vni_table
);
8498 /* init the l3vni table */
8499 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
8501 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
8502 "Zebra VRF L3 VNI table");
8505 /* free l3vni table */
8506 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
8508 hash_free(zrouter
.l3vni_table
);
8511 /* get the l3vni svi ifindex */
8512 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
8514 zebra_l3vni_t
*zl3vni
= NULL
;
8516 zl3vni
= zl3vni_from_vrf(vrf_id
);
8517 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
8520 return zl3vni
->svi_if
->ifindex
;
8523 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
8525 struct zebra_vrf
*zvrf
= NULL
;
8526 zebra_neigh_t
*nbr
= NULL
;
8527 zebra_vni_t
*zvni
= NULL
;
8528 char buf1
[INET6_ADDRSTRLEN
];
8529 char buf2
[ETHER_ADDR_STRLEN
];
8531 nbr
= THREAD_ARG(t
);
8533 /* since this is asynchronous we need sanity checks*/
8534 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
8538 zvni
= zvni_lookup(nbr
->zvni
->vni
);
8542 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
8546 if (IS_ZEBRA_DEBUG_VXLAN
)
8547 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
8548 __PRETTY_FUNCTION__
,
8549 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
8550 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
8552 nbr
->dad_count
, zvni
->vni
);
8554 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8556 nbr
->detect_start_time
.tv_sec
= 0;
8557 nbr
->detect_start_time
.tv_usec
= 0;
8558 nbr
->dad_dup_detect_time
= 0;
8559 nbr
->dad_ip_auto_recovery_timer
= NULL
;
8562 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8563 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
8564 nbr
->flags
, nbr
->loc_seq
);
8565 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8566 zvni_neigh_install(zvni
, nbr
);
8572 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
8574 struct zebra_vrf
*zvrf
= NULL
;
8575 zebra_mac_t
*mac
= NULL
;
8576 zebra_vni_t
*zvni
= NULL
;
8577 struct listnode
*node
= NULL
;
8578 zebra_neigh_t
*nbr
= NULL
;
8579 char buf
[ETHER_ADDR_STRLEN
];
8581 mac
= THREAD_ARG(t
);
8583 /* since this is asynchronous we need sanity checks*/
8584 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
8588 zvni
= zvni_lookup(mac
->zvni
->vni
);
8592 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
8596 if (IS_ZEBRA_DEBUG_VXLAN
)
8597 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
8598 __PRETTY_FUNCTION__
,
8599 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
8602 listcount(mac
->neigh_list
));
8604 /* Remove all IPs as duplicate associcated with this MAC */
8605 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
8606 if (nbr
->dad_count
) {
8607 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
8608 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
8609 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
8610 zvni_neigh_install(zvni
, nbr
);
8613 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8615 nbr
->detect_start_time
.tv_sec
= 0;
8616 nbr
->dad_dup_detect_time
= 0;
8619 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
8621 mac
->detect_start_time
.tv_sec
= 0;
8622 mac
->detect_start_time
.tv_usec
= 0;
8623 mac
->dad_dup_detect_time
= 0;
8624 mac
->dad_mac_auto_recovery_timer
= NULL
;
8626 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8628 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
8629 mac
->flags
, mac
->loc_seq
))
8632 /* Process all neighbors associated with this MAC. */
8633 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
8635 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8636 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
8638 /* Install the entry. */
8639 zvni_mac_install(zvni
, mac
);