2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 #include <linux/neighbour.h>
40 #include "zebra/zebra_router.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/rib.h"
45 #include "zebra/rt_netlink.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_l2.h"
48 #include "zebra/zebra_memory.h"
49 #include "zebra/zebra_ns.h"
50 #include "zebra/zebra_vrf.h"
51 #include "zebra/zebra_vxlan.h"
52 #include "zebra/zebra_vxlan_private.h"
53 #include "zebra/zebra_router.h"
55 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
58 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
59 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
60 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
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_bucket
*bucket
, void *ctxt
);
69 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
70 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
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_bucket
*bucket
, void *ctxt
);
78 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
);
79 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
80 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
82 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
83 struct ipaddr
*ip
, uint8_t flags
,
84 uint32_t seq
, int state
, uint16_t cmd
);
85 static unsigned int neigh_hash_keymake(void *p
);
86 static void *zvni_neigh_alloc(void *p
);
87 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
89 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
90 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
91 struct in_addr
*r_vtep_ip
);
92 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
94 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
95 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
96 struct ethaddr
*macaddr
,
97 uint8_t flags
, uint32_t seq
);
98 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
99 struct ethaddr
*macaddr
,
100 uint8_t flags
, int state
);
101 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
102 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
103 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
104 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
105 struct interface
*br_if
);
106 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
108 /* l3-vni next-hop neigh related APIs */
109 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
111 static void *zl3vni_nh_alloc(void *p
);
112 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
113 struct ipaddr
*vtep_ip
,
114 struct ethaddr
*rmac
);
115 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
116 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
117 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
119 /* l3-vni rmac related APIs */
120 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
121 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
122 struct ethaddr
*rmac
);
123 static void *zl3vni_rmac_alloc(void *p
);
124 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
125 struct ethaddr
*rmac
);
126 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
127 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
128 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
130 /* l3-vni related APIs*/
131 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
132 static void *zl3vni_alloc(void *p
);
133 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
134 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
135 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
136 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
137 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
138 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
139 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
141 static unsigned int mac_hash_keymake(void *p
);
142 static bool mac_cmp(const void *p1
, const void *p2
);
143 static void *zvni_mac_alloc(void *p
);
144 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
145 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
146 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
147 struct in_addr
*r_vtep_ip
);
148 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
150 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
151 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
152 uint8_t flags
, uint32_t seq
);
153 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
154 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
155 struct interface
*br_if
, vlanid_t vid
);
156 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
157 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
158 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
160 static unsigned int vni_hash_keymake(void *p
);
161 static void *zvni_alloc(void *p
);
162 static zebra_vni_t
*zvni_lookup(vni_t vni
);
163 static zebra_vni_t
*zvni_add(vni_t vni
);
164 static int zvni_del(zebra_vni_t
*zvni
);
165 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
166 static int zvni_send_del_to_client(vni_t vni
);
167 static void zvni_build_hash_table(void);
168 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
169 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
170 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
171 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
172 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
173 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
174 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
175 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
176 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
177 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
178 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
179 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
181 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
182 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
183 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
184 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
185 zebra_mac_t
*old_zmac
,
186 zebra_mac_t
*new_zmac
,
188 static int remote_neigh_count(zebra_mac_t
*zmac
);
189 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
190 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
191 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
192 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
194 struct in_addr vtep_ip
,
198 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
200 struct in_addr vtep_ip
,
205 /* Private functions */
206 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
207 const struct host_rb_entry
*hle2
)
209 if (hle1
->p
.family
< hle2
->p
.family
)
212 if (hle1
->p
.family
> hle2
->p
.family
)
215 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
218 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
221 if (hle1
->p
.family
== AF_INET
) {
222 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
225 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
229 } else if (hle1
->p
.family
== AF_INET6
) {
230 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
233 zlog_debug("%s: Unexpected family type: %d",
234 __PRETTY_FUNCTION__
, hle1
->p
.family
);
238 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
240 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
242 struct host_rb_entry
*hle
;
245 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
252 * Return number of valid MACs in a VNI's MAC hash table - all
253 * remote MACs and non-internal (auto) local MACs count.
255 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
258 uint32_t num_macs
= 0;
260 struct hash_bucket
*hb
;
263 hash
= zvni
->mac_table
;
266 for (i
= 0; i
< hash
->size
; i
++) {
267 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
268 mac
= (zebra_mac_t
*)hb
->data
;
269 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
270 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
271 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
279 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
282 uint32_t num_macs
= 0;
284 struct hash_bucket
*hb
;
287 hash
= zvni
->mac_table
;
290 for (i
= 0; i
< hash
->size
; i
++) {
291 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
292 mac
= (zebra_mac_t
*)hb
->data
;
293 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
301 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
304 uint32_t num_neighs
= 0;
306 struct hash_bucket
*hb
;
309 hash
= zvni
->neigh_table
;
312 for (i
= 0; i
< hash
->size
; i
++) {
313 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
314 nbr
= (zebra_neigh_t
*)hb
->data
;
315 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
323 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
325 struct zebra_vrf
*zvrf
;
327 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
328 if (zvrf
&& zvrf
->advertise_gw_macip
)
331 if (zvni
&& zvni
->advertise_gw_macip
)
337 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
339 struct zebra_vrf
*zvrf
;
341 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
342 if (zvrf
&& zvrf
->advertise_svi_macip
)
345 if (zvni
&& zvni
->advertise_svi_macip
)
351 /* As part Duplicate Address Detection (DAD) for IP mobility
352 * MAC binding changes, ensure to inherit duplicate flag
355 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
356 zebra_mac_t
*old_zmac
,
357 zebra_mac_t
*new_zmac
,
360 bool is_old_mac_dup
= false;
361 bool is_new_mac_dup
= false;
363 if (!zvrf
->dup_addr_detect
)
365 /* Check old or new MAC is detected as duplicate
366 * mark this neigh as duplicate
369 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
370 ZEBRA_MAC_DUPLICATE
);
372 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
373 ZEBRA_MAC_DUPLICATE
);
374 /* Old and/or new MAC can be in duplicate state,
375 * based on that IP/Neigh Inherits the flag.
376 * If New MAC is marked duplicate, inherit to the IP.
377 * If old MAC is duplicate but new MAC is not, clear
378 * duplicate flag for IP and reset detection params
379 * and let IP DAD retrigger.
381 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
382 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
383 /* Capture Duplicate detection time */
384 nbr
->dad_dup_detect_time
= monotime(NULL
);
386 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
387 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
389 nbr
->detect_start_time
.tv_sec
= 0;
390 nbr
->detect_start_time
.tv_usec
= 0;
395 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
397 struct in_addr vtep_ip
,
403 struct listnode
*node
= NULL
;
404 struct timeval elapsed
= {0, 0};
405 char buf
[ETHER_ADDR_STRLEN
];
406 char buf1
[INET6_ADDRSTRLEN
];
407 bool reset_params
= false;
409 if (!(zvrf
->dup_addr_detect
&& do_dad
))
412 /* MAC is detected as duplicate,
413 * Local MAC event -> hold on advertising to BGP.
414 * Remote MAC event -> hold on installing it.
416 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
417 if (IS_ZEBRA_DEBUG_VXLAN
)
419 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
421 prefix_mac2str(&mac
->macaddr
, buf
,
423 mac
->flags
, mac
->dad_count
,
424 zvrf
->dad_freeze_time
);
426 /* For duplicate MAC do not update
427 * client but update neigh due to
430 if (zvrf
->dad_freeze
)
431 *is_dup_detect
= true;
436 /* Check if detection time (M-secs) expired.
437 * Reset learn count and detection start time.
439 monotime_since(&mac
->detect_start_time
, &elapsed
);
440 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
441 if (is_local
&& !reset_params
) {
442 /* RFC-7432: A PE/VTEP that detects a MAC mobility
443 * event via LOCAL learning starts an M-second timer.
445 * NOTE: This is the START of the probe with count is
446 * 0 during LOCAL learn event.
447 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
449 reset_params
= !mac
->dad_count
;
453 if (IS_ZEBRA_DEBUG_VXLAN
)
455 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
456 , __PRETTY_FUNCTION__
,
457 prefix_mac2str(&mac
->macaddr
, buf
,
459 mac
->flags
, mac
->dad_count
);
462 /* Start dup. addr detection (DAD) start time,
463 * ONLY during LOCAL learn.
466 monotime(&mac
->detect_start_time
);
468 } else if (!is_local
) {
469 /* For REMOTE MAC, increment detection count
470 * ONLY while in probe window, once window passed,
471 * next local learn event should trigger DAD.
476 /* For LOCAL MAC learn event, once count is reset above via either
477 * initial/start detection time or passed the probe time, the count
478 * needs to be incremented.
483 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
484 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
485 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
487 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
488 is_local
? "local update, last" :
489 "remote update, from", inet_ntoa(vtep_ip
));
491 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
493 /* Capture Duplicate detection time */
494 mac
->dad_dup_detect_time
= monotime(NULL
);
496 /* Mark all IPs/Neighs as duplicate
497 * associcated with this MAC
499 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
501 /* Ony Mark IPs which are Local */
502 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
505 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
507 nbr
->dad_dup_detect_time
= monotime(NULL
);
509 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
510 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
512 prefix_mac2str(&mac
->macaddr
,
514 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
515 is_local
? "local" : "remote");
518 /* Start auto recovery timer for this MAC */
519 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
520 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
521 if (IS_ZEBRA_DEBUG_VXLAN
)
523 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
524 , __PRETTY_FUNCTION__
,
525 prefix_mac2str(&mac
->macaddr
, buf
,
527 mac
->flags
, zvrf
->dad_freeze_time
);
529 thread_add_timer(zrouter
.master
,
530 zebra_vxlan_dad_mac_auto_recovery_exp
,
531 mac
, zvrf
->dad_freeze_time
,
532 &mac
->dad_mac_auto_recovery_timer
);
535 /* In case of local update, do not inform to client (BGPd),
536 * upd_neigh for neigh sequence change.
538 if (zvrf
->dad_freeze
)
539 *is_dup_detect
= true;
543 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
545 struct in_addr vtep_ip
,
551 struct timeval elapsed
= {0, 0};
552 char buf
[ETHER_ADDR_STRLEN
];
553 char buf1
[INET6_ADDRSTRLEN
];
554 bool reset_params
= false;
556 if (!zvrf
->dup_addr_detect
)
559 /* IP is detected as duplicate or inherit dup
560 * state, hold on to install as remote entry
561 * only if freeze is enabled.
563 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
564 if (IS_ZEBRA_DEBUG_VXLAN
)
566 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
568 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
569 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
570 nbr
->flags
, nbr
->dad_count
,
571 zvrf
->dad_freeze_time
);
573 if (zvrf
->dad_freeze
)
574 *is_dup_detect
= true;
576 /* warn-only action, neigh will be installed.
577 * freeze action, it wil not be installed.
585 /* Check if detection time (M-secs) expired.
586 * Reset learn count and detection start time.
587 * During remote mac add, count should already be 1
588 * via local learning.
590 monotime_since(&nbr
->detect_start_time
, &elapsed
);
591 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
593 if (is_local
&& !reset_params
) {
594 /* RFC-7432: A PE/VTEP that detects a MAC mobility
595 * event via LOCAL learning starts an M-second timer.
597 * NOTE: This is the START of the probe with count is
598 * 0 during LOCAL learn event.
600 reset_params
= !nbr
->dad_count
;
604 if (IS_ZEBRA_DEBUG_VXLAN
)
606 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
608 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
609 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
610 nbr
->flags
, nbr
->dad_count
);
611 /* Reset learn count but do not start detection
612 * during REMOTE learn event.
615 /* Start dup. addr detection (DAD) start time,
616 * ONLY during LOCAL learn.
619 monotime(&nbr
->detect_start_time
);
621 } else if (!is_local
) {
622 /* For REMOTE IP/Neigh, increment detection count
623 * ONLY while in probe window, once window passed,
624 * next local learn event should trigger DAD.
629 /* For LOCAL IP/Neigh learn event, once count is reset above via either
630 * initial/start detection time or passed the probe time, the count
631 * needs to be incremented.
636 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
637 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
638 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
640 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
641 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
642 is_local
? "local update, last" :
643 "remote update, from",
646 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
648 /* Capture Duplicate detection time */
649 nbr
->dad_dup_detect_time
= monotime(NULL
);
651 /* Start auto recovery timer for this IP */
652 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
653 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
654 if (IS_ZEBRA_DEBUG_VXLAN
)
656 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
658 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
659 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
660 nbr
->flags
, zvrf
->dad_freeze_time
);
662 thread_add_timer(zrouter
.master
,
663 zebra_vxlan_dad_ip_auto_recovery_exp
,
664 nbr
, zvrf
->dad_freeze_time
,
665 &nbr
->dad_ip_auto_recovery_timer
);
667 if (zvrf
->dad_freeze
)
668 *is_dup_detect
= true;
673 * Helper function to determine maximum width of neighbor IP address for
674 * display - just because we're dealing with IPv6 addresses that can
677 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
680 char buf
[INET6_ADDRSTRLEN
];
681 struct neigh_walk_ctx
*wctx
= ctxt
;
684 n
= (zebra_neigh_t
*)bucket
->data
;
686 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
688 if (width
> wctx
->addr_width
)
689 wctx
->addr_width
= width
;
694 * Print a specific neighbor entry.
696 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
699 char buf1
[ETHER_ADDR_STRLEN
];
700 char buf2
[INET6_ADDRSTRLEN
];
701 const char *type_str
;
702 const char *state_str
;
703 bool flags_present
= false;
704 struct zebra_vrf
*zvrf
= NULL
;
705 struct timeval detect_start_time
= {0, 0};
707 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
711 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
712 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
713 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
714 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
716 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
717 vty
= (struct vty
*)ctxt
;
719 vty_out(vty
, "IP: %s\n",
720 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
721 vty_out(vty
, " Type: %s\n", type_str
);
722 vty_out(vty
, " State: %s\n", state_str
);
723 vty_out(vty
, " MAC: %s\n",
724 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
726 json_object_string_add(json
, "ip", buf2
);
727 json_object_string_add(json
, "type", type_str
);
728 json_object_string_add(json
, "state", state_str
);
729 json_object_string_add(json
, "mac", buf1
);
731 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
733 vty_out(vty
, " Remote VTEP: %s\n",
734 inet_ntoa(n
->r_vtep_ip
));
736 json_object_string_add(json
, "remoteVtep",
737 inet_ntoa(n
->r_vtep_ip
));
739 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
741 vty_out(vty
, " Flags: Default-gateway");
742 flags_present
= true;
744 json_object_boolean_true_add(json
, "defaultGateway");
746 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
749 flags_present
? " ,Router" : " Flags: Router");
750 flags_present
= true;
756 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
757 n
->loc_seq
, n
->rem_seq
);
759 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
760 vty_out(vty
, " Duplicate, detected at %s",
761 time_to_string(n
->dad_dup_detect_time
));
762 } else if (n
->dad_count
) {
763 monotime_since(&n
->detect_start_time
,
765 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
766 char *buf
= time_to_string(
767 n
->detect_start_time
.tv_sec
);
770 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
772 " Duplicate detection started at %s, detection count %u\n",
773 tmp_buf
, n
->dad_count
);
777 json_object_int_add(json
, "localSequence", n
->loc_seq
);
778 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
779 json_object_int_add(json
, "detectionCount",
781 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
782 json_object_boolean_true_add(json
, "isDuplicate");
784 json_object_boolean_false_add(json
, "isDuplicate");
791 * Print neighbor hash entry - called for display of all neighbors.
793 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
796 json_object
*json_vni
= NULL
, *json_row
= NULL
;
798 char buf1
[ETHER_ADDR_STRLEN
];
799 char buf2
[INET6_ADDRSTRLEN
];
800 struct neigh_walk_ctx
*wctx
= ctxt
;
801 const char *state_str
;
804 json_vni
= wctx
->json
;
805 n
= (zebra_neigh_t
*)bucket
->data
;
808 json_row
= json_object_new_object();
810 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
811 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
812 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
813 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
814 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
817 if (json_vni
== NULL
) {
818 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
819 -wctx
->addr_width
, buf2
, "local",
822 json_object_string_add(json_row
, "type", "local");
823 json_object_string_add(json_row
, "state", state_str
);
824 json_object_string_add(json_row
, "mac", buf1
);
825 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
826 json_object_boolean_true_add(
827 json_row
, "defaultGateway");
828 json_object_int_add(json_row
, "localSequence",
830 json_object_int_add(json_row
, "remoteSequence",
832 json_object_int_add(json_row
, "detectionCount",
834 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
835 json_object_boolean_true_add(json_row
,
838 json_object_boolean_false_add(json_row
,
842 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
843 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
844 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
847 if (json_vni
== NULL
) {
848 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
851 "%*s %-6s %-8s %-17s %-21s\n",
852 -wctx
->addr_width
, "Neighbor", "Type",
853 "State", "MAC", "Remote VTEP");
854 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
855 -wctx
->addr_width
, buf2
, "remote", state_str
,
856 buf1
, inet_ntoa(n
->r_vtep_ip
));
858 json_object_string_add(json_row
, "type", "remote");
859 json_object_string_add(json_row
, "state", state_str
);
860 json_object_string_add(json_row
, "mac", buf1
);
861 json_object_string_add(json_row
, "remoteVtep",
862 inet_ntoa(n
->r_vtep_ip
));
863 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
864 json_object_boolean_true_add(json_row
,
866 json_object_int_add(json_row
, "localSequence",
868 json_object_int_add(json_row
, "remoteSequence",
870 json_object_int_add(json_row
, "detectionCount",
872 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
873 json_object_boolean_true_add(json_row
,
876 json_object_boolean_false_add(json_row
,
883 json_object_object_add(json_vni
, buf2
, json_row
);
887 * Print neighbor hash entry in detail - called for display of all neighbors.
889 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
892 json_object
*json_vni
= NULL
, *json_row
= NULL
;
894 char buf
[INET6_ADDRSTRLEN
];
895 struct neigh_walk_ctx
*wctx
= ctxt
;
898 json_vni
= wctx
->json
;
899 n
= (zebra_neigh_t
*)bucket
->data
;
903 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
905 json_row
= json_object_new_object();
907 zvni_print_neigh(n
, vty
, json_row
);
910 json_object_object_add(json_vni
, buf
, json_row
);
914 * Print neighbors for all VNI.
916 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
920 json_object
*json
= NULL
, *json_vni
= NULL
;
923 struct neigh_walk_ctx wctx
;
924 char vni_str
[VNI_STR_LEN
];
927 vty
= (struct vty
*)args
[0];
928 json
= (json_object
*)args
[1];
929 print_dup
= (uint32_t)(uintptr_t)args
[2];
931 zvni
= (zebra_vni_t
*)bucket
->data
;
933 num_neigh
= hashcount(zvni
->neigh_table
);
936 num_neigh
= num_dup_detected_neighs(zvni
);
940 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
941 zvni
->vni
, num_neigh
);
943 json_vni
= json_object_new_object();
944 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
945 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
950 json_object_object_add(json
, vni_str
, json_vni
);
954 /* Since we have IPv6 addresses to deal with which can vary widely in
955 * size, we try to be a bit more elegant in display by first computing
958 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
961 wctx
.addr_width
= 15;
962 wctx
.json
= json_vni
;
963 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
966 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
967 -wctx
.addr_width
, "IP", "Type",
968 "State", "MAC", "Remote VTEP");
971 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
974 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
977 json_object_object_add(json
, vni_str
, json_vni
);
980 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
984 nbr
= (zebra_neigh_t
*)bucket
->data
;
988 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
989 zvni_print_neigh_hash(bucket
, ctxt
);
992 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
997 nbr
= (zebra_neigh_t
*)bucket
->data
;
1001 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1002 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1006 * Print neighbors for all VNIs in detail.
1008 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1012 json_object
*json
= NULL
, *json_vni
= NULL
;
1015 struct neigh_walk_ctx wctx
;
1016 char vni_str
[VNI_STR_LEN
];
1019 vty
= (struct vty
*)args
[0];
1020 json
= (json_object
*)args
[1];
1021 print_dup
= (uint32_t)(uintptr_t)args
[2];
1023 zvni
= (zebra_vni_t
*)bucket
->data
;
1026 vty_out(vty
, "{}\n");
1029 num_neigh
= hashcount(zvni
->neigh_table
);
1031 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1036 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1037 zvni
->vni
, num_neigh
);
1039 json_vni
= json_object_new_object();
1040 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1041 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1045 json_object_object_add(json
, vni_str
, json_vni
);
1049 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1052 wctx
.addr_width
= 15;
1053 wctx
.json
= json_vni
;
1056 hash_iterate(zvni
->neigh_table
,
1057 zvni_print_dad_neigh_hash_detail
, &wctx
);
1059 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1063 json_object_object_add(json
, vni_str
, json_vni
);
1066 /* print a specific next hop for an l3vni */
1067 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1070 char buf1
[ETHER_ADDR_STRLEN
];
1071 char buf2
[INET6_ADDRSTRLEN
];
1072 json_object
*json_hosts
= NULL
;
1073 struct host_rb_entry
*hle
;
1076 vty_out(vty
, "Ip: %s\n",
1077 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1078 vty_out(vty
, " RMAC: %s\n",
1079 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1080 vty_out(vty
, " Refcount: %d\n",
1081 rb_host_count(&n
->host_rb
));
1082 vty_out(vty
, " Prefixes:\n");
1083 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1084 vty_out(vty
, " %s\n",
1085 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1087 json_hosts
= json_object_new_array();
1088 json_object_string_add(
1089 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1090 json_object_string_add(
1092 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1093 json_object_int_add(json
, "refCount",
1094 rb_host_count(&n
->host_rb
));
1095 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1096 json_object_array_add(json_hosts
,
1097 json_object_new_string(prefix2str(
1098 &hle
->p
, buf2
, sizeof(buf2
))));
1099 json_object_object_add(json
, "prefixList", json_hosts
);
1103 /* Print a specific RMAC entry */
1104 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1107 char buf1
[ETHER_ADDR_STRLEN
];
1108 char buf2
[PREFIX_STRLEN
];
1109 json_object
*json_hosts
= NULL
;
1110 struct host_rb_entry
*hle
;
1113 vty_out(vty
, "MAC: %s\n",
1114 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1115 vty_out(vty
, " Remote VTEP: %s\n",
1116 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1117 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1118 vty_out(vty
, " Prefixes:\n");
1119 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1120 vty_out(vty
, " %s\n",
1121 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1123 json_hosts
= json_object_new_array();
1124 json_object_string_add(
1126 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1127 json_object_string_add(json
, "vtepIp",
1128 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1129 json_object_int_add(json
, "refCount",
1130 rb_host_count(&zrmac
->host_rb
));
1131 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1132 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1133 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1134 json_object_array_add(
1136 json_object_new_string(prefix2str(
1137 &hle
->p
, buf2
, sizeof(buf2
))));
1138 json_object_object_add(json
, "prefixList", json_hosts
);
1143 * Print a specific MAC entry.
1145 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1148 zebra_neigh_t
*n
= NULL
;
1149 struct listnode
*node
= NULL
;
1150 char buf1
[ETHER_ADDR_STRLEN
];
1151 char buf2
[INET6_ADDRSTRLEN
];
1152 struct zebra_vrf
*zvrf
;
1153 struct timeval detect_start_time
= {0, 0};
1155 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1157 vty
= (struct vty
*)ctxt
;
1158 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1161 json_object
*json_mac
= json_object_new_object();
1163 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1164 struct zebra_ns
*zns
;
1165 struct interface
*ifp
;
1168 ifindex
= mac
->fwd_info
.local
.ifindex
;
1169 zns
= zebra_ns_lookup(NS_DEFAULT
);
1170 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1173 json_object_string_add(json_mac
, "type", "local");
1174 json_object_string_add(json_mac
, "intf", ifp
->name
);
1175 json_object_int_add(json_mac
, "ifindex", ifindex
);
1176 if (mac
->fwd_info
.local
.vid
)
1177 json_object_int_add(json_mac
, "vlan",
1178 mac
->fwd_info
.local
.vid
);
1179 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1180 json_object_string_add(json_mac
, "type", "remote");
1181 json_object_string_add(
1182 json_mac
, "remoteVtep",
1183 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1184 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1185 json_object_string_add(json_mac
, "type", "auto");
1187 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1188 json_object_boolean_true_add(json_mac
, "stickyMac");
1190 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1191 json_object_boolean_true_add(json_mac
,
1194 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1195 json_object_boolean_true_add(json_mac
,
1196 "remoteGatewayMac");
1198 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1199 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1201 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1202 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1203 json_object_boolean_true_add(json_mac
, "isDuplicate");
1205 json_object_boolean_false_add(json_mac
, "isDuplicate");
1207 /* print all the associated neigh */
1208 if (!listcount(mac
->neigh_list
))
1209 json_object_string_add(json_mac
, "neighbors", "none");
1211 json_object
*json_active_nbrs
= json_object_new_array();
1212 json_object
*json_inactive_nbrs
=
1213 json_object_new_array();
1214 json_object
*json_nbrs
= json_object_new_object();
1216 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1217 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1218 json_object_array_add(
1220 json_object_new_string(
1225 json_object_array_add(
1227 json_object_new_string(
1233 json_object_object_add(json_nbrs
, "active",
1235 json_object_object_add(json_nbrs
, "inactive",
1236 json_inactive_nbrs
);
1237 json_object_object_add(json_mac
, "neighbors",
1241 json_object_object_add(json
, buf1
, json_mac
);
1243 vty_out(vty
, "MAC: %s\n", buf1
);
1245 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1246 struct zebra_ns
*zns
;
1247 struct interface
*ifp
;
1250 ifindex
= mac
->fwd_info
.local
.ifindex
;
1251 zns
= zebra_ns_lookup(NS_DEFAULT
);
1252 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1255 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1256 if (mac
->fwd_info
.local
.vid
)
1257 vty_out(vty
, " VLAN: %u",
1258 mac
->fwd_info
.local
.vid
);
1259 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1260 vty_out(vty
, " Remote VTEP: %s",
1261 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1262 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1263 vty_out(vty
, " Auto Mac ");
1266 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1267 vty_out(vty
, " Sticky Mac ");
1269 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1270 vty_out(vty
, " Default-gateway Mac ");
1272 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1273 vty_out(vty
, " Remote-gateway Mac ");
1276 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1280 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1281 vty_out(vty
, " Duplicate, detected at %s",
1282 time_to_string(mac
->dad_dup_detect_time
));
1283 } else if (mac
->dad_count
) {
1284 monotime_since(&mac
->detect_start_time
,
1285 &detect_start_time
);
1286 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1287 char *buf
= time_to_string(
1288 mac
->detect_start_time
.tv_sec
);
1291 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1293 " Duplicate detection started at %s, detection count %u\n",
1294 tmp_buf
, mac
->dad_count
);
1298 /* print all the associated neigh */
1299 vty_out(vty
, " Neighbors:\n");
1300 if (!listcount(mac
->neigh_list
))
1301 vty_out(vty
, " No Neighbors\n");
1303 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1304 vty_out(vty
, " %s %s\n",
1305 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1306 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1317 * Print MAC hash entry - called for display of all MACs.
1319 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1322 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1324 char buf1
[ETHER_ADDR_STRLEN
];
1325 struct mac_walk_ctx
*wctx
= ctxt
;
1328 json_mac_hdr
= wctx
->json
;
1329 mac
= (zebra_mac_t
*)bucket
->data
;
1331 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1334 json_mac
= json_object_new_object();
1336 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1337 struct zebra_ns
*zns
;
1339 struct interface
*ifp
;
1342 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1345 zns
= zebra_ns_lookup(NS_DEFAULT
);
1346 ifindex
= mac
->fwd_info
.local
.ifindex
;
1347 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1348 if (!ifp
) // unexpected
1350 vid
= mac
->fwd_info
.local
.vid
;
1351 if (json_mac_hdr
== NULL
)
1352 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1355 json_object_string_add(json_mac
, "type", "local");
1356 json_object_string_add(json_mac
, "intf", ifp
->name
);
1359 if (json_mac_hdr
== NULL
)
1360 vty_out(vty
, " %-5u", vid
);
1362 json_object_int_add(json_mac
, "vlan", vid
);
1364 if (json_mac_hdr
== NULL
) {
1367 json_object_int_add(json_mac
, "localSequence",
1369 json_object_int_add(json_mac
, "remoteSequence",
1371 json_object_int_add(json_mac
, "detectionCount",
1373 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1374 json_object_boolean_true_add(json_mac
,
1377 json_object_boolean_false_add(json_mac
,
1379 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1384 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1386 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1387 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1391 if (json_mac_hdr
== NULL
) {
1392 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1393 (wctx
->count
== 0)) {
1394 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1395 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1396 "Type", "Intf/Remote VTEP", "VLAN");
1398 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1399 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1401 json_object_string_add(json_mac
, "type", "remote");
1402 json_object_string_add(json_mac
, "remoteVtep",
1403 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1404 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1405 json_object_int_add(json_mac
, "localSequence",
1407 json_object_int_add(json_mac
, "remoteSequence",
1409 json_object_int_add(json_mac
, "detectionCount",
1411 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1412 json_object_boolean_true_add(json_mac
,
1415 json_object_boolean_false_add(json_mac
,
1424 /* Print Duplicate MAC */
1425 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1429 mac
= (zebra_mac_t
*)bucket
->data
;
1433 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1434 zvni_print_mac_hash(bucket
, ctxt
);
1438 * Print MAC hash entry in detail - called for display of all MACs.
1440 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1443 json_object
*json_mac_hdr
= NULL
;
1445 struct mac_walk_ctx
*wctx
= ctxt
;
1446 char buf1
[ETHER_ADDR_STRLEN
];
1449 json_mac_hdr
= wctx
->json
;
1450 mac
= (zebra_mac_t
*)bucket
->data
;
1455 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1457 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1460 /* Print Duplicate MAC in detail */
1461 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1466 mac
= (zebra_mac_t
*)bucket
->data
;
1470 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1471 zvni_print_mac_hash_detail(bucket
, ctxt
);
1475 * Print MACs for all VNI.
1477 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1480 json_object
*json
= NULL
, *json_vni
= NULL
;
1481 json_object
*json_mac
= NULL
;
1484 struct mac_walk_ctx
*wctx
= ctxt
;
1485 char vni_str
[VNI_STR_LEN
];
1487 vty
= (struct vty
*)wctx
->vty
;
1488 json
= (struct json_object
*)wctx
->json
;
1490 zvni
= (zebra_vni_t
*)bucket
->data
;
1493 /*We are iterating over a new VNI, set the count to 0*/
1496 num_macs
= num_valid_macs(zvni
);
1500 if (wctx
->print_dup
)
1501 num_macs
= num_dup_detected_macs(zvni
);
1504 json_vni
= json_object_new_object();
1505 json_mac
= json_object_new_object();
1506 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1509 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1511 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1512 zvni
->vni
, num_macs
);
1513 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1514 "Intf/Remote VTEP", "VLAN");
1516 json_object_int_add(json_vni
, "numMacs", num_macs
);
1521 json_object_int_add(json_vni
, "numMacs", num_macs
);
1522 json_object_object_add(json
, vni_str
, json_vni
);
1527 /* assign per-vni to wctx->json object to fill macs
1528 * under the vni. Re-assign primary json object to fill
1529 * next vni information.
1531 wctx
->json
= json_mac
;
1532 if (wctx
->print_dup
)
1533 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1535 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1539 json_object_object_add(json_vni
, "macs", json_mac
);
1540 json_object_object_add(json
, vni_str
, json_vni
);
1545 * Print MACs in detail for all VNI.
1547 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1551 json_object
*json
= NULL
, *json_vni
= NULL
;
1552 json_object
*json_mac
= NULL
;
1555 struct mac_walk_ctx
*wctx
= ctxt
;
1556 char vni_str
[VNI_STR_LEN
];
1558 vty
= (struct vty
*)wctx
->vty
;
1559 json
= (struct json_object
*)wctx
->json
;
1561 zvni
= (zebra_vni_t
*)bucket
->data
;
1564 vty_out(vty
, "{}\n");
1569 /*We are iterating over a new VNI, set the count to 0*/
1572 num_macs
= num_valid_macs(zvni
);
1576 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1580 json_vni
= json_object_new_object();
1581 json_mac
= json_object_new_object();
1582 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1585 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1587 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1588 zvni
->vni
, num_macs
);
1590 json_object_int_add(json_vni
, "numMacs", num_macs
);
1592 /* assign per-vni to wctx->json object to fill macs
1593 * under the vni. Re-assign primary json object to fill
1594 * next vni information.
1596 wctx
->json
= json_mac
;
1597 if (wctx
->print_dup
)
1598 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1601 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1605 json_object_object_add(json_vni
, "macs", json_mac
);
1606 json_object_object_add(json
, vni_str
, json_vni
);
1610 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1612 struct nh_walk_ctx
*wctx
= NULL
;
1613 struct vty
*vty
= NULL
;
1614 struct json_object
*json_vni
= NULL
;
1615 struct json_object
*json_nh
= NULL
;
1616 zebra_neigh_t
*n
= NULL
;
1617 char buf1
[ETHER_ADDR_STRLEN
];
1618 char buf2
[INET6_ADDRSTRLEN
];
1620 wctx
= (struct nh_walk_ctx
*)ctx
;
1622 json_vni
= wctx
->json
;
1624 json_nh
= json_object_new_object();
1625 n
= (zebra_neigh_t
*)bucket
->data
;
1628 vty_out(vty
, "%-15s %-17s\n",
1629 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1630 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1632 json_object_string_add(json_nh
, "nexthopIp",
1633 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1634 json_object_string_add(
1635 json_nh
, "routerMac",
1636 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1637 json_object_object_add(json_vni
,
1638 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1643 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1646 struct vty
*vty
= NULL
;
1647 json_object
*json
= NULL
;
1648 json_object
*json_vni
= NULL
;
1649 zebra_l3vni_t
*zl3vni
= NULL
;
1650 uint32_t num_nh
= 0;
1651 struct nh_walk_ctx wctx
;
1652 char vni_str
[VNI_STR_LEN
];
1654 vty
= (struct vty
*)args
[0];
1655 json
= (struct json_object
*)args
[1];
1657 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1659 num_nh
= hashcount(zl3vni
->nh_table
);
1664 json_vni
= json_object_new_object();
1665 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1669 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1670 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1672 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1674 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1676 wctx
.json
= json_vni
;
1677 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1679 json_object_object_add(json
, vni_str
, json_vni
);
1682 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1685 struct vty
*vty
= NULL
;
1686 json_object
*json
= NULL
;
1687 json_object
*json_vni
= NULL
;
1688 zebra_l3vni_t
*zl3vni
= NULL
;
1690 struct rmac_walk_ctx wctx
;
1691 char vni_str
[VNI_STR_LEN
];
1693 vty
= (struct vty
*)args
[0];
1694 json
= (struct json_object
*)args
[1];
1696 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1698 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1703 json_vni
= json_object_new_object();
1704 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1708 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1709 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1711 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1713 /* assign per-vni to wctx->json object to fill macs
1714 * under the vni. Re-assign primary json object to fill
1715 * next vni information.
1717 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1719 wctx
.json
= json_vni
;
1720 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1722 json_object_object_add(json
, vni_str
, json_vni
);
1725 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1727 zebra_mac_t
*zrmac
= NULL
;
1728 struct rmac_walk_ctx
*wctx
= NULL
;
1729 struct vty
*vty
= NULL
;
1730 struct json_object
*json
= NULL
;
1731 struct json_object
*json_rmac
= NULL
;
1732 char buf
[ETHER_ADDR_STRLEN
];
1734 wctx
= (struct rmac_walk_ctx
*)ctx
;
1738 json_rmac
= json_object_new_object();
1739 zrmac
= (zebra_mac_t
*)bucket
->data
;
1742 vty_out(vty
, "%-17s %-21s\n",
1743 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1744 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1746 json_object_string_add(
1747 json_rmac
, "routerMac",
1748 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1749 json_object_string_add(json_rmac
, "vtepIp",
1750 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1751 json_object_object_add(
1752 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1757 /* print a specific L3 VNI entry */
1758 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1760 char buf
[ETHER_ADDR_STRLEN
];
1761 struct vty
*vty
= NULL
;
1762 json_object
*json
= NULL
;
1763 zebra_vni_t
*zvni
= NULL
;
1764 json_object
*json_vni_list
= NULL
;
1765 struct listnode
*node
= NULL
, *nnode
= NULL
;
1771 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1772 vty_out(vty
, " Type: %s\n", "L3");
1773 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1774 vty_out(vty
, " Local Vtep Ip: %s\n",
1775 inet_ntoa(zl3vni
->local_vtep_ip
));
1776 vty_out(vty
, " Vxlan-Intf: %s\n",
1777 zl3vni_vxlan_if_name(zl3vni
));
1778 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1779 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1780 vty_out(vty
, " VNI Filter: %s\n",
1781 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1782 ? "prefix-routes-only"
1784 vty_out(vty
, " Router MAC: %s\n",
1785 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1786 vty_out(vty
, " L2 VNIs: ");
1787 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1788 vty_out(vty
, "%u ", zvni
->vni
);
1791 json_vni_list
= json_object_new_array();
1792 json_object_int_add(json
, "vni", zl3vni
->vni
);
1793 json_object_string_add(json
, "type", "L3");
1794 json_object_string_add(json
, "localVtepIp",
1795 inet_ntoa(zl3vni
->local_vtep_ip
));
1796 json_object_string_add(json
, "vxlanIntf",
1797 zl3vni_vxlan_if_name(zl3vni
));
1798 json_object_string_add(json
, "sviIntf",
1799 zl3vni_svi_if_name(zl3vni
));
1800 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1801 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1802 json_object_string_add(
1804 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1805 json_object_string_add(
1807 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1808 ? "prefix-routes-only"
1810 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1811 json_object_array_add(json_vni_list
,
1812 json_object_new_int(zvni
->vni
));
1814 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1819 * Print a specific VNI entry.
1821 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1824 zebra_vtep_t
*zvtep
;
1827 json_object
*json
= NULL
;
1828 json_object
*json_vtep_list
= NULL
;
1829 json_object
*json_ip_str
= NULL
;
1835 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1836 vty_out(vty
, " Type: %s\n", "L2");
1837 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1839 json_object_int_add(json
, "vni", zvni
->vni
);
1840 json_object_string_add(json
, "type", "L2");
1841 json_object_string_add(json
, "vrf",
1842 vrf_id_to_name(zvni
->vrf_id
));
1845 if (!zvni
->vxlan_if
) { // unexpected
1847 vty_out(vty
, " VxLAN interface: unknown\n");
1850 num_macs
= num_valid_macs(zvni
);
1851 num_neigh
= hashcount(zvni
->neigh_table
);
1853 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1854 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1855 vty_out(vty
, " Local VTEP IP: %s\n",
1856 inet_ntoa(zvni
->local_vtep_ip
));
1858 json_object_string_add(json
, "vxlanInterface",
1859 zvni
->vxlan_if
->name
);
1860 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1861 json_object_string_add(json
, "vtepIp",
1862 inet_ntoa(zvni
->local_vtep_ip
));
1863 json_object_string_add(json
, "advertiseGatewayMacip",
1864 zvni
->advertise_gw_macip
? "Yes" : "No");
1865 json_object_int_add(json
, "numMacs", num_macs
);
1866 json_object_int_add(json
, "numArpNd", num_neigh
);
1870 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1873 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1875 json_vtep_list
= json_object_new_array();
1876 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1878 vty_out(vty
, " %s\n",
1879 inet_ntoa(zvtep
->vtep_ip
));
1881 json_ip_str
= json_object_new_string(
1882 inet_ntoa(zvtep
->vtep_ip
));
1883 json_object_array_add(json_vtep_list
,
1888 json_object_object_add(json
, "numRemoteVteps",
1893 " Number of MACs (local and remote) known for this VNI: %u\n",
1896 " Number of ARPs (IPv4 and IPv6, local and remote) "
1897 "known for this VNI: %u\n",
1899 vty_out(vty
, " Advertise-gw-macip: %s\n",
1900 zvni
->advertise_gw_macip
? "Yes" : "No");
1904 /* print a L3 VNI hash entry */
1905 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1907 struct vty
*vty
= NULL
;
1908 json_object
*json
= NULL
;
1909 json_object
*json_vni
= NULL
;
1910 zebra_l3vni_t
*zl3vni
= NULL
;
1912 vty
= (struct vty
*)ctx
[0];
1913 json
= (json_object
*)ctx
[1];
1915 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1918 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1919 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1920 hashcount(zl3vni
->rmac_table
),
1921 hashcount(zl3vni
->nh_table
), "n/a",
1922 zl3vni_vrf_name(zl3vni
));
1924 char vni_str
[VNI_STR_LEN
];
1926 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1927 json_vni
= json_object_new_object();
1928 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1929 json_object_string_add(json_vni
, "vxlanIf",
1930 zl3vni_vxlan_if_name(zl3vni
));
1931 json_object_int_add(json_vni
, "numMacs",
1932 hashcount(zl3vni
->rmac_table
));
1933 json_object_int_add(json_vni
, "numArpNd",
1934 hashcount(zl3vni
->nh_table
));
1935 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1936 json_object_string_add(json_vni
, "type", "L3");
1937 json_object_string_add(json_vni
, "tenantVrf",
1938 zl3vni_vrf_name(zl3vni
));
1939 json_object_object_add(json
, vni_str
, json_vni
);
1943 /* Private Structure to pass callback data for hash iterator */
1944 struct zvni_evpn_show
{
1947 struct zebra_vrf
*zvrf
;
1950 /* print a L3 VNI hash entry in detail*/
1951 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1953 struct vty
*vty
= NULL
;
1954 zebra_l3vni_t
*zl3vni
= NULL
;
1955 json_object
*json
= NULL
;
1956 bool use_json
= false;
1957 struct zvni_evpn_show
*zes
= data
;
1965 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1967 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1973 * Print a VNI hash entry - called for display of all VNIs.
1975 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
1979 zebra_vtep_t
*zvtep
;
1980 uint32_t num_vteps
= 0;
1981 uint32_t num_macs
= 0;
1982 uint32_t num_neigh
= 0;
1983 json_object
*json
= NULL
;
1984 json_object
*json_vni
= NULL
;
1985 json_object
*json_ip_str
= NULL
;
1986 json_object
*json_vtep_list
= NULL
;
1991 zvni
= (zebra_vni_t
*)bucket
->data
;
1993 zvtep
= zvni
->vteps
;
1996 zvtep
= zvtep
->next
;
1999 num_macs
= num_valid_macs(zvni
);
2000 num_neigh
= hashcount(zvni
->neigh_table
);
2002 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2004 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2005 num_macs
, num_neigh
, num_vteps
,
2006 vrf_id_to_name(zvni
->vrf_id
));
2008 char vni_str
[VNI_STR_LEN
];
2009 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2010 json_vni
= json_object_new_object();
2011 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2012 json_object_string_add(json_vni
, "type", "L2");
2013 json_object_string_add(json_vni
, "vxlanIf",
2014 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2016 json_object_int_add(json_vni
, "numMacs", num_macs
);
2017 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2018 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2019 json_object_string_add(json_vni
, "tenantVrf",
2020 vrf_id_to_name(zvni
->vrf_id
));
2022 json_vtep_list
= json_object_new_array();
2023 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2024 json_ip_str
= json_object_new_string(
2025 inet_ntoa(zvtep
->vtep_ip
));
2026 json_object_array_add(json_vtep_list
,
2029 json_object_object_add(json_vni
, "remoteVteps",
2032 json_object_object_add(json
, vni_str
, json_vni
);
2037 * Print a VNI hash entry in detail - called for display of all VNIs.
2039 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2043 json_object
*json
= NULL
;
2044 bool use_json
= false;
2045 struct zvni_evpn_show
*zes
= data
;
2053 zvni
= (zebra_vni_t
*)bucket
->data
;
2055 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2060 * Inform BGP about local MACIP.
2062 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2063 struct ipaddr
*ip
, uint8_t flags
,
2064 uint32_t seq
, int state
, uint16_t cmd
)
2066 char buf
[ETHER_ADDR_STRLEN
];
2067 char buf2
[INET6_ADDRSTRLEN
];
2069 struct zserv
*client
= NULL
;
2070 struct stream
*s
= NULL
;
2072 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2073 /* BGP may not be running. */
2077 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2079 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
2080 stream_putl(s
, vni
);
2081 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2084 if (IS_IPADDR_V4(ip
))
2085 ipa_len
= IPV4_MAX_BYTELEN
;
2086 else if (IS_IPADDR_V6(ip
))
2087 ipa_len
= IPV6_MAX_BYTELEN
;
2089 stream_putl(s
, ipa_len
); /* IP address length */
2091 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2093 stream_putl(s
, 0); /* Just MAC. */
2095 if (cmd
== ZEBRA_MACIP_ADD
) {
2096 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2097 stream_putl(s
, seq
); /* sequence number */
2099 stream_putl(s
, state
); /* state - active/inactive */
2103 /* Write packet size. */
2104 stream_putw_at(s
, 0, stream_get_endp(s
));
2106 if (IS_ZEBRA_DEBUG_VXLAN
)
2108 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2109 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2110 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2111 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2112 zebra_route_string(client
->proto
));
2114 if (cmd
== ZEBRA_MACIP_ADD
)
2115 client
->macipadd_cnt
++;
2117 client
->macipdel_cnt
++;
2119 return zserv_send_message(client
, s
);
2123 * Make hash key for neighbors.
2125 static unsigned int neigh_hash_keymake(void *p
)
2127 zebra_neigh_t
*n
= p
;
2128 struct ipaddr
*ip
= &n
->ip
;
2130 if (IS_IPADDR_V4(ip
))
2131 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2133 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2134 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2138 * Compare two neighbor hash structures.
2140 static bool neigh_cmp(const void *p1
, const void *p2
)
2142 const zebra_neigh_t
*n1
= p1
;
2143 const zebra_neigh_t
*n2
= p2
;
2145 if (n1
== NULL
&& n2
== NULL
)
2148 if (n1
== NULL
|| n2
== NULL
)
2151 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2154 static int neigh_list_cmp(void *p1
, void *p2
)
2156 const zebra_neigh_t
*n1
= p1
;
2157 const zebra_neigh_t
*n2
= p2
;
2159 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2163 * Callback to allocate neighbor hash entry.
2165 static void *zvni_neigh_alloc(void *p
)
2167 const zebra_neigh_t
*tmp_n
= p
;
2170 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2177 * Add neighbor entry.
2179 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2180 struct ethaddr
*mac
)
2182 zebra_neigh_t tmp_n
;
2183 zebra_neigh_t
*n
= NULL
;
2184 zebra_mac_t
*zmac
= NULL
;
2186 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2187 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2188 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2191 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2192 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2194 /* Associate the neigh to mac */
2195 zmac
= zvni_mac_lookup(zvni
, mac
);
2197 listnode_add_sort(zmac
->neigh_list
, n
);
2203 * Delete neighbor entry.
2205 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2207 zebra_neigh_t
*tmp_n
;
2208 zebra_mac_t
*zmac
= NULL
;
2210 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2212 listnode_delete(zmac
->neigh_list
, n
);
2214 /* Free the VNI hash entry and allocated memory. */
2215 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2216 XFREE(MTYPE_NEIGH
, tmp_n
);
2222 * Free neighbor hash entry (callback)
2224 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2226 struct neigh_walk_ctx
*wctx
= arg
;
2227 zebra_neigh_t
*n
= bucket
->data
;
2229 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2230 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2231 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2232 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2233 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2234 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2235 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2236 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2237 &n
->emac
, 0, n
->state
);
2239 if (wctx
->uninstall
)
2240 zvni_neigh_uninstall(wctx
->zvni
, n
);
2242 zvni_neigh_del(wctx
->zvni
, n
);
2249 * Delete all neighbor entries from specific VTEP for a particular VNI.
2251 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2252 struct in_addr
*r_vtep_ip
)
2254 struct neigh_walk_ctx wctx
;
2256 if (!zvni
->neigh_table
)
2259 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2261 wctx
.uninstall
= uninstall
;
2262 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2263 wctx
.r_vtep_ip
= *r_vtep_ip
;
2265 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2269 * Delete all neighbor entries for this VNI.
2271 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2274 struct neigh_walk_ctx wctx
;
2276 if (!zvni
->neigh_table
)
2279 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2281 wctx
.uninstall
= uninstall
;
2282 wctx
.upd_client
= upd_client
;
2285 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2289 * Look up neighbor hash entry.
2291 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2296 memset(&tmp
, 0, sizeof(tmp
));
2297 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2298 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2304 * Process all neighbors associated with a MAC upon the MAC being learnt
2305 * locally or undergoing any other change (such as sequence number).
2307 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2311 zebra_neigh_t
*n
= NULL
;
2312 struct listnode
*node
= NULL
;
2313 struct zebra_vrf
*zvrf
= NULL
;
2314 char buf
[ETHER_ADDR_STRLEN
];
2316 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2318 if (IS_ZEBRA_DEBUG_VXLAN
)
2319 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2320 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2321 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2323 /* Walk all neighbors and mark any inactive local neighbors as
2324 * active and/or update sequence number upon a move, and inform BGP.
2325 * The action for remote neighbors is TBD.
2326 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2327 * accidentally end up deleting a just-learnt local neighbor.
2329 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2330 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2331 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2332 ZEBRA_NEIGH_SET_ACTIVE(n
);
2333 n
->loc_seq
= zmac
->loc_seq
;
2334 if (!(zvrf
->dup_addr_detect
&&
2335 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2336 ZEBRA_NEIGH_DUPLICATE
)))
2337 zvni_neigh_send_add_to_client(
2338 zvni
->vni
, &n
->ip
, &n
->emac
,
2339 n
->flags
, n
->loc_seq
);
2346 * Process all neighbors associated with a local MAC upon the MAC being
2349 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2352 zebra_neigh_t
*n
= NULL
;
2353 struct listnode
*node
= NULL
;
2354 char buf
[ETHER_ADDR_STRLEN
];
2356 if (IS_ZEBRA_DEBUG_VXLAN
)
2357 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2358 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2361 /* Walk all local neighbors and mark as inactive and inform
2363 * TBD: There is currently no handling for remote neighbors. We
2364 * don't expect them to exist, if they do, do we install the MAC
2365 * as a remote MAC and the neighbor as remote?
2367 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2368 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2369 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2370 ZEBRA_NEIGH_SET_INACTIVE(n
);
2372 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2373 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2380 * Process all neighbors associated with a MAC upon the MAC being remotely
2383 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2386 zebra_neigh_t
*n
= NULL
;
2387 struct listnode
*node
= NULL
;
2388 char buf
[ETHER_ADDR_STRLEN
];
2390 if (IS_ZEBRA_DEBUG_VXLAN
)
2391 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2392 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2395 /* Walk all local neighbors and mark as inactive and inform
2398 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2399 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2400 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2401 ZEBRA_NEIGH_SET_INACTIVE(n
);
2403 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2404 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2411 * Process all neighbors associated with a remote MAC upon the MAC being
2414 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2417 /* NOTE: Currently a NO-OP. */
2420 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2422 zebra_neigh_t
*nbr
= NULL
;
2423 struct listnode
*node
= NULL
;
2425 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2426 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2427 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2428 zvni_neigh_probe(zvni
, nbr
);
2433 * Inform BGP about local neighbor addition.
2435 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2436 struct ethaddr
*macaddr
,
2437 uint8_t neigh_flags
,
2442 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2443 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2444 /* Set router flag (R-bit) based on local neigh entry add */
2445 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2446 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2448 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2449 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2453 * Inform BGP about local neighbor deletion.
2455 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2456 struct ethaddr
*macaddr
, uint8_t flags
,
2459 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2460 0, state
, ZEBRA_MACIP_DEL
);
2464 * Install remote neighbor into the kernel.
2466 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2468 struct zebra_if
*zif
;
2469 struct zebra_l2info_vxlan
*vxl
;
2470 struct interface
*vlan_if
;
2476 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2479 zif
= zvni
->vxlan_if
->info
;
2482 vxl
= &zif
->l2info
.vxl
;
2484 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2488 flags
= NTF_EXT_LEARNED
;
2489 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2490 flags
|= NTF_ROUTER
;
2491 ZEBRA_NEIGH_SET_ACTIVE(n
);
2492 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2498 * Uninstall remote neighbor from the kernel.
2500 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2502 struct zebra_if
*zif
;
2503 struct zebra_l2info_vxlan
*vxl
;
2504 struct interface
*vlan_if
;
2506 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2509 if (!zvni
->vxlan_if
) {
2510 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2515 zif
= zvni
->vxlan_if
->info
;
2518 vxl
= &zif
->l2info
.vxl
;
2519 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2523 ZEBRA_NEIGH_SET_INACTIVE(n
);
2525 return kernel_del_neigh(vlan_if
, &n
->ip
);
2529 * Probe neighbor from the kernel.
2531 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2533 struct zebra_if
*zif
;
2534 struct zebra_l2info_vxlan
*vxl
;
2535 struct interface
*vlan_if
;
2537 zif
= zvni
->vxlan_if
->info
;
2540 vxl
= &zif
->l2info
.vxl
;
2542 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2547 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2555 * Install neighbor hash entry - called upon access VLAN change.
2557 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2560 struct neigh_walk_ctx
*wctx
= ctxt
;
2562 n
= (zebra_neigh_t
*)bucket
->data
;
2564 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2565 zvni_neigh_install(wctx
->zvni
, n
);
2568 /* Get the VRR interface for SVI if any */
2569 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2571 struct zebra_vrf
*zvrf
= NULL
;
2572 struct interface
*tmp_if
= NULL
;
2573 struct zebra_if
*zif
= NULL
;
2575 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2578 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2583 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2586 if (zif
->link
== ifp
)
2593 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2595 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2596 struct connected
*c
= NULL
;
2597 struct ethaddr macaddr
;
2599 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2601 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2604 memset(&ip
, 0, sizeof(struct ipaddr
));
2605 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2608 if (c
->address
->family
== AF_INET
) {
2609 ip
.ipa_type
= IPADDR_V4
;
2610 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2611 sizeof(struct in_addr
));
2612 } else if (c
->address
->family
== AF_INET6
) {
2613 ip
.ipa_type
= IPADDR_V6
;
2614 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2615 sizeof(struct in6_addr
));
2620 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2626 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2628 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2629 struct connected
*c
= NULL
;
2630 struct ethaddr macaddr
;
2632 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2634 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2637 memset(&ip
, 0, sizeof(struct ipaddr
));
2638 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2641 if (c
->address
->family
== AF_INET
) {
2642 ip
.ipa_type
= IPADDR_V4
;
2643 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2644 sizeof(struct in_addr
));
2645 } else if (c
->address
->family
== AF_INET6
) {
2646 ip
.ipa_type
= IPADDR_V6
;
2647 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2648 sizeof(struct in6_addr
));
2653 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2659 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2662 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2663 struct connected
*c
= NULL
;
2664 struct ethaddr macaddr
;
2666 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2668 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2671 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2673 /* skip link local address */
2674 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2679 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2680 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2682 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2683 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2689 * zvni_gw_macip_add_to_client
2691 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2692 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2694 char buf
[ETHER_ADDR_STRLEN
];
2695 char buf2
[INET6_ADDRSTRLEN
];
2696 zebra_neigh_t
*n
= NULL
;
2697 zebra_mac_t
*mac
= NULL
;
2698 struct zebra_if
*zif
= NULL
;
2699 struct zebra_l2info_vxlan
*vxl
= NULL
;
2701 zif
= zvni
->vxlan_if
->info
;
2705 vxl
= &zif
->l2info
.vxl
;
2707 mac
= zvni_mac_lookup(zvni
, macaddr
);
2709 mac
= zvni_mac_add(zvni
, macaddr
);
2711 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2712 "Failed to add MAC %s intf %s(%u) VID %u",
2713 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2714 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2719 /* Set "local" forwarding info. */
2720 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2721 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2722 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2723 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2724 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2725 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2727 n
= zvni_neigh_lookup(zvni
, ip
);
2729 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2732 EC_ZEBRA_MAC_ADD_FAILED
,
2733 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2734 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2735 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2736 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2741 /* Set "local" forwarding info. */
2742 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2743 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2744 ZEBRA_NEIGH_SET_ACTIVE(n
);
2745 /* Set Router flag (R-bit) */
2746 if (ip
->ipa_type
== IPADDR_V6
)
2747 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2748 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2749 n
->ifindex
= ifp
->ifindex
;
2751 /* Only advertise in BGP if the knob is enabled */
2752 if (!advertise_gw_macip_enabled(zvni
))
2755 if (IS_ZEBRA_DEBUG_VXLAN
)
2757 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2758 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2759 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2760 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2762 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2763 n
->flags
, n
->loc_seq
);
2769 * zvni_gw_macip_del_from_client
2771 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2774 char buf1
[ETHER_ADDR_STRLEN
];
2775 char buf2
[INET6_ADDRSTRLEN
];
2776 zebra_neigh_t
*n
= NULL
;
2777 zebra_mac_t
*mac
= NULL
;
2779 /* If the neigh entry is not present nothing to do*/
2780 n
= zvni_neigh_lookup(zvni
, ip
);
2784 /* mac entry should be present */
2785 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2787 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2788 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2789 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2793 /* If the entry is not local nothing to do*/
2794 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2797 /* only need to delete the entry from bgp if we sent it before */
2798 if (IS_ZEBRA_DEBUG_VXLAN
)
2800 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2801 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2802 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2803 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2805 /* Remove neighbor from BGP. */
2806 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2807 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2809 /* Delete this neighbor entry. */
2810 zvni_neigh_del(zvni
, n
);
2812 /* see if the mac needs to be deleted as well*/
2814 zvni_deref_ip2mac(zvni
, mac
);
2819 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2822 zebra_vni_t
*zvni
= NULL
;
2823 struct zebra_if
*zif
= NULL
;
2824 struct zebra_l2info_vxlan zl2_info
;
2825 struct interface
*vlan_if
= NULL
;
2826 struct interface
*vrr_if
= NULL
;
2827 struct interface
*ifp
;
2829 /* Add primary SVI MAC*/
2830 zvni
= (zebra_vni_t
*)bucket
->data
;
2832 ifp
= zvni
->vxlan_if
;
2837 /* If down or not mapped to a bridge, we're done. */
2838 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2841 zl2_info
= zif
->l2info
.vxl
;
2844 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2848 /* Del primary MAC-IP */
2849 zvni_del_macip_for_intf(vlan_if
, zvni
);
2851 /* Del VRR MAC-IP - if any*/
2852 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2854 zvni_del_macip_for_intf(vrr_if
, zvni
);
2859 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2862 zebra_vni_t
*zvni
= NULL
;
2863 struct zebra_if
*zif
= NULL
;
2864 struct zebra_l2info_vxlan zl2_info
;
2865 struct interface
*vlan_if
= NULL
;
2866 struct interface
*vrr_if
= NULL
;
2867 struct interface
*ifp
= NULL
;
2869 zvni
= (zebra_vni_t
*)bucket
->data
;
2871 ifp
= zvni
->vxlan_if
;
2876 /* If down or not mapped to a bridge, we're done. */
2877 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2879 zl2_info
= zif
->l2info
.vxl
;
2882 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2886 /* Add primary SVI MAC-IP */
2887 zvni_add_macip_for_intf(vlan_if
, zvni
);
2889 if (advertise_gw_macip_enabled(zvni
)) {
2890 /* Add VRR MAC-IP - if any*/
2891 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2893 zvni_add_macip_for_intf(vrr_if
, zvni
);
2899 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2902 zebra_vni_t
*zvni
= NULL
;
2903 struct zebra_if
*zif
= NULL
;
2904 struct zebra_l2info_vxlan zl2_info
;
2905 struct interface
*vlan_if
= NULL
;
2906 struct interface
*ifp
;
2908 /* Add primary SVI MAC*/
2909 zvni
= (zebra_vni_t
*)bucket
->data
;
2913 ifp
= zvni
->vxlan_if
;
2918 /* If down or not mapped to a bridge, we're done. */
2919 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2922 zl2_info
= zif
->l2info
.vxl
;
2924 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2925 zif
->brslave_info
.br_if
);
2929 /* Del primary MAC-IP */
2930 zvni_del_macip_for_intf(vlan_if
, zvni
);
2935 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2936 struct interface
*ifp
,
2938 struct ethaddr
*macaddr
,
2941 char buf
[ETHER_ADDR_STRLEN
];
2942 char buf2
[INET6_ADDRSTRLEN
];
2943 struct zebra_vrf
*zvrf
;
2944 zebra_neigh_t
*n
= NULL
;
2945 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2946 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2947 bool upd_mac_seq
= false;
2948 bool neigh_mac_change
= false;
2949 bool neigh_on_hold
= false;
2950 bool neigh_was_remote
= false;
2951 bool do_dad
= false;
2952 struct in_addr vtep_ip
= {.s_addr
= 0};
2954 /* Check if the MAC exists. */
2955 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2957 /* create a dummy MAC if the MAC is not already present */
2958 if (IS_ZEBRA_DEBUG_VXLAN
)
2960 "AUTO MAC %s created for neigh %s on VNI %u",
2961 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2962 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2964 zmac
= zvni_mac_add(zvni
, macaddr
);
2966 zlog_debug("Failed to add MAC %s VNI %u",
2967 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2972 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2973 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2974 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2976 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2978 * We don't change the MAC to local upon a neighbor
2979 * learn event, we wait for the explicit local MAC
2980 * learn. However, we have to compute its sequence
2981 * number in preparation for when it actually turns
2988 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2990 if (IS_ZEBRA_DEBUG_VXLAN
)
2991 zlog_debug("\tUnable to find vrf for: %d",
2992 zvni
->vxlan_if
->vrf_id
);
2996 /* Check if the neighbor exists. */
2997 n
= zvni_neigh_lookup(zvni
, ip
);
2999 /* New neighbor - create */
3000 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3003 EC_ZEBRA_MAC_ADD_FAILED
,
3004 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3005 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3006 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3007 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3010 /* Set "local" forwarding info. */
3011 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3012 n
->ifindex
= ifp
->ifindex
;
3014 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3018 /* Note any changes and see if of interest to BGP. */
3019 mac_different
= (memcmp(n
->emac
.octet
,
3020 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3021 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3022 ZEBRA_NEIGH_ROUTER_FLAG
);
3023 if (!mac_different
&& is_router
== cur_is_router
) {
3024 if (IS_ZEBRA_DEBUG_VXLAN
)
3026 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3027 n
->ifindex
= ifp
->ifindex
;
3031 if (!mac_different
) {
3032 bool is_neigh_freezed
= false;
3034 /* Only the router flag has changed. */
3037 ZEBRA_NEIGH_ROUTER_FLAG
);
3039 UNSET_FLAG(n
->flags
,
3040 ZEBRA_NEIGH_ROUTER_FLAG
);
3042 /* Neigh is in freeze state and freeze action
3043 * is enabled, do not send update to client.
3045 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3047 CHECK_FLAG(n
->flags
,
3048 ZEBRA_NEIGH_DUPLICATE
));
3050 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3052 return zvni_neigh_send_add_to_client(
3053 zvni
->vni
, ip
, macaddr
,
3054 n
->flags
, n
->loc_seq
);
3056 if (IS_ZEBRA_DEBUG_VXLAN
)
3058 "\tNeighbor active and frozen");
3063 /* The MAC has changed, need to issue a delete
3064 * first as this means a different MACIP route.
3065 * Also, need to do some unlinking/relinking.
3066 * We also need to update the MAC's sequence number
3067 * in different situations.
3069 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3070 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3071 &n
->emac
, 0, n
->state
);
3072 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3074 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3076 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3077 neigh_mac_change
= upd_mac_seq
= true;
3078 listnode_delete(old_zmac
->neigh_list
, n
);
3079 zvni_deref_ip2mac(zvni
, old_zmac
);
3082 /* Update the forwarding info. */
3083 n
->ifindex
= ifp
->ifindex
;
3084 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3086 /* Link to new MAC */
3087 listnode_add_sort(zmac
->neigh_list
, n
);
3088 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3090 * Neighbor has moved from remote to local. Its
3091 * MAC could have also changed as part of the move.
3093 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3095 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3097 old_mac_seq
= CHECK_FLAG(
3102 neigh_mac_change
= upd_mac_seq
= true;
3103 listnode_delete(old_zmac
->neigh_list
,
3105 zvni_deref_ip2mac(zvni
, old_zmac
);
3108 /* Link to new MAC */
3109 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3110 listnode_add_sort(zmac
->neigh_list
, n
);
3112 /* Based on Mobility event Scenario-B from the
3113 * draft, neigh's previous state was remote treat this
3116 neigh_was_remote
= true;
3117 vtep_ip
= n
->r_vtep_ip
;
3118 /* Mark appropriately */
3119 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3120 n
->r_vtep_ip
.s_addr
= 0;
3121 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3122 n
->ifindex
= ifp
->ifindex
;
3126 /* If MAC was previously remote, or the neighbor had a different
3127 * MAC earlier, recompute the sequence number.
3130 uint32_t seq1
, seq2
;
3132 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3133 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3134 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3135 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3136 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3139 /* Mark Router flag (R-bit) */
3141 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3143 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3145 /* Check old and/or new MAC detected as duplicate mark
3146 * the neigh as duplicate
3148 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3149 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3150 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3152 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3153 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3156 /* For IP Duplicate Address Detection (DAD) is trigger,
3157 * when the event is extended mobility based on scenario-B
3158 * from the draft, IP/Neigh's MAC binding changed and
3159 * neigh's previous state was remote.
3161 if (neigh_mac_change
&& neigh_was_remote
)
3164 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3165 &neigh_on_hold
, true);
3167 /* Before we program this in BGP, we need to check if MAC is locally
3168 * learnt. If not, force neighbor to be inactive and reset its seq.
3170 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3171 ZEBRA_NEIGH_SET_INACTIVE(n
);
3173 zmac
->loc_seq
= mac_new_seq
;
3177 /* If the MAC's sequence number has changed, inform the MAC and all
3178 * neighbors associated with the MAC to BGP, else just inform this
3181 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3182 if (IS_ZEBRA_DEBUG_VXLAN
)
3183 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3184 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3185 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3186 zmac
->loc_seq
= mac_new_seq
;
3187 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3188 zmac
->flags
, zmac
->loc_seq
))
3190 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3194 ZEBRA_NEIGH_SET_ACTIVE(n
);
3195 n
->loc_seq
= zmac
->loc_seq
;
3198 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3199 n
->flags
, n
->loc_seq
);
3201 if (IS_ZEBRA_DEBUG_VXLAN
)
3202 zlog_debug("\tNeighbor on hold not sending");
3207 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3208 struct interface
*ifp
,
3210 struct ethaddr
*macaddr
,
3213 char buf
[ETHER_ADDR_STRLEN
];
3214 char buf2
[INET6_ADDRSTRLEN
];
3215 zebra_neigh_t
*n
= NULL
;
3216 zebra_mac_t
*zmac
= NULL
;
3218 /* If the neighbor is unknown, there is no further action. */
3219 n
= zvni_neigh_lookup(zvni
, ip
);
3223 /* If a remote entry, see if it needs to be refreshed */
3224 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3226 if (state
& NUD_STALE
)
3227 zvni_neigh_install(zvni
, n
);
3230 /* We got a "remote" neighbor notification for an entry
3231 * we think is local. This can happen in a multihoming
3232 * scenario - but only if the MAC is already "remote".
3233 * Just mark our entry as "remote".
3235 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3236 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3238 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3239 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3240 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3245 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3246 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3247 ZEBRA_NEIGH_SET_ACTIVE(n
);
3248 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3255 * Make hash key for MAC.
3257 static unsigned int mac_hash_keymake(void *p
)
3259 zebra_mac_t
*pmac
= p
;
3260 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3262 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3266 * Compare two MAC addresses.
3268 static bool mac_cmp(const void *p1
, const void *p2
)
3270 const zebra_mac_t
*pmac1
= p1
;
3271 const zebra_mac_t
*pmac2
= p2
;
3273 if (pmac1
== NULL
&& pmac2
== NULL
)
3276 if (pmac1
== NULL
|| pmac2
== NULL
)
3279 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3284 * Callback to allocate MAC hash entry.
3286 static void *zvni_mac_alloc(void *p
)
3288 const zebra_mac_t
*tmp_mac
= p
;
3291 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3294 return ((void *)mac
);
3300 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3302 zebra_mac_t tmp_mac
;
3303 zebra_mac_t
*mac
= NULL
;
3305 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3306 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3307 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3310 mac
->neigh_list
= list_new();
3311 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3319 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3321 zebra_mac_t
*tmp_mac
;
3323 list_delete(&mac
->neigh_list
);
3325 /* Free the VNI hash entry and allocated memory. */
3326 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3327 XFREE(MTYPE_MAC
, tmp_mac
);
3333 * Free MAC hash entry (callback)
3335 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3337 struct mac_walk_ctx
*wctx
= arg
;
3338 zebra_mac_t
*mac
= bucket
->data
;
3340 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3341 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3342 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3343 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3344 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3345 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3346 &wctx
->r_vtep_ip
))) {
3347 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3348 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3352 if (wctx
->uninstall
)
3353 zvni_mac_uninstall(wctx
->zvni
, mac
);
3355 zvni_mac_del(wctx
->zvni
, mac
);
3362 * Delete all MAC entries from specific VTEP for a particular VNI.
3364 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3365 struct in_addr
*r_vtep_ip
)
3367 struct mac_walk_ctx wctx
;
3369 if (!zvni
->mac_table
)
3372 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3374 wctx
.uninstall
= uninstall
;
3375 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3376 wctx
.r_vtep_ip
= *r_vtep_ip
;
3378 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3382 * Delete all MAC entries for this VNI.
3384 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3387 struct mac_walk_ctx wctx
;
3389 if (!zvni
->mac_table
)
3392 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3394 wctx
.uninstall
= uninstall
;
3395 wctx
.upd_client
= upd_client
;
3398 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3402 * Look up MAC hash entry.
3404 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3409 memset(&tmp
, 0, sizeof(tmp
));
3410 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3411 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3417 * Inform BGP about local MAC addition.
3419 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3420 uint8_t mac_flags
, uint32_t seq
)
3424 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3425 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3426 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3427 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3429 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3430 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3434 * Inform BGP about local MAC deletion.
3436 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3438 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3439 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3443 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3444 * notifications, to see if they are of interest.
3446 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3447 struct interface
*br_if
, vlanid_t vid
)
3449 struct zebra_ns
*zns
;
3450 struct route_node
*rn
;
3451 struct interface
*tmp_if
= NULL
;
3452 struct zebra_if
*zif
;
3453 struct zebra_l2info_bridge
*br
;
3454 struct zebra_l2info_vxlan
*vxl
= NULL
;
3455 uint8_t bridge_vlan_aware
;
3459 /* Determine if bridge is VLAN-aware or not */
3462 br
= &zif
->l2info
.br
;
3463 bridge_vlan_aware
= br
->vlan_aware
;
3465 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3466 /* TODO: Optimize with a hash. */
3467 zns
= zebra_ns_lookup(NS_DEFAULT
);
3468 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3469 tmp_if
= (struct interface
*)rn
->info
;
3473 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3475 if (!if_is_operative(tmp_if
))
3477 vxl
= &zif
->l2info
.vxl
;
3479 if (zif
->brslave_info
.br_if
!= br_if
)
3482 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3491 zvni
= zvni_lookup(vxl
->vni
);
3496 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3497 * neighbor notifications, to see if they are of interest.
3499 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3500 struct interface
*br_if
)
3502 struct zebra_ns
*zns
;
3503 struct route_node
*rn
;
3504 struct interface
*tmp_if
= NULL
;
3505 struct zebra_if
*zif
;
3506 struct zebra_l2info_bridge
*br
;
3507 struct zebra_l2info_vxlan
*vxl
= NULL
;
3508 uint8_t bridge_vlan_aware
;
3516 /* Make sure the linked interface is a bridge. */
3517 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3520 /* Determine if bridge is VLAN-aware or not */
3523 br
= &zif
->l2info
.br
;
3524 bridge_vlan_aware
= br
->vlan_aware
;
3525 if (bridge_vlan_aware
) {
3526 struct zebra_l2info_vlan
*vl
;
3528 if (!IS_ZEBRA_IF_VLAN(ifp
))
3533 vl
= &zif
->l2info
.vl
;
3537 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3538 /* TODO: Optimize with a hash. */
3539 zns
= zebra_ns_lookup(NS_DEFAULT
);
3540 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3541 tmp_if
= (struct interface
*)rn
->info
;
3545 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3547 if (!if_is_operative(tmp_if
))
3549 vxl
= &zif
->l2info
.vxl
;
3551 if (zif
->brslave_info
.br_if
!= br_if
)
3554 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3563 zvni
= zvni_lookup(vxl
->vni
);
3567 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3569 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3570 * linked to the bridge
3571 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3574 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3576 struct zebra_ns
*zns
;
3577 struct route_node
*rn
;
3578 struct interface
*tmp_if
= NULL
;
3579 struct zebra_if
*zif
;
3580 struct zebra_l2info_bridge
*br
;
3581 struct zebra_l2info_vlan
*vl
;
3582 uint8_t bridge_vlan_aware
;
3585 /* Defensive check, caller expected to invoke only with valid bridge. */
3589 /* Determine if bridge is VLAN-aware or not */
3592 br
= &zif
->l2info
.br
;
3593 bridge_vlan_aware
= br
->vlan_aware
;
3595 /* Check oper status of the SVI. */
3596 if (!bridge_vlan_aware
)
3597 return if_is_operative(br_if
) ? br_if
: NULL
;
3599 /* Identify corresponding VLAN interface. */
3600 /* TODO: Optimize with a hash. */
3601 zns
= zebra_ns_lookup(NS_DEFAULT
);
3602 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3603 tmp_if
= (struct interface
*)rn
->info
;
3604 /* Check oper status of the SVI. */
3605 if (!tmp_if
|| !if_is_operative(tmp_if
))
3608 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3609 || zif
->link
!= br_if
)
3611 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3613 if (vl
->vid
== vid
) {
3619 return found
? tmp_if
: NULL
;
3623 * Install remote MAC into the kernel.
3625 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3627 struct zebra_if
*zif
;
3628 struct zebra_l2info_vxlan
*vxl
;
3631 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3634 zif
= zvni
->vxlan_if
->info
;
3637 vxl
= &zif
->l2info
.vxl
;
3639 sticky
= !!CHECK_FLAG(mac
->flags
,
3640 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3642 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3643 mac
->fwd_info
.r_vtep_ip
, sticky
);
3647 * Uninstall remote MAC from the kernel.
3649 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3651 struct zebra_if
*zif
;
3652 struct zebra_l2info_vxlan
*vxl
;
3653 struct in_addr vtep_ip
;
3654 struct interface
*ifp
;
3656 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3659 if (!zvni
->vxlan_if
) {
3660 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3665 zif
= zvni
->vxlan_if
->info
;
3668 vxl
= &zif
->l2info
.vxl
;
3670 ifp
= zvni
->vxlan_if
;
3671 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3673 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3677 * Install MAC hash entry - called upon access VLAN change.
3679 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3682 struct mac_walk_ctx
*wctx
= ctxt
;
3684 mac
= (zebra_mac_t
*)bucket
->data
;
3686 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3687 zvni_mac_install(wctx
->zvni
, mac
);
3691 * Count of remote neighbors referencing this MAC.
3693 static int remote_neigh_count(zebra_mac_t
*zmac
)
3695 zebra_neigh_t
*n
= NULL
;
3696 struct listnode
*node
= NULL
;
3699 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3700 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3708 * Decrement neighbor refcount of MAC; uninstall and free it if
3711 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3713 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3716 /* If all remote neighbors referencing a remote MAC go away,
3717 * we need to uninstall the MAC.
3719 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3720 remote_neigh_count(mac
) == 0) {
3721 zvni_mac_uninstall(zvni
, mac
);
3722 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3725 /* If no neighbors, delete the MAC. */
3726 if (list_isempty(mac
->neigh_list
))
3727 zvni_mac_del(zvni
, mac
);
3731 * Read and populate local MACs and neighbors corresponding to this VNI.
3733 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3735 struct zebra_ns
*zns
;
3736 struct zebra_if
*zif
;
3737 struct interface
*vlan_if
;
3738 struct zebra_l2info_vxlan
*vxl
;
3739 struct interface
*vrr_if
;
3742 vxl
= &zif
->l2info
.vxl
;
3743 zns
= zebra_ns_lookup(NS_DEFAULT
);
3745 if (IS_ZEBRA_DEBUG_VXLAN
)
3747 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3748 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3749 zif
->brslave_info
.bridge_ifindex
);
3751 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3752 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3755 /* Add SVI MAC-IP */
3756 zvni_add_macip_for_intf(vlan_if
, zvni
);
3758 /* Add VRR MAC-IP - if any*/
3759 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3761 zvni_add_macip_for_intf(vrr_if
, zvni
);
3763 neigh_read_for_vlan(zns
, vlan_if
);
3768 * Hash function for VNI.
3770 static unsigned int vni_hash_keymake(void *p
)
3772 const zebra_vni_t
*zvni
= p
;
3774 return (jhash_1word(zvni
->vni
, 0));
3778 * Compare 2 VNI hash entries.
3780 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3782 const zebra_vni_t
*zvni1
= p1
;
3783 const zebra_vni_t
*zvni2
= p2
;
3785 return (zvni1
->vni
== zvni2
->vni
);
3788 static int vni_list_cmp(void *p1
, void *p2
)
3790 const zebra_vni_t
*zvni1
= p1
;
3791 const zebra_vni_t
*zvni2
= p2
;
3793 if (zvni1
->vni
== zvni2
->vni
)
3795 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3799 * Callback to allocate VNI hash entry.
3801 static void *zvni_alloc(void *p
)
3803 const zebra_vni_t
*tmp_vni
= p
;
3806 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3807 zvni
->vni
= tmp_vni
->vni
;
3808 return ((void *)zvni
);
3812 * Look up VNI hash entry.
3814 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3816 struct zebra_vrf
*zvrf
;
3817 zebra_vni_t tmp_vni
;
3818 zebra_vni_t
*zvni
= NULL
;
3820 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3822 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3824 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3830 * Add VNI hash entry.
3832 static zebra_vni_t
*zvni_add(vni_t vni
)
3834 struct zebra_vrf
*zvrf
;
3835 zebra_vni_t tmp_zvni
;
3836 zebra_vni_t
*zvni
= NULL
;
3838 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3840 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3842 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3845 /* Create hash table for MAC */
3847 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3849 /* Create hash table for neighbors */
3850 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3851 "Zebra VNI Neighbor Table");
3857 * Delete VNI hash entry.
3859 static int zvni_del(zebra_vni_t
*zvni
)
3861 struct zebra_vrf
*zvrf
;
3862 zebra_vni_t
*tmp_zvni
;
3864 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3867 zvni
->vxlan_if
= NULL
;
3869 /* Free the neighbor hash table. */
3870 hash_free(zvni
->neigh_table
);
3871 zvni
->neigh_table
= NULL
;
3873 /* Free the MAC hash table. */
3874 hash_free(zvni
->mac_table
);
3875 zvni
->mac_table
= NULL
;
3877 /* Free the VNI hash entry and allocated memory. */
3878 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3879 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3885 * Inform BGP about local VNI addition.
3887 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3889 struct zserv
*client
;
3892 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3893 /* BGP may not be running. */
3897 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3899 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3900 stream_putl(s
, zvni
->vni
);
3901 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3902 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3904 /* Write packet size. */
3905 stream_putw_at(s
, 0, stream_get_endp(s
));
3907 if (IS_ZEBRA_DEBUG_VXLAN
)
3908 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3909 inet_ntoa(zvni
->local_vtep_ip
),
3910 vrf_id_to_name(zvni
->vrf_id
),
3911 zebra_route_string(client
->proto
));
3913 client
->vniadd_cnt
++;
3914 return zserv_send_message(client
, s
);
3918 * Inform BGP about local VNI deletion.
3920 static int zvni_send_del_to_client(vni_t vni
)
3922 struct zserv
*client
;
3925 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3926 /* BGP may not be running. */
3930 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3933 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3934 stream_putl(s
, vni
);
3936 /* Write packet size. */
3937 stream_putw_at(s
, 0, stream_get_endp(s
));
3939 if (IS_ZEBRA_DEBUG_VXLAN
)
3940 zlog_debug("Send VNI_DEL %u to %s", vni
,
3941 zebra_route_string(client
->proto
));
3943 client
->vnidel_cnt
++;
3944 return zserv_send_message(client
, s
);
3948 * Build the VNI hash table by going over the VxLAN interfaces. This
3949 * is called when EVPN (advertise-all-vni) is enabled.
3951 static void zvni_build_hash_table(void)
3953 struct zebra_ns
*zns
;
3954 struct route_node
*rn
;
3955 struct interface
*ifp
;
3957 /* Walk VxLAN interfaces and create VNI hash. */
3958 zns
= zebra_ns_lookup(NS_DEFAULT
);
3959 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3961 zebra_vni_t
*zvni
= NULL
;
3962 zebra_l3vni_t
*zl3vni
= NULL
;
3963 struct zebra_if
*zif
;
3964 struct zebra_l2info_vxlan
*vxl
;
3966 ifp
= (struct interface
*)rn
->info
;
3970 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3973 vxl
= &zif
->l2info
.vxl
;
3976 /* L3-VNI and L2-VNI are handled seperately */
3977 zl3vni
= zl3vni_lookup(vni
);
3980 if (IS_ZEBRA_DEBUG_VXLAN
)
3982 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3983 ifp
->name
, ifp
->ifindex
, vni
);
3985 /* associate with vxlan_if */
3986 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3987 zl3vni
->vxlan_if
= ifp
;
3990 * we need to associate with SVI.
3991 * we can associate with svi-if only after association
3992 * with vxlan-intf is complete
3994 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3996 if (is_l3vni_oper_up(zl3vni
))
3997 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4000 struct interface
*vlan_if
= NULL
;
4002 if (IS_ZEBRA_DEBUG_VXLAN
)
4004 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4005 ifp
->name
, ifp
->ifindex
, vni
,
4006 inet_ntoa(vxl
->vtep_ip
));
4008 /* VNI hash entry is not expected to exist. */
4009 zvni
= zvni_lookup(vni
);
4012 "VNI hash already present for IF %s(%u) L2-VNI %u",
4013 ifp
->name
, ifp
->ifindex
, vni
);
4017 zvni
= zvni_add(vni
);
4020 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4021 ifp
->name
, ifp
->ifindex
, vni
);
4025 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4026 zvni
->vxlan_if
= ifp
;
4027 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4028 zif
->brslave_info
.br_if
);
4030 zvni
->vrf_id
= vlan_if
->vrf_id
;
4031 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4033 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4037 /* Inform BGP if intf is up and mapped to bridge. */
4038 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4039 zvni_send_add_to_client(zvni
);
4045 * See if remote VTEP matches with prefix.
4047 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4049 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4053 * Locate remote VTEP in VNI hash table.
4055 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4057 zebra_vtep_t
*zvtep
;
4062 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4063 if (zvni_vtep_match(vtep_ip
, zvtep
))
4071 * Add remote VTEP to VNI hash table.
4073 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4075 zebra_vtep_t
*zvtep
;
4077 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4079 zvtep
->vtep_ip
= *vtep_ip
;
4082 zvni
->vteps
->prev
= zvtep
;
4083 zvtep
->next
= zvni
->vteps
;
4084 zvni
->vteps
= zvtep
;
4090 * Remove remote VTEP from VNI hash table.
4092 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4095 zvtep
->next
->prev
= zvtep
->prev
;
4097 zvtep
->prev
->next
= zvtep
->next
;
4099 zvni
->vteps
= zvtep
->next
;
4101 zvtep
->prev
= zvtep
->next
= NULL
;
4102 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4108 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4109 * uninstall from kernel if asked to.
4111 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4113 zebra_vtep_t
*zvtep
, *zvtep_next
;
4118 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4119 zvtep_next
= zvtep
->next
;
4121 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4122 zvni_vtep_del(zvni
, zvtep
);
4129 * Install remote VTEP into the kernel.
4131 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4133 if (is_vxlan_flooding_head_end())
4134 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4139 * Uninstall remote VTEP from the kernel.
4141 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4143 if (!zvni
->vxlan_if
) {
4144 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4149 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4153 * Install or uninstall flood entries in the kernel corresponding to
4154 * remote VTEPs. This is invoked upon change to BUM handling.
4156 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4160 zebra_vtep_t
*zvtep
;
4162 zvni
= (zebra_vni_t
*)bucket
->data
;
4166 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4167 if (is_vxlan_flooding_head_end())
4168 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4170 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4175 * Cleanup VNI/VTEP and update kernel
4177 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4179 zebra_vni_t
*zvni
= NULL
;
4180 zebra_l3vni_t
*zl3vni
= NULL
;
4181 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4183 zvni
= (zebra_vni_t
*)bucket
->data
;
4185 /* remove from l3-vni list */
4187 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4189 listnode_delete(zl3vni
->l2vnis
, zvni
);
4191 /* Free up all neighbors and MACs, if any. */
4192 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4193 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4195 /* Free up all remote VTEPs, if any. */
4196 zvni_vtep_del_all(zvni
, 1);
4198 /* Delete the hash entry. */
4203 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4205 zebra_l3vni_t
*zl3vni
= NULL
;
4207 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4209 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4212 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4213 struct prefix
*host
)
4215 struct host_rb_entry lookup
;
4216 struct host_rb_entry
*hle
;
4218 memset(&lookup
, 0, sizeof(lookup
));
4219 memcpy(&lookup
.p
, host
, sizeof(*host
));
4221 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4225 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4226 memcpy(hle
, &lookup
, sizeof(lookup
));
4228 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4231 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4233 struct host_rb_entry lookup
;
4234 struct host_rb_entry
*hle
;
4236 memset(&lookup
, 0, sizeof(lookup
));
4237 memcpy(&lookup
.p
, host
, sizeof(*host
));
4239 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4241 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4242 XFREE(MTYPE_HOST_PREFIX
, hle
);
4249 * Look up MAC hash entry.
4251 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4252 struct ethaddr
*rmac
)
4257 memset(&tmp
, 0, sizeof(tmp
));
4258 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4259 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4265 * Callback to allocate RMAC hash entry.
4267 static void *zl3vni_rmac_alloc(void *p
)
4269 const zebra_mac_t
*tmp_rmac
= p
;
4272 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4275 return ((void *)zrmac
);
4279 * Add RMAC entry to l3-vni
4281 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4283 zebra_mac_t tmp_rmac
;
4284 zebra_mac_t
*zrmac
= NULL
;
4286 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4287 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4288 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4291 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4293 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4294 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4302 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4304 zebra_mac_t
*tmp_rmac
;
4305 struct host_rb_entry
*hle
;
4307 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4308 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4310 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4311 XFREE(MTYPE_HOST_PREFIX
, hle
);
4314 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4315 XFREE(MTYPE_MAC
, tmp_rmac
);
4321 * Install remote RMAC into the kernel.
4323 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4325 struct zebra_if
*zif
= NULL
;
4326 struct zebra_l2info_vxlan
*vxl
= NULL
;
4328 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4329 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4332 zif
= zl3vni
->vxlan_if
->info
;
4336 vxl
= &zif
->l2info
.vxl
;
4338 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4339 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4343 * Uninstall remote RMAC from the kernel.
4345 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4347 char buf
[ETHER_ADDR_STRLEN
];
4348 struct zebra_if
*zif
= NULL
;
4349 struct zebra_l2info_vxlan
*vxl
= NULL
;
4351 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4352 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4355 if (!zl3vni
->vxlan_if
) {
4357 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4358 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4359 zl3vni
->vni
, zl3vni
);
4363 zif
= zl3vni
->vxlan_if
->info
;
4367 vxl
= &zif
->l2info
.vxl
;
4369 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4370 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4373 /* handle rmac add */
4374 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4375 struct ipaddr
*vtep_ip
,
4376 struct prefix
*host_prefix
)
4378 char buf
[ETHER_ADDR_STRLEN
];
4379 char buf1
[INET6_ADDRSTRLEN
];
4380 zebra_mac_t
*zrmac
= NULL
;
4382 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4385 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4388 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4389 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4391 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4394 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4395 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4397 /* install rmac in kernel */
4398 zl3vni_rmac_install(zl3vni
, zrmac
);
4401 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4407 /* handle rmac delete */
4408 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4409 struct prefix
*host_prefix
)
4411 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4413 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4414 /* uninstall from kernel */
4415 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4417 /* del the rmac entry */
4418 zl3vni_rmac_del(zl3vni
, zrmac
);
4423 * Look up nh hash entry on a l3-vni.
4425 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4430 memset(&tmp
, 0, sizeof(tmp
));
4431 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4432 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4439 * Callback to allocate NH hash entry on L3-VNI.
4441 static void *zl3vni_nh_alloc(void *p
)
4443 const zebra_neigh_t
*tmp_n
= p
;
4446 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4453 * Add neighbor entry.
4455 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4456 struct ethaddr
*mac
)
4458 zebra_neigh_t tmp_n
;
4459 zebra_neigh_t
*n
= NULL
;
4461 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4462 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4463 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4466 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4468 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4469 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4470 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4476 * Delete neighbor entry.
4478 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4480 zebra_neigh_t
*tmp_n
;
4481 struct host_rb_entry
*hle
;
4483 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4484 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4486 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4487 XFREE(MTYPE_HOST_PREFIX
, hle
);
4490 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4491 XFREE(MTYPE_NEIGH
, tmp_n
);
4497 * Install remote nh as neigh into the kernel.
4499 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4506 if (!is_l3vni_oper_up(zl3vni
))
4509 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4510 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4513 flags
= NTF_EXT_LEARNED
;
4514 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4515 flags
|= NTF_ROUTER
;
4516 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4522 * Uninstall remote nh from the kernel.
4524 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4526 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4527 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4530 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4533 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4536 /* add remote vtep as a neigh entry */
4537 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4538 struct ethaddr
*rmac
,
4539 struct prefix
*host_prefix
)
4541 char buf
[ETHER_ADDR_STRLEN
];
4542 char buf1
[INET6_ADDRSTRLEN
];
4543 zebra_neigh_t
*nh
= NULL
;
4545 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4547 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4551 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4552 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4553 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4558 /* install the nh neigh in kernel */
4559 zl3vni_nh_install(zl3vni
, nh
);
4562 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4567 /* handle nh neigh delete */
4568 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4569 struct prefix
*host_prefix
)
4571 rb_delete_host(&nh
->host_rb
, host_prefix
);
4573 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4574 /* uninstall from kernel */
4575 zl3vni_nh_uninstall(zl3vni
, nh
);
4577 /* delete the nh entry */
4578 zl3vni_nh_del(zl3vni
, nh
);
4582 /* handle neigh update from kernel - the only thing of interest is to
4583 * readd stale entries.
4585 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4589 zebra_neigh_t
*n
= NULL
;
4591 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4595 /* all next hop neigh are remote and installed by frr.
4596 * If the kernel has aged this entry, re-install.
4598 if (state
& NUD_STALE
)
4599 zl3vni_nh_install(zl3vni
, n
);
4604 /* handle neigh delete from kernel */
4605 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4607 zebra_neigh_t
*n
= NULL
;
4609 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4613 /* all next hop neigh are remote and installed by frr.
4614 * If we get an age out notification for these neigh entries, we have to
4617 zl3vni_nh_install(zl3vni
, n
);
4623 * Hash function for L3 VNI.
4625 static unsigned int l3vni_hash_keymake(void *p
)
4627 const zebra_l3vni_t
*zl3vni
= p
;
4629 return jhash_1word(zl3vni
->vni
, 0);
4633 * Compare 2 L3 VNI hash entries.
4635 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4637 const zebra_l3vni_t
*zl3vni1
= p1
;
4638 const zebra_l3vni_t
*zl3vni2
= p2
;
4640 return (zl3vni1
->vni
== zl3vni2
->vni
);
4644 * Callback to allocate L3 VNI hash entry.
4646 static void *zl3vni_alloc(void *p
)
4648 zebra_l3vni_t
*zl3vni
= NULL
;
4649 const zebra_l3vni_t
*tmp_l3vni
= p
;
4651 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4652 zl3vni
->vni
= tmp_l3vni
->vni
;
4653 return ((void *)zl3vni
);
4657 * Look up L3 VNI hash entry.
4659 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4661 zebra_l3vni_t tmp_l3vni
;
4662 zebra_l3vni_t
*zl3vni
= NULL
;
4664 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4665 tmp_l3vni
.vni
= vni
;
4666 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4672 * Add L3 VNI hash entry.
4674 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4676 zebra_l3vni_t tmp_zl3vni
;
4677 zebra_l3vni_t
*zl3vni
= NULL
;
4679 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4680 tmp_zl3vni
.vni
= vni
;
4682 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4685 zl3vni
->vrf_id
= vrf_id
;
4686 zl3vni
->svi_if
= NULL
;
4687 zl3vni
->vxlan_if
= NULL
;
4688 zl3vni
->l2vnis
= list_new();
4689 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4691 /* Create hash table for remote RMAC */
4692 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4693 "Zebra L3-VNI RMAC-Table");
4695 /* Create hash table for neighbors */
4696 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4697 "Zebra L3-VNI next-hop table");
4703 * Delete L3 VNI hash entry.
4705 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4707 zebra_l3vni_t
*tmp_zl3vni
;
4709 /* free the list of l2vnis */
4710 list_delete(&zl3vni
->l2vnis
);
4711 zl3vni
->l2vnis
= NULL
;
4713 /* Free the rmac table */
4714 hash_free(zl3vni
->rmac_table
);
4715 zl3vni
->rmac_table
= NULL
;
4717 /* Free the nh table */
4718 hash_free(zl3vni
->nh_table
);
4719 zl3vni
->nh_table
= NULL
;
4721 /* Free the VNI hash entry and allocated memory. */
4722 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4723 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4728 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4730 struct zebra_ns
*zns
= NULL
;
4731 struct route_node
*rn
= NULL
;
4732 struct interface
*ifp
= NULL
;
4734 /* loop through all vxlan-interface */
4735 zns
= zebra_ns_lookup(NS_DEFAULT
);
4736 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4738 struct zebra_if
*zif
= NULL
;
4739 struct zebra_l2info_vxlan
*vxl
= NULL
;
4741 ifp
= (struct interface
*)rn
->info
;
4746 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4749 vxl
= &zif
->l2info
.vxl
;
4750 if (vxl
->vni
== zl3vni
->vni
) {
4751 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4759 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4761 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4762 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4767 if (!zl3vni
->vxlan_if
)
4770 zif
= zl3vni
->vxlan_if
->info
;
4774 vxl
= &zif
->l2info
.vxl
;
4776 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4779 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4781 struct zebra_vrf
*zvrf
= NULL
;
4783 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4787 return zl3vni_lookup(zvrf
->l3vni
);
4791 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4792 * neighbor notifications, to see if they are of interest.
4794 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4795 struct interface
*br_if
)
4799 uint8_t bridge_vlan_aware
= 0;
4800 zebra_l3vni_t
*zl3vni
= NULL
;
4801 struct zebra_ns
*zns
= NULL
;
4802 struct route_node
*rn
= NULL
;
4803 struct zebra_if
*zif
= NULL
;
4804 struct interface
*tmp_if
= NULL
;
4805 struct zebra_l2info_bridge
*br
= NULL
;
4806 struct zebra_l2info_vxlan
*vxl
= NULL
;
4811 /* Make sure the linked interface is a bridge. */
4812 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4815 /* Determine if bridge is VLAN-aware or not */
4818 br
= &zif
->l2info
.br
;
4819 bridge_vlan_aware
= br
->vlan_aware
;
4820 if (bridge_vlan_aware
) {
4821 struct zebra_l2info_vlan
*vl
;
4823 if (!IS_ZEBRA_IF_VLAN(ifp
))
4828 vl
= &zif
->l2info
.vl
;
4832 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4833 /* TODO: Optimize with a hash. */
4834 zns
= zebra_ns_lookup(NS_DEFAULT
);
4835 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4836 tmp_if
= (struct interface
*)rn
->info
;
4840 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4842 if (!if_is_operative(tmp_if
))
4844 vxl
= &zif
->l2info
.vxl
;
4846 if (zif
->brslave_info
.br_if
!= br_if
)
4849 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4858 zl3vni
= zl3vni_lookup(vxl
->vni
);
4863 * Inform BGP about l3-vni.
4865 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4867 struct stream
*s
= NULL
;
4868 struct zserv
*client
= NULL
;
4869 struct ethaddr rmac
;
4870 char buf
[ETHER_ADDR_STRLEN
];
4872 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4873 /* BGP may not be running. */
4878 memset(&rmac
, 0, sizeof(struct ethaddr
));
4879 zl3vni_get_rmac(zl3vni
, &rmac
);
4881 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4883 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4884 stream_putl(s
, zl3vni
->vni
);
4885 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4886 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4887 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4888 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4890 /* Write packet size. */
4891 stream_putw_at(s
, 0, stream_get_endp(s
));
4893 if (IS_ZEBRA_DEBUG_VXLAN
)
4895 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4896 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4897 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4898 inet_ntoa(zl3vni
->local_vtep_ip
),
4899 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4900 ? "prefix-routes-only"
4902 zebra_route_string(client
->proto
));
4904 client
->l3vniadd_cnt
++;
4905 return zserv_send_message(client
, s
);
4909 * Inform BGP about local l3-VNI deletion.
4911 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4913 struct stream
*s
= NULL
;
4914 struct zserv
*client
= NULL
;
4916 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4917 /* BGP may not be running. */
4921 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4923 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4924 stream_putl(s
, zl3vni
->vni
);
4926 /* Write packet size. */
4927 stream_putw_at(s
, 0, stream_get_endp(s
));
4929 if (IS_ZEBRA_DEBUG_VXLAN
)
4930 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4931 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4932 zebra_route_string(client
->proto
));
4934 client
->l3vnidel_cnt
++;
4935 return zserv_send_message(client
, s
);
4938 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4943 /* send l3vni add to BGP */
4944 zl3vni_send_add_to_client(zl3vni
);
4947 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4952 /* send l3-vni del to BGP*/
4953 zl3vni_send_del_to_client(zl3vni
);
4956 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
4958 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
4959 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4961 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4962 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4966 * handle transition of vni from l2 to l3 and vice versa
4968 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4971 zebra_vni_t
*zvni
= NULL
;
4973 /* There is a possibility that VNI notification was already received
4974 * from kernel and we programmed it as L2-VNI
4975 * In such a case we need to delete this L2-VNI first, so
4976 * that it can be reprogrammed as L3-VNI in the system. It is also
4977 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4978 * interface is still present in kernel. In this case to keep it
4979 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4982 /* Locate hash entry */
4983 zvni
= zvni_lookup(vni
);
4987 if (IS_ZEBRA_DEBUG_VXLAN
)
4988 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4990 /* Delete VNI from BGP. */
4991 zvni_send_del_to_client(zvni
->vni
);
4993 /* Free up all neighbors and MAC, if any. */
4994 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4995 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4997 /* Free up all remote VTEPs, if any. */
4998 zvni_vtep_del_all(zvni
, 0);
5000 /* Delete the hash entry. */
5001 if (zvni_del(zvni
)) {
5002 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5003 "Failed to del VNI hash %p, VNI %u", zvni
,
5008 /* TODO_MITESH: This needs to be thought through. We don't have
5009 * enough information at this point to reprogram the vni as
5010 * l2-vni. One way is to store the required info in l3-vni and
5011 * used it solely for this purpose
5018 /* delete and uninstall rmac hash entry */
5019 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5021 zebra_mac_t
*zrmac
= NULL
;
5022 zebra_l3vni_t
*zl3vni
= NULL
;
5024 zrmac
= (zebra_mac_t
*)bucket
->data
;
5025 zl3vni
= (zebra_l3vni_t
*)ctx
;
5026 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5027 zl3vni_rmac_del(zl3vni
, zrmac
);
5030 /* delete and uninstall nh hash entry */
5031 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5033 zebra_neigh_t
*n
= NULL
;
5034 zebra_l3vni_t
*zl3vni
= NULL
;
5036 n
= (zebra_neigh_t
*)bucket
->data
;
5037 zl3vni
= (zebra_l3vni_t
*)ctx
;
5038 zl3vni_nh_uninstall(zl3vni
, n
);
5039 zl3vni_nh_del(zl3vni
, n
);
5042 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5045 struct zserv
*client
= NULL
;
5046 struct stream
*s
= NULL
;
5047 char buf
[PREFIX_STRLEN
];
5049 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5050 /* BGP may not be running. */
5054 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5056 zclient_create_header(s
, cmd
, vrf_id
);
5057 stream_put(s
, p
, sizeof(struct prefix
));
5059 /* Write packet size. */
5060 stream_putw_at(s
, 0, stream_get_endp(s
));
5062 if (IS_ZEBRA_DEBUG_VXLAN
)
5063 zlog_debug("Send ip prefix %s %s on vrf %s",
5064 prefix2str(p
, buf
, sizeof(buf
)),
5065 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5066 vrf_id_to_name(vrf_id
));
5068 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5069 client
->prefixadd_cnt
++;
5071 client
->prefixdel_cnt
++;
5073 return zserv_send_message(client
, s
);
5076 /* re-add remote rmac if needed */
5077 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5078 struct ethaddr
*rmac
)
5080 char buf
[ETHER_ADDR_STRLEN
];
5081 zebra_mac_t
*zrmac
= NULL
;
5083 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5087 if (IS_ZEBRA_DEBUG_VXLAN
)
5088 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5089 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5091 zl3vni_rmac_install(zl3vni
, zrmac
);
5095 /* Process a remote MACIP add from BGP. */
5096 static void process_remote_macip_add(vni_t vni
,
5097 struct ethaddr
*macaddr
,
5099 struct ipaddr
*ipaddr
,
5102 struct in_addr vtep_ip
)
5105 zebra_vtep_t
*zvtep
;
5106 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5107 zebra_neigh_t
*n
= NULL
;
5108 int update_mac
= 0, update_neigh
= 0;
5109 char buf
[ETHER_ADDR_STRLEN
];
5110 char buf1
[INET6_ADDRSTRLEN
];
5111 struct interface
*ifp
= NULL
;
5112 struct zebra_if
*zif
= NULL
;
5113 struct zebra_vrf
*zvrf
;
5118 bool do_dad
= false;
5119 bool is_dup_detect
= false;
5121 /* Locate VNI hash entry - expected to exist. */
5122 zvni
= zvni_lookup(vni
);
5124 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5128 ifp
= zvni
->vxlan_if
;
5132 !if_is_operative(ifp
) ||
5134 !zif
->brslave_info
.br_if
) {
5135 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5140 /* The remote VTEP specified should normally exist, but it is
5141 * possible that when peering comes up, peer may advertise MACIP
5142 * routes before advertising type-3 routes.
5144 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5146 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5148 EC_ZEBRA_VTEP_ADD_FAILED
,
5149 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5154 zvni_vtep_install(zvni
, &vtep_ip
);
5157 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5158 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5159 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5161 mac
= zvni_mac_lookup(zvni
, macaddr
);
5163 /* Ignore if the mac is already present as a gateway mac */
5165 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5166 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5167 if (IS_ZEBRA_DEBUG_VXLAN
)
5168 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5170 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5171 ipa_len
? " IP " : "",
5173 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5177 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5181 /* check if the remote MAC is unknown or has a change.
5182 * If so, that needs to be updated first. Note that client could
5183 * install MAC and MACIP separately or just install the latter.
5186 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5187 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5188 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5189 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5190 || seq
!= mac
->rem_seq
)
5195 mac
= zvni_mac_add(zvni
, macaddr
);
5198 "Failed to add MAC %s VNI %u Remote VTEP %s",
5199 prefix_mac2str(macaddr
, buf
,
5201 vni
, inet_ntoa(vtep_ip
));
5205 /* Is this MAC created for a MACIP? */
5207 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5209 const char *mac_type
;
5211 /* When host moves but changes its (MAC,IP)
5212 * binding, BGP may install a MACIP entry that
5213 * corresponds to "older" location of the host
5214 * in transient situations (because {IP1,M1}
5215 * is a different route from {IP1,M2}). Check
5216 * the sequence number and ignore this update
5219 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5220 tmp_seq
= mac
->loc_seq
;
5223 tmp_seq
= mac
->rem_seq
;
5224 mac_type
= "remote";
5226 if (seq
< tmp_seq
) {
5227 if (IS_ZEBRA_DEBUG_VXLAN
)
5228 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5230 prefix_mac2str(macaddr
,
5232 ipa_len
? " IP " : "",
5235 buf1
, sizeof(buf1
)) : "",
5242 /* Check MAC's curent state is local (this is the case
5243 * where MAC has moved from L->R) and check previous
5244 * detection started via local learning.
5245 * RFC-7432: A PE/VTEP that detects a MAC mobility
5246 * event via local learning starts an M-second timer.
5248 * VTEP-IP or seq. change alone is not considered
5249 * for dup. detection.
5251 * MAC is already marked duplicate set dad, then
5252 * is_dup_detect will be set to not install the entry.
5254 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5256 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5259 /* Remove local MAC from BGP. */
5260 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5261 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5263 /* Set "auto" and "remote" forwarding info. */
5264 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5265 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5266 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5267 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5270 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5272 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5275 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5277 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5279 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5280 mac
->fwd_info
.r_vtep_ip
,
5281 do_dad
, &is_dup_detect
,
5284 if (!is_dup_detect
) {
5285 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5286 /* Install the entry. */
5287 zvni_mac_install(zvni
, mac
);
5291 /* Update seq number. */
5294 /* If there is no IP, return after clearing AUTO flag of MAC. */
5296 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5303 /* Check if the remote neighbor itself is unknown or has a
5304 * change. If so, create or update and then install the entry.
5306 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5308 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5309 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5310 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5311 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5312 || seq
!= n
->rem_seq
)
5317 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5320 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5321 ipaddr2str(ipaddr
, buf1
,
5323 prefix_mac2str(macaddr
, buf
,
5325 vni
, inet_ntoa(vtep_ip
));
5332 /* When host moves but changes its (MAC,IP)
5333 * binding, BGP may install a MACIP entry that
5334 * corresponds to "older" location of the host
5335 * in transient situations (because {IP1,M1}
5336 * is a different route from {IP1,M2}). Check
5337 * the sequence number and ignore this update
5340 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5341 tmp_seq
= n
->loc_seq
;
5344 tmp_seq
= n
->rem_seq
;
5347 if (seq
< tmp_seq
) {
5348 if (IS_ZEBRA_DEBUG_VXLAN
)
5349 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5351 prefix_mac2str(macaddr
,
5354 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5359 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5360 /* MAC change, send a delete for old
5361 * neigh if learnt locally.
5363 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5364 IS_ZEBRA_NEIGH_ACTIVE(n
))
5365 zvni_neigh_send_del_to_client(
5367 &n
->emac
, 0, n
->state
);
5369 /* update neigh list for macs */
5370 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5372 listnode_delete(old_mac
->neigh_list
, n
);
5373 zvni_deref_ip2mac(zvni
, old_mac
);
5375 listnode_add_sort(mac
->neigh_list
, n
);
5376 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5378 /* Check Neigh's curent state is local
5379 * (this is the case where neigh/host has moved
5380 * from L->R) and check previous detction
5381 * started via local learning.
5383 * RFC-7432: A PE/VTEP that detects a MAC
5384 * mobilit event via local learning starts
5385 * an M-second timer.
5386 * VTEP-IP or seq. change along is not
5387 * considered for dup. detection.
5389 * Mobilty event scenario-B IP-MAC binding
5392 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5399 /* Set "remote" forwarding info. */
5400 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5401 n
->r_vtep_ip
= vtep_ip
;
5402 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5404 /* Set router flag (R-bit) to this Neighbor entry */
5405 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5406 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5408 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5410 /* Check old or new MAC detected as duplicate,
5411 * inherit duplicate flag to this neigh.
5413 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5415 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5416 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5418 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5419 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5422 /* Check duplicate address detection for IP */
5423 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5428 /* Install the entry. */
5430 zvni_neigh_install(zvni
, n
);
5433 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5435 /* Update seq number. */
5439 /* Process a remote MACIP delete from BGP. */
5440 static void process_remote_macip_del(vni_t vni
,
5441 struct ethaddr
*macaddr
,
5443 struct ipaddr
*ipaddr
,
5444 struct in_addr vtep_ip
)
5447 zebra_mac_t
*mac
= NULL
;
5448 zebra_neigh_t
*n
= NULL
;
5449 struct interface
*ifp
= NULL
;
5450 struct zebra_if
*zif
= NULL
;
5451 struct zebra_ns
*zns
;
5452 struct zebra_l2info_vxlan
*vxl
;
5453 struct zebra_vrf
*zvrf
;
5454 char buf
[ETHER_ADDR_STRLEN
];
5455 char buf1
[INET6_ADDRSTRLEN
];
5457 /* Locate VNI hash entry - expected to exist. */
5458 zvni
= zvni_lookup(vni
);
5460 if (IS_ZEBRA_DEBUG_VXLAN
)
5461 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5465 ifp
= zvni
->vxlan_if
;
5469 !if_is_operative(ifp
) ||
5471 !zif
->brslave_info
.br_if
) {
5472 if (IS_ZEBRA_DEBUG_VXLAN
)
5473 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5477 zns
= zebra_ns_lookup(NS_DEFAULT
);
5478 vxl
= &zif
->l2info
.vxl
;
5480 /* The remote VTEP specified is normally expected to exist, but
5481 * it is possible that the peer may delete the VTEP before deleting
5482 * any MACs referring to the VTEP, in which case the handler (see
5483 * remote_vtep_del) would have already deleted the MACs.
5485 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5488 mac
= zvni_mac_lookup(zvni
, macaddr
);
5490 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5493 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5494 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5495 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5499 /* If the remote mac or neighbor doesn't exist there is nothing
5500 * more to do. Otherwise, uninstall the entry and then remove it.
5505 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5507 /* Ignore the delete if this mac is a gateway mac-ip */
5508 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5509 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5511 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5513 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5514 ipa_len
? " IP " : "",
5516 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5520 /* Uninstall remote neighbor or MAC. */
5522 if (zvrf
->dad_freeze
&&
5523 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5524 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5525 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5526 struct interface
*vlan_if
;
5528 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5529 zif
->brslave_info
.br_if
);
5530 if (IS_ZEBRA_DEBUG_VXLAN
)
5531 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5532 __PRETTY_FUNCTION__
,
5533 ipaddr2str(ipaddr
, buf1
,
5534 sizeof(buf1
)), n
->flags
,
5536 neigh_read_specific_ip(ipaddr
, vlan_if
);
5539 /* When the MAC changes for an IP, it is possible the
5540 * client may update the new MAC before trying to delete the
5541 * "old" neighbor (as these are two different MACIP routes).
5542 * Do the delete only if the MAC matches.
5544 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5545 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5546 zvni_neigh_uninstall(zvni
, n
);
5547 zvni_neigh_del(zvni
, n
);
5548 zvni_deref_ip2mac(zvni
, mac
);
5551 /* DAD: when MAC is freeze state as remote learn event,
5552 * remote mac-ip delete event is received will result in freeze
5553 * entry removal, first fetch kernel for the same entry present
5554 * as LOCAL and reachable, avoid deleting this entry instead
5555 * use kerenel local entry to update during unfreeze time.
5557 if (zvrf
->dad_freeze
&&
5558 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5559 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5560 if (IS_ZEBRA_DEBUG_VXLAN
)
5561 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5562 __PRETTY_FUNCTION__
,
5563 prefix_mac2str(macaddr
, buf
,
5566 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5567 macaddr
, vxl
->access_vlan
);
5570 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5571 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5573 * the remote sequence number in the auto mac entry
5574 * needs to be reset to 0 as the mac entry may have
5575 * been removed on all VTEPs (including
5576 * the originating one)
5580 /* If all remote neighbors referencing a remote MAC
5581 * go away, we need to uninstall the MAC.
5583 if (remote_neigh_count(mac
) == 0) {
5584 zvni_mac_uninstall(zvni
, mac
);
5585 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5587 if (list_isempty(mac
->neigh_list
))
5588 zvni_mac_del(zvni
, mac
);
5590 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5596 /* Public functions */
5598 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5600 zebra_l3vni_t
*zl3vni
= NULL
;
5602 zl3vni
= zl3vni_lookup(vni
);
5606 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5609 /* handle evpn route in vrf table */
5610 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5611 struct ipaddr
*vtep_ip
,
5612 struct prefix
*host_prefix
)
5614 zebra_l3vni_t
*zl3vni
= NULL
;
5615 struct ipaddr ipv4_vtep
;
5617 zl3vni
= zl3vni_from_vrf(vrf_id
);
5618 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5622 * add the next hop neighbor -
5623 * neigh to be installed is the ipv6 nexthop neigh
5625 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5628 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5629 * address. Rmac is programmed against the ipv4 vtep because we only
5630 * support ipv4 tunnels in the h/w right now
5632 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5633 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5634 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5635 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5636 &(ipv4_vtep
.ipaddr_v4
));
5638 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5639 sizeof(struct in_addr
));
5642 * add the rmac - remote rmac to be installed is against the ipv4
5645 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5648 /* handle evpn vrf route delete */
5649 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5650 struct ipaddr
*vtep_ip
,
5651 struct prefix
*host_prefix
)
5653 zebra_l3vni_t
*zl3vni
= NULL
;
5654 zebra_neigh_t
*nh
= NULL
;
5655 zebra_mac_t
*zrmac
= NULL
;
5657 zl3vni
= zl3vni_from_vrf(vrf_id
);
5661 /* find the next hop entry and rmac entry */
5662 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5665 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5667 /* delete the next hop entry */
5668 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5670 /* delete the rmac entry */
5672 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5676 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5677 struct ethaddr
*rmac
, bool use_json
)
5679 zebra_l3vni_t
*zl3vni
= NULL
;
5680 zebra_mac_t
*zrmac
= NULL
;
5681 json_object
*json
= NULL
;
5683 if (!is_evpn_enabled()) {
5685 vty_out(vty
, "{}\n");
5690 json
= json_object_new_object();
5692 zl3vni
= zl3vni_lookup(l3vni
);
5695 vty_out(vty
, "{}\n");
5697 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5701 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5704 vty_out(vty
, "{}\n");
5707 "%% Requested RMAC doesn't exist in L3-VNI %u",
5712 zl3vni_print_rmac(zrmac
, vty
, json
);
5715 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5716 json
, JSON_C_TO_STRING_PRETTY
));
5717 json_object_free(json
);
5721 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5723 zebra_l3vni_t
*zl3vni
;
5725 struct rmac_walk_ctx wctx
;
5726 json_object
*json
= NULL
;
5728 if (!is_evpn_enabled())
5731 zl3vni
= zl3vni_lookup(l3vni
);
5734 vty_out(vty
, "{}\n");
5736 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5739 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5744 json
= json_object_new_object();
5746 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5750 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5752 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5754 json_object_int_add(json
, "numRmacs", num_rmacs
);
5756 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5759 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5760 json
, JSON_C_TO_STRING_PRETTY
));
5761 json_object_free(json
);
5765 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5767 json_object
*json
= NULL
;
5770 if (!is_evpn_enabled()) {
5772 vty_out(vty
, "{}\n");
5777 json
= json_object_new_object();
5781 hash_iterate(zrouter
.l3vni_table
,
5782 (void (*)(struct hash_bucket
*,
5783 void *))zl3vni_print_rmac_hash_all_vni
,
5787 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5788 json
, JSON_C_TO_STRING_PRETTY
));
5789 json_object_free(json
);
5793 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5794 struct ipaddr
*ip
, bool use_json
)
5796 zebra_l3vni_t
*zl3vni
= NULL
;
5797 zebra_neigh_t
*n
= NULL
;
5798 json_object
*json
= NULL
;
5800 if (!is_evpn_enabled()) {
5802 vty_out(vty
, "{}\n");
5807 json
= json_object_new_object();
5809 zl3vni
= zl3vni_lookup(l3vni
);
5812 vty_out(vty
, "{}\n");
5814 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5818 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5821 vty_out(vty
, "{}\n");
5824 "%% Requested next-hop not present for L3-VNI %u",
5829 zl3vni_print_nh(n
, vty
, json
);
5832 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5833 json
, JSON_C_TO_STRING_PRETTY
));
5834 json_object_free(json
);
5838 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5841 struct nh_walk_ctx wctx
;
5842 json_object
*json
= NULL
;
5843 zebra_l3vni_t
*zl3vni
= NULL
;
5845 if (!is_evpn_enabled())
5848 zl3vni
= zl3vni_lookup(l3vni
);
5851 vty_out(vty
, "{}\n");
5853 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5857 num_nh
= hashcount(zl3vni
->nh_table
);
5862 json
= json_object_new_object();
5867 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5869 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5871 json_object_int_add(json
, "numNextHops", num_nh
);
5873 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5876 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5877 json
, JSON_C_TO_STRING_PRETTY
));
5878 json_object_free(json
);
5882 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5884 json_object
*json
= NULL
;
5887 if (!is_evpn_enabled()) {
5889 vty_out(vty
, "{}\n");
5894 json
= json_object_new_object();
5898 hash_iterate(zrouter
.l3vni_table
,
5899 (void (*)(struct hash_bucket
*,
5900 void *))zl3vni_print_nh_hash_all_vni
,
5904 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5905 json
, JSON_C_TO_STRING_PRETTY
));
5906 json_object_free(json
);
5911 * Display L3 VNI information (VTY command handler).
5913 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5916 json_object
*json
= NULL
;
5917 zebra_l3vni_t
*zl3vni
= NULL
;
5919 if (!is_evpn_enabled()) {
5921 vty_out(vty
, "{}\n");
5925 zl3vni
= zl3vni_lookup(vni
);
5928 vty_out(vty
, "{}\n");
5930 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5935 json
= json_object_new_object();
5939 zl3vni_print(zl3vni
, (void *)args
);
5942 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5943 json
, JSON_C_TO_STRING_PRETTY
));
5944 json_object_free(json
);
5948 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5949 json_object
*json_vrfs
)
5951 char buf
[ETHER_ADDR_STRLEN
];
5952 zebra_l3vni_t
*zl3vni
= NULL
;
5954 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5959 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5960 zvrf_name(zvrf
), zl3vni
->vni
,
5961 zl3vni_vxlan_if_name(zl3vni
),
5962 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5963 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5965 json_object
*json_vrf
= NULL
;
5967 json_vrf
= json_object_new_object();
5968 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5969 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5970 json_object_string_add(json_vrf
, "vxlanIntf",
5971 zl3vni_vxlan_if_name(zl3vni
));
5972 json_object_string_add(json_vrf
, "sviIntf",
5973 zl3vni_svi_if_name(zl3vni
));
5974 json_object_string_add(json_vrf
, "state",
5975 zl3vni_state2str(zl3vni
));
5976 json_object_string_add(
5977 json_vrf
, "routerMac",
5978 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5979 json_object_array_add(json_vrfs
, json_vrf
);
5984 * Display Neighbors for a VNI (VTY command handler).
5986 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5987 vni_t vni
, bool use_json
)
5991 struct neigh_walk_ctx wctx
;
5992 json_object
*json
= NULL
;
5994 if (!is_evpn_enabled())
5996 zvni
= zvni_lookup(vni
);
5999 vty_out(vty
, "{}\n");
6001 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6004 num_neigh
= hashcount(zvni
->neigh_table
);
6009 json
= json_object_new_object();
6011 /* Since we have IPv6 addresses to deal with which can vary widely in
6012 * size, we try to be a bit more elegant in display by first computing
6013 * the maximum width.
6015 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6018 wctx
.addr_width
= 15;
6020 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6024 "Number of ARPs (local and remote) known for this VNI: %u\n",
6026 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6027 -wctx
.addr_width
, "IP", "Type",
6028 "State", "MAC", "Remote VTEP");
6030 json_object_int_add(json
, "numArpNd", num_neigh
);
6032 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6034 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6035 json
, JSON_C_TO_STRING_PRETTY
));
6036 json_object_free(json
);
6041 * Display neighbors across all VNIs (VTY command handler).
6043 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6044 bool print_dup
, bool use_json
)
6046 json_object
*json
= NULL
;
6049 if (!is_evpn_enabled())
6053 json
= json_object_new_object();
6057 args
[2] = (void *)(ptrdiff_t)print_dup
;
6059 hash_iterate(zvrf
->vni_table
,
6060 (void (*)(struct hash_bucket
*,
6061 void *))zvni_print_neigh_hash_all_vni
,
6064 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6065 json
, JSON_C_TO_STRING_PRETTY
));
6066 json_object_free(json
);
6071 * Display neighbors across all VNIs in detail(VTY command handler).
6073 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6074 struct zebra_vrf
*zvrf
,
6075 bool print_dup
, bool use_json
)
6077 json_object
*json
= NULL
;
6080 if (!is_evpn_enabled())
6084 json
= json_object_new_object();
6088 args
[2] = (void *)(ptrdiff_t)print_dup
;
6090 hash_iterate(zvrf
->vni_table
,
6091 (void (*)(struct hash_bucket
*,
6092 void *))zvni_print_neigh_hash_all_vni_detail
,
6095 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6096 json
, JSON_C_TO_STRING_PRETTY
));
6097 json_object_free(json
);
6102 * Display specific neighbor for a VNI, if present (VTY command handler).
6104 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6105 struct zebra_vrf
*zvrf
, vni_t vni
,
6106 struct ipaddr
*ip
, bool use_json
)
6110 json_object
*json
= NULL
;
6112 if (!is_evpn_enabled())
6114 zvni
= zvni_lookup(vni
);
6117 vty_out(vty
, "{}\n");
6119 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6122 n
= zvni_neigh_lookup(zvni
, ip
);
6126 "%% Requested neighbor does not exist in VNI %u\n",
6131 json
= json_object_new_object();
6133 zvni_print_neigh(n
, vty
, json
);
6136 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6137 json
, JSON_C_TO_STRING_PRETTY
));
6138 json_object_free(json
);
6143 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6144 * By definition, these are remote neighbors.
6146 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6147 vni_t vni
, struct in_addr vtep_ip
,
6152 struct neigh_walk_ctx wctx
;
6153 json_object
*json
= NULL
;
6155 if (!is_evpn_enabled())
6157 zvni
= zvni_lookup(vni
);
6160 vty_out(vty
, "{}\n");
6162 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6165 num_neigh
= hashcount(zvni
->neigh_table
);
6169 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6172 wctx
.addr_width
= 15;
6173 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6174 wctx
.r_vtep_ip
= vtep_ip
;
6176 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6177 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6180 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6181 json
, JSON_C_TO_STRING_PRETTY
));
6182 json_object_free(json
);
6187 * Display Duplicate detected Neighbors for a VNI
6188 * (VTY command handler).
6190 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6191 struct zebra_vrf
*zvrf
,
6197 struct neigh_walk_ctx wctx
;
6198 json_object
*json
= NULL
;
6200 if (!is_evpn_enabled())
6203 zvni
= zvni_lookup(vni
);
6205 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6209 num_neigh
= hashcount(zvni
->neigh_table
);
6213 num_neigh
= num_dup_detected_neighs(zvni
);
6218 json
= json_object_new_object();
6220 /* Since we have IPv6 addresses to deal with which can vary widely in
6221 * size, we try to be a bit more elegant in display by first computing
6222 * the maximum width.
6224 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6227 wctx
.addr_width
= 15;
6229 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6233 "Number of ARPs (local and remote) known for this VNI: %u\n",
6235 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6236 -wctx
.addr_width
, "IP", "Type",
6237 "State", "MAC", "Remote VTEP");
6239 json_object_int_add(json
, "numArpNd", num_neigh
);
6241 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6244 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6245 json
, JSON_C_TO_STRING_PRETTY
));
6246 json_object_free(json
);
6251 * Display MACs for a VNI (VTY command handler).
6253 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6254 vni_t vni
, bool use_json
)
6258 struct mac_walk_ctx wctx
;
6259 json_object
*json
= NULL
;
6260 json_object
*json_mac
= NULL
;
6262 if (!is_evpn_enabled())
6264 zvni
= zvni_lookup(vni
);
6267 vty_out(vty
, "{}\n");
6269 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6272 num_macs
= num_valid_macs(zvni
);
6277 json
= json_object_new_object();
6278 json_mac
= json_object_new_object();
6281 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6284 wctx
.json
= json_mac
;
6288 "Number of MACs (local and remote) known for this VNI: %u\n",
6290 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6291 "Intf/Remote VTEP", "VLAN");
6293 json_object_int_add(json
, "numMacs", num_macs
);
6295 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6298 json_object_object_add(json
, "macs", json_mac
);
6299 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6300 json
, JSON_C_TO_STRING_PRETTY
));
6301 json_object_free(json
);
6306 * Display MACs for all VNIs (VTY command handler).
6308 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6309 bool print_dup
, bool use_json
)
6311 struct mac_walk_ctx wctx
;
6312 json_object
*json
= NULL
;
6314 if (!is_evpn_enabled()) {
6316 vty_out(vty
, "{}\n");
6320 json
= json_object_new_object();
6322 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6325 wctx
.print_dup
= print_dup
;
6326 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6329 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6330 json
, JSON_C_TO_STRING_PRETTY
));
6331 json_object_free(json
);
6336 * Display MACs in detail for all VNIs (VTY command handler).
6338 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6339 struct zebra_vrf
*zvrf
,
6340 bool print_dup
, bool use_json
)
6342 struct mac_walk_ctx wctx
;
6343 json_object
*json
= NULL
;
6345 if (!is_evpn_enabled()) {
6347 vty_out(vty
, "{}\n");
6351 json
= json_object_new_object();
6353 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6356 wctx
.print_dup
= print_dup
;
6357 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6361 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6362 json
, JSON_C_TO_STRING_PRETTY
));
6363 json_object_free(json
);
6368 * Display MACs for all VNIs (VTY command handler).
6370 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6371 struct zebra_vrf
*zvrf
,
6372 struct in_addr vtep_ip
, bool use_json
)
6374 struct mac_walk_ctx wctx
;
6375 json_object
*json
= NULL
;
6377 if (!is_evpn_enabled())
6381 json
= json_object_new_object();
6383 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6385 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6386 wctx
.r_vtep_ip
= vtep_ip
;
6388 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6391 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6392 json
, JSON_C_TO_STRING_PRETTY
));
6393 json_object_free(json
);
6398 * Display specific MAC for a VNI, if present (VTY command handler).
6400 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6401 vni_t vni
, struct ethaddr
*macaddr
,
6406 json_object
*json
= NULL
;
6408 if (!is_evpn_enabled())
6411 zvni
= zvni_lookup(vni
);
6414 vty_out(vty
, "{}\n");
6416 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6419 mac
= zvni_mac_lookup(zvni
, macaddr
);
6422 vty_out(vty
, "{}\n");
6425 "%% Requested MAC does not exist in VNI %u\n",
6431 json
= json_object_new_object();
6433 zvni_print_mac(mac
, vty
, json
);
6435 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6436 json
, JSON_C_TO_STRING_PRETTY
));
6437 json_object_free(json
);
6441 /* Print Duplicate MACs per VNI */
6442 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6443 struct zebra_vrf
*zvrf
,
6444 vni_t vni
, bool use_json
)
6447 struct mac_walk_ctx wctx
;
6449 json_object
*json
= NULL
;
6450 json_object
*json_mac
= NULL
;
6452 if (!is_evpn_enabled())
6455 zvni
= zvni_lookup(vni
);
6457 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6461 num_macs
= num_valid_macs(zvni
);
6465 num_macs
= num_dup_detected_macs(zvni
);
6470 json
= json_object_new_object();
6471 json_mac
= json_object_new_object();
6474 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6477 wctx
.json
= json_mac
;
6481 "Number of MACs (local and remote) known for this VNI: %u\n",
6483 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6484 "Intf/Remote VTEP", "VLAN");
6486 json_object_int_add(json
, "numMacs", num_macs
);
6488 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6491 json_object_object_add(json
, "macs", json_mac
);
6492 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6493 json
, JSON_C_TO_STRING_PRETTY
));
6494 json_object_free(json
);
6499 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6500 struct zebra_vrf
*zvrf
,
6501 vni_t vni
, struct ethaddr
*macaddr
)
6505 struct listnode
*node
= NULL
;
6506 zebra_neigh_t
*nbr
= NULL
;
6508 if (!is_evpn_enabled())
6511 zvni
= zvni_lookup(vni
);
6513 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6517 mac
= zvni_mac_lookup(zvni
, macaddr
);
6519 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6524 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6525 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6529 /* Remove all IPs as duplicate associcated with this MAC */
6530 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6531 /* For local neigh mark inactive so MACIP update is generated
6532 * to BGP. This is a scenario where MAC update received
6533 * and detected as duplicate which marked neigh as duplicate.
6534 * Later local neigh update did not get a chance to relay
6535 * to BGP. Similarly remote macip update, neigh needs to be
6536 * installed locally.
6538 if (zvrf
->dad_freeze
&&
6539 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6540 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6541 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6542 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6543 zvni_neigh_install(zvni
, nbr
);
6546 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6548 nbr
->detect_start_time
.tv_sec
= 0;
6549 nbr
->dad_dup_detect_time
= 0;
6552 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6554 mac
->detect_start_time
.tv_sec
= 0;
6555 mac
->detect_start_time
.tv_usec
= 0;
6556 mac
->dad_dup_detect_time
= 0;
6557 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6559 /* warn-only action return */
6560 if (!zvrf
->dad_freeze
)
6563 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6564 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6566 if (zvni_mac_send_add_to_client(zvni
->vni
,
6572 /* Process all neighbors associated with this MAC. */
6573 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6575 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6576 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6578 /* Install the entry. */
6579 zvni_mac_install(zvni
, mac
);
6585 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6586 struct zebra_vrf
*zvrf
,
6587 vni_t vni
, struct ipaddr
*ip
)
6592 char buf
[INET6_ADDRSTRLEN
];
6593 char buf2
[ETHER_ADDR_STRLEN
];
6595 if (!is_evpn_enabled())
6598 zvni
= zvni_lookup(vni
);
6600 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6604 nbr
= zvni_neigh_lookup(zvni
, ip
);
6607 "%% Requested host IP does not exist in VNI %u\n",
6612 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6614 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6616 "%% Requsted host IP %s is not duplicate detected\n",
6621 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6623 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6625 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6626 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6627 return CMD_WARNING_CONFIG_FAILED
;
6630 if (IS_ZEBRA_DEBUG_VXLAN
)
6631 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6632 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6635 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6637 nbr
->detect_start_time
.tv_sec
= 0;
6638 nbr
->detect_start_time
.tv_usec
= 0;
6639 nbr
->dad_dup_detect_time
= 0;
6640 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6642 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6643 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6645 nbr
->flags
, nbr
->loc_seq
);
6646 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6647 zvni_neigh_install(zvni
, nbr
);
6653 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6655 struct mac_walk_ctx
*wctx
= ctxt
;
6658 struct listnode
*node
= NULL
;
6659 zebra_neigh_t
*nbr
= NULL
;
6661 mac
= (zebra_mac_t
*)bucket
->data
;
6667 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6670 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6672 mac
->detect_start_time
.tv_sec
= 0;
6673 mac
->detect_start_time
.tv_usec
= 0;
6674 mac
->dad_dup_detect_time
= 0;
6675 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6677 /* Remove all IPs as duplicate associcated with this MAC */
6678 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6679 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6681 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6683 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6685 nbr
->detect_start_time
.tv_sec
= 0;
6686 nbr
->dad_dup_detect_time
= 0;
6689 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6690 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6692 if (zvni_mac_send_add_to_client(zvni
->vni
,
6694 mac
->flags
, mac
->loc_seq
))
6697 /* Process all neighbors associated with this MAC. */
6698 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6700 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6701 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6703 /* Install the entry. */
6704 zvni_mac_install(zvni
, mac
);
6708 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6710 struct neigh_walk_ctx
*wctx
= ctxt
;
6713 char buf
[INET6_ADDRSTRLEN
];
6715 nbr
= (zebra_neigh_t
*)bucket
->data
;
6721 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6724 if (IS_ZEBRA_DEBUG_VXLAN
) {
6725 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6727 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6728 __PRETTY_FUNCTION__
, buf
,
6729 nbr
->flags
, nbr
->loc_seq
);
6732 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6734 nbr
->detect_start_time
.tv_sec
= 0;
6735 nbr
->detect_start_time
.tv_usec
= 0;
6736 nbr
->dad_dup_detect_time
= 0;
6737 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6739 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6740 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6742 nbr
->flags
, nbr
->loc_seq
);
6743 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6744 zvni_neigh_install(zvni
, nbr
);
6748 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6753 struct zebra_vrf
*zvrf
;
6754 struct mac_walk_ctx m_wctx
;
6755 struct neigh_walk_ctx n_wctx
;
6757 zvni
= (zebra_vni_t
*)bucket
->data
;
6761 vty
= (struct vty
*)args
[0];
6762 zvrf
= (struct zebra_vrf
*)args
[1];
6764 if (hashcount(zvni
->neigh_table
)) {
6765 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6769 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6773 if (num_valid_macs(zvni
)) {
6774 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6778 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6783 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6784 struct zebra_vrf
*zvrf
)
6788 if (!is_evpn_enabled())
6794 hash_iterate(zvrf
->vni_table
,
6795 (void (*)(struct hash_bucket
*, void *))
6796 zvni_clear_dup_detect_hash_vni_all
, args
);
6801 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6802 struct zebra_vrf
*zvrf
,
6806 struct mac_walk_ctx m_wctx
;
6807 struct neigh_walk_ctx n_wctx
;
6809 if (!is_evpn_enabled())
6812 zvni
= zvni_lookup(vni
);
6814 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6818 if (hashcount(zvni
->neigh_table
)) {
6819 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6823 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6827 if (num_valid_macs(zvni
)) {
6828 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6832 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6839 * Display MACs for a VNI from specific VTEP (VTY command handler).
6841 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6842 vni_t vni
, struct in_addr vtep_ip
,
6847 struct mac_walk_ctx wctx
;
6848 json_object
*json
= NULL
;
6849 json_object
*json_mac
= NULL
;
6851 if (!is_evpn_enabled())
6853 zvni
= zvni_lookup(vni
);
6856 vty_out(vty
, "{}\n");
6858 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6861 num_macs
= num_valid_macs(zvni
);
6866 json
= json_object_new_object();
6867 json_mac
= json_object_new_object();
6870 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6873 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6874 wctx
.r_vtep_ip
= vtep_ip
;
6875 wctx
.json
= json_mac
;
6876 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6879 json_object_int_add(json
, "numMacs", wctx
.count
);
6881 json_object_object_add(json
, "macs", json_mac
);
6882 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6883 json
, JSON_C_TO_STRING_PRETTY
));
6884 json_object_free(json
);
6890 * Display VNI information (VTY command handler).
6892 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6895 json_object
*json
= NULL
;
6897 zebra_l3vni_t
*zl3vni
= NULL
;
6898 zebra_vni_t
*zvni
= NULL
;
6900 if (!is_evpn_enabled())
6904 json
= json_object_new_object();
6908 zl3vni
= zl3vni_lookup(vni
);
6910 zl3vni_print(zl3vni
, (void *)args
);
6912 zvni
= zvni_lookup(vni
);
6915 vty_out(vty
, "{}\n");
6917 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6921 zvni_print(zvni
, (void *)args
);
6925 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6926 json
, JSON_C_TO_STRING_PRETTY
));
6927 json_object_free(json
);
6931 /* Display all global details for EVPN */
6932 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6937 json_object
*json
= NULL
;
6938 struct zebra_vrf
*zvrf
= NULL
;
6940 if (!is_evpn_enabled())
6943 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6947 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6948 num_l2vnis
= hashcount(zvrf
->vni_table
);
6949 num_vnis
= num_l2vnis
+ num_l3vnis
;
6952 json
= json_object_new_object();
6953 json_object_string_add(json
, "advertiseGatewayMacip",
6954 zvrf
->advertise_gw_macip
? "Yes" : "No");
6955 json_object_int_add(json
, "numVnis", num_vnis
);
6956 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6957 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6958 if (zvrf
->dup_addr_detect
)
6959 json_object_boolean_true_add(json
,
6960 "isDuplicateAddrDetection");
6962 json_object_boolean_false_add(json
,
6963 "isDuplicateAddrDetection");
6964 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6965 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6966 json_object_int_add(json
, "detectionFreezeTime",
6967 zvrf
->dad_freeze_time
);
6970 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6971 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6972 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6973 zvrf
->advertise_gw_macip
? "Yes" : "No");
6974 vty_out(vty
, "Advertise svi mac-ip: %s\n",
6975 zvrf
->advertise_svi_macip
? "Yes" : "No");
6976 vty_out(vty
, "Duplicate address detection: %s\n",
6977 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6978 vty_out(vty
, " Detection max-moves %u, time %d\n",
6979 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6980 if (zvrf
->dad_freeze
) {
6981 if (zvrf
->dad_freeze_time
)
6982 vty_out(vty
, " Detection freeze %u\n",
6983 zvrf
->dad_freeze_time
);
6985 vty_out(vty
, " Detection freeze %s\n",
6991 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6992 json
, JSON_C_TO_STRING_PRETTY
));
6993 json_object_free(json
);
6998 * Display VNI hash table (VTY command handler).
7000 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7003 json_object
*json
= NULL
;
7006 if (!is_evpn_enabled())
7010 json
= json_object_new_object();
7012 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7013 "Type", "VxLAN IF", "# MACs", "# ARPs",
7014 "# Remote VTEPs", "Tenant VRF");
7019 /* Display all L2-VNIs */
7020 hash_iterate(zvrf
->vni_table
,
7021 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7024 /* Display all L3-VNIs */
7025 hash_iterate(zrouter
.l3vni_table
,
7026 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7030 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7031 json
, JSON_C_TO_STRING_PRETTY
));
7032 json_object_free(json
);
7036 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7040 uint32_t max_moves
= 0;
7041 uint32_t freeze_time
= 0;
7042 bool dup_addr_detect
= false;
7043 bool freeze
= false;
7046 STREAM_GETL(s
, dup_addr_detect
);
7047 STREAM_GETL(s
, time
);
7048 STREAM_GETL(s
, max_moves
);
7049 STREAM_GETL(s
, freeze
);
7050 STREAM_GETL(s
, freeze_time
);
7052 /* DAD previous state was enabled, and new state is disable,
7053 * clear all duplicate detected addresses.
7055 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7056 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7058 zvrf
->dup_addr_detect
= dup_addr_detect
;
7059 zvrf
->dad_time
= time
;
7060 zvrf
->dad_max_moves
= max_moves
;
7061 zvrf
->dad_freeze
= freeze
;
7062 zvrf
->dad_freeze_time
= freeze_time
;
7064 if (IS_ZEBRA_DEBUG_VXLAN
)
7066 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7067 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7068 zvrf
->dup_addr_detect
? "enable" : "disable",
7069 zvrf
->dad_max_moves
,
7071 zvrf
->dad_freeze
? "enable" : "disable",
7072 zvrf
->dad_freeze_time
);
7079 * Display VNI hash table in detail(VTY command handler).
7081 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7084 json_object
*json
= NULL
;
7085 struct zebra_ns
*zns
= NULL
;
7086 struct zvni_evpn_show zes
;
7088 if (!is_evpn_enabled())
7091 zns
= zebra_ns_lookup(NS_DEFAULT
);
7097 json
= json_object_new_object();
7103 /* Display all L2-VNIs */
7106 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7109 /* Display all L3-VNIs */
7110 hash_iterate(zrouter
.l3vni_table
,
7111 (void (*)(struct hash_bucket
*,
7112 void *))zl3vni_print_hash_detail
,
7116 vty_out(vty
, "%s\n",
7117 json_object_to_json_string_ext(
7118 json
, JSON_C_TO_STRING_PRETTY
));
7119 json_object_free(json
);
7124 * Handle neighbor delete notification from the kernel (on a VLAN device
7125 * / L3 interface). This may result in either the neighbor getting deleted
7126 * from our database or being re-added to the kernel (if it is a valid
7129 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7130 struct interface
*link_if
,
7133 char buf
[INET6_ADDRSTRLEN
];
7134 char buf2
[ETHER_ADDR_STRLEN
];
7135 zebra_neigh_t
*n
= NULL
;
7136 zebra_vni_t
*zvni
= NULL
;
7137 zebra_mac_t
*zmac
= NULL
;
7138 zebra_l3vni_t
*zl3vni
= NULL
;
7139 struct zebra_vrf
*zvrf
;
7141 /* check if this is a remote neigh entry corresponding to remote
7144 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7146 return zl3vni_local_nh_del(zl3vni
, ip
);
7148 /* We are only interested in neighbors on an SVI that resides on top
7149 * of a VxLAN bridge.
7151 zvni
= zvni_from_svi(ifp
, link_if
);
7155 if (!zvni
->vxlan_if
) {
7157 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7162 if (IS_ZEBRA_DEBUG_VXLAN
)
7163 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7164 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7165 ifp
->ifindex
, zvni
->vni
);
7167 /* If entry doesn't exist, nothing to do. */
7168 n
= zvni_neigh_lookup(zvni
, ip
);
7172 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7174 if (IS_ZEBRA_DEBUG_VXLAN
)
7176 "Trying to del a neigh %s without a mac %s on VNI %u",
7177 ipaddr2str(ip
, buf
, sizeof(buf
)),
7178 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7184 /* If it is a remote entry, the kernel has aged this out or someone has
7185 * deleted it, it needs to be re-installed as Quagga is the owner.
7187 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7188 zvni_neigh_install(zvni
, n
);
7192 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7194 zlog_debug("%s: VNI %u vrf lookup failed.",
7195 __PRETTY_FUNCTION__
, zvni
->vni
);
7199 /* In case of feeze action, if local neigh is in duplicate state,
7200 * Mark the Neigh as inactive before sending delete request to BGPd,
7201 * If BGPd has remote entry, it will re-install
7203 if (zvrf
->dad_freeze
&&
7204 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7205 ZEBRA_NEIGH_SET_INACTIVE(n
);
7207 /* Remove neighbor from BGP. */
7208 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7210 /* Delete this neighbor entry. */
7211 zvni_neigh_del(zvni
, n
);
7213 /* see if the AUTO mac needs to be deleted */
7214 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7215 && !listcount(zmac
->neigh_list
))
7216 zvni_mac_del(zvni
, zmac
);
7222 * Handle neighbor add or update notification from the kernel (on a VLAN
7223 * device / L3 interface). This is typically for a local neighbor but can
7224 * also be for a remote neighbor (e.g., ageout notification). It could
7225 * also be a "move" scenario.
7227 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7228 struct interface
*link_if
,
7230 struct ethaddr
*macaddr
,
7235 char buf
[ETHER_ADDR_STRLEN
];
7236 char buf2
[INET6_ADDRSTRLEN
];
7237 zebra_vni_t
*zvni
= NULL
;
7238 zebra_l3vni_t
*zl3vni
= NULL
;
7240 /* check if this is a remote neigh entry corresponding to remote
7243 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7245 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7247 /* We are only interested in neighbors on an SVI that resides on top
7248 * of a VxLAN bridge.
7250 zvni
= zvni_from_svi(ifp
, link_if
);
7254 if (IS_ZEBRA_DEBUG_VXLAN
)
7256 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7257 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7258 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7259 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7260 is_router
? "router " : "",
7263 /* Is this about a local neighbor or a remote one? */
7265 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7268 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7273 * Handle message from client to delete a remote MACIP for a VNI.
7275 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7279 struct ethaddr macaddr
;
7281 struct in_addr vtep_ip
;
7282 uint16_t l
= 0, ipa_len
;
7283 char buf
[ETHER_ADDR_STRLEN
];
7284 char buf1
[INET6_ADDRSTRLEN
];
7286 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7287 memset(&ip
, 0, sizeof(struct ipaddr
));
7288 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7292 while (l
< hdr
->length
) {
7293 /* Obtain each remote MACIP and process. */
7294 /* Message contains VNI, followed by MAC followed by IP (if any)
7295 * followed by remote VTEP IP.
7297 memset(&ip
, 0, sizeof(ip
));
7298 STREAM_GETL(s
, vni
);
7299 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7300 STREAM_GETL(s
, ipa_len
);
7302 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7304 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7306 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7307 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7308 l
+= IPV4_MAX_BYTELEN
;
7310 if (IS_ZEBRA_DEBUG_VXLAN
)
7312 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7314 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7315 ipa_len
? " IP " : "",
7317 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7319 zebra_route_string(client
->proto
));
7321 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7329 * Handle message from client to add a remote MACIP for a VNI. This
7330 * could be just the add of a MAC address or the add of a neighbor
7333 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7337 struct ethaddr macaddr
;
7339 struct in_addr vtep_ip
;
7340 uint16_t l
= 0, ipa_len
;
7343 char buf
[ETHER_ADDR_STRLEN
];
7344 char buf1
[INET6_ADDRSTRLEN
];
7346 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7347 memset(&ip
, 0, sizeof(struct ipaddr
));
7348 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7350 if (!EVPN_ENABLED(zvrf
)) {
7351 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7357 while (l
< hdr
->length
) {
7358 /* Obtain each remote MACIP and process. */
7359 /* Message contains VNI, followed by MAC followed by IP (if any)
7360 * followed by remote VTEP IP.
7362 memset(&ip
, 0, sizeof(ip
));
7363 STREAM_GETL(s
, vni
);
7364 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7365 STREAM_GETL(s
, ipa_len
);
7367 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7369 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7371 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7372 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7373 l
+= IPV4_MAX_BYTELEN
;
7375 /* Get flags - sticky mac and/or gateway mac */
7376 STREAM_GETC(s
, flags
);
7378 STREAM_GETL(s
, seq
);
7381 if (IS_ZEBRA_DEBUG_VXLAN
)
7383 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7385 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7386 ipa_len
? " IP " : "",
7388 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7389 flags
, seq
, inet_ntoa(vtep_ip
),
7390 zebra_route_string(client
->proto
));
7392 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7393 flags
, seq
, vtep_ip
);
7401 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7402 * us, this must involve a multihoming scenario. Treat this as implicit delete
7403 * of any prior local MAC.
7405 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7406 struct interface
*br_if
,
7407 struct ethaddr
*macaddr
, vlanid_t vid
)
7409 struct zebra_if
*zif
;
7410 struct zebra_l2info_vxlan
*vxl
;
7414 char buf
[ETHER_ADDR_STRLEN
];
7418 vxl
= &zif
->l2info
.vxl
;
7421 /* Check if EVPN is enabled. */
7422 if (!is_evpn_enabled())
7425 /* Locate hash entry; it is expected to exist. */
7426 zvni
= zvni_lookup(vni
);
7430 /* If entry doesn't exist, nothing to do. */
7431 mac
= zvni_mac_lookup(zvni
, macaddr
);
7435 /* Is it a local entry? */
7436 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7439 if (IS_ZEBRA_DEBUG_VXLAN
)
7441 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7442 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7445 /* Remove MAC from BGP. */
7446 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7449 * If there are no neigh associated with the mac delete the mac
7450 * else mark it as AUTO for forward reference
7452 if (!listcount(mac
->neigh_list
)) {
7453 zvni_mac_del(zvni
, mac
);
7455 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7456 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7463 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7464 * This can happen because the remote MAC entries are also added as "dynamic",
7465 * so the kernel can ageout the entry.
7467 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7468 struct interface
*br_if
,
7469 struct ethaddr
*macaddr
, vlanid_t vid
)
7471 struct zebra_if
*zif
= NULL
;
7472 struct zebra_l2info_vxlan
*vxl
= NULL
;
7474 zebra_vni_t
*zvni
= NULL
;
7475 zebra_l3vni_t
*zl3vni
= NULL
;
7476 zebra_mac_t
*mac
= NULL
;
7477 char buf
[ETHER_ADDR_STRLEN
];
7481 vxl
= &zif
->l2info
.vxl
;
7484 /* Check if EVPN is enabled. */
7485 if (!is_evpn_enabled())
7488 /* check if this is a remote RMAC and readd simillar to remote macs */
7489 zl3vni
= zl3vni_lookup(vni
);
7491 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7493 /* Locate hash entry; it is expected to exist. */
7494 zvni
= zvni_lookup(vni
);
7498 /* If entry doesn't exist, nothing to do. */
7499 mac
= zvni_mac_lookup(zvni
, macaddr
);
7503 /* Is it a remote entry? */
7504 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7507 if (IS_ZEBRA_DEBUG_VXLAN
)
7508 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7509 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7512 zvni_mac_install(zvni
, mac
);
7517 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7519 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7520 struct ethaddr
*macaddr
, vlanid_t vid
)
7524 char buf
[ETHER_ADDR_STRLEN
];
7526 /* We are interested in MACs only on ports or (port, VLAN) that
7529 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7532 if (!zvni
->vxlan_if
) {
7534 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7539 if (IS_ZEBRA_DEBUG_VXLAN
)
7540 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7541 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7542 ifp
->ifindex
, vid
, zvni
->vni
);
7544 /* If entry doesn't exist, nothing to do. */
7545 mac
= zvni_mac_lookup(zvni
, macaddr
);
7549 /* Is it a local entry? */
7550 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7553 /* Update all the neigh entries associated with this mac */
7554 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7556 /* Remove MAC from BGP. */
7557 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7560 * If there are no neigh associated with the mac delete the mac
7561 * else mark it as AUTO for forward reference
7563 if (!listcount(mac
->neigh_list
)) {
7564 zvni_mac_del(zvni
, mac
);
7566 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7567 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7574 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7576 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7577 struct interface
*br_if
,
7578 struct ethaddr
*macaddr
, vlanid_t vid
,
7583 struct zebra_vrf
*zvrf
;
7584 char buf
[ETHER_ADDR_STRLEN
];
7585 bool mac_sticky
= false;
7586 bool inform_client
= false;
7587 bool upd_neigh
= false;
7588 bool is_dup_detect
= false;
7589 struct in_addr vtep_ip
= {.s_addr
= 0};
7591 /* We are interested in MACs only on ports or (port, VLAN) that
7594 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7596 if (IS_ZEBRA_DEBUG_VXLAN
)
7598 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7599 sticky
? "sticky " : "",
7600 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7601 ifp
->name
, ifp
->ifindex
, vid
);
7605 if (!zvni
->vxlan_if
) {
7606 if (IS_ZEBRA_DEBUG_VXLAN
)
7608 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7613 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7615 if (IS_ZEBRA_DEBUG_VXLAN
)
7616 zlog_debug("\tNo Vrf found for vrf_id: %d",
7617 zvni
->vxlan_if
->vrf_id
);
7621 /* Check if we need to create or update or it is a NO-OP. */
7622 mac
= zvni_mac_lookup(zvni
, macaddr
);
7624 if (IS_ZEBRA_DEBUG_VXLAN
)
7626 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7627 sticky
? "sticky " : "",
7628 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7629 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7631 mac
= zvni_mac_add(zvni
, macaddr
);
7634 EC_ZEBRA_MAC_ADD_FAILED
,
7635 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7636 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7637 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7640 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7641 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7642 mac
->fwd_info
.local
.vid
= vid
;
7644 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7645 inform_client
= true;
7648 if (IS_ZEBRA_DEBUG_VXLAN
)
7650 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7651 sticky
? "sticky " : "",
7652 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7653 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7656 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7657 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7661 * Update any changes and if changes are relevant to
7664 if (mac_sticky
== sticky
7665 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7666 && mac
->fwd_info
.local
.vid
== vid
) {
7667 if (IS_ZEBRA_DEBUG_VXLAN
)
7669 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7670 "entry exists and has not changed ",
7671 sticky
? "sticky " : "",
7672 prefix_mac2str(macaddr
, buf
,
7674 ifp
->name
, ifp
->ifindex
, vid
,
7678 if (mac_sticky
!= sticky
) {
7680 SET_FLAG(mac
->flags
,
7683 UNSET_FLAG(mac
->flags
,
7685 inform_client
= true;
7688 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7689 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7690 mac
->fwd_info
.local
.vid
= vid
;
7692 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7693 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7694 bool do_dad
= false;
7697 * MAC has either moved or was "internally" created due
7698 * to a neighbor learn and is now actually learnt. If
7699 * it was learnt as a remote sticky MAC, this is an
7702 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7704 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7705 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7706 prefix_mac2str(macaddr
, buf
,
7708 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7713 /* If an actual move, compute MAC's seq number */
7714 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7715 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7717 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7718 /* Trigger DAD for remote MAC */
7722 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7723 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7724 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7725 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7726 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7727 mac
->fwd_info
.local
.vid
= vid
;
7729 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7731 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7733 * We have to inform BGP of this MAC as well as process
7736 inform_client
= true;
7739 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7743 if (is_dup_detect
) {
7744 inform_client
= false;
7750 /* Inform BGP if required. */
7751 if (inform_client
) {
7752 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7753 mac
->flags
, mac
->loc_seq
))
7757 /* Process all neighbors associated with this MAC, if required. */
7759 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7765 * Handle message from client to delete a remote VTEP for a VNI.
7767 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7770 unsigned short l
= 0;
7772 struct in_addr vtep_ip
;
7774 zebra_vtep_t
*zvtep
;
7775 struct interface
*ifp
;
7776 struct zebra_if
*zif
;
7778 if (!is_evpn_enabled()) {
7780 "%s: EVPN is not enabled yet we have received a vtep del command",
7781 __PRETTY_FUNCTION__
);
7785 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7786 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7793 while (l
< hdr
->length
) {
7794 /* Obtain each remote VTEP and process. */
7795 STREAM_GETL(s
, vni
);
7797 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7798 l
+= IPV4_MAX_BYTELEN
;
7800 if (IS_ZEBRA_DEBUG_VXLAN
)
7801 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7802 inet_ntoa(vtep_ip
), vni
,
7803 zebra_route_string(client
->proto
));
7805 /* Locate VNI hash entry - expected to exist. */
7806 zvni
= zvni_lookup(vni
);
7808 if (IS_ZEBRA_DEBUG_VXLAN
)
7810 "Failed to locate VNI hash upon remote VTEP DEL, "
7816 ifp
= zvni
->vxlan_if
;
7819 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7825 /* If down or not mapped to a bridge, we're done. */
7826 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7829 /* If the remote VTEP does not exist, there's nothing more to
7831 * Otherwise, uninstall any remote MACs pointing to this VTEP
7833 * then, the VTEP entry itself and remove it.
7835 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7839 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7840 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7841 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7842 zvni_vtep_del(zvni
, zvtep
);
7850 * Handle message from client to add a remote VTEP for a VNI.
7852 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7855 unsigned short l
= 0;
7857 struct in_addr vtep_ip
;
7859 struct interface
*ifp
;
7860 struct zebra_if
*zif
;
7862 if (!is_evpn_enabled()) {
7864 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7865 __PRETTY_FUNCTION__
);
7869 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7870 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7877 while (l
< hdr
->length
) {
7878 /* Obtain each remote VTEP and process. */
7879 STREAM_GETL(s
, vni
);
7881 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7882 l
+= IPV4_MAX_BYTELEN
;
7884 if (IS_ZEBRA_DEBUG_VXLAN
)
7885 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7886 inet_ntoa(vtep_ip
), vni
,
7887 zebra_route_string(client
->proto
));
7889 /* Locate VNI hash entry - expected to exist. */
7890 zvni
= zvni_lookup(vni
);
7893 EC_ZEBRA_VTEP_ADD_FAILED
,
7894 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7899 ifp
= zvni
->vxlan_if
;
7902 EC_ZEBRA_VTEP_ADD_FAILED
,
7903 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7910 /* If down or not mapped to a bridge, we're done. */
7911 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7914 /* If the remote VTEP already exists,
7915 there's nothing more to do. */
7916 if (zvni_vtep_find(zvni
, &vtep_ip
))
7919 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7920 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7921 "Failed to add remote VTEP, VNI %u zvni %p",
7926 zvni_vtep_install(zvni
, &vtep_ip
);
7934 * Add/Del gateway macip to evpn
7936 * 1. SVI interface on a vlan aware bridge
7937 * 2. SVI interface on a vlan unaware bridge
7938 * 3. vrr interface (MACVLAN) associated to a SVI
7939 * We advertise macip routes for an interface if it is associated to VxLan vlan
7941 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7945 struct ethaddr macaddr
;
7946 zebra_vni_t
*zvni
= NULL
;
7948 memset(&ip
, 0, sizeof(struct ipaddr
));
7949 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7951 /* Check if EVPN is enabled. */
7952 if (!is_evpn_enabled())
7955 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7956 struct interface
*svi_if
=
7957 NULL
; /* SVI corresponding to the MACVLAN */
7958 struct zebra_if
*ifp_zif
=
7959 NULL
; /* Zebra daemon specific info for MACVLAN */
7960 struct zebra_if
*svi_if_zif
=
7961 NULL
; /* Zebra daemon specific info for SVI*/
7963 ifp_zif
= ifp
->info
;
7968 * for a MACVLAN interface the link represents the svi_if
7970 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7971 ifp_zif
->link_ifindex
);
7973 zlog_debug("MACVLAN %s(%u) without link information",
7974 ifp
->name
, ifp
->ifindex
);
7978 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7980 * If it is a vlan aware bridge then the link gives the
7981 * bridge information
7983 struct interface
*svi_if_link
= NULL
;
7985 svi_if_zif
= svi_if
->info
;
7987 svi_if_link
= if_lookup_by_index_per_ns(
7988 zebra_ns_lookup(NS_DEFAULT
),
7989 svi_if_zif
->link_ifindex
);
7990 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7992 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7994 * If it is a vlan unaware bridge then svi is the bridge
7997 zvni
= zvni_from_svi(svi_if
, svi_if
);
7999 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8000 struct zebra_if
*svi_if_zif
=
8001 NULL
; /* Zebra daemon specific info for SVI */
8002 struct interface
*svi_if_link
=
8003 NULL
; /* link info for the SVI = bridge info */
8005 svi_if_zif
= ifp
->info
;
8007 svi_if_link
= if_lookup_by_index_per_ns(
8008 zebra_ns_lookup(NS_DEFAULT
),
8009 svi_if_zif
->link_ifindex
);
8011 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8013 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8014 zvni
= zvni_from_svi(ifp
, ifp
);
8020 if (!zvni
->vxlan_if
) {
8021 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8027 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8029 if (p
->family
== AF_INET
) {
8030 ip
.ipa_type
= IPADDR_V4
;
8031 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8032 sizeof(struct in_addr
));
8033 } else if (p
->family
== AF_INET6
) {
8034 ip
.ipa_type
= IPADDR_V6
;
8035 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8036 sizeof(struct in6_addr
));
8041 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8043 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8049 * Handle SVI interface going down.
8050 * SVI can be associated to either L3-VNI or L2-VNI.
8051 * For L2-VNI: At this point, this is a NOP since
8052 * the kernel deletes the neighbor entries on this SVI (if any).
8053 * We only need to update the vrf corresponding to zvni.
8054 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8057 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8059 zebra_l3vni_t
*zl3vni
= NULL
;
8061 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8064 /* process l3-vni down */
8065 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8067 /* remove association with svi-if */
8068 zl3vni
->svi_if
= NULL
;
8070 zebra_vni_t
*zvni
= NULL
;
8072 /* since we dont have svi corresponding to zvni, we associate it
8073 * to default vrf. Note: the corresponding neigh entries on the
8074 * SVI would have already been deleted */
8075 zvni
= zvni_from_svi(ifp
, link_if
);
8077 zvni
->vrf_id
= VRF_DEFAULT
;
8079 /* update the tenant vrf in BGP */
8080 zvni_send_add_to_client(zvni
);
8087 * Handle SVI interface coming up.
8088 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8090 * For L2-VNI: we need to install any remote neighbors entried (used for
8092 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8094 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8096 zebra_vni_t
*zvni
= NULL
;
8097 zebra_l3vni_t
*zl3vni
= NULL
;
8099 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8102 /* associate with svi */
8103 zl3vni
->svi_if
= ifp
;
8105 /* process oper-up */
8106 if (is_l3vni_oper_up(zl3vni
))
8107 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8110 /* process SVI up for l2-vni */
8111 struct neigh_walk_ctx n_wctx
;
8113 zvni
= zvni_from_svi(ifp
, link_if
);
8117 if (!zvni
->vxlan_if
) {
8119 "VNI %u hash %p doesn't have intf upon SVI up",
8124 if (IS_ZEBRA_DEBUG_VXLAN
)
8126 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8127 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8128 vrf_id_to_name(ifp
->vrf_id
));
8130 /* update the vrf information for l2-vni and inform bgp */
8131 zvni
->vrf_id
= ifp
->vrf_id
;
8132 zvni_send_add_to_client(zvni
);
8134 /* Install any remote neighbors for this VNI. */
8135 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8137 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8145 * Handle VxLAN interface down
8147 int zebra_vxlan_if_down(struct interface
*ifp
)
8150 struct zebra_if
*zif
= NULL
;
8151 struct zebra_l2info_vxlan
*vxl
= NULL
;
8152 zebra_l3vni_t
*zl3vni
= NULL
;
8155 /* Check if EVPN is enabled. */
8156 if (!is_evpn_enabled())
8161 vxl
= &zif
->l2info
.vxl
;
8164 zl3vni
= zl3vni_lookup(vni
);
8166 /* process-if-down for l3-vni */
8167 if (IS_ZEBRA_DEBUG_VXLAN
)
8168 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8171 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8173 /* process if-down for l2-vni */
8174 if (IS_ZEBRA_DEBUG_VXLAN
)
8175 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8178 /* Locate hash entry; it is expected to exist. */
8179 zvni
= zvni_lookup(vni
);
8182 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8183 ifp
->name
, ifp
->ifindex
, vni
);
8187 assert(zvni
->vxlan_if
== ifp
);
8189 /* Delete this VNI from BGP. */
8190 zvni_send_del_to_client(zvni
->vni
);
8192 /* Free up all neighbors and MACs, if any. */
8193 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8194 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8196 /* Free up all remote VTEPs, if any. */
8197 zvni_vtep_del_all(zvni
, 1);
8203 * Handle VxLAN interface up - update BGP if required.
8205 int zebra_vxlan_if_up(struct interface
*ifp
)
8208 struct zebra_if
*zif
= NULL
;
8209 struct zebra_l2info_vxlan
*vxl
= NULL
;
8210 zebra_vni_t
*zvni
= NULL
;
8211 zebra_l3vni_t
*zl3vni
= NULL
;
8213 /* Check if EVPN is enabled. */
8214 if (!is_evpn_enabled())
8219 vxl
= &zif
->l2info
.vxl
;
8222 zl3vni
= zl3vni_lookup(vni
);
8225 if (IS_ZEBRA_DEBUG_VXLAN
)
8226 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8229 /* we need to associate with SVI, if any, we can associate with
8230 * svi-if only after association with vxlan-intf is complete
8232 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8234 if (is_l3vni_oper_up(zl3vni
))
8235 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8237 /* Handle L2-VNI add */
8238 struct interface
*vlan_if
= NULL
;
8240 if (IS_ZEBRA_DEBUG_VXLAN
)
8241 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8244 /* Locate hash entry; it is expected to exist. */
8245 zvni
= zvni_lookup(vni
);
8248 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8249 ifp
->name
, ifp
->ifindex
, vni
);
8253 assert(zvni
->vxlan_if
== ifp
);
8254 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8255 zif
->brslave_info
.br_if
);
8257 zvni
->vrf_id
= vlan_if
->vrf_id
;
8258 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8260 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8263 /* If part of a bridge, inform BGP about this VNI. */
8264 /* Also, read and populate local MACs and neighbors. */
8265 if (zif
->brslave_info
.br_if
) {
8266 zvni_send_add_to_client(zvni
);
8267 zvni_read_mac_neigh(zvni
, ifp
);
8275 * Handle VxLAN interface delete. Locate and remove entry in hash table
8276 * and update BGP, if required.
8278 int zebra_vxlan_if_del(struct interface
*ifp
)
8281 struct zebra_if
*zif
= NULL
;
8282 struct zebra_l2info_vxlan
*vxl
= NULL
;
8283 zebra_vni_t
*zvni
= NULL
;
8284 zebra_l3vni_t
*zl3vni
= NULL
;
8286 /* Check if EVPN is enabled. */
8287 if (!is_evpn_enabled())
8292 vxl
= &zif
->l2info
.vxl
;
8295 zl3vni
= zl3vni_lookup(vni
);
8298 if (IS_ZEBRA_DEBUG_VXLAN
)
8299 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8302 /* process oper-down for l3-vni */
8303 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8305 /* remove the association with vxlan_if */
8306 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8307 zl3vni
->vxlan_if
= NULL
;
8310 /* process if-del for l2-vni*/
8311 if (IS_ZEBRA_DEBUG_VXLAN
)
8312 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8315 /* Locate hash entry; it is expected to exist. */
8316 zvni
= zvni_lookup(vni
);
8319 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8320 ifp
->name
, ifp
->ifindex
, vni
);
8324 /* remove from l3-vni list */
8325 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8327 listnode_delete(zl3vni
->l2vnis
, zvni
);
8329 /* Delete VNI from BGP. */
8330 zvni_send_del_to_client(zvni
->vni
);
8332 /* Free up all neighbors and MAC, if any. */
8333 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8334 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8336 /* Free up all remote VTEPs, if any. */
8337 zvni_vtep_del_all(zvni
, 0);
8339 /* Delete the hash entry. */
8340 if (zvni_del(zvni
)) {
8341 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8342 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8343 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8351 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8353 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8356 struct zebra_if
*zif
= NULL
;
8357 struct zebra_l2info_vxlan
*vxl
= NULL
;
8358 zebra_vni_t
*zvni
= NULL
;
8359 zebra_l3vni_t
*zl3vni
= NULL
;
8361 /* Check if EVPN is enabled. */
8362 if (!is_evpn_enabled())
8367 vxl
= &zif
->l2info
.vxl
;
8370 zl3vni
= zl3vni_lookup(vni
);
8373 if (IS_ZEBRA_DEBUG_VXLAN
)
8375 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8376 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8377 inet_ntoa(vxl
->vtep_ip
),
8378 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8380 /* Removed from bridge? Cleanup and return */
8381 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8382 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8383 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8387 /* access-vlan change - process oper down, associate with new
8388 * svi_if and then process oper up again
8390 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8391 if (if_is_operative(ifp
)) {
8392 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8393 zl3vni
->svi_if
= NULL
;
8394 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8395 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8396 if (is_l3vni_oper_up(zl3vni
))
8397 zebra_vxlan_process_l3vni_oper_up(
8403 * local-ip change - process oper down, associate with new
8404 * local-ip and then process oper up again
8406 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8407 if (if_is_operative(ifp
)) {
8408 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8409 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8410 if (is_l3vni_oper_up(zl3vni
))
8411 zebra_vxlan_process_l3vni_oper_up(
8416 /* Update local tunnel IP. */
8417 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8419 /* if we have a valid new master, process l3-vni oper up */
8420 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8421 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8422 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8426 /* Update VNI hash. */
8427 zvni
= zvni_lookup(vni
);
8430 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8431 ifp
->name
, ifp
->ifindex
, vni
);
8435 if (IS_ZEBRA_DEBUG_VXLAN
)
8437 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8438 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8439 inet_ntoa(vxl
->vtep_ip
),
8440 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8442 /* Removed from bridge? Cleanup and return */
8443 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8444 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8445 /* Delete from client, remove all remote VTEPs */
8446 /* Also, free up all MACs and neighbors. */
8447 zvni_send_del_to_client(zvni
->vni
);
8448 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8449 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8450 zvni_vtep_del_all(zvni
, 1);
8454 /* Handle other changes. */
8455 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8456 /* Remove all existing local neigh and MACs for this VNI
8457 * (including from BGP)
8459 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8460 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8463 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8464 zvni
->vxlan_if
= ifp
;
8466 /* Take further actions needed.
8467 * Note that if we are here, there is a change of interest.
8469 /* If down or not mapped to a bridge, we're done. */
8470 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8473 /* Inform BGP, if there is a change of interest. */
8475 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8476 zvni_send_add_to_client(zvni
);
8478 /* If there is a valid new master or a VLAN mapping change,
8479 * read and populate local MACs and neighbors.
8480 * Also, reinstall any remote MACs and neighbors
8481 * for this VNI (based on new VLAN).
8483 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8484 zvni_read_mac_neigh(zvni
, ifp
);
8485 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8486 struct mac_walk_ctx m_wctx
;
8487 struct neigh_walk_ctx n_wctx
;
8489 zvni_read_mac_neigh(zvni
, ifp
);
8491 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8493 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8496 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8498 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8507 * Handle VxLAN interface add.
8509 int zebra_vxlan_if_add(struct interface
*ifp
)
8512 struct zebra_if
*zif
= NULL
;
8513 struct zebra_l2info_vxlan
*vxl
= NULL
;
8514 zebra_vni_t
*zvni
= NULL
;
8515 zebra_l3vni_t
*zl3vni
= NULL
;
8517 /* Check if EVPN is enabled. */
8518 if (!is_evpn_enabled())
8523 vxl
= &zif
->l2info
.vxl
;
8526 zl3vni
= zl3vni_lookup(vni
);
8529 /* process if-add for l3-vni*/
8530 if (IS_ZEBRA_DEBUG_VXLAN
)
8532 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8533 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8534 inet_ntoa(vxl
->vtep_ip
),
8535 zif
->brslave_info
.bridge_ifindex
);
8537 /* associate with vxlan_if */
8538 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8539 zl3vni
->vxlan_if
= ifp
;
8541 /* Associate with SVI, if any. We can associate with svi-if only
8542 * after association with vxlan_if is complete */
8543 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8545 if (is_l3vni_oper_up(zl3vni
))
8546 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8549 /* process if-add for l2-vni */
8550 struct interface
*vlan_if
= NULL
;
8552 /* Create or update VNI hash. */
8553 zvni
= zvni_lookup(vni
);
8555 zvni
= zvni_add(vni
);
8558 EC_ZEBRA_VNI_ADD_FAILED
,
8559 "Failed to add VNI hash, IF %s(%u) VNI %u",
8560 ifp
->name
, ifp
->ifindex
, vni
);
8565 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8566 zvni
->vxlan_if
= ifp
;
8567 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8568 zif
->brslave_info
.br_if
);
8570 zvni
->vrf_id
= vlan_if
->vrf_id
;
8571 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8573 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8576 if (IS_ZEBRA_DEBUG_VXLAN
)
8578 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8580 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8582 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8583 inet_ntoa(vxl
->vtep_ip
),
8584 zif
->brslave_info
.bridge_ifindex
);
8586 /* If down or not mapped to a bridge, we're done. */
8587 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8591 zvni_send_add_to_client(zvni
);
8593 /* Read and populate local MACs and neighbors */
8594 zvni_read_mac_neigh(zvni
, ifp
);
8600 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8601 char *err
, int err_str_sz
, int filter
,
8604 zebra_l3vni_t
*zl3vni
= NULL
;
8605 struct zebra_vrf
*zvrf_default
= NULL
;
8607 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8611 if (IS_ZEBRA_DEBUG_VXLAN
)
8612 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8613 add
? "ADD" : "DEL");
8617 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8619 /* check if the vni is already present under zvrf */
8621 snprintf(err
, err_str_sz
,
8622 "VNI is already configured under the vrf");
8626 /* check if this VNI is already present in the system */
8627 zl3vni
= zl3vni_lookup(vni
);
8629 snprintf(err
, err_str_sz
,
8630 "VNI is already configured as L3-VNI");
8634 /* add the L3-VNI to the global table */
8635 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8637 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8641 /* associate the vrf with vni */
8644 /* set the filter in l3vni to denote if we are using l3vni only
8648 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8650 /* associate with vxlan-intf;
8651 * we need to associate with the vxlan-intf first
8653 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8655 /* associate with corresponding SVI interface, we can associate
8656 * with svi-if only after vxlan interface association is
8659 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8661 /* formulate l2vni list */
8662 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8665 if (is_l3vni_oper_up(zl3vni
))
8666 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8669 zl3vni
= zl3vni_lookup(vni
);
8671 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8675 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8676 snprintf(err
, ERR_STR_SZ
,
8677 "prefix-routes-only is not set for the vni");
8681 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8683 /* delete and uninstall all rmacs */
8684 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8687 /* delete and uninstall all next-hops */
8688 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8694 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8699 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8701 zebra_l3vni_t
*zl3vni
= NULL
;
8704 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8708 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8709 if (is_l3vni_oper_up(zl3vni
))
8710 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8714 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8716 zebra_l3vni_t
*zl3vni
= NULL
;
8719 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8723 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8724 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8728 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8730 zebra_l3vni_t
*zl3vni
= NULL
;
8734 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8740 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8746 * Handle message from client to specify the flooding mechanism for
8747 * BUM packets. The default is to do head-end (ingress) replication
8748 * and the other supported option is to disable it. This applies to
8749 * all BUM traffic and disabling it applies to both the transmit and
8750 * receive direction.
8752 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8755 enum vxlan_flood_control flood_ctrl
;
8757 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8758 zlog_err("EVPN flood control for non-default VRF %u",
8764 STREAM_GETC(s
, flood_ctrl
);
8766 if (IS_ZEBRA_DEBUG_VXLAN
)
8767 zlog_debug("EVPN flood control %u, currently %u",
8768 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8770 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8773 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8775 /* Install or uninstall flood entries corresponding to
8778 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8786 * Handle message from client to enable/disable advertisement of svi macip
8789 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8794 zebra_vni_t
*zvni
= NULL
;
8795 struct interface
*ifp
= NULL
;
8797 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8798 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8804 STREAM_GETC(s
, advertise
);
8805 STREAM_GETL(s
, vni
);
8808 if (IS_ZEBRA_DEBUG_VXLAN
)
8809 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8810 advertise
? "enabled" : "disabled",
8811 advertise_gw_macip_enabled(NULL
)
8815 if (zvrf
->advertise_svi_macip
== advertise
)
8820 zvrf
->advertise_svi_macip
= advertise
;
8821 hash_iterate(zvrf
->vni_table
,
8822 zvni_gw_macip_add_for_vni_hash
, NULL
);
8824 hash_iterate(zvrf
->vni_table
,
8825 zvni_svi_macip_del_for_vni_hash
, NULL
);
8826 zvrf
->advertise_svi_macip
= advertise
;
8830 struct zebra_if
*zif
= NULL
;
8831 struct zebra_l2info_vxlan zl2_info
;
8832 struct interface
*vlan_if
= NULL
;
8834 zvni
= zvni_lookup(vni
);
8838 if (IS_ZEBRA_DEBUG_VXLAN
)
8840 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8841 advertise
? "enabled" : "disabled", vni
,
8842 advertise_svi_macip_enabled(zvni
)
8846 if (zvni
->advertise_svi_macip
== advertise
)
8849 ifp
= zvni
->vxlan_if
;
8855 /* If down or not mapped to a bridge, we're done. */
8856 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8859 zl2_info
= zif
->l2info
.vxl
;
8861 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8862 zif
->brslave_info
.br_if
);
8867 zvni
->advertise_svi_macip
= advertise
;
8868 /* Add primary SVI MAC-IP */
8869 zvni_add_macip_for_intf(vlan_if
, zvni
);
8871 /* Del primary MAC-IP */
8872 zvni_del_macip_for_intf(vlan_if
, zvni
);
8873 zvni
->advertise_svi_macip
= advertise
;
8882 * Handle message from client to enable/disable advertisement of g/w macip
8885 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8890 zebra_vni_t
*zvni
= NULL
;
8891 struct interface
*ifp
= NULL
;
8892 struct zebra_if
*zif
= NULL
;
8893 struct zebra_l2info_vxlan zl2_info
;
8894 struct interface
*vlan_if
= NULL
;
8896 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8897 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8903 STREAM_GETC(s
, advertise
);
8904 vni
= stream_get3(s
);
8906 zvni
= zvni_lookup(vni
);
8910 if (zvni
->advertise_subnet
== advertise
)
8913 if (IS_ZEBRA_DEBUG_VXLAN
)
8914 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8915 advertise
? "enabled" : "disabled", vni
,
8916 zvni
->advertise_subnet
? "enabled" : "disabled");
8919 zvni
->advertise_subnet
= advertise
;
8921 ifp
= zvni
->vxlan_if
;
8927 /* If down or not mapped to a bridge, we're done. */
8928 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8931 zl2_info
= zif
->l2info
.vxl
;
8934 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8938 if (zvni
->advertise_subnet
)
8939 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8941 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8948 * Handle message from client to enable/disable advertisement of g/w macip
8951 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8956 zebra_vni_t
*zvni
= NULL
;
8957 struct interface
*ifp
= NULL
;
8959 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8960 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8966 STREAM_GETC(s
, advertise
);
8967 STREAM_GETL(s
, vni
);
8970 if (IS_ZEBRA_DEBUG_VXLAN
)
8971 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8972 advertise
? "enabled" : "disabled",
8973 advertise_gw_macip_enabled(NULL
)
8977 if (zvrf
->advertise_gw_macip
== advertise
)
8980 zvrf
->advertise_gw_macip
= advertise
;
8982 if (advertise_gw_macip_enabled(zvni
))
8983 hash_iterate(zvrf
->vni_table
,
8984 zvni_gw_macip_add_for_vni_hash
, NULL
);
8986 hash_iterate(zvrf
->vni_table
,
8987 zvni_gw_macip_del_for_vni_hash
, NULL
);
8990 struct zebra_if
*zif
= NULL
;
8991 struct zebra_l2info_vxlan zl2_info
;
8992 struct interface
*vlan_if
= NULL
;
8993 struct interface
*vrr_if
= NULL
;
8995 zvni
= zvni_lookup(vni
);
8999 if (IS_ZEBRA_DEBUG_VXLAN
)
9001 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9002 advertise
? "enabled" : "disabled", vni
,
9003 advertise_gw_macip_enabled(zvni
) ? "enabled"
9006 if (zvni
->advertise_gw_macip
== advertise
)
9009 zvni
->advertise_gw_macip
= advertise
;
9011 ifp
= zvni
->vxlan_if
;
9017 /* If down or not mapped to a bridge, we're done. */
9018 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9021 zl2_info
= zif
->l2info
.vxl
;
9023 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9024 zif
->brslave_info
.br_if
);
9028 if (advertise_gw_macip_enabled(zvni
)) {
9029 /* Add primary SVI MAC-IP */
9030 zvni_add_macip_for_intf(vlan_if
, zvni
);
9032 /* Add VRR MAC-IP - if any*/
9033 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9035 zvni_add_macip_for_intf(vrr_if
, zvni
);
9037 /* Del primary MAC-IP */
9038 zvni_del_macip_for_intf(vlan_if
, zvni
);
9040 /* Del VRR MAC-IP - if any*/
9041 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9043 zvni_del_macip_for_intf(vrr_if
, zvni
);
9053 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9054 * When enabled, the VNI hash table will be built and MAC FDB table read;
9055 * when disabled, the entries should be deleted and remote VTEPs and MACs
9056 * uninstalled from the kernel.
9057 * This also informs the setting for BUM handling at the time this change
9058 * occurs; it is relevant only when specifying "learn".
9060 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9062 struct stream
*s
= NULL
;
9064 enum vxlan_flood_control flood_ctrl
;
9066 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
9067 zlog_debug("EVPN VNI Adv for non-default VRF %u",
9073 STREAM_GETC(s
, advertise
);
9074 STREAM_GETC(s
, flood_ctrl
);
9076 if (IS_ZEBRA_DEBUG_VXLAN
)
9077 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
9078 advertise
? "enabled" : "disabled",
9079 is_evpn_enabled() ? "enabled" : "disabled",
9082 if (zvrf
->advertise_all_vni
== advertise
)
9085 zvrf
->advertise_all_vni
= advertise
;
9086 if (is_evpn_enabled()) {
9087 /* Note BUM handling */
9088 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9090 /* Build VNI hash table and inform BGP. */
9091 zvni_build_hash_table();
9093 /* Add all SVI (L3 GW) MACs to BGP*/
9094 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9097 /* Read the MAC FDB */
9098 macfdb_read(zvrf
->zns
);
9100 /* Read neighbors */
9101 neigh_read(zvrf
->zns
);
9103 /* Cleanup VTEPs for all VNIs - uninstall from
9104 * kernel and free entries.
9106 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9108 /* cleanup all l3vnis */
9109 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9117 * Allocate VNI hash table for this VRF and do other initialization.
9118 * NOTE: Currently supported only for default VRF.
9120 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9124 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9125 "Zebra VRF VNI Table");
9128 /* Cleanup VNI info, but don't free the table. */
9129 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9133 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9136 /* Close all VNI handling */
9137 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9141 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9142 hash_free(zvrf
->vni_table
);
9145 /* init the l3vni table */
9146 void zebra_vxlan_init(void)
9148 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9149 "Zebra VRF L3 VNI table");
9152 /* free l3vni table */
9153 void zebra_vxlan_disable(void)
9155 hash_free(zrouter
.l3vni_table
);
9158 /* get the l3vni svi ifindex */
9159 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9161 zebra_l3vni_t
*zl3vni
= NULL
;
9163 zl3vni
= zl3vni_from_vrf(vrf_id
);
9164 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9167 return zl3vni
->svi_if
->ifindex
;
9170 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9172 struct zebra_vrf
*zvrf
= NULL
;
9173 zebra_neigh_t
*nbr
= NULL
;
9174 zebra_vni_t
*zvni
= NULL
;
9175 char buf1
[INET6_ADDRSTRLEN
];
9176 char buf2
[ETHER_ADDR_STRLEN
];
9178 nbr
= THREAD_ARG(t
);
9180 /* since this is asynchronous we need sanity checks*/
9181 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9185 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9189 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9193 if (IS_ZEBRA_DEBUG_VXLAN
)
9194 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9195 __PRETTY_FUNCTION__
,
9196 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
9197 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
9199 nbr
->dad_count
, zvni
->vni
);
9201 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9203 nbr
->detect_start_time
.tv_sec
= 0;
9204 nbr
->detect_start_time
.tv_usec
= 0;
9205 nbr
->dad_dup_detect_time
= 0;
9206 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9209 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9210 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9211 nbr
->flags
, nbr
->loc_seq
);
9212 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9213 zvni_neigh_install(zvni
, nbr
);
9219 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9221 struct zebra_vrf
*zvrf
= NULL
;
9222 zebra_mac_t
*mac
= NULL
;
9223 zebra_vni_t
*zvni
= NULL
;
9224 struct listnode
*node
= NULL
;
9225 zebra_neigh_t
*nbr
= NULL
;
9226 char buf
[ETHER_ADDR_STRLEN
];
9228 mac
= THREAD_ARG(t
);
9230 /* since this is asynchronous we need sanity checks*/
9231 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9235 zvni
= zvni_lookup(mac
->zvni
->vni
);
9239 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9243 if (IS_ZEBRA_DEBUG_VXLAN
)
9244 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9245 __PRETTY_FUNCTION__
,
9246 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9249 listcount(mac
->neigh_list
));
9251 /* Remove all IPs as duplicate associcated with this MAC */
9252 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9253 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9254 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9255 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9256 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9257 zvni_neigh_install(zvni
, nbr
);
9260 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9262 nbr
->detect_start_time
.tv_sec
= 0;
9263 nbr
->dad_dup_detect_time
= 0;
9266 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9268 mac
->detect_start_time
.tv_sec
= 0;
9269 mac
->detect_start_time
.tv_usec
= 0;
9270 mac
->dad_dup_detect_time
= 0;
9271 mac
->dad_mac_auto_recovery_timer
= NULL
;
9273 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9275 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9276 mac
->flags
, mac
->loc_seq
))
9279 /* Process all neighbors associated with this MAC. */
9280 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9282 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9283 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9285 /* Install the entry. */
9286 zvni_mac_install(zvni
, mac
);