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
);
1130 vty_out(vty
, "MAC: %s\n", buf1
);
1132 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1133 struct zebra_ns
*zns
;
1134 struct interface
*ifp
;
1137 ifindex
= mac
->fwd_info
.local
.ifindex
;
1138 zns
= zebra_ns_lookup(NS_DEFAULT
);
1139 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1142 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1143 if (mac
->fwd_info
.local
.vid
)
1144 vty_out(vty
, " VLAN: %u",
1145 mac
->fwd_info
.local
.vid
);
1146 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1147 vty_out(vty
, " Remote VTEP: %s",
1148 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1149 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1150 vty_out(vty
, " Auto Mac ");
1153 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1154 vty_out(vty
, " Sticky Mac ");
1156 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1157 vty_out(vty
, " Default-gateway Mac ");
1159 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1160 vty_out(vty
, " Remote-gateway Mac ");
1163 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1167 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1168 vty_out(vty
, " Duplicate, detected at %s",
1169 time_to_string(mac
->dad_dup_detect_time
));
1170 } else if (mac
->dad_count
) {
1171 monotime_since(&mac
->detect_start_time
,
1172 &detect_start_time
);
1173 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1174 char *buf
= time_to_string(
1175 mac
->detect_start_time
.tv_sec
);
1178 memset(tmp_buf
, 0, 30);
1179 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
1181 " Duplicate detection started at %s, detection count %u\n",
1182 tmp_buf
, mac
->dad_count
);
1186 /* print all the associated neigh */
1187 vty_out(vty
, " Neighbors:\n");
1188 if (!listcount(mac
->neigh_list
))
1189 vty_out(vty
, " No Neighbors\n");
1191 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1192 vty_out(vty
, " %s %s\n",
1193 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1194 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1205 * Print MAC hash entry - called for display of all MACs.
1207 static void zvni_print_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1210 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1213 struct mac_walk_ctx
*wctx
= ctxt
;
1216 json_mac_hdr
= wctx
->json
;
1217 mac
= (zebra_mac_t
*)backet
->data
;
1219 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1222 json_mac
= json_object_new_object();
1224 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1225 struct zebra_ns
*zns
;
1227 struct interface
*ifp
;
1230 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1233 zns
= zebra_ns_lookup(NS_DEFAULT
);
1234 ifindex
= mac
->fwd_info
.local
.ifindex
;
1235 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1236 if (!ifp
) // unexpected
1238 vid
= mac
->fwd_info
.local
.vid
;
1239 if (json_mac_hdr
== NULL
)
1240 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1243 json_object_string_add(json_mac
, "type", "local");
1244 json_object_string_add(json_mac
, "intf", ifp
->name
);
1247 if (json_mac_hdr
== NULL
)
1248 vty_out(vty
, " %-5u", vid
);
1250 json_object_int_add(json_mac
, "vlan", vid
);
1252 if (json_mac_hdr
== NULL
) {
1255 json_object_int_add(json_mac
, "localSequence",
1257 json_object_int_add(json_mac
, "remoteSequence",
1259 json_object_int_add(json_mac
, "detectionCount",
1261 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1262 json_object_boolean_true_add(json_mac
,
1265 json_object_boolean_false_add(json_mac
,
1267 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1272 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1274 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1275 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1279 if (json_mac_hdr
== NULL
) {
1280 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1281 (wctx
->count
== 0)) {
1282 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1283 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1284 "Type", "Intf/Remote VTEP", "VLAN");
1286 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1287 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1289 json_object_string_add(json_mac
, "type", "remote");
1290 json_object_string_add(json_mac
, "remoteVtep",
1291 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1292 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1293 json_object_int_add(json_mac
, "localSequence",
1295 json_object_int_add(json_mac
, "remoteSequence",
1297 json_object_int_add(json_mac
, "detectionCount",
1299 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1300 json_object_boolean_true_add(json_mac
,
1303 json_object_boolean_false_add(json_mac
,
1312 /* Print Duplicate MAC */
1313 static void zvni_print_dad_mac_hash(struct hash_backet
*backet
, void *ctxt
)
1317 mac
= (zebra_mac_t
*)backet
->data
;
1321 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1322 zvni_print_mac_hash(backet
, ctxt
);
1326 * Print MAC hash entry in detail - called for display of all MACs.
1328 static void zvni_print_mac_hash_detail(struct hash_backet
*backet
, void *ctxt
)
1331 json_object
*json_mac_hdr
= NULL
;
1333 struct mac_walk_ctx
*wctx
= ctxt
;
1337 json_mac_hdr
= wctx
->json
;
1338 mac
= (zebra_mac_t
*)backet
->data
;
1343 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1345 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1348 /* Print Duplicate MAC in detail */
1349 static void zvni_print_dad_mac_hash_detail(struct hash_backet
*backet
,
1354 mac
= (zebra_mac_t
*)backet
->data
;
1358 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1359 zvni_print_mac_hash_detail(backet
, ctxt
);
1363 * Print MACs for all VNI.
1365 static void zvni_print_mac_hash_all_vni(struct hash_backet
*backet
, void *ctxt
)
1368 json_object
*json
= NULL
, *json_vni
= NULL
;
1369 json_object
*json_mac
= NULL
;
1372 struct mac_walk_ctx
*wctx
= ctxt
;
1373 char vni_str
[VNI_STR_LEN
];
1375 vty
= (struct vty
*)wctx
->vty
;
1376 json
= (struct json_object
*)wctx
->json
;
1378 zvni
= (zebra_vni_t
*)backet
->data
;
1381 /*We are iterating over a new VNI, set the count to 0*/
1384 num_macs
= num_valid_macs(zvni
);
1388 if (wctx
->print_dup
)
1389 num_macs
= num_dup_detected_macs(zvni
);
1392 json_vni
= json_object_new_object();
1393 json_mac
= json_object_new_object();
1394 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1397 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1399 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1400 zvni
->vni
, num_macs
);
1401 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1402 "Intf/Remote VTEP", "VLAN");
1404 json_object_int_add(json_vni
, "numMacs", num_macs
);
1409 json_object_int_add(json_vni
, "numMacs", num_macs
);
1410 json_object_object_add(json
, vni_str
, json_vni
);
1415 /* assign per-vni to wctx->json object to fill macs
1416 * under the vni. Re-assign primary json object to fill
1417 * next vni information.
1419 wctx
->json
= json_mac
;
1420 if (wctx
->print_dup
)
1421 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1423 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1427 json_object_object_add(json_vni
, "macs", json_mac
);
1428 json_object_object_add(json
, vni_str
, json_vni
);
1433 * Print MACs in detail for all VNI.
1435 static void zvni_print_mac_hash_all_vni_detail(struct hash_backet
*backet
,
1439 json_object
*json
= NULL
, *json_vni
= NULL
;
1440 json_object
*json_mac
= NULL
;
1443 struct mac_walk_ctx
*wctx
= ctxt
;
1444 char vni_str
[VNI_STR_LEN
];
1446 vty
= (struct vty
*)wctx
->vty
;
1447 json
= (struct json_object
*)wctx
->json
;
1449 zvni
= (zebra_vni_t
*)backet
->data
;
1452 vty_out(vty
, "{}\n");
1457 /*We are iterating over a new VNI, set the count to 0*/
1460 num_macs
= num_valid_macs(zvni
);
1464 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1468 json_vni
= json_object_new_object();
1469 json_mac
= json_object_new_object();
1470 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1473 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1475 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1476 zvni
->vni
, num_macs
);
1478 json_object_int_add(json_vni
, "numMacs", num_macs
);
1480 /* assign per-vni to wctx->json object to fill macs
1481 * under the vni. Re-assign primary json object to fill
1482 * next vni information.
1484 wctx
->json
= json_mac
;
1485 if (wctx
->print_dup
)
1486 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1489 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1493 json_object_object_add(json_vni
, "macs", json_mac
);
1494 json_object_object_add(json
, vni_str
, json_vni
);
1498 static void zl3vni_print_nh_hash(struct hash_backet
*backet
, void *ctx
)
1500 struct nh_walk_ctx
*wctx
= NULL
;
1501 struct vty
*vty
= NULL
;
1502 struct json_object
*json_vni
= NULL
;
1503 struct json_object
*json_nh
= NULL
;
1504 zebra_neigh_t
*n
= NULL
;
1505 char buf1
[ETHER_ADDR_STRLEN
];
1506 char buf2
[INET6_ADDRSTRLEN
];
1508 wctx
= (struct nh_walk_ctx
*)ctx
;
1510 json_vni
= wctx
->json
;
1512 json_nh
= json_object_new_object();
1513 n
= (zebra_neigh_t
*)backet
->data
;
1516 vty_out(vty
, "%-15s %-17s\n",
1517 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1518 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1520 json_object_string_add(json_nh
, "nexthopIp",
1521 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1522 json_object_string_add(
1523 json_nh
, "routerMac",
1524 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1525 json_object_object_add(json_vni
,
1526 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1531 static void zl3vni_print_nh_hash_all_vni(struct hash_backet
*backet
,
1534 struct vty
*vty
= NULL
;
1535 json_object
*json
= NULL
;
1536 json_object
*json_vni
= NULL
;
1537 zebra_l3vni_t
*zl3vni
= NULL
;
1538 uint32_t num_nh
= 0;
1539 struct nh_walk_ctx wctx
;
1540 char vni_str
[VNI_STR_LEN
];
1542 vty
= (struct vty
*)args
[0];
1543 json
= (struct json_object
*)args
[1];
1545 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1547 num_nh
= hashcount(zl3vni
->nh_table
);
1552 json_vni
= json_object_new_object();
1553 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1557 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1558 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1560 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1562 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1564 wctx
.json
= json_vni
;
1565 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1567 json_object_object_add(json
, vni_str
, json_vni
);
1570 static void zl3vni_print_rmac_hash_all_vni(struct hash_backet
*backet
,
1573 struct vty
*vty
= NULL
;
1574 json_object
*json
= NULL
;
1575 json_object
*json_vni
= NULL
;
1576 zebra_l3vni_t
*zl3vni
= NULL
;
1578 struct rmac_walk_ctx wctx
;
1579 char vni_str
[VNI_STR_LEN
];
1581 vty
= (struct vty
*)args
[0];
1582 json
= (struct json_object
*)args
[1];
1584 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1586 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1591 json_vni
= json_object_new_object();
1592 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1596 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1597 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1599 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1601 /* assign per-vni to wctx->json object to fill macs
1602 * under the vni. Re-assign primary json object to fill
1603 * next vni information.
1605 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1607 wctx
.json
= json_vni
;
1608 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1610 json_object_object_add(json
, vni_str
, json_vni
);
1613 static void zl3vni_print_rmac_hash(struct hash_backet
*backet
, void *ctx
)
1615 zebra_mac_t
*zrmac
= NULL
;
1616 struct rmac_walk_ctx
*wctx
= NULL
;
1617 struct vty
*vty
= NULL
;
1618 struct json_object
*json
= NULL
;
1619 struct json_object
*json_rmac
= NULL
;
1620 char buf
[ETHER_ADDR_STRLEN
];
1622 wctx
= (struct rmac_walk_ctx
*)ctx
;
1626 json_rmac
= json_object_new_object();
1627 zrmac
= (zebra_mac_t
*)backet
->data
;
1630 vty_out(vty
, "%-17s %-21s\n",
1631 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1632 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1634 json_object_string_add(
1635 json_rmac
, "routerMac",
1636 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1637 json_object_string_add(json_rmac
, "vtepIp",
1638 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1639 json_object_object_add(
1640 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1645 /* print a specific L3 VNI entry */
1646 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1648 char buf
[ETHER_ADDR_STRLEN
];
1649 struct vty
*vty
= NULL
;
1650 json_object
*json
= NULL
;
1651 zebra_vni_t
*zvni
= NULL
;
1652 json_object
*json_vni_list
= NULL
;
1653 struct listnode
*node
= NULL
, *nnode
= NULL
;
1659 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1660 vty_out(vty
, " Type: %s\n", "L3");
1661 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1662 vty_out(vty
, " Local Vtep Ip: %s\n",
1663 inet_ntoa(zl3vni
->local_vtep_ip
));
1664 vty_out(vty
, " Vxlan-Intf: %s\n",
1665 zl3vni_vxlan_if_name(zl3vni
));
1666 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1667 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1668 vty_out(vty
, " VNI Filter: %s\n",
1669 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1670 ? "prefix-routes-only"
1672 vty_out(vty
, " Router MAC: %s\n",
1673 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1674 vty_out(vty
, " L2 VNIs: ");
1675 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1676 vty_out(vty
, "%u ", zvni
->vni
);
1679 json_vni_list
= json_object_new_array();
1680 json_object_int_add(json
, "vni", zl3vni
->vni
);
1681 json_object_string_add(json
, "type", "L3");
1682 json_object_string_add(json
, "localVtepIp",
1683 inet_ntoa(zl3vni
->local_vtep_ip
));
1684 json_object_string_add(json
, "vxlanIntf",
1685 zl3vni_vxlan_if_name(zl3vni
));
1686 json_object_string_add(json
, "sviIntf",
1687 zl3vni_svi_if_name(zl3vni
));
1688 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1689 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1690 json_object_string_add(
1692 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1693 json_object_string_add(
1695 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1696 ? "prefix-routes-only"
1698 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1699 json_object_array_add(json_vni_list
,
1700 json_object_new_int(zvni
->vni
));
1702 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1707 * Print a specific VNI entry.
1709 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1712 zebra_vtep_t
*zvtep
;
1715 json_object
*json
= NULL
;
1716 json_object
*json_vtep_list
= NULL
;
1717 json_object
*json_ip_str
= NULL
;
1723 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1724 vty_out(vty
, " Type: %s\n", "L2");
1725 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1727 json_object_int_add(json
, "vni", zvni
->vni
);
1728 json_object_string_add(json
, "type", "L2");
1729 json_object_string_add(json
, "vrf",
1730 vrf_id_to_name(zvni
->vrf_id
));
1733 if (!zvni
->vxlan_if
) { // unexpected
1735 vty_out(vty
, " VxLAN interface: unknown\n");
1738 num_macs
= num_valid_macs(zvni
);
1739 num_neigh
= hashcount(zvni
->neigh_table
);
1741 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1742 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1743 vty_out(vty
, " Local VTEP IP: %s\n",
1744 inet_ntoa(zvni
->local_vtep_ip
));
1746 json_object_string_add(json
, "vxlanInterface",
1747 zvni
->vxlan_if
->name
);
1748 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1749 json_object_string_add(json
, "vtepIp",
1750 inet_ntoa(zvni
->local_vtep_ip
));
1751 json_object_string_add(json
, "advertiseGatewayMacip",
1752 zvni
->advertise_gw_macip
? "Yes" : "No");
1753 json_object_int_add(json
, "numMacs", num_macs
);
1754 json_object_int_add(json
, "numArpNd", num_neigh
);
1758 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1761 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1763 json_vtep_list
= json_object_new_array();
1764 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1766 vty_out(vty
, " %s\n",
1767 inet_ntoa(zvtep
->vtep_ip
));
1769 json_ip_str
= json_object_new_string(
1770 inet_ntoa(zvtep
->vtep_ip
));
1771 json_object_array_add(json_vtep_list
,
1776 json_object_object_add(json
, "numRemoteVteps",
1781 " Number of MACs (local and remote) known for this VNI: %u\n",
1784 " Number of ARPs (IPv4 and IPv6, local and remote) "
1785 "known for this VNI: %u\n",
1787 vty_out(vty
, " Advertise-gw-macip: %s\n",
1788 zvni
->advertise_gw_macip
? "Yes" : "No");
1792 /* print a L3 VNI hash entry */
1793 static void zl3vni_print_hash(struct hash_backet
*backet
, void *ctx
[])
1795 struct vty
*vty
= NULL
;
1796 json_object
*json
= NULL
;
1797 json_object
*json_vni
= NULL
;
1798 zebra_l3vni_t
*zl3vni
= NULL
;
1800 vty
= (struct vty
*)ctx
[0];
1801 json
= (json_object
*)ctx
[1];
1803 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
1806 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1807 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1808 hashcount(zl3vni
->rmac_table
),
1809 hashcount(zl3vni
->nh_table
), "n/a",
1810 zl3vni_vrf_name(zl3vni
));
1812 char vni_str
[VNI_STR_LEN
];
1814 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1815 json_vni
= json_object_new_object();
1816 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1817 json_object_string_add(json_vni
, "vxlanIf",
1818 zl3vni_vxlan_if_name(zl3vni
));
1819 json_object_int_add(json_vni
, "numMacs",
1820 hashcount(zl3vni
->rmac_table
));
1821 json_object_int_add(json_vni
, "numArpNd",
1822 hashcount(zl3vni
->nh_table
));
1823 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1824 json_object_string_add(json_vni
, "type", "L3");
1825 json_object_string_add(json_vni
, "tenantVrf",
1826 zl3vni_vrf_name(zl3vni
));
1827 json_object_object_add(json
, vni_str
, json_vni
);
1832 * Print a VNI hash entry - called for display of all VNIs.
1834 static void zvni_print_hash(struct hash_backet
*backet
, void *ctxt
[])
1838 zebra_vtep_t
*zvtep
;
1839 uint32_t num_vteps
= 0;
1840 uint32_t num_macs
= 0;
1841 uint32_t num_neigh
= 0;
1842 json_object
*json
= NULL
;
1843 json_object
*json_vni
= NULL
;
1844 json_object
*json_ip_str
= NULL
;
1845 json_object
*json_vtep_list
= NULL
;
1850 zvni
= (zebra_vni_t
*)backet
->data
;
1852 zvtep
= zvni
->vteps
;
1855 zvtep
= zvtep
->next
;
1858 num_macs
= num_valid_macs(zvni
);
1859 num_neigh
= hashcount(zvni
->neigh_table
);
1861 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
1863 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
1864 num_macs
, num_neigh
, num_vteps
,
1865 vrf_id_to_name(zvni
->vrf_id
));
1867 char vni_str
[VNI_STR_LEN
];
1868 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1869 json_vni
= json_object_new_object();
1870 json_object_int_add(json_vni
, "vni", zvni
->vni
);
1871 json_object_string_add(json_vni
, "type", "L2");
1872 json_object_string_add(json_vni
, "vxlanIf",
1873 zvni
->vxlan_if
? zvni
->vxlan_if
->name
1875 json_object_int_add(json_vni
, "numMacs", num_macs
);
1876 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1877 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
1878 json_object_string_add(json_vni
, "tenantVrf",
1879 vrf_id_to_name(zvni
->vrf_id
));
1881 json_vtep_list
= json_object_new_array();
1882 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1883 json_ip_str
= json_object_new_string(
1884 inet_ntoa(zvtep
->vtep_ip
));
1885 json_object_array_add(json_vtep_list
,
1888 json_object_object_add(json_vni
, "remoteVteps",
1891 json_object_object_add(json
, vni_str
, json_vni
);
1896 * Inform BGP about local MACIP.
1898 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
1899 struct ipaddr
*ip
, uint8_t flags
,
1900 uint32_t seq
, uint16_t cmd
)
1902 char buf
[ETHER_ADDR_STRLEN
];
1903 char buf2
[INET6_ADDRSTRLEN
];
1905 struct zserv
*client
= NULL
;
1906 struct stream
*s
= NULL
;
1908 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
1909 /* BGP may not be running. */
1913 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
1915 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
1916 stream_putl(s
, vni
);
1917 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
1920 if (IS_IPADDR_V4(ip
))
1921 ipa_len
= IPV4_MAX_BYTELEN
;
1922 else if (IS_IPADDR_V6(ip
))
1923 ipa_len
= IPV6_MAX_BYTELEN
;
1925 stream_putl(s
, ipa_len
); /* IP address length */
1927 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
1929 stream_putl(s
, 0); /* Just MAC. */
1931 if (cmd
== ZEBRA_MACIP_ADD
) {
1932 stream_putc(s
, flags
); /* sticky mac/gateway mac */
1933 stream_putl(s
, seq
); /* sequence number */
1937 /* Write packet size. */
1938 stream_putw_at(s
, 0, stream_get_endp(s
));
1940 if (IS_ZEBRA_DEBUG_VXLAN
)
1942 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
1943 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
1944 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
1945 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
1946 zebra_route_string(client
->proto
));
1948 if (cmd
== ZEBRA_MACIP_ADD
)
1949 client
->macipadd_cnt
++;
1951 client
->macipdel_cnt
++;
1953 return zserv_send_message(client
, s
);
1957 * Make hash key for neighbors.
1959 static unsigned int neigh_hash_keymake(void *p
)
1961 zebra_neigh_t
*n
= p
;
1962 struct ipaddr
*ip
= &n
->ip
;
1964 if (IS_IPADDR_V4(ip
))
1965 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
1967 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
1968 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
1972 * Compare two neighbor hash structures.
1974 static bool neigh_cmp(const void *p1
, const void *p2
)
1976 const zebra_neigh_t
*n1
= p1
;
1977 const zebra_neigh_t
*n2
= p2
;
1979 if (n1
== NULL
&& n2
== NULL
)
1982 if (n1
== NULL
|| n2
== NULL
)
1985 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
1988 static int neigh_list_cmp(void *p1
, void *p2
)
1990 const zebra_neigh_t
*n1
= p1
;
1991 const zebra_neigh_t
*n2
= p2
;
1993 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
1997 * Callback to allocate neighbor hash entry.
1999 static void *zvni_neigh_alloc(void *p
)
2001 const zebra_neigh_t
*tmp_n
= p
;
2004 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2011 * Add neighbor entry.
2013 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2014 struct ethaddr
*mac
)
2016 zebra_neigh_t tmp_n
;
2017 zebra_neigh_t
*n
= NULL
;
2018 zebra_mac_t
*zmac
= NULL
;
2020 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2021 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2022 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2025 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2026 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2028 /* Associate the neigh to mac */
2029 zmac
= zvni_mac_lookup(zvni
, mac
);
2031 listnode_add_sort(zmac
->neigh_list
, n
);
2037 * Delete neighbor entry.
2039 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2041 zebra_neigh_t
*tmp_n
;
2042 zebra_mac_t
*zmac
= NULL
;
2044 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2046 listnode_delete(zmac
->neigh_list
, n
);
2048 /* Free the VNI hash entry and allocated memory. */
2049 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2051 XFREE(MTYPE_NEIGH
, tmp_n
);
2057 * Free neighbor hash entry (callback)
2059 static void zvni_neigh_del_hash_entry(struct hash_backet
*backet
, void *arg
)
2061 struct neigh_walk_ctx
*wctx
= arg
;
2062 zebra_neigh_t
*n
= backet
->data
;
2064 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2065 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2066 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2067 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2068 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2069 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2070 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2071 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2074 if (wctx
->uninstall
)
2075 zvni_neigh_uninstall(wctx
->zvni
, n
);
2077 zvni_neigh_del(wctx
->zvni
, n
);
2084 * Delete all neighbor entries from specific VTEP for a particular VNI.
2086 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2087 struct in_addr
*r_vtep_ip
)
2089 struct neigh_walk_ctx wctx
;
2091 if (!zvni
->neigh_table
)
2094 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2096 wctx
.uninstall
= uninstall
;
2097 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2098 wctx
.r_vtep_ip
= *r_vtep_ip
;
2100 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2104 * Delete all neighbor entries for this VNI.
2106 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2109 struct neigh_walk_ctx wctx
;
2111 if (!zvni
->neigh_table
)
2114 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2116 wctx
.uninstall
= uninstall
;
2117 wctx
.upd_client
= upd_client
;
2120 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2124 * Look up neighbor hash entry.
2126 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2131 memset(&tmp
, 0, sizeof(tmp
));
2132 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2133 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2139 * Process all neighbors associated with a MAC upon the MAC being learnt
2140 * locally or undergoing any other change (such as sequence number).
2142 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2146 zebra_neigh_t
*n
= NULL
;
2147 struct listnode
*node
= NULL
;
2148 struct zebra_vrf
*zvrf
= NULL
;
2149 char buf
[ETHER_ADDR_STRLEN
];
2151 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2153 if (IS_ZEBRA_DEBUG_VXLAN
)
2154 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2155 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2156 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2158 /* Walk all neighbors and mark any inactive local neighbors as
2159 * active and/or update sequence number upon a move, and inform BGP.
2160 * The action for remote neighbors is TBD.
2161 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2162 * accidentally end up deleting a just-learnt local neighbor.
2164 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2165 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2166 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2167 ZEBRA_NEIGH_SET_ACTIVE(n
);
2168 n
->loc_seq
= zmac
->loc_seq
;
2169 if (!(zvrf
->dup_addr_detect
&&
2170 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2171 ZEBRA_NEIGH_DUPLICATE
)))
2172 zvni_neigh_send_add_to_client(
2173 zvni
->vni
, &n
->ip
, &n
->emac
,
2174 n
->flags
, n
->loc_seq
);
2181 * Process all neighbors associated with a local MAC upon the MAC being
2184 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2187 zebra_neigh_t
*n
= NULL
;
2188 struct listnode
*node
= NULL
;
2189 char buf
[ETHER_ADDR_STRLEN
];
2191 if (IS_ZEBRA_DEBUG_VXLAN
)
2192 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2193 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2196 /* Walk all local neighbors and mark as inactive and inform
2198 * TBD: There is currently no handling for remote neighbors. We
2199 * don't expect them to exist, if they do, do we install the MAC
2200 * as a remote MAC and the neighbor as remote?
2202 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2203 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2204 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2205 ZEBRA_NEIGH_SET_INACTIVE(n
);
2207 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2215 * Process all neighbors associated with a MAC upon the MAC being remotely
2218 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2221 zebra_neigh_t
*n
= NULL
;
2222 struct listnode
*node
= NULL
;
2223 char buf
[ETHER_ADDR_STRLEN
];
2225 if (IS_ZEBRA_DEBUG_VXLAN
)
2226 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2227 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2230 /* Walk all local neighbors and mark as inactive and inform
2233 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2234 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2235 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2236 ZEBRA_NEIGH_SET_INACTIVE(n
);
2238 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2246 * Process all neighbors associated with a remote MAC upon the MAC being
2249 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2252 /* NOTE: Currently a NO-OP. */
2256 * Inform BGP about local neighbor addition.
2258 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2259 struct ethaddr
*macaddr
,
2260 uint8_t neigh_flags
,
2265 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2266 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2267 /* Set router flag (R-bit) based on local neigh entry add */
2268 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2269 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2271 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2272 seq
, ZEBRA_MACIP_ADD
);
2276 * Inform BGP about local neighbor deletion.
2278 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2279 struct ethaddr
*macaddr
, uint8_t flags
)
2281 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2282 0, ZEBRA_MACIP_DEL
);
2286 * Install remote neighbor into the kernel.
2288 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2290 struct zebra_if
*zif
;
2291 struct zebra_l2info_vxlan
*vxl
;
2292 struct interface
*vlan_if
;
2298 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2301 zif
= zvni
->vxlan_if
->info
;
2304 vxl
= &zif
->l2info
.vxl
;
2306 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2310 flags
= NTF_EXT_LEARNED
;
2311 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2312 flags
|= NTF_ROUTER
;
2313 ZEBRA_NEIGH_SET_ACTIVE(n
);
2314 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2320 * Uninstall remote neighbor from the kernel.
2322 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2324 struct zebra_if
*zif
;
2325 struct zebra_l2info_vxlan
*vxl
;
2326 struct interface
*vlan_if
;
2328 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2331 if (!zvni
->vxlan_if
) {
2332 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2337 zif
= zvni
->vxlan_if
->info
;
2340 vxl
= &zif
->l2info
.vxl
;
2341 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2345 ZEBRA_NEIGH_SET_INACTIVE(n
);
2347 return kernel_del_neigh(vlan_if
, &n
->ip
);
2351 * Install neighbor hash entry - called upon access VLAN change.
2353 static void zvni_install_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
2356 struct neigh_walk_ctx
*wctx
= ctxt
;
2358 n
= (zebra_neigh_t
*)backet
->data
;
2360 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2361 zvni_neigh_install(wctx
->zvni
, n
);
2364 /* Get the VRR interface for SVI if any */
2365 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2367 struct zebra_vrf
*zvrf
= NULL
;
2368 struct interface
*tmp_if
= NULL
;
2369 struct zebra_if
*zif
= NULL
;
2371 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2374 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2379 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2382 if (zif
->link
== ifp
)
2389 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2391 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2392 struct connected
*c
= NULL
;
2393 struct ethaddr macaddr
;
2395 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2397 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2400 memset(&ip
, 0, sizeof(struct ipaddr
));
2401 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2404 if (c
->address
->family
== AF_INET
) {
2405 ip
.ipa_type
= IPADDR_V4
;
2406 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2407 sizeof(struct in_addr
));
2408 } else if (c
->address
->family
== AF_INET6
) {
2409 ip
.ipa_type
= IPADDR_V6
;
2410 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2411 sizeof(struct in6_addr
));
2416 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2422 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2424 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2425 struct connected
*c
= NULL
;
2426 struct ethaddr macaddr
;
2428 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2430 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2433 memset(&ip
, 0, sizeof(struct ipaddr
));
2434 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2437 if (c
->address
->family
== AF_INET
) {
2438 ip
.ipa_type
= IPADDR_V4
;
2439 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2440 sizeof(struct in_addr
));
2441 } else if (c
->address
->family
== AF_INET6
) {
2442 ip
.ipa_type
= IPADDR_V6
;
2443 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2444 sizeof(struct in6_addr
));
2449 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2455 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2458 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2459 struct connected
*c
= NULL
;
2460 struct ethaddr macaddr
;
2462 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2464 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2467 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2469 /* skip link local address */
2470 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2475 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2476 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2478 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2479 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2485 * zvni_gw_macip_add_to_client
2487 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2488 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2490 char buf
[ETHER_ADDR_STRLEN
];
2491 char buf2
[INET6_ADDRSTRLEN
];
2492 zebra_neigh_t
*n
= NULL
;
2493 zebra_mac_t
*mac
= NULL
;
2494 struct zebra_if
*zif
= NULL
;
2495 struct zebra_l2info_vxlan
*vxl
= NULL
;
2497 zif
= zvni
->vxlan_if
->info
;
2501 vxl
= &zif
->l2info
.vxl
;
2503 mac
= zvni_mac_lookup(zvni
, macaddr
);
2505 mac
= zvni_mac_add(zvni
, macaddr
);
2507 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2508 "Failed to add MAC %s intf %s(%u) VID %u",
2509 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2510 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2515 /* Set "local" forwarding info. */
2516 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2517 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2518 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2519 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2520 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2521 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2523 n
= zvni_neigh_lookup(zvni
, ip
);
2525 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2528 EC_ZEBRA_MAC_ADD_FAILED
,
2529 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2530 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2531 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2532 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2537 /* Set "local" forwarding info. */
2538 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2539 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2540 ZEBRA_NEIGH_SET_ACTIVE(n
);
2541 /* Set Router flag (R-bit) */
2542 if (ip
->ipa_type
== IPADDR_V6
)
2543 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2544 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2545 n
->ifindex
= ifp
->ifindex
;
2547 /* Only advertise in BGP if the knob is enabled */
2548 if (!advertise_gw_macip_enabled(zvni
))
2551 if (IS_ZEBRA_DEBUG_VXLAN
)
2553 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2554 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2555 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2556 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2558 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2559 n
->flags
, n
->loc_seq
);
2565 * zvni_gw_macip_del_from_client
2567 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2570 char buf1
[ETHER_ADDR_STRLEN
];
2571 char buf2
[INET6_ADDRSTRLEN
];
2572 zebra_neigh_t
*n
= NULL
;
2573 zebra_mac_t
*mac
= NULL
;
2575 /* If the neigh entry is not present nothing to do*/
2576 n
= zvni_neigh_lookup(zvni
, ip
);
2580 /* mac entry should be present */
2581 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2583 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2584 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2585 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2589 /* If the entry is not local nothing to do*/
2590 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2593 /* only need to delete the entry from bgp if we sent it before */
2594 if (IS_ZEBRA_DEBUG_VXLAN
)
2596 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2597 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2598 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2599 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2601 /* Remove neighbor from BGP. */
2602 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2603 ZEBRA_MACIP_TYPE_GW
);
2605 /* Delete this neighbor entry. */
2606 zvni_neigh_del(zvni
, n
);
2608 /* see if the mac needs to be deleted as well*/
2610 zvni_deref_ip2mac(zvni
, mac
);
2615 static void zvni_gw_macip_del_for_vni_hash(struct hash_backet
*backet
,
2618 zebra_vni_t
*zvni
= NULL
;
2619 struct zebra_if
*zif
= NULL
;
2620 struct zebra_l2info_vxlan zl2_info
;
2621 struct interface
*vlan_if
= NULL
;
2622 struct interface
*vrr_if
= NULL
;
2623 struct interface
*ifp
;
2625 /* Add primary SVI MAC*/
2626 zvni
= (zebra_vni_t
*)backet
->data
;
2628 ifp
= zvni
->vxlan_if
;
2633 /* If down or not mapped to a bridge, we're done. */
2634 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2637 zl2_info
= zif
->l2info
.vxl
;
2640 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2644 /* Del primary MAC-IP */
2645 zvni_del_macip_for_intf(vlan_if
, zvni
);
2647 /* Del VRR MAC-IP - if any*/
2648 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2650 zvni_del_macip_for_intf(vrr_if
, zvni
);
2655 static void zvni_gw_macip_add_for_vni_hash(struct hash_backet
*backet
,
2658 zebra_vni_t
*zvni
= NULL
;
2659 struct zebra_if
*zif
= NULL
;
2660 struct zebra_l2info_vxlan zl2_info
;
2661 struct interface
*vlan_if
= NULL
;
2662 struct interface
*vrr_if
= NULL
;
2663 struct interface
*ifp
= NULL
;
2665 zvni
= (zebra_vni_t
*)backet
->data
;
2667 ifp
= zvni
->vxlan_if
;
2672 /* If down or not mapped to a bridge, we're done. */
2673 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2675 zl2_info
= zif
->l2info
.vxl
;
2678 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2682 /* Add primary SVI MAC-IP */
2683 zvni_add_macip_for_intf(vlan_if
, zvni
);
2685 /* Add VRR MAC-IP - if any*/
2686 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2688 zvni_add_macip_for_intf(vrr_if
, zvni
);
2693 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2694 struct interface
*ifp
,
2696 struct ethaddr
*macaddr
,
2699 char buf
[ETHER_ADDR_STRLEN
];
2700 char buf2
[INET6_ADDRSTRLEN
];
2701 struct zebra_vrf
*zvrf
;
2702 zebra_neigh_t
*n
= NULL
;
2703 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2704 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2705 bool upd_mac_seq
= false;
2706 bool neigh_mac_change
= false;
2707 bool neigh_on_hold
= false;
2708 bool neigh_was_remote
= false;
2709 bool do_dad
= false;
2710 struct in_addr vtep_ip
= {.s_addr
= 0};
2712 /* Check if the MAC exists. */
2713 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2715 /* create a dummy MAC if the MAC is not already present */
2716 if (IS_ZEBRA_DEBUG_VXLAN
)
2718 "AUTO MAC %s created for neigh %s on VNI %u",
2719 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2720 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2722 zmac
= zvni_mac_add(zvni
, macaddr
);
2724 zlog_debug("Failed to add MAC %s VNI %u",
2725 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2730 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2731 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2732 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2734 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2736 * We don't change the MAC to local upon a neighbor
2737 * learn event, we wait for the explicit local MAC
2738 * learn. However, we have to compute its sequence
2739 * number in preparation for when it actually turns
2746 zvrf
= vrf_info_lookup(zvni
->vrf_id
);
2750 /* Check if the neighbor exists. */
2751 n
= zvni_neigh_lookup(zvni
, ip
);
2753 /* New neighbor - create */
2754 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2757 EC_ZEBRA_MAC_ADD_FAILED
,
2758 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2759 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2760 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2761 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2764 /* Set "local" forwarding info. */
2765 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2766 n
->ifindex
= ifp
->ifindex
;
2768 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2772 /* Note any changes and see if of interest to BGP. */
2773 mac_different
= (memcmp(n
->emac
.octet
,
2774 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
2775 cur_is_router
= !!CHECK_FLAG(n
->flags
,
2776 ZEBRA_NEIGH_ROUTER_FLAG
);
2777 if (!mac_different
&& is_router
== cur_is_router
) {
2778 n
->ifindex
= ifp
->ifindex
;
2782 if (!mac_different
) {
2783 bool is_neigh_freezed
= false;
2785 /* Only the router flag has changed. */
2788 ZEBRA_NEIGH_ROUTER_FLAG
);
2790 UNSET_FLAG(n
->flags
,
2791 ZEBRA_NEIGH_ROUTER_FLAG
);
2793 /* Neigh is in freeze state and freeze action
2794 * is enabled, do not send update to client.
2796 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
2798 CHECK_FLAG(n
->flags
,
2799 ZEBRA_NEIGH_DUPLICATE
));
2801 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
2803 return zvni_neigh_send_add_to_client(
2804 zvni
->vni
, ip
, macaddr
,
2805 n
->flags
, n
->loc_seq
);
2809 /* The MAC has changed, need to issue a delete
2810 * first as this means a different MACIP route.
2811 * Also, need to do some unlinking/relinking.
2812 * We also need to update the MAC's sequence number
2813 * in different situations.
2815 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
2816 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2818 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2820 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
2822 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
2823 neigh_mac_change
= upd_mac_seq
= true;
2824 listnode_delete(old_zmac
->neigh_list
, n
);
2825 zvni_deref_ip2mac(zvni
, old_zmac
);
2828 /* Update the forwarding info. */
2829 n
->ifindex
= ifp
->ifindex
;
2830 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2832 /* Link to new MAC */
2833 listnode_add_sort(zmac
->neigh_list
, n
);
2834 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2836 * Neighbor has moved from remote to local. Its
2837 * MAC could have also changed as part of the move.
2839 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
2841 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2843 old_mac_seq
= CHECK_FLAG(
2848 neigh_mac_change
= upd_mac_seq
= true;
2849 listnode_delete(old_zmac
->neigh_list
,
2851 zvni_deref_ip2mac(zvni
, old_zmac
);
2854 /* Link to new MAC */
2855 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2856 listnode_add_sort(zmac
->neigh_list
, n
);
2858 /* Based on Mobility event Scenario-B from the
2859 * draft, neigh's previous state was remote treat this
2862 neigh_was_remote
= true;
2863 vtep_ip
= n
->r_vtep_ip
;
2864 /* Mark appropriately */
2865 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2866 n
->r_vtep_ip
.s_addr
= 0;
2867 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2868 n
->ifindex
= ifp
->ifindex
;
2872 /* If MAC was previously remote, or the neighbor had a different
2873 * MAC earlier, recompute the sequence number.
2876 uint32_t seq1
, seq2
;
2878 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
2879 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
2880 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
2881 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
2882 MAX(seq1
, seq2
) : zmac
->loc_seq
;
2885 /* Mark Router flag (R-bit) */
2887 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2889 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2891 /* Check old and/or new MAC detected as duplicate mark
2892 * the neigh as duplicate
2894 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
2895 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
2896 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
2898 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2899 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
2902 /* For IP Duplicate Address Detection (DAD) is trigger,
2903 * when the event is extended mobility based on scenario-B
2904 * from the draft, IP/Neigh's MAC binding changed and
2905 * neigh's previous state was remote.
2907 if (neigh_mac_change
&& neigh_was_remote
)
2910 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
2911 &neigh_on_hold
, true);
2913 /* Before we program this in BGP, we need to check if MAC is locally
2914 * learnt. If not, force neighbor to be inactive and reset its seq.
2916 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
2917 ZEBRA_NEIGH_SET_INACTIVE(n
);
2919 zmac
->loc_seq
= mac_new_seq
;
2923 /* If the MAC's sequence number has changed, inform the MAC and all
2924 * neighbors associated with the MAC to BGP, else just inform this
2927 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
2928 if (IS_ZEBRA_DEBUG_VXLAN
)
2929 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
2930 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2931 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
2932 zmac
->loc_seq
= mac_new_seq
;
2933 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
2934 zmac
->flags
, zmac
->loc_seq
))
2936 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
2940 ZEBRA_NEIGH_SET_ACTIVE(n
);
2941 n
->loc_seq
= zmac
->loc_seq
;
2944 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2945 n
->flags
, n
->loc_seq
);
2949 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
2950 struct interface
*ifp
,
2952 struct ethaddr
*macaddr
,
2955 char buf
[ETHER_ADDR_STRLEN
];
2956 char buf2
[INET6_ADDRSTRLEN
];
2957 zebra_neigh_t
*n
= NULL
;
2958 zebra_mac_t
*zmac
= NULL
;
2960 /* If the neighbor is unknown, there is no further action. */
2961 n
= zvni_neigh_lookup(zvni
, ip
);
2965 /* If a remote entry, see if it needs to be refreshed */
2966 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
2968 if (state
& NUD_STALE
)
2969 zvni_neigh_install(zvni
, n
);
2972 /* We got a "remote" neighbor notification for an entry
2973 * we think is local. This can happen in a multihoming
2974 * scenario - but only if the MAC is already "remote".
2975 * Just mark our entry as "remote".
2977 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2978 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2980 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
2981 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
2982 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2987 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2988 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
2989 ZEBRA_NEIGH_SET_ACTIVE(n
);
2990 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
2997 * Make hash key for MAC.
2999 static unsigned int mac_hash_keymake(void *p
)
3001 zebra_mac_t
*pmac
= p
;
3002 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3004 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3008 * Compare two MAC addresses.
3010 static bool mac_cmp(const void *p1
, const void *p2
)
3012 const zebra_mac_t
*pmac1
= p1
;
3013 const zebra_mac_t
*pmac2
= p2
;
3015 if (pmac1
== NULL
&& pmac2
== NULL
)
3018 if (pmac1
== NULL
|| pmac2
== NULL
)
3021 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3026 * Callback to allocate MAC hash entry.
3028 static void *zvni_mac_alloc(void *p
)
3030 const zebra_mac_t
*tmp_mac
= p
;
3033 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3036 return ((void *)mac
);
3042 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3044 zebra_mac_t tmp_mac
;
3045 zebra_mac_t
*mac
= NULL
;
3047 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3048 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3049 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3052 mac
->neigh_list
= list_new();
3053 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3061 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3063 zebra_mac_t
*tmp_mac
;
3065 list_delete(&mac
->neigh_list
);
3067 /* Free the VNI hash entry and allocated memory. */
3068 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3070 XFREE(MTYPE_MAC
, tmp_mac
);
3076 * Free MAC hash entry (callback)
3078 static void zvni_mac_del_hash_entry(struct hash_backet
*backet
, void *arg
)
3080 struct mac_walk_ctx
*wctx
= arg
;
3081 zebra_mac_t
*mac
= backet
->data
;
3083 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3084 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3085 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3086 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3087 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3088 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3089 &wctx
->r_vtep_ip
))) {
3090 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3091 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3095 if (wctx
->uninstall
)
3096 zvni_mac_uninstall(wctx
->zvni
, mac
);
3098 zvni_mac_del(wctx
->zvni
, mac
);
3105 * Delete all MAC entries from specific VTEP for a particular VNI.
3107 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3108 struct in_addr
*r_vtep_ip
)
3110 struct mac_walk_ctx wctx
;
3112 if (!zvni
->mac_table
)
3115 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3117 wctx
.uninstall
= uninstall
;
3118 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3119 wctx
.r_vtep_ip
= *r_vtep_ip
;
3121 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3125 * Delete all MAC entries for this VNI.
3127 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3130 struct mac_walk_ctx wctx
;
3132 if (!zvni
->mac_table
)
3135 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3137 wctx
.uninstall
= uninstall
;
3138 wctx
.upd_client
= upd_client
;
3141 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3145 * Look up MAC hash entry.
3147 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3152 memset(&tmp
, 0, sizeof(tmp
));
3153 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3154 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3160 * Inform BGP about local MAC addition.
3162 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3163 uint8_t mac_flags
, uint32_t seq
)
3167 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3168 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3169 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3170 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3172 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3173 seq
, ZEBRA_MACIP_ADD
);
3177 * Inform BGP about local MAC deletion.
3179 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3181 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3182 0 /* seq */, ZEBRA_MACIP_DEL
);
3186 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3187 * notifications, to see if they are of interest.
3189 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3190 struct interface
*br_if
, vlanid_t vid
)
3192 struct zebra_ns
*zns
;
3193 struct route_node
*rn
;
3194 struct interface
*tmp_if
= NULL
;
3195 struct zebra_if
*zif
;
3196 struct zebra_l2info_bridge
*br
;
3197 struct zebra_l2info_vxlan
*vxl
= NULL
;
3198 uint8_t bridge_vlan_aware
;
3202 /* Determine if bridge is VLAN-aware or not */
3205 br
= &zif
->l2info
.br
;
3206 bridge_vlan_aware
= br
->vlan_aware
;
3208 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3209 /* TODO: Optimize with a hash. */
3210 zns
= zebra_ns_lookup(NS_DEFAULT
);
3211 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3212 tmp_if
= (struct interface
*)rn
->info
;
3216 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3218 if (!if_is_operative(tmp_if
))
3220 vxl
= &zif
->l2info
.vxl
;
3222 if (zif
->brslave_info
.br_if
!= br_if
)
3225 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3234 zvni
= zvni_lookup(vxl
->vni
);
3239 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3240 * neighbor notifications, to see if they are of interest.
3242 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3243 struct interface
*br_if
)
3245 struct zebra_ns
*zns
;
3246 struct route_node
*rn
;
3247 struct interface
*tmp_if
= NULL
;
3248 struct zebra_if
*zif
;
3249 struct zebra_l2info_bridge
*br
;
3250 struct zebra_l2info_vxlan
*vxl
= NULL
;
3251 uint8_t bridge_vlan_aware
;
3259 /* Make sure the linked interface is a bridge. */
3260 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3263 /* Determine if bridge is VLAN-aware or not */
3266 br
= &zif
->l2info
.br
;
3267 bridge_vlan_aware
= br
->vlan_aware
;
3268 if (bridge_vlan_aware
) {
3269 struct zebra_l2info_vlan
*vl
;
3271 if (!IS_ZEBRA_IF_VLAN(ifp
))
3276 vl
= &zif
->l2info
.vl
;
3280 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3281 /* TODO: Optimize with a hash. */
3282 zns
= zebra_ns_lookup(NS_DEFAULT
);
3283 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3284 tmp_if
= (struct interface
*)rn
->info
;
3288 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3290 if (!if_is_operative(tmp_if
))
3292 vxl
= &zif
->l2info
.vxl
;
3294 if (zif
->brslave_info
.br_if
!= br_if
)
3297 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3306 zvni
= zvni_lookup(vxl
->vni
);
3310 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3312 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3313 * linked to the bridge
3314 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3317 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3319 struct zebra_ns
*zns
;
3320 struct route_node
*rn
;
3321 struct interface
*tmp_if
= NULL
;
3322 struct zebra_if
*zif
;
3323 struct zebra_l2info_bridge
*br
;
3324 struct zebra_l2info_vlan
*vl
;
3325 uint8_t bridge_vlan_aware
;
3328 /* Defensive check, caller expected to invoke only with valid bridge. */
3332 /* Determine if bridge is VLAN-aware or not */
3335 br
= &zif
->l2info
.br
;
3336 bridge_vlan_aware
= br
->vlan_aware
;
3338 /* Check oper status of the SVI. */
3339 if (!bridge_vlan_aware
)
3340 return if_is_operative(br_if
) ? br_if
: NULL
;
3342 /* Identify corresponding VLAN interface. */
3343 /* TODO: Optimize with a hash. */
3344 zns
= zebra_ns_lookup(NS_DEFAULT
);
3345 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3346 tmp_if
= (struct interface
*)rn
->info
;
3347 /* Check oper status of the SVI. */
3348 if (!tmp_if
|| !if_is_operative(tmp_if
))
3351 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3352 || zif
->link
!= br_if
)
3354 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3356 if (vl
->vid
== vid
) {
3362 return found
? tmp_if
: NULL
;
3366 * Install remote MAC into the kernel.
3368 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3370 struct zebra_if
*zif
;
3371 struct zebra_l2info_vxlan
*vxl
;
3374 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3377 zif
= zvni
->vxlan_if
->info
;
3380 vxl
= &zif
->l2info
.vxl
;
3382 sticky
= !!CHECK_FLAG(mac
->flags
,
3383 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3385 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3386 mac
->fwd_info
.r_vtep_ip
, sticky
);
3390 * Uninstall remote MAC from the kernel.
3392 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3394 struct zebra_if
*zif
;
3395 struct zebra_l2info_vxlan
*vxl
;
3396 struct in_addr vtep_ip
;
3397 struct interface
*ifp
;
3399 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3402 if (!zvni
->vxlan_if
) {
3403 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3408 zif
= zvni
->vxlan_if
->info
;
3411 vxl
= &zif
->l2info
.vxl
;
3413 ifp
= zvni
->vxlan_if
;
3414 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3416 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3420 * Install MAC hash entry - called upon access VLAN change.
3422 static void zvni_install_mac_hash(struct hash_backet
*backet
, void *ctxt
)
3425 struct mac_walk_ctx
*wctx
= ctxt
;
3427 mac
= (zebra_mac_t
*)backet
->data
;
3429 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3430 zvni_mac_install(wctx
->zvni
, mac
);
3434 * Count of remote neighbors referencing this MAC.
3436 static int remote_neigh_count(zebra_mac_t
*zmac
)
3438 zebra_neigh_t
*n
= NULL
;
3439 struct listnode
*node
= NULL
;
3442 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3443 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3451 * Decrement neighbor refcount of MAC; uninstall and free it if
3454 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3456 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3459 /* If all remote neighbors referencing a remote MAC go away,
3460 * we need to uninstall the MAC.
3462 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3463 remote_neigh_count(mac
) == 0) {
3464 zvni_mac_uninstall(zvni
, mac
);
3465 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3468 /* If no neighbors, delete the MAC. */
3469 if (list_isempty(mac
->neigh_list
))
3470 zvni_mac_del(zvni
, mac
);
3474 * Read and populate local MACs and neighbors corresponding to this VNI.
3476 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3478 struct zebra_ns
*zns
;
3479 struct zebra_if
*zif
;
3480 struct interface
*vlan_if
;
3481 struct zebra_l2info_vxlan
*vxl
;
3482 struct interface
*vrr_if
;
3485 vxl
= &zif
->l2info
.vxl
;
3486 zns
= zebra_ns_lookup(NS_DEFAULT
);
3488 if (IS_ZEBRA_DEBUG_VXLAN
)
3490 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3491 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3492 zif
->brslave_info
.bridge_ifindex
);
3494 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3495 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3498 /* Add SVI MAC-IP */
3499 zvni_add_macip_for_intf(vlan_if
, zvni
);
3501 /* Add VRR MAC-IP - if any*/
3502 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3504 zvni_add_macip_for_intf(vrr_if
, zvni
);
3506 neigh_read_for_vlan(zns
, vlan_if
);
3511 * Hash function for VNI.
3513 static unsigned int vni_hash_keymake(void *p
)
3515 const zebra_vni_t
*zvni
= p
;
3517 return (jhash_1word(zvni
->vni
, 0));
3521 * Compare 2 VNI hash entries.
3523 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3525 const zebra_vni_t
*zvni1
= p1
;
3526 const zebra_vni_t
*zvni2
= p2
;
3528 return (zvni1
->vni
== zvni2
->vni
);
3531 static int vni_list_cmp(void *p1
, void *p2
)
3533 const zebra_vni_t
*zvni1
= p1
;
3534 const zebra_vni_t
*zvni2
= p2
;
3536 if (zvni1
->vni
== zvni2
->vni
)
3538 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3542 * Callback to allocate VNI hash entry.
3544 static void *zvni_alloc(void *p
)
3546 const zebra_vni_t
*tmp_vni
= p
;
3549 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3550 zvni
->vni
= tmp_vni
->vni
;
3551 return ((void *)zvni
);
3555 * Look up VNI hash entry.
3557 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3559 struct zebra_vrf
*zvrf
;
3560 zebra_vni_t tmp_vni
;
3561 zebra_vni_t
*zvni
= NULL
;
3563 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3565 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3567 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3573 * Add VNI hash entry.
3575 static zebra_vni_t
*zvni_add(vni_t vni
)
3577 struct zebra_vrf
*zvrf
;
3578 zebra_vni_t tmp_zvni
;
3579 zebra_vni_t
*zvni
= NULL
;
3581 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3583 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3585 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3588 /* Create hash table for MAC */
3590 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3592 /* Create hash table for neighbors */
3593 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3594 "Zebra VNI Neighbor Table");
3600 * Delete VNI hash entry.
3602 static int zvni_del(zebra_vni_t
*zvni
)
3604 struct zebra_vrf
*zvrf
;
3605 zebra_vni_t
*tmp_zvni
;
3607 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3610 zvni
->vxlan_if
= NULL
;
3612 /* Free the neighbor hash table. */
3613 hash_free(zvni
->neigh_table
);
3614 zvni
->neigh_table
= NULL
;
3616 /* Free the MAC hash table. */
3617 hash_free(zvni
->mac_table
);
3618 zvni
->mac_table
= NULL
;
3620 /* Free the VNI hash entry and allocated memory. */
3621 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3623 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3629 * Inform BGP about local VNI addition.
3631 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3633 struct zserv
*client
;
3636 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3637 /* BGP may not be running. */
3641 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3643 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3644 stream_putl(s
, zvni
->vni
);
3645 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3646 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3648 /* Write packet size. */
3649 stream_putw_at(s
, 0, stream_get_endp(s
));
3651 if (IS_ZEBRA_DEBUG_VXLAN
)
3652 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3653 inet_ntoa(zvni
->local_vtep_ip
),
3654 vrf_id_to_name(zvni
->vrf_id
),
3655 zebra_route_string(client
->proto
));
3657 client
->vniadd_cnt
++;
3658 return zserv_send_message(client
, s
);
3662 * Inform BGP about local VNI deletion.
3664 static int zvni_send_del_to_client(vni_t vni
)
3666 struct zserv
*client
;
3669 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3670 /* BGP may not be running. */
3674 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3677 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3678 stream_putl(s
, vni
);
3680 /* Write packet size. */
3681 stream_putw_at(s
, 0, stream_get_endp(s
));
3683 if (IS_ZEBRA_DEBUG_VXLAN
)
3684 zlog_debug("Send VNI_DEL %u to %s", vni
,
3685 zebra_route_string(client
->proto
));
3687 client
->vnidel_cnt
++;
3688 return zserv_send_message(client
, s
);
3692 * Build the VNI hash table by going over the VxLAN interfaces. This
3693 * is called when EVPN (advertise-all-vni) is enabled.
3695 static void zvni_build_hash_table()
3697 struct zebra_ns
*zns
;
3698 struct route_node
*rn
;
3699 struct interface
*ifp
;
3701 /* Walk VxLAN interfaces and create VNI hash. */
3702 zns
= zebra_ns_lookup(NS_DEFAULT
);
3703 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3705 zebra_vni_t
*zvni
= NULL
;
3706 zebra_l3vni_t
*zl3vni
= NULL
;
3707 struct zebra_if
*zif
;
3708 struct zebra_l2info_vxlan
*vxl
;
3710 ifp
= (struct interface
*)rn
->info
;
3714 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3717 vxl
= &zif
->l2info
.vxl
;
3720 /* L3-VNI and L2-VNI are handled seperately */
3721 zl3vni
= zl3vni_lookup(vni
);
3724 if (IS_ZEBRA_DEBUG_VXLAN
)
3726 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3727 ifp
->name
, ifp
->ifindex
, vni
);
3729 /* associate with vxlan_if */
3730 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3731 zl3vni
->vxlan_if
= ifp
;
3734 * we need to associate with SVI.
3735 * we can associate with svi-if only after association
3736 * with vxlan-intf is complete
3738 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3740 if (is_l3vni_oper_up(zl3vni
))
3741 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3744 struct interface
*vlan_if
= NULL
;
3746 if (IS_ZEBRA_DEBUG_VXLAN
)
3748 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3749 ifp
->name
, ifp
->ifindex
, vni
,
3750 inet_ntoa(vxl
->vtep_ip
));
3752 /* VNI hash entry is not expected to exist. */
3753 zvni
= zvni_lookup(vni
);
3756 "VNI hash already present for IF %s(%u) L2-VNI %u",
3757 ifp
->name
, ifp
->ifindex
, vni
);
3761 zvni
= zvni_add(vni
);
3764 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
3765 ifp
->name
, ifp
->ifindex
, vni
);
3769 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
3770 zvni
->vxlan_if
= ifp
;
3771 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
3772 zif
->brslave_info
.br_if
);
3774 zvni
->vrf_id
= vlan_if
->vrf_id
;
3775 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
3777 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
3781 /* Inform BGP if intf is up and mapped to bridge. */
3782 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
3783 zvni_send_add_to_client(zvni
);
3789 * See if remote VTEP matches with prefix.
3791 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
3793 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
3797 * Locate remote VTEP in VNI hash table.
3799 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3801 zebra_vtep_t
*zvtep
;
3806 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3807 if (zvni_vtep_match(vtep_ip
, zvtep
))
3815 * Add remote VTEP to VNI hash table.
3817 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3819 zebra_vtep_t
*zvtep
;
3821 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
3823 zvtep
->vtep_ip
= *vtep_ip
;
3826 zvni
->vteps
->prev
= zvtep
;
3827 zvtep
->next
= zvni
->vteps
;
3828 zvni
->vteps
= zvtep
;
3834 * Remove remote VTEP from VNI hash table.
3836 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
3839 zvtep
->next
->prev
= zvtep
->prev
;
3841 zvtep
->prev
->next
= zvtep
->next
;
3843 zvni
->vteps
= zvtep
->next
;
3845 zvtep
->prev
= zvtep
->next
= NULL
;
3846 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
3852 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
3853 * uninstall from kernel if asked to.
3855 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
3857 zebra_vtep_t
*zvtep
, *zvtep_next
;
3862 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
3863 zvtep_next
= zvtep
->next
;
3865 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3866 zvni_vtep_del(zvni
, zvtep
);
3873 * Install remote VTEP into the kernel.
3875 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3877 if (is_vxlan_flooding_head_end())
3878 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3883 * Uninstall remote VTEP from the kernel.
3885 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
3887 if (!zvni
->vxlan_if
) {
3888 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3893 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
3897 * Install or uninstall flood entries in the kernel corresponding to
3898 * remote VTEPs. This is invoked upon change to BUM handling.
3900 static void zvni_handle_flooding_remote_vteps(struct hash_backet
*backet
,
3904 zebra_vtep_t
*zvtep
;
3906 zvni
= (zebra_vni_t
*)backet
->data
;
3910 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
3911 if (is_vxlan_flooding_head_end())
3912 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
3914 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
3919 * Cleanup VNI/VTEP and update kernel
3921 static void zvni_cleanup_all(struct hash_backet
*backet
, void *arg
)
3923 zebra_vni_t
*zvni
= NULL
;
3924 zebra_l3vni_t
*zl3vni
= NULL
;
3925 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
3927 zvni
= (zebra_vni_t
*)backet
->data
;
3929 /* remove from l3-vni list */
3931 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
3933 listnode_delete(zl3vni
->l2vnis
, zvni
);
3935 /* Free up all neighbors and MACs, if any. */
3936 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
3937 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
3939 /* Free up all remote VTEPs, if any. */
3940 zvni_vtep_del_all(zvni
, 1);
3942 /* Delete the hash entry. */
3947 static void zl3vni_cleanup_all(struct hash_backet
*backet
, void *args
)
3949 zebra_l3vni_t
*zl3vni
= NULL
;
3951 zl3vni
= (zebra_l3vni_t
*)backet
->data
;
3953 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
3956 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
3957 struct prefix
*host
)
3959 struct host_rb_entry lookup
;
3960 struct host_rb_entry
*hle
;
3962 memset(&lookup
, 0, sizeof(lookup
));
3963 memcpy(&lookup
.p
, host
, sizeof(*host
));
3965 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3969 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
3970 memcpy(hle
, &lookup
, sizeof(lookup
));
3972 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
3975 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
3977 struct host_rb_entry lookup
;
3978 struct host_rb_entry
*hle
;
3980 memset(&lookup
, 0, sizeof(lookup
));
3981 memcpy(&lookup
.p
, host
, sizeof(*host
));
3983 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
3985 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
3986 XFREE(MTYPE_HOST_PREFIX
, hle
);
3993 * Look up MAC hash entry.
3995 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
3996 struct ethaddr
*rmac
)
4001 memset(&tmp
, 0, sizeof(tmp
));
4002 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4003 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4009 * Callback to allocate RMAC hash entry.
4011 static void *zl3vni_rmac_alloc(void *p
)
4013 const zebra_mac_t
*tmp_rmac
= p
;
4016 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4019 return ((void *)zrmac
);
4023 * Add RMAC entry to l3-vni
4025 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4027 zebra_mac_t tmp_rmac
;
4028 zebra_mac_t
*zrmac
= NULL
;
4030 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4031 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4032 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4035 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4037 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4038 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4046 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4048 zebra_mac_t
*tmp_rmac
;
4049 struct host_rb_entry
*hle
;
4051 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4052 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4054 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4055 XFREE(MTYPE_HOST_PREFIX
, hle
);
4058 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4060 XFREE(MTYPE_MAC
, tmp_rmac
);
4066 * Install remote RMAC into the kernel.
4068 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4070 struct zebra_if
*zif
= NULL
;
4071 struct zebra_l2info_vxlan
*vxl
= NULL
;
4073 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4074 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4077 zif
= zl3vni
->vxlan_if
->info
;
4081 vxl
= &zif
->l2info
.vxl
;
4083 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4084 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4088 * Uninstall remote RMAC from the kernel.
4090 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4092 char buf
[ETHER_ADDR_STRLEN
];
4093 struct zebra_if
*zif
= NULL
;
4094 struct zebra_l2info_vxlan
*vxl
= NULL
;
4096 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4097 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4100 if (!zl3vni
->vxlan_if
) {
4102 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4103 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4104 zl3vni
->vni
, zl3vni
);
4108 zif
= zl3vni
->vxlan_if
->info
;
4112 vxl
= &zif
->l2info
.vxl
;
4114 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4115 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4118 /* handle rmac add */
4119 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4120 struct ipaddr
*vtep_ip
,
4121 struct prefix
*host_prefix
)
4123 char buf
[ETHER_ADDR_STRLEN
];
4124 char buf1
[INET6_ADDRSTRLEN
];
4125 zebra_mac_t
*zrmac
= NULL
;
4127 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4130 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4133 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4134 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4136 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4139 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4140 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4142 /* install rmac in kernel */
4143 zl3vni_rmac_install(zl3vni
, zrmac
);
4146 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4152 /* handle rmac delete */
4153 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4154 struct prefix
*host_prefix
)
4156 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4158 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4159 /* uninstall from kernel */
4160 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4162 /* del the rmac entry */
4163 zl3vni_rmac_del(zl3vni
, zrmac
);
4168 * Look up nh hash entry on a l3-vni.
4170 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4175 memset(&tmp
, 0, sizeof(tmp
));
4176 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4177 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4184 * Callback to allocate NH hash entry on L3-VNI.
4186 static void *zl3vni_nh_alloc(void *p
)
4188 const zebra_neigh_t
*tmp_n
= p
;
4191 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4198 * Add neighbor entry.
4200 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4201 struct ethaddr
*mac
)
4203 zebra_neigh_t tmp_n
;
4204 zebra_neigh_t
*n
= NULL
;
4206 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4207 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4208 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4211 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4213 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4214 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4215 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4221 * Delete neighbor entry.
4223 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4225 zebra_neigh_t
*tmp_n
;
4226 struct host_rb_entry
*hle
;
4228 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4229 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4231 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4232 XFREE(MTYPE_HOST_PREFIX
, hle
);
4235 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4237 XFREE(MTYPE_NEIGH
, tmp_n
);
4243 * Install remote nh as neigh into the kernel.
4245 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4252 if (!is_l3vni_oper_up(zl3vni
))
4255 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4256 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4259 flags
= NTF_EXT_LEARNED
;
4260 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4261 flags
|= NTF_ROUTER
;
4262 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4268 * Uninstall remote nh from the kernel.
4270 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4272 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4273 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4276 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4279 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4282 /* add remote vtep as a neigh entry */
4283 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4284 struct ethaddr
*rmac
,
4285 struct prefix
*host_prefix
)
4287 char buf
[ETHER_ADDR_STRLEN
];
4288 char buf1
[INET6_ADDRSTRLEN
];
4289 zebra_neigh_t
*nh
= NULL
;
4291 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4293 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4297 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4298 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4299 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4304 /* install the nh neigh in kernel */
4305 zl3vni_nh_install(zl3vni
, nh
);
4308 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4313 /* handle nh neigh delete */
4314 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4315 struct prefix
*host_prefix
)
4317 rb_delete_host(&nh
->host_rb
, host_prefix
);
4319 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4320 /* uninstall from kernel */
4321 zl3vni_nh_uninstall(zl3vni
, nh
);
4323 /* delete the nh entry */
4324 zl3vni_nh_del(zl3vni
, nh
);
4328 /* handle neigh update from kernel - the only thing of interest is to
4329 * readd stale entries.
4331 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4335 zebra_neigh_t
*n
= NULL
;
4337 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4341 /* all next hop neigh are remote and installed by frr.
4342 * If the kernel has aged this entry, re-install.
4344 if (state
& NUD_STALE
)
4345 zl3vni_nh_install(zl3vni
, n
);
4350 /* handle neigh delete from kernel */
4351 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4353 zebra_neigh_t
*n
= NULL
;
4355 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4359 /* all next hop neigh are remote and installed by frr.
4360 * If we get an age out notification for these neigh entries, we have to
4363 zl3vni_nh_install(zl3vni
, n
);
4369 * Hash function for L3 VNI.
4371 static unsigned int l3vni_hash_keymake(void *p
)
4373 const zebra_l3vni_t
*zl3vni
= p
;
4375 return jhash_1word(zl3vni
->vni
, 0);
4379 * Compare 2 L3 VNI hash entries.
4381 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4383 const zebra_l3vni_t
*zl3vni1
= p1
;
4384 const zebra_l3vni_t
*zl3vni2
= p2
;
4386 return (zl3vni1
->vni
== zl3vni2
->vni
);
4390 * Callback to allocate L3 VNI hash entry.
4392 static void *zl3vni_alloc(void *p
)
4394 zebra_l3vni_t
*zl3vni
= NULL
;
4395 const zebra_l3vni_t
*tmp_l3vni
= p
;
4397 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4398 zl3vni
->vni
= tmp_l3vni
->vni
;
4399 return ((void *)zl3vni
);
4403 * Look up L3 VNI hash entry.
4405 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4407 zebra_l3vni_t tmp_l3vni
;
4408 zebra_l3vni_t
*zl3vni
= NULL
;
4410 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4411 tmp_l3vni
.vni
= vni
;
4412 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4418 * Add L3 VNI hash entry.
4420 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4422 zebra_l3vni_t tmp_zl3vni
;
4423 zebra_l3vni_t
*zl3vni
= NULL
;
4425 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4426 tmp_zl3vni
.vni
= vni
;
4428 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4431 zl3vni
->vrf_id
= vrf_id
;
4432 zl3vni
->svi_if
= NULL
;
4433 zl3vni
->vxlan_if
= NULL
;
4434 zl3vni
->l2vnis
= list_new();
4435 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4437 /* Create hash table for remote RMAC */
4438 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4439 "Zebra L3-VNI RMAC-Table");
4441 /* Create hash table for neighbors */
4442 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4443 "Zebra L3-VNI next-hop table");
4449 * Delete L3 VNI hash entry.
4451 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4453 zebra_l3vni_t
*tmp_zl3vni
;
4455 /* free the list of l2vnis */
4456 list_delete(&zl3vni
->l2vnis
);
4457 zl3vni
->l2vnis
= NULL
;
4459 /* Free the rmac table */
4460 hash_free(zl3vni
->rmac_table
);
4461 zl3vni
->rmac_table
= NULL
;
4463 /* Free the nh table */
4464 hash_free(zl3vni
->nh_table
);
4465 zl3vni
->nh_table
= NULL
;
4467 /* Free the VNI hash entry and allocated memory. */
4468 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4470 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4475 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4477 struct zebra_ns
*zns
= NULL
;
4478 struct route_node
*rn
= NULL
;
4479 struct interface
*ifp
= NULL
;
4481 /* loop through all vxlan-interface */
4482 zns
= zebra_ns_lookup(NS_DEFAULT
);
4483 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4485 struct zebra_if
*zif
= NULL
;
4486 struct zebra_l2info_vxlan
*vxl
= NULL
;
4488 ifp
= (struct interface
*)rn
->info
;
4493 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4496 vxl
= &zif
->l2info
.vxl
;
4497 if (vxl
->vni
== zl3vni
->vni
) {
4498 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4506 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4508 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4509 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4514 if (!zl3vni
->vxlan_if
)
4517 zif
= zl3vni
->vxlan_if
->info
;
4521 vxl
= &zif
->l2info
.vxl
;
4523 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4526 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4528 struct zebra_vrf
*zvrf
= NULL
;
4530 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4534 return zl3vni_lookup(zvrf
->l3vni
);
4538 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4539 * neighbor notifications, to see if they are of interest.
4541 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4542 struct interface
*br_if
)
4546 uint8_t bridge_vlan_aware
= 0;
4547 zebra_l3vni_t
*zl3vni
= NULL
;
4548 struct zebra_ns
*zns
= NULL
;
4549 struct route_node
*rn
= NULL
;
4550 struct zebra_if
*zif
= NULL
;
4551 struct interface
*tmp_if
= NULL
;
4552 struct zebra_l2info_bridge
*br
= NULL
;
4553 struct zebra_l2info_vxlan
*vxl
= NULL
;
4558 /* Make sure the linked interface is a bridge. */
4559 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4562 /* Determine if bridge is VLAN-aware or not */
4565 br
= &zif
->l2info
.br
;
4566 bridge_vlan_aware
= br
->vlan_aware
;
4567 if (bridge_vlan_aware
) {
4568 struct zebra_l2info_vlan
*vl
;
4570 if (!IS_ZEBRA_IF_VLAN(ifp
))
4575 vl
= &zif
->l2info
.vl
;
4579 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4580 /* TODO: Optimize with a hash. */
4581 zns
= zebra_ns_lookup(NS_DEFAULT
);
4582 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4583 tmp_if
= (struct interface
*)rn
->info
;
4587 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4589 if (!if_is_operative(tmp_if
))
4591 vxl
= &zif
->l2info
.vxl
;
4593 if (zif
->brslave_info
.br_if
!= br_if
)
4596 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4605 zl3vni
= zl3vni_lookup(vxl
->vni
);
4610 * Inform BGP about l3-vni.
4612 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4614 struct stream
*s
= NULL
;
4615 struct zserv
*client
= NULL
;
4616 struct ethaddr rmac
;
4617 char buf
[ETHER_ADDR_STRLEN
];
4619 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4620 /* BGP may not be running. */
4625 memset(&rmac
, 0, sizeof(struct ethaddr
));
4626 zl3vni_get_rmac(zl3vni
, &rmac
);
4628 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4630 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4631 stream_putl(s
, zl3vni
->vni
);
4632 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4633 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4634 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4636 /* Write packet size. */
4637 stream_putw_at(s
, 0, stream_get_endp(s
));
4639 if (IS_ZEBRA_DEBUG_VXLAN
)
4641 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4642 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4643 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4644 inet_ntoa(zl3vni
->local_vtep_ip
),
4645 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4646 ? "prefix-routes-only"
4648 zebra_route_string(client
->proto
));
4650 client
->l3vniadd_cnt
++;
4651 return zserv_send_message(client
, s
);
4655 * Inform BGP about local l3-VNI deletion.
4657 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4659 struct stream
*s
= NULL
;
4660 struct zserv
*client
= NULL
;
4662 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4663 /* BGP may not be running. */
4667 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4669 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4670 stream_putl(s
, zl3vni
->vni
);
4672 /* Write packet size. */
4673 stream_putw_at(s
, 0, stream_get_endp(s
));
4675 if (IS_ZEBRA_DEBUG_VXLAN
)
4676 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4677 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4678 zebra_route_string(client
->proto
));
4680 client
->l3vnidel_cnt
++;
4681 return zserv_send_message(client
, s
);
4684 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4689 /* send l3vni add to BGP */
4690 zl3vni_send_add_to_client(zl3vni
);
4693 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4698 /* send l3-vni del to BGP*/
4699 zl3vni_send_del_to_client(zl3vni
);
4702 static void zvni_add_to_l3vni_list(struct hash_backet
*backet
, void *ctxt
)
4704 zebra_vni_t
*zvni
= (zebra_vni_t
*)backet
->data
;
4705 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4707 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4708 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4712 * handle transition of vni from l2 to l3 and vice versa
4714 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4717 zebra_vni_t
*zvni
= NULL
;
4719 /* There is a possibility that VNI notification was already received
4720 * from kernel and we programmed it as L2-VNI
4721 * In such a case we need to delete this L2-VNI first, so
4722 * that it can be reprogrammed as L3-VNI in the system. It is also
4723 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4724 * interface is still present in kernel. In this case to keep it
4725 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4728 /* Locate hash entry */
4729 zvni
= zvni_lookup(vni
);
4733 if (IS_ZEBRA_DEBUG_VXLAN
)
4734 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4736 /* Delete VNI from BGP. */
4737 zvni_send_del_to_client(zvni
->vni
);
4739 /* Free up all neighbors and MAC, if any. */
4740 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4741 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4743 /* Free up all remote VTEPs, if any. */
4744 zvni_vtep_del_all(zvni
, 0);
4746 /* Delete the hash entry. */
4747 if (zvni_del(zvni
)) {
4748 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4749 "Failed to del VNI hash %p, VNI %u", zvni
,
4754 /* TODO_MITESH: This needs to be thought through. We don't have
4755 * enough information at this point to reprogram the vni as
4756 * l2-vni. One way is to store the required info in l3-vni and
4757 * used it solely for this purpose
4764 /* delete and uninstall rmac hash entry */
4765 static void zl3vni_del_rmac_hash_entry(struct hash_backet
*backet
, void *ctx
)
4767 zebra_mac_t
*zrmac
= NULL
;
4768 zebra_l3vni_t
*zl3vni
= NULL
;
4770 zrmac
= (zebra_mac_t
*)backet
->data
;
4771 zl3vni
= (zebra_l3vni_t
*)ctx
;
4772 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4773 zl3vni_rmac_del(zl3vni
, zrmac
);
4776 /* delete and uninstall nh hash entry */
4777 static void zl3vni_del_nh_hash_entry(struct hash_backet
*backet
, void *ctx
)
4779 zebra_neigh_t
*n
= NULL
;
4780 zebra_l3vni_t
*zl3vni
= NULL
;
4782 n
= (zebra_neigh_t
*)backet
->data
;
4783 zl3vni
= (zebra_l3vni_t
*)ctx
;
4784 zl3vni_nh_uninstall(zl3vni
, n
);
4785 zl3vni_nh_del(zl3vni
, n
);
4788 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
4791 struct zserv
*client
= NULL
;
4792 struct stream
*s
= NULL
;
4793 char buf
[PREFIX_STRLEN
];
4795 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4796 /* BGP may not be running. */
4800 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4802 zclient_create_header(s
, cmd
, vrf_id
);
4803 stream_put(s
, p
, sizeof(struct prefix
));
4805 /* Write packet size. */
4806 stream_putw_at(s
, 0, stream_get_endp(s
));
4808 if (IS_ZEBRA_DEBUG_VXLAN
)
4809 zlog_debug("Send ip prefix %s %s on vrf %s",
4810 prefix2str(p
, buf
, sizeof(buf
)),
4811 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
4812 vrf_id_to_name(vrf_id
));
4814 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
4815 client
->prefixadd_cnt
++;
4817 client
->prefixdel_cnt
++;
4819 return zserv_send_message(client
, s
);
4822 /* re-add remote rmac if needed */
4823 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
4824 struct ethaddr
*rmac
)
4826 char buf
[ETHER_ADDR_STRLEN
];
4827 zebra_mac_t
*zrmac
= NULL
;
4829 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4833 if (IS_ZEBRA_DEBUG_VXLAN
)
4834 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
4835 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
4837 zl3vni_rmac_install(zl3vni
, zrmac
);
4841 /* Process a remote MACIP add from BGP. */
4842 static void process_remote_macip_add(vni_t vni
,
4843 struct ethaddr
*macaddr
,
4845 struct ipaddr
*ipaddr
,
4848 struct in_addr vtep_ip
)
4851 zebra_vtep_t
*zvtep
;
4852 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
4853 zebra_neigh_t
*n
= NULL
;
4854 int update_mac
= 0, update_neigh
= 0;
4855 char buf
[ETHER_ADDR_STRLEN
];
4856 char buf1
[INET6_ADDRSTRLEN
];
4857 struct interface
*ifp
= NULL
;
4858 struct zebra_if
*zif
= NULL
;
4859 struct zebra_vrf
*zvrf
;
4864 bool do_dad
= false;
4865 bool is_dup_detect
= false;
4867 /* Locate VNI hash entry - expected to exist. */
4868 zvni
= zvni_lookup(vni
);
4870 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
4874 ifp
= zvni
->vxlan_if
;
4878 !if_is_operative(ifp
) ||
4880 !zif
->brslave_info
.br_if
) {
4881 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
4886 /* The remote VTEP specified should normally exist, but it is
4887 * possible that when peering comes up, peer may advertise MACIP
4888 * routes before advertising type-3 routes.
4890 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
4892 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
4894 EC_ZEBRA_VTEP_ADD_FAILED
,
4895 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
4900 zvni_vtep_install(zvni
, &vtep_ip
);
4903 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
4904 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
4905 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
4907 mac
= zvni_mac_lookup(zvni
, macaddr
);
4909 /* Ignore if the mac is already present as a gateway mac */
4911 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
4912 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
4913 if (IS_ZEBRA_DEBUG_VXLAN
)
4914 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
4916 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
4917 ipa_len
? " IP " : "",
4919 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
4923 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
4927 /* check if the remote MAC is unknown or has a change.
4928 * If so, that needs to be updated first. Note that client could
4929 * install MAC and MACIP separately or just install the latter.
4932 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
4933 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
4934 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
4935 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
4936 || seq
!= mac
->rem_seq
)
4941 mac
= zvni_mac_add(zvni
, macaddr
);
4944 "Failed to add MAC %s VNI %u Remote VTEP %s",
4945 prefix_mac2str(macaddr
, buf
,
4947 vni
, inet_ntoa(vtep_ip
));
4951 /* Is this MAC created for a MACIP? */
4953 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
4955 const char *mac_type
;
4957 /* When host moves but changes its (MAC,IP)
4958 * binding, BGP may install a MACIP entry that
4959 * corresponds to "older" location of the host
4960 * in transient situations (because {IP1,M1}
4961 * is a different route from {IP1,M2}). Check
4962 * the sequence number and ignore this update
4965 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
4966 tmp_seq
= mac
->loc_seq
;
4969 tmp_seq
= mac
->rem_seq
;
4970 mac_type
= "remote";
4972 if (seq
< tmp_seq
) {
4973 if (IS_ZEBRA_DEBUG_VXLAN
)
4974 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
4976 prefix_mac2str(macaddr
,
4978 ipa_len
? " IP " : "",
4981 buf1
, sizeof(buf1
)) : "",
4988 /* Check MAC's curent state is local (this is the case
4989 * where MAC has moved from L->R) and check previous
4990 * detection started via local learning.
4991 * RFC-7432: A PE/VTEP that detects a MAC mobility
4992 * event via local learning starts an M-second timer.
4994 * VTEP-IP or seq. change along is not considered
4995 * for dup. detection.
4997 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) &&
5001 /* Remove local MAC from BGP. */
5002 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5003 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5005 /* Set "auto" and "remote" forwarding info. */
5006 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5007 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5008 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5009 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5012 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5014 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5017 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5019 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5021 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5022 mac
->fwd_info
.r_vtep_ip
,
5023 do_dad
, &is_dup_detect
,
5026 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5028 /* Install the entry. */
5030 zvni_mac_install(zvni
, mac
);
5033 /* Update seq number. */
5036 /* If there is no IP, return after clearing AUTO flag of MAC. */
5038 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5045 /* Check if the remote neighbor itself is unknown or has a
5046 * change. If so, create or update and then install the entry.
5048 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5050 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5051 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5052 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5053 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5054 || seq
!= n
->rem_seq
)
5059 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5062 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5063 ipaddr2str(ipaddr
, buf1
,
5065 prefix_mac2str(macaddr
, buf
,
5067 vni
, inet_ntoa(vtep_ip
));
5074 /* When host moves but changes its (MAC,IP)
5075 * binding, BGP may install a MACIP entry that
5076 * corresponds to "older" location of the host
5077 * in transient situations (because {IP1,M1}
5078 * is a different route from {IP1,M2}). Check
5079 * the sequence number and ignore this update
5082 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5083 tmp_seq
= n
->loc_seq
;
5086 tmp_seq
= n
->rem_seq
;
5089 if (seq
< tmp_seq
) {
5090 if (IS_ZEBRA_DEBUG_VXLAN
)
5091 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5093 prefix_mac2str(macaddr
,
5096 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5101 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5102 /* MAC change, send a delete for old
5103 * neigh if learnt locally.
5105 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5106 IS_ZEBRA_NEIGH_ACTIVE(n
))
5107 zvni_neigh_send_del_to_client(
5111 /* update neigh list for macs */
5112 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5114 listnode_delete(old_mac
->neigh_list
, n
);
5115 zvni_deref_ip2mac(zvni
, old_mac
);
5117 listnode_add_sort(mac
->neigh_list
, n
);
5118 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5120 /* Check Neigh's curent state is local
5121 * (this is the case where neigh/host has moved
5122 * from L->R) and check previous detction
5123 * started via local learning.
5125 * RFC-7432: A PE/VTEP that detects a MAC
5126 * mobilit event via local learning starts
5127 * an M-second timer.
5128 * VTEP-IP or seq. change along is not
5129 * considered for dup. detection.
5131 * Mobilty event scenario-B IP-MAC binding
5134 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5141 /* Set "remote" forwarding info. */
5142 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5143 n
->r_vtep_ip
= vtep_ip
;
5144 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5146 /* Set router flag (R-bit) to this Neighbor entry */
5147 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5148 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5150 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5152 /* Check old or new MAC detected as duplicate,
5153 * inherit duplicate flag to this neigh.
5155 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5157 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5158 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5160 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5161 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5164 /* Check duplicate address detection for IP */
5165 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5170 /* Install the entry. */
5172 zvni_neigh_install(zvni
, n
);
5175 /* Update seq number. */
5179 /* Process a remote MACIP delete from BGP. */
5180 static void process_remote_macip_del(vni_t vni
,
5181 struct ethaddr
*macaddr
,
5183 struct ipaddr
*ipaddr
,
5184 struct in_addr vtep_ip
)
5187 zebra_mac_t
*mac
= NULL
;
5188 zebra_neigh_t
*n
= NULL
;
5189 struct interface
*ifp
= NULL
;
5190 struct zebra_if
*zif
= NULL
;
5191 char buf
[ETHER_ADDR_STRLEN
];
5192 char buf1
[INET6_ADDRSTRLEN
];
5194 /* Locate VNI hash entry - expected to exist. */
5195 zvni
= zvni_lookup(vni
);
5197 if (IS_ZEBRA_DEBUG_VXLAN
)
5198 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5202 ifp
= zvni
->vxlan_if
;
5206 !if_is_operative(ifp
) ||
5208 !zif
->brslave_info
.br_if
) {
5209 if (IS_ZEBRA_DEBUG_VXLAN
)
5210 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5215 /* The remote VTEP specified is normally expected to exist, but
5216 * it is possible that the peer may delete the VTEP before deleting
5217 * any MACs referring to the VTEP, in which case the handler (see
5218 * remote_vtep_del) would have already deleted the MACs.
5220 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5223 mac
= zvni_mac_lookup(zvni
, macaddr
);
5225 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5228 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5229 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5230 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5234 /* If the remote mac or neighbor doesn't exist there is nothing
5235 * more to do. Otherwise, uninstall the entry and then remove it.
5240 /* Ignore the delete if this mac is a gateway mac-ip */
5242 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5243 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5245 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5247 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5248 ipa_len
? " IP " : "",
5250 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5254 /* Uninstall remote neighbor or MAC. */
5256 /* When the MAC changes for an IP, it is possible the
5257 * client may update the new MAC before trying to delete the
5258 * "old" neighbor (as these are two different MACIP routes).
5259 * Do the delete only if the MAC matches.
5261 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5262 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5263 zvni_neigh_uninstall(zvni
, n
);
5264 zvni_neigh_del(zvni
, n
);
5265 zvni_deref_ip2mac(zvni
, mac
);
5268 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5269 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5271 * the remote sequence number in the auto mac entry
5272 * needs to be reset to 0 as the mac entry may have
5273 * been removed on all VTEPs (including
5274 * the originating one)
5278 /* If all remote neighbors referencing a remote MAC
5279 * go away, we need to uninstall the MAC.
5281 if (remote_neigh_count(mac
) == 0) {
5282 zvni_mac_uninstall(zvni
, mac
);
5283 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5285 if (list_isempty(mac
->neigh_list
))
5286 zvni_mac_del(zvni
, mac
);
5288 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5294 /* Public functions */
5296 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5298 zebra_l3vni_t
*zl3vni
= NULL
;
5300 zl3vni
= zl3vni_lookup(vni
);
5304 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5307 /* handle evpn route in vrf table */
5308 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5309 struct ipaddr
*vtep_ip
,
5310 struct prefix
*host_prefix
)
5312 zebra_l3vni_t
*zl3vni
= NULL
;
5313 struct ipaddr ipv4_vtep
;
5315 zl3vni
= zl3vni_from_vrf(vrf_id
);
5316 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5320 * add the next hop neighbor -
5321 * neigh to be installed is the ipv6 nexthop neigh
5323 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5326 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5327 * address. Rmac is programmed against the ipv4 vtep because we only
5328 * support ipv4 tunnels in the h/w right now
5330 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5331 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5332 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5333 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5334 &(ipv4_vtep
.ipaddr_v4
));
5336 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5337 sizeof(struct in_addr
));
5340 * add the rmac - remote rmac to be installed is against the ipv4
5343 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5346 /* handle evpn vrf route delete */
5347 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5348 struct ipaddr
*vtep_ip
,
5349 struct prefix
*host_prefix
)
5351 zebra_l3vni_t
*zl3vni
= NULL
;
5352 zebra_neigh_t
*nh
= NULL
;
5353 zebra_mac_t
*zrmac
= NULL
;
5355 zl3vni
= zl3vni_from_vrf(vrf_id
);
5359 /* find the next hop entry and rmac entry */
5360 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5363 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5365 /* delete the next hop entry */
5366 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5368 /* delete the rmac entry */
5370 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5374 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5375 struct ethaddr
*rmac
, bool use_json
)
5377 zebra_l3vni_t
*zl3vni
= NULL
;
5378 zebra_mac_t
*zrmac
= NULL
;
5379 json_object
*json
= NULL
;
5381 if (!is_evpn_enabled()) {
5383 vty_out(vty
, "{}\n");
5388 json
= json_object_new_object();
5390 zl3vni
= zl3vni_lookup(l3vni
);
5393 vty_out(vty
, "{}\n");
5395 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5399 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5402 vty_out(vty
, "{}\n");
5405 "%% Requested RMAC doesn't exist in L3-VNI %u",
5410 zl3vni_print_rmac(zrmac
, vty
, json
);
5413 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5414 json
, JSON_C_TO_STRING_PRETTY
));
5415 json_object_free(json
);
5419 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5421 zebra_l3vni_t
*zl3vni
;
5423 struct rmac_walk_ctx wctx
;
5424 json_object
*json
= NULL
;
5426 if (!is_evpn_enabled())
5429 zl3vni
= zl3vni_lookup(l3vni
);
5432 vty_out(vty
, "{}\n");
5434 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5437 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5442 json
= json_object_new_object();
5444 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5448 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5450 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5452 json_object_int_add(json
, "numRmacs", num_rmacs
);
5454 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5457 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5458 json
, JSON_C_TO_STRING_PRETTY
));
5459 json_object_free(json
);
5463 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5465 json_object
*json
= NULL
;
5468 if (!is_evpn_enabled()) {
5470 vty_out(vty
, "{}\n");
5475 json
= json_object_new_object();
5479 hash_iterate(zrouter
.l3vni_table
,
5480 (void (*)(struct hash_backet
*,
5481 void *))zl3vni_print_rmac_hash_all_vni
,
5485 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5486 json
, JSON_C_TO_STRING_PRETTY
));
5487 json_object_free(json
);
5491 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5492 struct ipaddr
*ip
, bool use_json
)
5494 zebra_l3vni_t
*zl3vni
= NULL
;
5495 zebra_neigh_t
*n
= NULL
;
5496 json_object
*json
= NULL
;
5498 if (!is_evpn_enabled()) {
5500 vty_out(vty
, "{}\n");
5505 json
= json_object_new_object();
5507 zl3vni
= zl3vni_lookup(l3vni
);
5510 vty_out(vty
, "{}\n");
5512 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5516 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5519 vty_out(vty
, "{}\n");
5522 "%% Requested next-hop not present for L3-VNI %u",
5527 zl3vni_print_nh(n
, vty
, json
);
5530 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5531 json
, JSON_C_TO_STRING_PRETTY
));
5532 json_object_free(json
);
5536 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5539 struct nh_walk_ctx wctx
;
5540 json_object
*json
= NULL
;
5541 zebra_l3vni_t
*zl3vni
= NULL
;
5543 if (!is_evpn_enabled())
5546 zl3vni
= zl3vni_lookup(l3vni
);
5549 vty_out(vty
, "{}\n");
5551 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5555 num_nh
= hashcount(zl3vni
->nh_table
);
5560 json
= json_object_new_object();
5565 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5567 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5569 json_object_int_add(json
, "numNextHops", num_nh
);
5571 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5574 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5575 json
, JSON_C_TO_STRING_PRETTY
));
5576 json_object_free(json
);
5580 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5582 json_object
*json
= NULL
;
5585 if (!is_evpn_enabled()) {
5587 vty_out(vty
, "{}\n");
5592 json
= json_object_new_object();
5596 hash_iterate(zrouter
.l3vni_table
,
5597 (void (*)(struct hash_backet
*,
5598 void *))zl3vni_print_nh_hash_all_vni
,
5602 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5603 json
, JSON_C_TO_STRING_PRETTY
));
5604 json_object_free(json
);
5609 * Display L3 VNI information (VTY command handler).
5611 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5614 json_object
*json
= NULL
;
5615 zebra_l3vni_t
*zl3vni
= NULL
;
5617 if (!is_evpn_enabled()) {
5619 vty_out(vty
, "{}\n");
5623 zl3vni
= zl3vni_lookup(vni
);
5626 vty_out(vty
, "{}\n");
5628 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5633 json
= json_object_new_object();
5637 zl3vni_print(zl3vni
, (void *)args
);
5640 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5641 json
, JSON_C_TO_STRING_PRETTY
));
5642 json_object_free(json
);
5646 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5647 json_object
*json_vrfs
)
5649 char buf
[ETHER_ADDR_STRLEN
];
5650 zebra_l3vni_t
*zl3vni
= NULL
;
5652 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5657 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5658 zvrf_name(zvrf
), zl3vni
->vni
,
5659 zl3vni_vxlan_if_name(zl3vni
),
5660 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5661 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5663 json_object
*json_vrf
= NULL
;
5665 json_vrf
= json_object_new_object();
5666 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5667 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5668 json_object_string_add(json_vrf
, "vxlanIntf",
5669 zl3vni_vxlan_if_name(zl3vni
));
5670 json_object_string_add(json_vrf
, "sviIntf",
5671 zl3vni_svi_if_name(zl3vni
));
5672 json_object_string_add(json_vrf
, "state",
5673 zl3vni_state2str(zl3vni
));
5674 json_object_string_add(
5675 json_vrf
, "routerMac",
5676 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5677 json_object_array_add(json_vrfs
, json_vrf
);
5682 * Display Neighbors for a VNI (VTY command handler).
5684 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5685 vni_t vni
, bool use_json
)
5689 struct neigh_walk_ctx wctx
;
5690 json_object
*json
= NULL
;
5692 if (!is_evpn_enabled())
5694 zvni
= zvni_lookup(vni
);
5697 vty_out(vty
, "{}\n");
5699 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5702 num_neigh
= hashcount(zvni
->neigh_table
);
5707 json
= json_object_new_object();
5709 /* Since we have IPv6 addresses to deal with which can vary widely in
5710 * size, we try to be a bit more elegant in display by first computing
5711 * the maximum width.
5713 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5716 wctx
.addr_width
= 15;
5718 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5722 "Number of ARPs (local and remote) known for this VNI: %u\n",
5724 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5725 -wctx
.addr_width
, "IP", "Type",
5726 "State", "MAC", "Remote VTEP");
5728 json_object_int_add(json
, "numArpNd", num_neigh
);
5730 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5732 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5733 json
, JSON_C_TO_STRING_PRETTY
));
5734 json_object_free(json
);
5739 * Display neighbors across all VNIs (VTY command handler).
5741 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5742 bool print_dup
, bool use_json
)
5744 json_object
*json
= NULL
;
5747 if (!is_evpn_enabled())
5751 json
= json_object_new_object();
5755 args
[2] = (void *)(ptrdiff_t)print_dup
;
5757 hash_iterate(zvrf
->vni_table
,
5758 (void (*)(struct hash_backet
*,
5759 void *))zvni_print_neigh_hash_all_vni
,
5762 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5763 json
, JSON_C_TO_STRING_PRETTY
));
5764 json_object_free(json
);
5769 * Display specific neighbor for a VNI, if present (VTY command handler).
5771 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
5772 struct zebra_vrf
*zvrf
, vni_t vni
,
5773 struct ipaddr
*ip
, bool use_json
)
5777 json_object
*json
= NULL
;
5779 if (!is_evpn_enabled())
5781 zvni
= zvni_lookup(vni
);
5784 vty_out(vty
, "{}\n");
5786 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5789 n
= zvni_neigh_lookup(zvni
, ip
);
5793 "%% Requested neighbor does not exist in VNI %u\n",
5798 json
= json_object_new_object();
5800 zvni_print_neigh(n
, vty
, json
);
5803 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5804 json
, JSON_C_TO_STRING_PRETTY
));
5805 json_object_free(json
);
5810 * Display neighbors for a VNI from specific VTEP (VTY command handler).
5811 * By definition, these are remote neighbors.
5813 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5814 vni_t vni
, struct in_addr vtep_ip
,
5819 struct neigh_walk_ctx wctx
;
5820 json_object
*json
= NULL
;
5822 if (!is_evpn_enabled())
5824 zvni
= zvni_lookup(vni
);
5827 vty_out(vty
, "{}\n");
5829 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5832 num_neigh
= hashcount(zvni
->neigh_table
);
5836 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5839 wctx
.addr_width
= 15;
5840 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
5841 wctx
.r_vtep_ip
= vtep_ip
;
5843 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5844 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
5847 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5848 json
, JSON_C_TO_STRING_PRETTY
));
5849 json_object_free(json
);
5854 * Display Duplicate detected Neighbors for a VNI
5855 * (VTY command handler).
5857 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
5858 struct zebra_vrf
*zvrf
,
5864 struct neigh_walk_ctx wctx
;
5865 json_object
*json
= NULL
;
5867 if (!is_evpn_enabled())
5870 zvni
= zvni_lookup(vni
);
5872 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5876 num_neigh
= hashcount(zvni
->neigh_table
);
5880 num_neigh
= num_dup_detected_neighs(zvni
);
5885 json
= json_object_new_object();
5887 /* Since we have IPv6 addresses to deal with which can vary widely in
5888 * size, we try to be a bit more elegant in display by first computing
5889 * the maximum width.
5891 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
5894 wctx
.addr_width
= 15;
5896 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
5900 "Number of ARPs (local and remote) known for this VNI: %u\n",
5902 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
5903 -wctx
.addr_width
, "IP", "Type",
5904 "State", "MAC", "Remote VTEP");
5906 json_object_int_add(json
, "numArpNd", num_neigh
);
5908 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
5911 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5912 json
, JSON_C_TO_STRING_PRETTY
));
5913 json_object_free(json
);
5918 * Display MACs for a VNI (VTY command handler).
5920 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5921 vni_t vni
, bool use_json
)
5925 struct mac_walk_ctx wctx
;
5926 json_object
*json
= NULL
;
5927 json_object
*json_mac
= NULL
;
5929 if (!is_evpn_enabled())
5931 zvni
= zvni_lookup(vni
);
5934 vty_out(vty
, "{}\n");
5936 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5939 num_macs
= num_valid_macs(zvni
);
5944 json
= json_object_new_object();
5945 json_mac
= json_object_new_object();
5948 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5951 wctx
.json
= json_mac
;
5955 "Number of MACs (local and remote) known for this VNI: %u\n",
5957 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
5958 "Intf/Remote VTEP", "VLAN");
5960 json_object_int_add(json
, "numMacs", num_macs
);
5962 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
5965 json_object_object_add(json
, "macs", json_mac
);
5966 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5967 json
, JSON_C_TO_STRING_PRETTY
));
5968 json_object_free(json
);
5973 * Display MACs for all VNIs (VTY command handler).
5975 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5976 bool print_dup
, bool use_json
)
5978 struct mac_walk_ctx wctx
;
5979 json_object
*json
= NULL
;
5981 if (!is_evpn_enabled()) {
5983 vty_out(vty
, "{}\n");
5987 json
= json_object_new_object();
5989 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
5992 wctx
.print_dup
= print_dup
;
5993 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
5996 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5997 json
, JSON_C_TO_STRING_PRETTY
));
5998 json_object_free(json
);
6003 * Display MACs in detail for all VNIs (VTY command handler).
6005 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6006 struct zebra_vrf
*zvrf
,
6007 bool print_dup
, bool use_json
)
6009 struct mac_walk_ctx wctx
;
6010 json_object
*json
= NULL
;
6012 if (!is_evpn_enabled()) {
6014 vty_out(vty
, "{}\n");
6018 json
= json_object_new_object();
6020 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6023 wctx
.print_dup
= print_dup
;
6024 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6028 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6029 json
, JSON_C_TO_STRING_PRETTY
));
6030 json_object_free(json
);
6035 * Display MACs for all VNIs (VTY command handler).
6037 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6038 struct zebra_vrf
*zvrf
,
6039 struct in_addr vtep_ip
, bool use_json
)
6041 struct mac_walk_ctx wctx
;
6042 json_object
*json
= NULL
;
6044 if (!is_evpn_enabled())
6048 json
= json_object_new_object();
6050 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6052 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6053 wctx
.r_vtep_ip
= vtep_ip
;
6055 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6058 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6059 json
, JSON_C_TO_STRING_PRETTY
));
6060 json_object_free(json
);
6065 * Display specific MAC for a VNI, if present (VTY command handler).
6067 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6068 vni_t vni
, struct ethaddr
*macaddr
,
6073 json_object
*json
= NULL
;
6075 if (!is_evpn_enabled())
6078 zvni
= zvni_lookup(vni
);
6081 vty_out(vty
, "{}\n");
6083 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6086 mac
= zvni_mac_lookup(zvni
, macaddr
);
6089 vty_out(vty
, "{}\n");
6092 "%% Requested MAC does not exist in VNI %u\n",
6098 json
= json_object_new_object();
6100 zvni_print_mac(mac
, vty
, json
);
6102 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6103 json
, JSON_C_TO_STRING_PRETTY
));
6104 json_object_free(json
);
6108 /* Print Duplicate MACs per VNI */
6109 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6110 struct zebra_vrf
*zvrf
,
6111 vni_t vni
, bool use_json
)
6114 struct mac_walk_ctx wctx
;
6116 json_object
*json
= NULL
;
6117 json_object
*json_mac
= NULL
;
6119 if (!is_evpn_enabled())
6122 zvni
= zvni_lookup(vni
);
6124 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6128 num_macs
= num_valid_macs(zvni
);
6132 num_macs
= num_dup_detected_macs(zvni
);
6137 json
= json_object_new_object();
6138 json_mac
= json_object_new_object();
6141 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6144 wctx
.json
= json_mac
;
6148 "Number of MACs (local and remote) known for this VNI: %u\n",
6150 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6151 "Intf/Remote VTEP", "VLAN");
6153 json_object_int_add(json
, "numMacs", num_macs
);
6155 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6158 json_object_object_add(json
, "macs", json_mac
);
6159 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6160 json
, JSON_C_TO_STRING_PRETTY
));
6161 json_object_free(json
);
6166 void zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6167 struct zebra_vrf
*zvrf
,
6168 vni_t vni
, struct ethaddr
*macaddr
)
6172 struct listnode
*node
= NULL
;
6173 zebra_neigh_t
*nbr
= NULL
;
6175 if (!is_evpn_enabled())
6177 zvni
= zvni_lookup(vni
);
6179 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6183 mac
= zvni_mac_lookup(zvni
, macaddr
);
6185 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6190 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6191 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6195 /* Remove all IPs as duplicate associcated with this MAC */
6196 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6197 /* For local neigh mark inactive so MACIP update is generated
6198 * to BGP. This is a scenario where MAC update received
6199 * and detected as duplicate which marked neigh as duplicate.
6200 * Later local neigh update did not get a chance to relay
6201 * to BGP. Similarly remote macip update, neigh needs to be
6202 * installed locally.
6204 if (nbr
->dad_count
) {
6205 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6206 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6207 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6208 zvni_neigh_install(zvni
, nbr
);
6211 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6213 nbr
->detect_start_time
.tv_sec
= 0;
6214 nbr
->dad_dup_detect_time
= 0;
6217 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6219 mac
->detect_start_time
.tv_sec
= 0;
6220 mac
->detect_start_time
.tv_usec
= 0;
6221 mac
->dad_dup_detect_time
= 0;
6222 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6224 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6225 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6227 if (zvni_mac_send_add_to_client(zvni
->vni
,
6233 /* Process all neighbors associated with this MAC. */
6234 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6236 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6237 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6239 /* Install the entry. */
6240 zvni_mac_install(zvni
, mac
);
6245 void zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6246 struct zebra_vrf
*zvrf
,
6247 vni_t vni
, struct ipaddr
*ip
)
6252 char buf
[INET6_ADDRSTRLEN
];
6253 char buf2
[ETHER_ADDR_STRLEN
];
6255 if (!is_evpn_enabled())
6258 zvni
= zvni_lookup(vni
);
6260 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6264 nbr
= zvni_neigh_lookup(zvni
, ip
);
6267 "%% Requested host IP does not exist in VNI %u\n",
6272 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6274 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6276 "%% Requsted host IP %s is not duplicate detected\n",
6281 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6283 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6285 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6286 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6290 if (IS_ZEBRA_DEBUG_VXLAN
)
6291 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6292 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6295 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6297 nbr
->detect_start_time
.tv_sec
= 0;
6298 nbr
->detect_start_time
.tv_usec
= 0;
6299 nbr
->dad_dup_detect_time
= 0;
6300 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6302 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6303 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6305 nbr
->flags
, nbr
->loc_seq
);
6306 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6307 zvni_neigh_install(zvni
, nbr
);
6312 static void zvni_clear_dup_mac_hash(struct hash_backet
*backet
, void *ctxt
)
6314 struct mac_walk_ctx
*wctx
= ctxt
;
6317 struct listnode
*node
= NULL
;
6318 zebra_neigh_t
*nbr
= NULL
;
6320 mac
= (zebra_mac_t
*)backet
->data
;
6326 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6329 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6331 mac
->detect_start_time
.tv_sec
= 0;
6332 mac
->detect_start_time
.tv_usec
= 0;
6333 mac
->dad_dup_detect_time
= 0;
6334 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6336 /* Remove all IPs as duplicate associcated with this MAC */
6337 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6338 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6340 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6342 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6344 nbr
->detect_start_time
.tv_sec
= 0;
6345 nbr
->dad_dup_detect_time
= 0;
6348 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6349 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6351 if (zvni_mac_send_add_to_client(zvni
->vni
,
6353 mac
->flags
, mac
->loc_seq
))
6356 /* Process all neighbors associated with this MAC. */
6357 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6359 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6360 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6362 /* Install the entry. */
6363 zvni_mac_install(zvni
, mac
);
6367 static void zvni_clear_dup_neigh_hash(struct hash_backet
*backet
, void *ctxt
)
6369 struct neigh_walk_ctx
*wctx
= ctxt
;
6372 char buf
[INET6_ADDRSTRLEN
];
6374 nbr
= (zebra_neigh_t
*)backet
->data
;
6380 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6383 if (IS_ZEBRA_DEBUG_VXLAN
) {
6384 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6386 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6387 __PRETTY_FUNCTION__
, buf
,
6388 nbr
->flags
, nbr
->loc_seq
);
6391 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6393 nbr
->detect_start_time
.tv_sec
= 0;
6394 nbr
->detect_start_time
.tv_usec
= 0;
6395 nbr
->dad_dup_detect_time
= 0;
6396 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6398 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6399 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6401 nbr
->flags
, nbr
->loc_seq
);
6402 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6403 zvni_neigh_install(zvni
, nbr
);
6407 static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet
*backet
,
6412 struct zebra_vrf
*zvrf
;
6413 struct mac_walk_ctx m_wctx
;
6414 struct neigh_walk_ctx n_wctx
;
6416 zvni
= (zebra_vni_t
*)backet
->data
;
6420 vty
= (struct vty
*)args
[0];
6421 zvrf
= (struct zebra_vrf
*)args
[1];
6423 if (hashcount(zvni
->neigh_table
)) {
6424 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6428 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6432 if (num_valid_macs(zvni
)) {
6433 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6437 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6442 void zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6443 struct zebra_vrf
*zvrf
)
6447 if (!is_evpn_enabled())
6453 hash_iterate(zvrf
->vni_table
,
6454 (void (*)(struct hash_backet
*, void *))
6455 zvni_clear_dup_detect_hash_vni_all
, args
);
6459 void zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6460 struct zebra_vrf
*zvrf
,
6464 struct mac_walk_ctx m_wctx
;
6465 struct neigh_walk_ctx n_wctx
;
6467 if (!is_evpn_enabled())
6470 zvni
= zvni_lookup(vni
);
6472 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6476 if (hashcount(zvni
->neigh_table
)) {
6477 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6481 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6485 if (num_valid_macs(zvni
)) {
6486 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6490 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6496 * Display MACs for a VNI from specific VTEP (VTY command handler).
6498 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6499 vni_t vni
, struct in_addr vtep_ip
,
6504 struct mac_walk_ctx wctx
;
6505 json_object
*json
= NULL
;
6506 json_object
*json_mac
= NULL
;
6508 if (!is_evpn_enabled())
6510 zvni
= zvni_lookup(vni
);
6513 vty_out(vty
, "{}\n");
6515 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6518 num_macs
= num_valid_macs(zvni
);
6523 json
= json_object_new_object();
6524 json_mac
= json_object_new_object();
6527 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6530 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6531 wctx
.r_vtep_ip
= vtep_ip
;
6532 wctx
.json
= json_mac
;
6533 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6536 json_object_int_add(json
, "numMacs", wctx
.count
);
6538 json_object_object_add(json
, "macs", json_mac
);
6539 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6540 json
, JSON_C_TO_STRING_PRETTY
));
6541 json_object_free(json
);
6547 * Display VNI information (VTY command handler).
6549 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6552 json_object
*json
= NULL
;
6554 zebra_l3vni_t
*zl3vni
= NULL
;
6555 zebra_vni_t
*zvni
= NULL
;
6557 if (!is_evpn_enabled())
6561 json
= json_object_new_object();
6565 zl3vni
= zl3vni_lookup(vni
);
6567 zl3vni_print(zl3vni
, (void *)args
);
6569 zvni
= zvni_lookup(vni
);
6572 vty_out(vty
, "{}\n");
6574 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6578 zvni_print(zvni
, (void *)args
);
6582 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6583 json
, JSON_C_TO_STRING_PRETTY
));
6584 json_object_free(json
);
6588 /* Display all global details for EVPN */
6589 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6594 json_object
*json
= NULL
;
6595 struct zebra_vrf
*zvrf
= NULL
;
6597 if (!is_evpn_enabled())
6600 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6604 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6605 num_l2vnis
= hashcount(zvrf
->vni_table
);
6606 num_vnis
= num_l2vnis
+ num_l3vnis
;
6609 json
= json_object_new_object();
6610 json_object_string_add(json
, "advertiseGatewayMacip",
6611 zvrf
->advertise_gw_macip
? "Yes" : "No");
6612 json_object_int_add(json
, "numVnis", num_vnis
);
6613 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6614 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6615 if (zvrf
->dup_addr_detect
)
6616 json_object_boolean_true_add(json
,
6617 "isDuplicateAddrDetection");
6619 json_object_boolean_false_add(json
,
6620 "isDuplicateAddrDetection");
6621 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6622 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6623 json_object_int_add(json
, "detectionFreezeTime",
6624 zvrf
->dad_freeze_time
);
6627 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6628 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6629 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6630 zvrf
->advertise_gw_macip
? "Yes" : "No");
6631 vty_out(vty
, "Duplicate address detection: %s\n",
6632 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6633 vty_out(vty
, " Detection max-moves %u, time %d\n",
6634 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6635 if (zvrf
->dad_freeze
) {
6636 if (zvrf
->dad_freeze_time
)
6637 vty_out(vty
, " Detection freeze %u\n",
6638 zvrf
->dad_freeze_time
);
6640 vty_out(vty
, " Detection freeze %s\n",
6646 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6647 json
, JSON_C_TO_STRING_PRETTY
));
6648 json_object_free(json
);
6653 * Display VNI hash table (VTY command handler).
6655 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6658 json_object
*json
= NULL
;
6661 if (!is_evpn_enabled())
6665 json
= json_object_new_object();
6667 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6668 "Type", "VxLAN IF", "# MACs", "# ARPs",
6669 "# Remote VTEPs", "Tenant VRF");
6674 /* Display all L2-VNIs */
6675 hash_iterate(zvrf
->vni_table
,
6676 (void (*)(struct hash_backet
*, void *))zvni_print_hash
,
6679 /* Display all L3-VNIs */
6680 hash_iterate(zrouter
.l3vni_table
,
6681 (void (*)(struct hash_backet
*, void *))zl3vni_print_hash
,
6685 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6686 json
, JSON_C_TO_STRING_PRETTY
));
6687 json_object_free(json
);
6691 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
6695 uint32_t max_moves
= 0;
6696 uint32_t freeze_time
= 0;
6697 bool dup_addr_detect
= false;
6698 bool freeze
= false;
6701 STREAM_GETL(s
, dup_addr_detect
);
6702 STREAM_GETL(s
, time
);
6703 STREAM_GETL(s
, max_moves
);
6704 STREAM_GETL(s
, freeze
);
6705 STREAM_GETL(s
, freeze_time
);
6707 /* DAD previous state was enabled, and new state is disable,
6708 * clear all duplicate detected addresses.
6710 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
6711 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
6713 zvrf
->dup_addr_detect
= dup_addr_detect
;
6714 zvrf
->dad_time
= time
;
6715 zvrf
->dad_max_moves
= max_moves
;
6716 zvrf
->dad_freeze
= freeze
;
6717 zvrf
->dad_freeze_time
= freeze_time
;
6719 if (IS_ZEBRA_DEBUG_VXLAN
)
6721 "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
6722 __PRETTY_FUNCTION__
,
6723 zvrf
->dup_addr_detect
? "enable" : "disable",
6724 zvrf
->dad_max_moves
,
6726 zvrf
->dad_freeze
? "enable" : "disable",
6727 zvrf
->dad_freeze_time
);
6734 * Handle neighbor delete notification from the kernel (on a VLAN device
6735 * / L3 interface). This may result in either the neighbor getting deleted
6736 * from our database or being re-added to the kernel (if it is a valid
6739 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
6740 struct interface
*link_if
,
6743 char buf
[INET6_ADDRSTRLEN
];
6744 char buf2
[ETHER_ADDR_STRLEN
];
6745 zebra_neigh_t
*n
= NULL
;
6746 zebra_vni_t
*zvni
= NULL
;
6747 zebra_mac_t
*zmac
= NULL
;
6748 zebra_l3vni_t
*zl3vni
= NULL
;
6750 /* check if this is a remote neigh entry corresponding to remote
6753 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6755 return zl3vni_local_nh_del(zl3vni
, ip
);
6757 /* We are only interested in neighbors on an SVI that resides on top
6758 * of a VxLAN bridge.
6760 zvni
= zvni_from_svi(ifp
, link_if
);
6764 if (!zvni
->vxlan_if
) {
6766 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
6771 if (IS_ZEBRA_DEBUG_VXLAN
)
6772 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
6773 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
6774 ifp
->ifindex
, zvni
->vni
);
6776 /* If entry doesn't exist, nothing to do. */
6777 n
= zvni_neigh_lookup(zvni
, ip
);
6781 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
6783 if (IS_ZEBRA_DEBUG_VXLAN
)
6785 "Trying to del a neigh %s without a mac %s on VNI %u",
6786 ipaddr2str(ip
, buf
, sizeof(buf
)),
6787 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
6793 /* If it is a remote entry, the kernel has aged this out or someone has
6794 * deleted it, it needs to be re-installed as Quagga is the owner.
6796 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6797 zvni_neigh_install(zvni
, n
);
6801 /* Remove neighbor from BGP. */
6802 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
6803 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0);
6805 /* Delete this neighbor entry. */
6806 zvni_neigh_del(zvni
, n
);
6808 /* see if the AUTO mac needs to be deleted */
6809 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
6810 && !listcount(zmac
->neigh_list
))
6811 zvni_mac_del(zvni
, zmac
);
6817 * Handle neighbor add or update notification from the kernel (on a VLAN
6818 * device / L3 interface). This is typically for a local neighbor but can
6819 * also be for a remote neighbor (e.g., ageout notification). It could
6820 * also be a "move" scenario.
6822 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
6823 struct interface
*link_if
,
6825 struct ethaddr
*macaddr
,
6830 char buf
[ETHER_ADDR_STRLEN
];
6831 char buf2
[INET6_ADDRSTRLEN
];
6832 zebra_vni_t
*zvni
= NULL
;
6833 zebra_l3vni_t
*zl3vni
= NULL
;
6835 /* check if this is a remote neigh entry corresponding to remote
6838 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
6840 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
6842 /* We are only interested in neighbors on an SVI that resides on top
6843 * of a VxLAN bridge.
6845 zvni
= zvni_from_svi(ifp
, link_if
);
6849 if (IS_ZEBRA_DEBUG_VXLAN
)
6851 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
6852 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
6853 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
6854 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
6855 is_router
? "router " : "",
6858 /* Is this about a local neighbor or a remote one? */
6860 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
6863 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
6868 * Handle message from client to delete a remote MACIP for a VNI.
6870 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
6874 struct ethaddr macaddr
;
6876 struct in_addr vtep_ip
;
6877 uint16_t l
= 0, ipa_len
;
6878 char buf
[ETHER_ADDR_STRLEN
];
6879 char buf1
[INET6_ADDRSTRLEN
];
6881 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6882 memset(&ip
, 0, sizeof(struct ipaddr
));
6883 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
6887 while (l
< hdr
->length
) {
6888 /* Obtain each remote MACIP and process. */
6889 /* Message contains VNI, followed by MAC followed by IP (if any)
6890 * followed by remote VTEP IP.
6892 memset(&ip
, 0, sizeof(ip
));
6893 STREAM_GETL(s
, vni
);
6894 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
6895 STREAM_GETL(s
, ipa_len
);
6897 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
6899 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
6901 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
6902 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6903 l
+= IPV4_MAX_BYTELEN
;
6905 if (IS_ZEBRA_DEBUG_VXLAN
)
6907 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
6909 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
6910 ipa_len
? " IP " : "",
6912 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
6914 zebra_route_string(client
->proto
));
6916 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
6924 * Handle message from client to add a remote MACIP for a VNI. This
6925 * could be just the add of a MAC address or the add of a neighbor
6928 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
6932 struct ethaddr macaddr
;
6934 struct in_addr vtep_ip
;
6935 uint16_t l
= 0, ipa_len
;
6938 char buf
[ETHER_ADDR_STRLEN
];
6939 char buf1
[INET6_ADDRSTRLEN
];
6941 memset(&macaddr
, 0, sizeof(struct ethaddr
));
6942 memset(&ip
, 0, sizeof(struct ipaddr
));
6943 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
6945 if (!EVPN_ENABLED(zvrf
)) {
6946 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
6952 while (l
< hdr
->length
) {
6953 /* Obtain each remote MACIP and process. */
6954 /* Message contains VNI, followed by MAC followed by IP (if any)
6955 * followed by remote VTEP IP.
6957 memset(&ip
, 0, sizeof(ip
));
6958 STREAM_GETL(s
, vni
);
6959 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
6960 STREAM_GETL(s
, ipa_len
);
6962 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
6964 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
6966 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
6967 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
6968 l
+= IPV4_MAX_BYTELEN
;
6970 /* Get flags - sticky mac and/or gateway mac */
6971 STREAM_GETC(s
, flags
);
6973 STREAM_GETL(s
, seq
);
6976 if (IS_ZEBRA_DEBUG_VXLAN
)
6978 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
6980 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
6981 ipa_len
? " IP " : "",
6983 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
6984 flags
, seq
, inet_ntoa(vtep_ip
),
6985 zebra_route_string(client
->proto
));
6987 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
6988 flags
, seq
, vtep_ip
);
6996 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
6997 * us, this must involve a multihoming scenario. Treat this as implicit delete
6998 * of any prior local MAC.
7000 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7001 struct interface
*br_if
,
7002 struct ethaddr
*macaddr
, vlanid_t vid
)
7004 struct zebra_if
*zif
;
7005 struct zebra_l2info_vxlan
*vxl
;
7009 char buf
[ETHER_ADDR_STRLEN
];
7013 vxl
= &zif
->l2info
.vxl
;
7016 /* Check if EVPN is enabled. */
7017 if (!is_evpn_enabled())
7020 /* Locate hash entry; it is expected to exist. */
7021 zvni
= zvni_lookup(vni
);
7025 /* If entry doesn't exist, nothing to do. */
7026 mac
= zvni_mac_lookup(zvni
, macaddr
);
7030 /* Is it a local entry? */
7031 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7034 if (IS_ZEBRA_DEBUG_VXLAN
)
7036 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7037 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7040 /* Remove MAC from BGP. */
7041 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7044 * If there are no neigh associated with the mac delete the mac
7045 * else mark it as AUTO for forward reference
7047 if (!listcount(mac
->neigh_list
)) {
7048 zvni_mac_del(zvni
, mac
);
7050 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7051 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7058 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7059 * This can happen because the remote MAC entries are also added as "dynamic",
7060 * so the kernel can ageout the entry.
7062 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7063 struct interface
*br_if
,
7064 struct ethaddr
*macaddr
, vlanid_t vid
)
7066 struct zebra_if
*zif
= NULL
;
7067 struct zebra_l2info_vxlan
*vxl
= NULL
;
7069 zebra_vni_t
*zvni
= NULL
;
7070 zebra_l3vni_t
*zl3vni
= NULL
;
7071 zebra_mac_t
*mac
= NULL
;
7072 char buf
[ETHER_ADDR_STRLEN
];
7076 vxl
= &zif
->l2info
.vxl
;
7079 /* Check if EVPN is enabled. */
7080 if (!is_evpn_enabled())
7083 /* check if this is a remote RMAC and readd simillar to remote macs */
7084 zl3vni
= zl3vni_lookup(vni
);
7086 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7088 /* Locate hash entry; it is expected to exist. */
7089 zvni
= zvni_lookup(vni
);
7093 /* If entry doesn't exist, nothing to do. */
7094 mac
= zvni_mac_lookup(zvni
, macaddr
);
7098 /* Is it a remote entry? */
7099 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7102 if (IS_ZEBRA_DEBUG_VXLAN
)
7103 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7104 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7107 zvni_mac_install(zvni
, mac
);
7112 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7114 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7115 struct ethaddr
*macaddr
, vlanid_t vid
)
7119 char buf
[ETHER_ADDR_STRLEN
];
7121 /* We are interested in MACs only on ports or (port, VLAN) that
7124 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7127 if (!zvni
->vxlan_if
) {
7129 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7134 if (IS_ZEBRA_DEBUG_VXLAN
)
7135 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7136 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7137 ifp
->ifindex
, vid
, zvni
->vni
);
7139 /* If entry doesn't exist, nothing to do. */
7140 mac
= zvni_mac_lookup(zvni
, macaddr
);
7144 /* Is it a local entry? */
7145 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7148 /* Update all the neigh entries associated with this mac */
7149 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7151 /* Remove MAC from BGP. */
7152 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7155 * If there are no neigh associated with the mac delete the mac
7156 * else mark it as AUTO for forward reference
7158 if (!listcount(mac
->neigh_list
)) {
7159 zvni_mac_del(zvni
, mac
);
7161 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7162 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7169 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7171 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7172 struct interface
*br_if
,
7173 struct ethaddr
*macaddr
, vlanid_t vid
,
7178 struct zebra_vrf
*zvrf
;
7179 char buf
[ETHER_ADDR_STRLEN
];
7180 bool mac_sticky
= false;
7181 bool inform_client
= false;
7182 bool upd_neigh
= false;
7183 struct in_addr vtep_ip
= {.s_addr
= 0};
7185 /* We are interested in MACs only on ports or (port, VLAN) that
7188 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7190 if (IS_ZEBRA_DEBUG_VXLAN
)
7192 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7193 sticky
? "sticky " : "",
7194 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7195 ifp
->name
, ifp
->ifindex
, vid
);
7199 if (!zvni
->vxlan_if
) {
7201 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7206 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7210 /* Check if we need to create or update or it is a NO-OP. */
7211 mac
= zvni_mac_lookup(zvni
, macaddr
);
7213 if (IS_ZEBRA_DEBUG_VXLAN
)
7215 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7216 sticky
? "sticky " : "",
7217 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7218 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7220 mac
= zvni_mac_add(zvni
, macaddr
);
7223 EC_ZEBRA_MAC_ADD_FAILED
,
7224 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7225 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7226 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7229 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7230 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7231 mac
->fwd_info
.local
.vid
= vid
;
7233 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7234 inform_client
= true;
7237 if (IS_ZEBRA_DEBUG_VXLAN
)
7239 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7240 sticky
? "sticky " : "",
7241 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7242 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7245 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7246 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7250 * Update any changes and if changes are relevant to
7253 if (mac_sticky
== sticky
7254 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7255 && mac
->fwd_info
.local
.vid
== vid
) {
7256 if (IS_ZEBRA_DEBUG_VXLAN
)
7258 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7259 "entry exists and has not changed ",
7260 sticky
? "sticky " : "",
7261 prefix_mac2str(macaddr
, buf
,
7263 ifp
->name
, ifp
->ifindex
, vid
,
7267 if (mac_sticky
!= sticky
) {
7269 SET_FLAG(mac
->flags
,
7272 UNSET_FLAG(mac
->flags
,
7274 inform_client
= true;
7277 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7278 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7279 mac
->fwd_info
.local
.vid
= vid
;
7281 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7282 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7283 bool do_dad
= false;
7286 * MAC has either moved or was "internally" created due
7287 * to a neighbor learn and is now actually learnt. If
7288 * it was learnt as a remote sticky MAC, this is an
7291 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7293 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7294 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7295 prefix_mac2str(macaddr
, buf
,
7297 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7302 /* If an actual move, compute MAC's seq number */
7303 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7304 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7306 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7307 /* Trigger DAD for remote MAC */
7311 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7312 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7313 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7314 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7315 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7316 mac
->fwd_info
.local
.vid
= vid
;
7318 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7320 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7322 * We have to inform BGP of this MAC as well as process
7325 inform_client
= true;
7328 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7335 /* Inform BGP if required. */
7336 if (inform_client
) {
7337 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7338 mac
->flags
, mac
->loc_seq
))
7342 /* Process all neighbors associated with this MAC, if required. */
7344 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7350 * Handle message from client to delete a remote VTEP for a VNI.
7352 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7355 unsigned short l
= 0;
7357 struct in_addr vtep_ip
;
7359 zebra_vtep_t
*zvtep
;
7360 struct interface
*ifp
;
7361 struct zebra_if
*zif
;
7363 if (!is_evpn_enabled()) {
7365 "%s: EVPN is not enabled yet we have received a vtep del command",
7366 __PRETTY_FUNCTION__
);
7370 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7371 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7378 while (l
< hdr
->length
) {
7379 /* Obtain each remote VTEP and process. */
7380 STREAM_GETL(s
, vni
);
7382 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7383 l
+= IPV4_MAX_BYTELEN
;
7385 if (IS_ZEBRA_DEBUG_VXLAN
)
7386 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7387 inet_ntoa(vtep_ip
), vni
,
7388 zebra_route_string(client
->proto
));
7390 /* Locate VNI hash entry - expected to exist. */
7391 zvni
= zvni_lookup(vni
);
7393 if (IS_ZEBRA_DEBUG_VXLAN
)
7395 "Failed to locate VNI hash upon remote VTEP DEL, "
7401 ifp
= zvni
->vxlan_if
;
7404 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7410 /* If down or not mapped to a bridge, we're done. */
7411 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7414 /* If the remote VTEP does not exist, there's nothing more to
7416 * Otherwise, uninstall any remote MACs pointing to this VTEP
7418 * then, the VTEP entry itself and remove it.
7420 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7424 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7425 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7426 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7427 zvni_vtep_del(zvni
, zvtep
);
7435 * Handle message from client to add a remote VTEP for a VNI.
7437 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7440 unsigned short l
= 0;
7442 struct in_addr vtep_ip
;
7444 struct interface
*ifp
;
7445 struct zebra_if
*zif
;
7447 if (!is_evpn_enabled()) {
7449 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7450 __PRETTY_FUNCTION__
);
7454 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7455 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7462 while (l
< hdr
->length
) {
7463 /* Obtain each remote VTEP and process. */
7464 STREAM_GETL(s
, vni
);
7466 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7467 l
+= IPV4_MAX_BYTELEN
;
7469 if (IS_ZEBRA_DEBUG_VXLAN
)
7470 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7471 inet_ntoa(vtep_ip
), vni
,
7472 zebra_route_string(client
->proto
));
7474 /* Locate VNI hash entry - expected to exist. */
7475 zvni
= zvni_lookup(vni
);
7478 EC_ZEBRA_VTEP_ADD_FAILED
,
7479 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7484 ifp
= zvni
->vxlan_if
;
7487 EC_ZEBRA_VTEP_ADD_FAILED
,
7488 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7495 /* If down or not mapped to a bridge, we're done. */
7496 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7499 /* If the remote VTEP already exists,
7500 there's nothing more to do. */
7501 if (zvni_vtep_find(zvni
, &vtep_ip
))
7504 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7505 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7506 "Failed to add remote VTEP, VNI %u zvni %p",
7511 zvni_vtep_install(zvni
, &vtep_ip
);
7519 * Add/Del gateway macip to evpn
7521 * 1. SVI interface on a vlan aware bridge
7522 * 2. SVI interface on a vlan unaware bridge
7523 * 3. vrr interface (MACVLAN) associated to a SVI
7524 * We advertise macip routes for an interface if it is associated to VxLan vlan
7526 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7530 struct ethaddr macaddr
;
7531 zebra_vni_t
*zvni
= NULL
;
7533 memset(&ip
, 0, sizeof(struct ipaddr
));
7534 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7536 /* Check if EVPN is enabled. */
7537 if (!is_evpn_enabled())
7540 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7541 struct interface
*svi_if
=
7542 NULL
; /* SVI corresponding to the MACVLAN */
7543 struct zebra_if
*ifp_zif
=
7544 NULL
; /* Zebra daemon specific info for MACVLAN */
7545 struct zebra_if
*svi_if_zif
=
7546 NULL
; /* Zebra daemon specific info for SVI*/
7548 ifp_zif
= ifp
->info
;
7553 * for a MACVLAN interface the link represents the svi_if
7555 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7556 ifp_zif
->link_ifindex
);
7558 zlog_debug("MACVLAN %s(%u) without link information",
7559 ifp
->name
, ifp
->ifindex
);
7563 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7565 * If it is a vlan aware bridge then the link gives the
7566 * bridge information
7568 struct interface
*svi_if_link
= NULL
;
7570 svi_if_zif
= svi_if
->info
;
7572 svi_if_link
= if_lookup_by_index_per_ns(
7573 zebra_ns_lookup(NS_DEFAULT
),
7574 svi_if_zif
->link_ifindex
);
7575 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7577 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7579 * If it is a vlan unaware bridge then svi is the bridge
7582 zvni
= zvni_from_svi(svi_if
, svi_if
);
7584 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7585 struct zebra_if
*svi_if_zif
=
7586 NULL
; /* Zebra daemon specific info for SVI */
7587 struct interface
*svi_if_link
=
7588 NULL
; /* link info for the SVI = bridge info */
7590 svi_if_zif
= ifp
->info
;
7592 svi_if_link
= if_lookup_by_index_per_ns(
7593 zebra_ns_lookup(NS_DEFAULT
),
7594 svi_if_zif
->link_ifindex
);
7596 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7598 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7599 zvni
= zvni_from_svi(ifp
, ifp
);
7605 if (!zvni
->vxlan_if
) {
7606 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
7612 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
7614 if (p
->family
== AF_INET
) {
7615 ip
.ipa_type
= IPADDR_V4
;
7616 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
7617 sizeof(struct in_addr
));
7618 } else if (p
->family
== AF_INET6
) {
7619 ip
.ipa_type
= IPADDR_V6
;
7620 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
7621 sizeof(struct in6_addr
));
7626 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
7628 zvni_gw_macip_del(ifp
, zvni
, &ip
);
7634 * Handle SVI interface going down.
7635 * SVI can be associated to either L3-VNI or L2-VNI.
7636 * For L2-VNI: At this point, this is a NOP since
7637 * the kernel deletes the neighbor entries on this SVI (if any).
7638 * We only need to update the vrf corresponding to zvni.
7639 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
7642 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
7644 zebra_l3vni_t
*zl3vni
= NULL
;
7646 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7649 /* process l3-vni down */
7650 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7652 /* remove association with svi-if */
7653 zl3vni
->svi_if
= NULL
;
7655 zebra_vni_t
*zvni
= NULL
;
7657 /* since we dont have svi corresponding to zvni, we associate it
7658 * to default vrf. Note: the corresponding neigh entries on the
7659 * SVI would have already been deleted */
7660 zvni
= zvni_from_svi(ifp
, link_if
);
7662 zvni
->vrf_id
= VRF_DEFAULT
;
7664 /* update the tenant vrf in BGP */
7665 zvni_send_add_to_client(zvni
);
7672 * Handle SVI interface coming up.
7673 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
7675 * For L2-VNI: we need to install any remote neighbors entried (used for
7677 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
7679 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
7681 zebra_vni_t
*zvni
= NULL
;
7682 zebra_l3vni_t
*zl3vni
= NULL
;
7684 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7687 /* associate with svi */
7688 zl3vni
->svi_if
= ifp
;
7690 /* process oper-up */
7691 if (is_l3vni_oper_up(zl3vni
))
7692 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7695 /* process SVI up for l2-vni */
7696 struct neigh_walk_ctx n_wctx
;
7698 zvni
= zvni_from_svi(ifp
, link_if
);
7702 if (!zvni
->vxlan_if
) {
7704 "VNI %u hash %p doesn't have intf upon SVI up",
7709 if (IS_ZEBRA_DEBUG_VXLAN
)
7711 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
7712 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
7713 vrf_id_to_name(ifp
->vrf_id
));
7715 /* update the vrf information for l2-vni and inform bgp */
7716 zvni
->vrf_id
= ifp
->vrf_id
;
7717 zvni_send_add_to_client(zvni
);
7719 /* Install any remote neighbors for this VNI. */
7720 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7722 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
7730 * Handle VxLAN interface down
7732 int zebra_vxlan_if_down(struct interface
*ifp
)
7735 struct zebra_if
*zif
= NULL
;
7736 struct zebra_l2info_vxlan
*vxl
= NULL
;
7737 zebra_l3vni_t
*zl3vni
= NULL
;
7740 /* Check if EVPN is enabled. */
7741 if (!is_evpn_enabled())
7746 vxl
= &zif
->l2info
.vxl
;
7749 zl3vni
= zl3vni_lookup(vni
);
7751 /* process-if-down for l3-vni */
7752 if (IS_ZEBRA_DEBUG_VXLAN
)
7753 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
7756 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7758 /* process if-down for l2-vni */
7759 if (IS_ZEBRA_DEBUG_VXLAN
)
7760 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
7763 /* Locate hash entry; it is expected to exist. */
7764 zvni
= zvni_lookup(vni
);
7767 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
7768 ifp
->name
, ifp
->ifindex
, vni
);
7772 assert(zvni
->vxlan_if
== ifp
);
7774 /* Delete this VNI from BGP. */
7775 zvni_send_del_to_client(zvni
->vni
);
7777 /* Free up all neighbors and MACs, if any. */
7778 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
7779 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
7781 /* Free up all remote VTEPs, if any. */
7782 zvni_vtep_del_all(zvni
, 1);
7788 * Handle VxLAN interface up - update BGP if required.
7790 int zebra_vxlan_if_up(struct interface
*ifp
)
7793 struct zebra_if
*zif
= NULL
;
7794 struct zebra_l2info_vxlan
*vxl
= NULL
;
7795 zebra_vni_t
*zvni
= NULL
;
7796 zebra_l3vni_t
*zl3vni
= NULL
;
7798 /* Check if EVPN is enabled. */
7799 if (!is_evpn_enabled())
7804 vxl
= &zif
->l2info
.vxl
;
7807 zl3vni
= zl3vni_lookup(vni
);
7810 if (IS_ZEBRA_DEBUG_VXLAN
)
7811 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
7814 /* we need to associate with SVI, if any, we can associate with
7815 * svi-if only after association with vxlan-intf is complete
7817 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7819 if (is_l3vni_oper_up(zl3vni
))
7820 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
7822 /* Handle L2-VNI add */
7823 struct interface
*vlan_if
= NULL
;
7825 if (IS_ZEBRA_DEBUG_VXLAN
)
7826 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
7829 /* Locate hash entry; it is expected to exist. */
7830 zvni
= zvni_lookup(vni
);
7833 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
7834 ifp
->name
, ifp
->ifindex
, vni
);
7838 assert(zvni
->vxlan_if
== ifp
);
7839 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
7840 zif
->brslave_info
.br_if
);
7842 zvni
->vrf_id
= vlan_if
->vrf_id
;
7843 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
7845 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
7848 /* If part of a bridge, inform BGP about this VNI. */
7849 /* Also, read and populate local MACs and neighbors. */
7850 if (zif
->brslave_info
.br_if
) {
7851 zvni_send_add_to_client(zvni
);
7852 zvni_read_mac_neigh(zvni
, ifp
);
7860 * Handle VxLAN interface delete. Locate and remove entry in hash table
7861 * and update BGP, if required.
7863 int zebra_vxlan_if_del(struct interface
*ifp
)
7866 struct zebra_if
*zif
= NULL
;
7867 struct zebra_l2info_vxlan
*vxl
= NULL
;
7868 zebra_vni_t
*zvni
= NULL
;
7869 zebra_l3vni_t
*zl3vni
= NULL
;
7871 /* Check if EVPN is enabled. */
7872 if (!is_evpn_enabled())
7877 vxl
= &zif
->l2info
.vxl
;
7880 zl3vni
= zl3vni_lookup(vni
);
7883 if (IS_ZEBRA_DEBUG_VXLAN
)
7884 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
7887 /* process oper-down for l3-vni */
7888 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7890 /* remove the association with vxlan_if */
7891 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
7892 zl3vni
->vxlan_if
= NULL
;
7895 /* process if-del for l2-vni*/
7896 if (IS_ZEBRA_DEBUG_VXLAN
)
7897 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
7900 /* Locate hash entry; it is expected to exist. */
7901 zvni
= zvni_lookup(vni
);
7904 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
7905 ifp
->name
, ifp
->ifindex
, vni
);
7909 /* remove from l3-vni list */
7910 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
7912 listnode_delete(zl3vni
->l2vnis
, zvni
);
7914 /* Delete VNI from BGP. */
7915 zvni_send_del_to_client(zvni
->vni
);
7917 /* Free up all neighbors and MAC, if any. */
7918 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
7919 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
7921 /* Free up all remote VTEPs, if any. */
7922 zvni_vtep_del_all(zvni
, 0);
7924 /* Delete the hash entry. */
7925 if (zvni_del(zvni
)) {
7926 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
7927 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
7928 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
7936 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
7938 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
7941 struct zebra_if
*zif
= NULL
;
7942 struct zebra_l2info_vxlan
*vxl
= NULL
;
7943 zebra_vni_t
*zvni
= NULL
;
7944 zebra_l3vni_t
*zl3vni
= NULL
;
7946 /* Check if EVPN is enabled. */
7947 if (!is_evpn_enabled())
7952 vxl
= &zif
->l2info
.vxl
;
7955 zl3vni
= zl3vni_lookup(vni
);
7958 if (IS_ZEBRA_DEBUG_VXLAN
)
7960 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
7961 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
7962 inet_ntoa(vxl
->vtep_ip
),
7963 zif
->brslave_info
.bridge_ifindex
, chgflags
);
7965 /* Removed from bridge? Cleanup and return */
7966 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
7967 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
7968 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7972 /* access-vlan change - process oper down, associate with new
7973 * svi_if and then process oper up again
7975 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
7976 if (if_is_operative(ifp
)) {
7977 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7978 zl3vni
->svi_if
= NULL
;
7979 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
7980 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7981 if (is_l3vni_oper_up(zl3vni
))
7982 zebra_vxlan_process_l3vni_oper_up(
7988 * local-ip change - process oper down, associate with new
7989 * local-ip and then process oper up again
7991 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
7992 if (if_is_operative(ifp
)) {
7993 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
7994 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
7995 if (is_l3vni_oper_up(zl3vni
))
7996 zebra_vxlan_process_l3vni_oper_up(
8001 /* Update local tunnel IP. */
8002 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8004 /* if we have a valid new master, process l3-vni oper up */
8005 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8006 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8007 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8011 /* Update VNI hash. */
8012 zvni
= zvni_lookup(vni
);
8015 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8016 ifp
->name
, ifp
->ifindex
, vni
);
8020 if (IS_ZEBRA_DEBUG_VXLAN
)
8022 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8023 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8024 inet_ntoa(vxl
->vtep_ip
),
8025 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8027 /* Removed from bridge? Cleanup and return */
8028 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8029 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8030 /* Delete from client, remove all remote VTEPs */
8031 /* Also, free up all MACs and neighbors. */
8032 zvni_send_del_to_client(zvni
->vni
);
8033 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8034 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8035 zvni_vtep_del_all(zvni
, 1);
8039 /* Handle other changes. */
8040 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8041 /* Remove all existing local neigh and MACs for this VNI
8042 * (including from BGP)
8044 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8045 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8048 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8049 zvni
->vxlan_if
= ifp
;
8051 /* Take further actions needed.
8052 * Note that if we are here, there is a change of interest.
8054 /* If down or not mapped to a bridge, we're done. */
8055 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8058 /* Inform BGP, if there is a change of interest. */
8060 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8061 zvni_send_add_to_client(zvni
);
8063 /* If there is a valid new master or a VLAN mapping change,
8064 * read and populate local MACs and neighbors.
8065 * Also, reinstall any remote MACs and neighbors
8066 * for this VNI (based on new VLAN).
8068 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8069 zvni_read_mac_neigh(zvni
, ifp
);
8070 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8071 struct mac_walk_ctx m_wctx
;
8072 struct neigh_walk_ctx n_wctx
;
8074 zvni_read_mac_neigh(zvni
, ifp
);
8076 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8078 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8081 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8083 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8092 * Handle VxLAN interface add.
8094 int zebra_vxlan_if_add(struct interface
*ifp
)
8097 struct zebra_if
*zif
= NULL
;
8098 struct zebra_l2info_vxlan
*vxl
= NULL
;
8099 zebra_vni_t
*zvni
= NULL
;
8100 zebra_l3vni_t
*zl3vni
= NULL
;
8102 /* Check if EVPN is enabled. */
8103 if (!is_evpn_enabled())
8108 vxl
= &zif
->l2info
.vxl
;
8111 zl3vni
= zl3vni_lookup(vni
);
8114 /* process if-add for l3-vni*/
8115 if (IS_ZEBRA_DEBUG_VXLAN
)
8117 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8118 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8119 inet_ntoa(vxl
->vtep_ip
),
8120 zif
->brslave_info
.bridge_ifindex
);
8122 /* associate with vxlan_if */
8123 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8124 zl3vni
->vxlan_if
= ifp
;
8126 /* Associate with SVI, if any. We can associate with svi-if only
8127 * after association with vxlan_if is complete */
8128 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8130 if (is_l3vni_oper_up(zl3vni
))
8131 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8134 /* process if-add for l2-vni */
8135 struct interface
*vlan_if
= NULL
;
8137 /* Create or update VNI hash. */
8138 zvni
= zvni_lookup(vni
);
8140 zvni
= zvni_add(vni
);
8143 EC_ZEBRA_VNI_ADD_FAILED
,
8144 "Failed to add VNI hash, IF %s(%u) VNI %u",
8145 ifp
->name
, ifp
->ifindex
, vni
);
8150 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8151 zvni
->vxlan_if
= ifp
;
8152 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8153 zif
->brslave_info
.br_if
);
8155 zvni
->vrf_id
= vlan_if
->vrf_id
;
8156 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8158 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8161 if (IS_ZEBRA_DEBUG_VXLAN
)
8163 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8165 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8167 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8168 inet_ntoa(vxl
->vtep_ip
),
8169 zif
->brslave_info
.bridge_ifindex
);
8171 /* If down or not mapped to a bridge, we're done. */
8172 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8176 zvni_send_add_to_client(zvni
);
8178 /* Read and populate local MACs and neighbors */
8179 zvni_read_mac_neigh(zvni
, ifp
);
8185 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8186 char *err
, int err_str_sz
, int filter
,
8189 zebra_l3vni_t
*zl3vni
= NULL
;
8190 struct zebra_vrf
*zvrf_default
= NULL
;
8192 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8196 if (IS_ZEBRA_DEBUG_VXLAN
)
8197 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8198 add
? "ADD" : "DEL");
8202 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8204 /* check if the vni is already present under zvrf */
8206 snprintf(err
, err_str_sz
,
8207 "VNI is already configured under the vrf");
8211 /* check if this VNI is already present in the system */
8212 zl3vni
= zl3vni_lookup(vni
);
8214 snprintf(err
, err_str_sz
,
8215 "VNI is already configured as L3-VNI");
8219 /* add the L3-VNI to the global table */
8220 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8222 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8226 /* associate the vrf with vni */
8229 /* set the filter in l3vni to denote if we are using l3vni only
8233 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8235 /* associate with vxlan-intf;
8236 * we need to associate with the vxlan-intf first
8238 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8240 /* associate with corresponding SVI interface, we can associate
8241 * with svi-if only after vxlan interface association is
8244 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8246 /* formulate l2vni list */
8247 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8250 if (is_l3vni_oper_up(zl3vni
))
8251 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8254 zl3vni
= zl3vni_lookup(vni
);
8256 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8260 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8261 snprintf(err
, ERR_STR_SZ
,
8262 "prefix-routes-only is not set for the vni");
8266 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8268 /* delete and uninstall all rmacs */
8269 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8272 /* delete and uninstall all next-hops */
8273 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8279 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8284 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8286 zebra_l3vni_t
*zl3vni
= NULL
;
8289 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8293 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8294 if (is_l3vni_oper_up(zl3vni
))
8295 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8299 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8301 zebra_l3vni_t
*zl3vni
= NULL
;
8304 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8308 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8309 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8313 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8315 zebra_l3vni_t
*zl3vni
= NULL
;
8319 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8325 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8331 * Handle message from client to specify the flooding mechanism for
8332 * BUM packets. The default is to do head-end (ingress) replication
8333 * and the other supported option is to disable it. This applies to
8334 * all BUM traffic and disabling it applies to both the transmit and
8335 * receive direction.
8337 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8340 enum vxlan_flood_control flood_ctrl
;
8342 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8343 zlog_err("EVPN flood control for non-default VRF %u",
8349 STREAM_GETC(s
, flood_ctrl
);
8351 if (IS_ZEBRA_DEBUG_VXLAN
)
8352 zlog_debug("EVPN flood control %u, currently %u",
8353 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8355 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8358 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8360 /* Install or uninstall flood entries corresponding to
8363 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8371 * Handle message from client to enable/disable advertisement of g/w macip
8374 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8379 zebra_vni_t
*zvni
= NULL
;
8380 struct interface
*ifp
= NULL
;
8381 struct zebra_if
*zif
= NULL
;
8382 struct zebra_l2info_vxlan zl2_info
;
8383 struct interface
*vlan_if
= NULL
;
8385 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8386 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8392 STREAM_GETC(s
, advertise
);
8393 vni
= stream_get3(s
);
8395 zvni
= zvni_lookup(vni
);
8399 if (zvni
->advertise_subnet
== advertise
)
8402 if (IS_ZEBRA_DEBUG_VXLAN
)
8403 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8404 advertise
? "enabled" : "disabled", vni
,
8405 zvni
->advertise_subnet
? "enabled" : "disabled");
8408 zvni
->advertise_subnet
= advertise
;
8410 ifp
= zvni
->vxlan_if
;
8416 /* If down or not mapped to a bridge, we're done. */
8417 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8420 zl2_info
= zif
->l2info
.vxl
;
8423 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8427 if (zvni
->advertise_subnet
)
8428 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8430 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8437 * Handle message from client to enable/disable advertisement of g/w macip
8440 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8445 zebra_vni_t
*zvni
= NULL
;
8446 struct interface
*ifp
= NULL
;
8448 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8449 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8455 STREAM_GETC(s
, advertise
);
8456 STREAM_GETL(s
, vni
);
8459 if (IS_ZEBRA_DEBUG_VXLAN
)
8460 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8461 advertise
? "enabled" : "disabled",
8462 advertise_gw_macip_enabled(NULL
)
8466 if (zvrf
->advertise_gw_macip
== advertise
)
8469 zvrf
->advertise_gw_macip
= advertise
;
8471 if (advertise_gw_macip_enabled(zvni
))
8472 hash_iterate(zvrf
->vni_table
,
8473 zvni_gw_macip_add_for_vni_hash
, NULL
);
8475 hash_iterate(zvrf
->vni_table
,
8476 zvni_gw_macip_del_for_vni_hash
, NULL
);
8479 struct zebra_if
*zif
= NULL
;
8480 struct zebra_l2info_vxlan zl2_info
;
8481 struct interface
*vlan_if
= NULL
;
8482 struct interface
*vrr_if
= NULL
;
8484 zvni
= zvni_lookup(vni
);
8488 if (IS_ZEBRA_DEBUG_VXLAN
)
8490 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8491 advertise
? "enabled" : "disabled", vni
,
8492 advertise_gw_macip_enabled(zvni
) ? "enabled"
8495 if (zvni
->advertise_gw_macip
== advertise
)
8498 zvni
->advertise_gw_macip
= advertise
;
8500 ifp
= zvni
->vxlan_if
;
8506 /* If down or not mapped to a bridge, we're done. */
8507 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8510 zl2_info
= zif
->l2info
.vxl
;
8512 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8513 zif
->brslave_info
.br_if
);
8517 if (advertise_gw_macip_enabled(zvni
)) {
8518 /* Add primary SVI MAC-IP */
8519 zvni_add_macip_for_intf(vlan_if
, zvni
);
8521 /* Add VRR MAC-IP - if any*/
8522 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8524 zvni_add_macip_for_intf(vrr_if
, zvni
);
8526 /* Del primary MAC-IP */
8527 zvni_del_macip_for_intf(vlan_if
, zvni
);
8529 /* Del VRR MAC-IP - if any*/
8530 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
8532 zvni_del_macip_for_intf(vrr_if
, zvni
);
8542 * Handle message from client to learn (or stop learning) about VNIs and MACs.
8543 * When enabled, the VNI hash table will be built and MAC FDB table read;
8544 * when disabled, the entries should be deleted and remote VTEPs and MACs
8545 * uninstalled from the kernel.
8546 * This also informs the setting for BUM handling at the time this change
8547 * occurs; it is relevant only when specifying "learn".
8549 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
8551 struct stream
*s
= NULL
;
8553 enum vxlan_flood_control flood_ctrl
;
8555 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8556 zlog_debug("EVPN VNI Adv for non-default VRF %u",
8562 STREAM_GETC(s
, advertise
);
8563 STREAM_GETC(s
, flood_ctrl
);
8565 if (IS_ZEBRA_DEBUG_VXLAN
)
8566 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
8567 advertise
? "enabled" : "disabled",
8568 is_evpn_enabled() ? "enabled" : "disabled",
8571 if (zvrf
->advertise_all_vni
== advertise
)
8574 zvrf
->advertise_all_vni
= advertise
;
8575 if (is_evpn_enabled()) {
8576 /* Note BUM handling */
8577 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8579 /* Build VNI hash table and inform BGP. */
8580 zvni_build_hash_table();
8582 /* Add all SVI (L3 GW) MACs to BGP*/
8583 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
8586 /* Read the MAC FDB */
8587 macfdb_read(zvrf
->zns
);
8589 /* Read neighbors */
8590 neigh_read(zvrf
->zns
);
8592 /* Cleanup VTEPs for all VNIs - uninstall from
8593 * kernel and free entries.
8595 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8597 /* cleanup all l3vnis */
8598 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
8606 * Allocate VNI hash table for this VRF and do other initialization.
8607 * NOTE: Currently supported only for default VRF.
8609 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
8613 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
8614 "Zebra VRF VNI Table");
8617 /* Cleanup VNI info, but don't free the table. */
8618 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
8622 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8625 /* Close all VNI handling */
8626 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
8630 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
8631 hash_free(zvrf
->vni_table
);
8634 /* init the l3vni table */
8635 void zebra_vxlan_ns_init(struct zebra_ns
*zns
)
8637 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
8638 "Zebra VRF L3 VNI table");
8641 /* free l3vni table */
8642 void zebra_vxlan_ns_disable(struct zebra_ns
*zns
)
8644 hash_free(zrouter
.l3vni_table
);
8647 /* get the l3vni svi ifindex */
8648 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
8650 zebra_l3vni_t
*zl3vni
= NULL
;
8652 zl3vni
= zl3vni_from_vrf(vrf_id
);
8653 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
8656 return zl3vni
->svi_if
->ifindex
;
8659 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
8661 struct zebra_vrf
*zvrf
= NULL
;
8662 zebra_neigh_t
*nbr
= NULL
;
8663 zebra_vni_t
*zvni
= NULL
;
8664 char buf1
[INET6_ADDRSTRLEN
];
8665 char buf2
[ETHER_ADDR_STRLEN
];
8667 nbr
= THREAD_ARG(t
);
8669 /* since this is asynchronous we need sanity checks*/
8670 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
8674 zvni
= zvni_lookup(nbr
->zvni
->vni
);
8678 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
8682 if (IS_ZEBRA_DEBUG_VXLAN
)
8683 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
8684 __PRETTY_FUNCTION__
,
8685 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
8686 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
8688 nbr
->dad_count
, zvni
->vni
);
8690 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8692 nbr
->detect_start_time
.tv_sec
= 0;
8693 nbr
->detect_start_time
.tv_usec
= 0;
8694 nbr
->dad_dup_detect_time
= 0;
8695 nbr
->dad_ip_auto_recovery_timer
= NULL
;
8698 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8699 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
8700 nbr
->flags
, nbr
->loc_seq
);
8701 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8702 zvni_neigh_install(zvni
, nbr
);
8708 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
8710 struct zebra_vrf
*zvrf
= NULL
;
8711 zebra_mac_t
*mac
= NULL
;
8712 zebra_vni_t
*zvni
= NULL
;
8713 struct listnode
*node
= NULL
;
8714 zebra_neigh_t
*nbr
= NULL
;
8715 char buf
[ETHER_ADDR_STRLEN
];
8717 mac
= THREAD_ARG(t
);
8719 /* since this is asynchronous we need sanity checks*/
8720 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
8724 zvni
= zvni_lookup(mac
->zvni
->vni
);
8728 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
8732 if (IS_ZEBRA_DEBUG_VXLAN
)
8733 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
8734 __PRETTY_FUNCTION__
,
8735 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
8738 listcount(mac
->neigh_list
));
8740 /* Remove all IPs as duplicate associcated with this MAC */
8741 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
8742 if (nbr
->dad_count
) {
8743 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
8744 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
8745 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
8746 zvni_neigh_install(zvni
, nbr
);
8749 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8751 nbr
->detect_start_time
.tv_sec
= 0;
8752 nbr
->dad_dup_detect_time
= 0;
8755 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
8757 mac
->detect_start_time
.tv_sec
= 0;
8758 mac
->detect_start_time
.tv_usec
= 0;
8759 mac
->dad_dup_detect_time
= 0;
8760 mac
->dad_mac_auto_recovery_timer
= NULL
;
8762 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8764 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
8765 mac
->flags
, mac
->loc_seq
))
8768 /* Process all neighbors associated with this MAC. */
8769 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
8771 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8772 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
8774 /* Install the entry. */
8775 zvni_mac_install(zvni
, mac
);