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 memset(tmp_buf
, 0, 30);
771 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
773 " Duplicate detection started at %s, detection count %u\n",
774 tmp_buf
, n
->dad_count
);
778 json_object_int_add(json
, "localSequence", n
->loc_seq
);
779 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
780 json_object_int_add(json
, "detectionCount",
782 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
783 json_object_boolean_true_add(json
, "isDuplicate");
785 json_object_boolean_false_add(json
, "isDuplicate");
792 * Print neighbor hash entry - called for display of all neighbors.
794 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
797 json_object
*json_vni
= NULL
, *json_row
= NULL
;
799 char buf1
[ETHER_ADDR_STRLEN
];
800 char buf2
[INET6_ADDRSTRLEN
];
801 struct neigh_walk_ctx
*wctx
= ctxt
;
802 const char *state_str
;
805 json_vni
= wctx
->json
;
806 n
= (zebra_neigh_t
*)bucket
->data
;
809 json_row
= json_object_new_object();
811 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
812 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
813 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
814 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
815 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
818 if (json_vni
== NULL
) {
819 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
820 -wctx
->addr_width
, buf2
, "local",
823 json_object_string_add(json_row
, "type", "local");
824 json_object_string_add(json_row
, "state", state_str
);
825 json_object_string_add(json_row
, "mac", buf1
);
826 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
827 json_object_boolean_true_add(
828 json_row
, "defaultGateway");
829 json_object_int_add(json_row
, "localSequence",
831 json_object_int_add(json_row
, "remoteSequence",
833 json_object_int_add(json_row
, "detectionCount",
835 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
836 json_object_boolean_true_add(json_row
,
839 json_object_boolean_false_add(json_row
,
843 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
844 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
845 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
848 if (json_vni
== NULL
) {
849 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
852 "%*s %-6s %-8s %-17s %-21s\n",
853 -wctx
->addr_width
, "Neighbor", "Type",
854 "State", "MAC", "Remote VTEP");
855 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
856 -wctx
->addr_width
, buf2
, "remote", state_str
,
857 buf1
, inet_ntoa(n
->r_vtep_ip
));
859 json_object_string_add(json_row
, "type", "remote");
860 json_object_string_add(json_row
, "state", state_str
);
861 json_object_string_add(json_row
, "mac", buf1
);
862 json_object_string_add(json_row
, "remoteVtep",
863 inet_ntoa(n
->r_vtep_ip
));
864 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
865 json_object_boolean_true_add(json_row
,
867 json_object_int_add(json_row
, "localSequence",
869 json_object_int_add(json_row
, "remoteSequence",
871 json_object_int_add(json_row
, "detectionCount",
873 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
874 json_object_boolean_true_add(json_row
,
877 json_object_boolean_false_add(json_row
,
884 json_object_object_add(json_vni
, buf2
, json_row
);
888 * Print neighbor hash entry in detail - called for display of all neighbors.
890 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
893 json_object
*json_vni
= NULL
, *json_row
= NULL
;
895 char buf
[INET6_ADDRSTRLEN
];
896 struct neigh_walk_ctx
*wctx
= ctxt
;
899 json_vni
= wctx
->json
;
900 n
= (zebra_neigh_t
*)bucket
->data
;
904 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
906 json_row
= json_object_new_object();
908 zvni_print_neigh(n
, vty
, json_row
);
911 json_object_object_add(json_vni
, buf
, json_row
);
915 * Print neighbors for all VNI.
917 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
921 json_object
*json
= NULL
, *json_vni
= NULL
;
924 struct neigh_walk_ctx wctx
;
925 char vni_str
[VNI_STR_LEN
];
928 vty
= (struct vty
*)args
[0];
929 json
= (json_object
*)args
[1];
930 print_dup
= (uint32_t)(uintptr_t)args
[2];
932 zvni
= (zebra_vni_t
*)bucket
->data
;
934 num_neigh
= hashcount(zvni
->neigh_table
);
937 num_neigh
= num_dup_detected_neighs(zvni
);
941 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
942 zvni
->vni
, num_neigh
);
944 json_vni
= json_object_new_object();
945 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
946 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
951 json_object_object_add(json
, vni_str
, json_vni
);
955 /* Since we have IPv6 addresses to deal with which can vary widely in
956 * size, we try to be a bit more elegant in display by first computing
959 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
962 wctx
.addr_width
= 15;
963 wctx
.json
= json_vni
;
964 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
967 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
968 -wctx
.addr_width
, "IP", "Type",
969 "State", "MAC", "Remote VTEP");
972 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
975 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
978 json_object_object_add(json
, vni_str
, json_vni
);
981 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
985 nbr
= (zebra_neigh_t
*)bucket
->data
;
989 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
990 zvni_print_neigh_hash(bucket
, ctxt
);
993 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
998 nbr
= (zebra_neigh_t
*)bucket
->data
;
1002 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1003 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1007 * Print neighbors for all VNIs in detail.
1009 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1013 json_object
*json
= NULL
, *json_vni
= NULL
;
1016 struct neigh_walk_ctx wctx
;
1017 char vni_str
[VNI_STR_LEN
];
1020 vty
= (struct vty
*)args
[0];
1021 json
= (json_object
*)args
[1];
1022 print_dup
= (uint32_t)(uintptr_t)args
[2];
1024 zvni
= (zebra_vni_t
*)bucket
->data
;
1027 vty_out(vty
, "{}\n");
1030 num_neigh
= hashcount(zvni
->neigh_table
);
1032 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1037 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1038 zvni
->vni
, num_neigh
);
1040 json_vni
= json_object_new_object();
1041 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1042 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1046 json_object_object_add(json
, vni_str
, json_vni
);
1050 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1053 wctx
.addr_width
= 15;
1054 wctx
.json
= json_vni
;
1057 hash_iterate(zvni
->neigh_table
,
1058 zvni_print_dad_neigh_hash_detail
, &wctx
);
1060 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1064 json_object_object_add(json
, vni_str
, json_vni
);
1067 /* print a specific next hop for an l3vni */
1068 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1071 char buf1
[ETHER_ADDR_STRLEN
];
1072 char buf2
[INET6_ADDRSTRLEN
];
1073 json_object
*json_hosts
= NULL
;
1074 struct host_rb_entry
*hle
;
1077 vty_out(vty
, "Ip: %s\n",
1078 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1079 vty_out(vty
, " RMAC: %s\n",
1080 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1081 vty_out(vty
, " Refcount: %d\n",
1082 rb_host_count(&n
->host_rb
));
1083 vty_out(vty
, " Prefixes:\n");
1084 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1085 vty_out(vty
, " %s\n",
1086 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1088 json_hosts
= json_object_new_array();
1089 json_object_string_add(
1090 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1091 json_object_string_add(
1093 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1094 json_object_int_add(json
, "refCount",
1095 rb_host_count(&n
->host_rb
));
1096 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1097 json_object_array_add(json_hosts
,
1098 json_object_new_string(prefix2str(
1099 &hle
->p
, buf2
, sizeof(buf2
))));
1100 json_object_object_add(json
, "prefixList", json_hosts
);
1104 /* Print a specific RMAC entry */
1105 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1108 char buf1
[ETHER_ADDR_STRLEN
];
1109 char buf2
[PREFIX_STRLEN
];
1110 json_object
*json_hosts
= NULL
;
1111 struct host_rb_entry
*hle
;
1114 vty_out(vty
, "MAC: %s\n",
1115 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1116 vty_out(vty
, " Remote VTEP: %s\n",
1117 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1118 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1119 vty_out(vty
, " Prefixes:\n");
1120 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1121 vty_out(vty
, " %s\n",
1122 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1124 json_hosts
= json_object_new_array();
1125 json_object_string_add(
1127 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1128 json_object_string_add(json
, "vtepIp",
1129 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1130 json_object_int_add(json
, "refCount",
1131 rb_host_count(&zrmac
->host_rb
));
1132 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1133 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1134 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1135 json_object_array_add(
1137 json_object_new_string(prefix2str(
1138 &hle
->p
, buf2
, sizeof(buf2
))));
1139 json_object_object_add(json
, "prefixList", json_hosts
);
1144 * Print a specific MAC entry.
1146 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1149 zebra_neigh_t
*n
= NULL
;
1150 struct listnode
*node
= NULL
;
1152 char buf2
[INET6_ADDRSTRLEN
];
1153 struct zebra_vrf
*zvrf
;
1154 struct timeval detect_start_time
= {0, 0};
1156 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1158 vty
= (struct vty
*)ctxt
;
1159 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1162 json_object
*json_mac
= json_object_new_object();
1164 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1165 struct zebra_ns
*zns
;
1166 struct interface
*ifp
;
1169 ifindex
= mac
->fwd_info
.local
.ifindex
;
1170 zns
= zebra_ns_lookup(NS_DEFAULT
);
1171 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1174 json_object_string_add(json_mac
, "type", "local");
1175 json_object_string_add(json_mac
, "intf", ifp
->name
);
1176 json_object_int_add(json_mac
, "ifindex", ifindex
);
1177 if (mac
->fwd_info
.local
.vid
)
1178 json_object_int_add(json_mac
, "vlan",
1179 mac
->fwd_info
.local
.vid
);
1180 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1181 json_object_string_add(json_mac
, "type", "remote");
1182 json_object_string_add(
1183 json_mac
, "remoteVtep",
1184 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1185 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1186 json_object_string_add(json_mac
, "type", "auto");
1188 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1189 json_object_boolean_true_add(json_mac
, "stickyMac");
1191 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1192 json_object_boolean_true_add(json_mac
,
1195 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1196 json_object_boolean_true_add(json_mac
,
1197 "remoteGatewayMac");
1199 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1200 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1202 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1203 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1204 json_object_boolean_true_add(json_mac
, "isDuplicate");
1206 json_object_boolean_false_add(json_mac
, "isDuplicate");
1208 /* print all the associated neigh */
1209 if (!listcount(mac
->neigh_list
))
1210 json_object_string_add(json_mac
, "neighbors", "none");
1212 json_object
*json_active_nbrs
= json_object_new_array();
1213 json_object
*json_inactive_nbrs
=
1214 json_object_new_array();
1215 json_object
*json_nbrs
= json_object_new_object();
1217 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1218 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1219 json_object_array_add(
1221 json_object_new_string(
1226 json_object_array_add(
1228 json_object_new_string(
1234 json_object_object_add(json_nbrs
, "active",
1236 json_object_object_add(json_nbrs
, "inactive",
1237 json_inactive_nbrs
);
1238 json_object_object_add(json_mac
, "neighbors",
1242 json_object_object_add(json
, buf1
, json_mac
);
1244 vty_out(vty
, "MAC: %s\n", buf1
);
1246 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1247 struct zebra_ns
*zns
;
1248 struct interface
*ifp
;
1251 ifindex
= mac
->fwd_info
.local
.ifindex
;
1252 zns
= zebra_ns_lookup(NS_DEFAULT
);
1253 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1256 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1257 if (mac
->fwd_info
.local
.vid
)
1258 vty_out(vty
, " VLAN: %u",
1259 mac
->fwd_info
.local
.vid
);
1260 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1261 vty_out(vty
, " Remote VTEP: %s",
1262 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1263 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1264 vty_out(vty
, " Auto Mac ");
1267 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1268 vty_out(vty
, " Sticky Mac ");
1270 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1271 vty_out(vty
, " Default-gateway Mac ");
1273 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1274 vty_out(vty
, " Remote-gateway Mac ");
1277 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1281 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1282 vty_out(vty
, " Duplicate, detected at %s",
1283 time_to_string(mac
->dad_dup_detect_time
));
1284 } else if (mac
->dad_count
) {
1285 monotime_since(&mac
->detect_start_time
,
1286 &detect_start_time
);
1287 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1288 char *buf
= time_to_string(
1289 mac
->detect_start_time
.tv_sec
);
1292 memset(tmp_buf
, 0, 30);
1293 strncpy(tmp_buf
, buf
, strlen(buf
) - 1);
1295 " Duplicate detection started at %s, detection count %u\n",
1296 tmp_buf
, mac
->dad_count
);
1300 /* print all the associated neigh */
1301 vty_out(vty
, " Neighbors:\n");
1302 if (!listcount(mac
->neigh_list
))
1303 vty_out(vty
, " No Neighbors\n");
1305 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1306 vty_out(vty
, " %s %s\n",
1307 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1308 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1319 * Print MAC hash entry - called for display of all MACs.
1321 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1324 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1327 struct mac_walk_ctx
*wctx
= ctxt
;
1330 json_mac_hdr
= wctx
->json
;
1331 mac
= (zebra_mac_t
*)bucket
->data
;
1333 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1336 json_mac
= json_object_new_object();
1338 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1339 struct zebra_ns
*zns
;
1341 struct interface
*ifp
;
1344 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1347 zns
= zebra_ns_lookup(NS_DEFAULT
);
1348 ifindex
= mac
->fwd_info
.local
.ifindex
;
1349 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1350 if (!ifp
) // unexpected
1352 vid
= mac
->fwd_info
.local
.vid
;
1353 if (json_mac_hdr
== NULL
)
1354 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1357 json_object_string_add(json_mac
, "type", "local");
1358 json_object_string_add(json_mac
, "intf", ifp
->name
);
1361 if (json_mac_hdr
== NULL
)
1362 vty_out(vty
, " %-5u", vid
);
1364 json_object_int_add(json_mac
, "vlan", vid
);
1366 if (json_mac_hdr
== NULL
) {
1369 json_object_int_add(json_mac
, "localSequence",
1371 json_object_int_add(json_mac
, "remoteSequence",
1373 json_object_int_add(json_mac
, "detectionCount",
1375 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1376 json_object_boolean_true_add(json_mac
,
1379 json_object_boolean_false_add(json_mac
,
1381 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1386 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1388 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1389 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1393 if (json_mac_hdr
== NULL
) {
1394 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1395 (wctx
->count
== 0)) {
1396 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1397 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1398 "Type", "Intf/Remote VTEP", "VLAN");
1400 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1401 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1403 json_object_string_add(json_mac
, "type", "remote");
1404 json_object_string_add(json_mac
, "remoteVtep",
1405 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1406 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1407 json_object_int_add(json_mac
, "localSequence",
1409 json_object_int_add(json_mac
, "remoteSequence",
1411 json_object_int_add(json_mac
, "detectionCount",
1413 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1414 json_object_boolean_true_add(json_mac
,
1417 json_object_boolean_false_add(json_mac
,
1426 /* Print Duplicate MAC */
1427 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1431 mac
= (zebra_mac_t
*)bucket
->data
;
1435 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1436 zvni_print_mac_hash(bucket
, ctxt
);
1440 * Print MAC hash entry in detail - called for display of all MACs.
1442 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1445 json_object
*json_mac_hdr
= NULL
;
1447 struct mac_walk_ctx
*wctx
= ctxt
;
1451 json_mac_hdr
= wctx
->json
;
1452 mac
= (zebra_mac_t
*)bucket
->data
;
1457 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1459 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1462 /* Print Duplicate MAC in detail */
1463 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1468 mac
= (zebra_mac_t
*)bucket
->data
;
1472 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1473 zvni_print_mac_hash_detail(bucket
, ctxt
);
1477 * Print MACs for all VNI.
1479 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1482 json_object
*json
= NULL
, *json_vni
= NULL
;
1483 json_object
*json_mac
= NULL
;
1486 struct mac_walk_ctx
*wctx
= ctxt
;
1487 char vni_str
[VNI_STR_LEN
];
1489 vty
= (struct vty
*)wctx
->vty
;
1490 json
= (struct json_object
*)wctx
->json
;
1492 zvni
= (zebra_vni_t
*)bucket
->data
;
1495 /*We are iterating over a new VNI, set the count to 0*/
1498 num_macs
= num_valid_macs(zvni
);
1502 if (wctx
->print_dup
)
1503 num_macs
= num_dup_detected_macs(zvni
);
1506 json_vni
= json_object_new_object();
1507 json_mac
= json_object_new_object();
1508 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1511 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1513 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1514 zvni
->vni
, num_macs
);
1515 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1516 "Intf/Remote VTEP", "VLAN");
1518 json_object_int_add(json_vni
, "numMacs", num_macs
);
1523 json_object_int_add(json_vni
, "numMacs", num_macs
);
1524 json_object_object_add(json
, vni_str
, json_vni
);
1529 /* assign per-vni to wctx->json object to fill macs
1530 * under the vni. Re-assign primary json object to fill
1531 * next vni information.
1533 wctx
->json
= json_mac
;
1534 if (wctx
->print_dup
)
1535 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1537 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1541 json_object_object_add(json_vni
, "macs", json_mac
);
1542 json_object_object_add(json
, vni_str
, json_vni
);
1547 * Print MACs in detail for all VNI.
1549 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1553 json_object
*json
= NULL
, *json_vni
= NULL
;
1554 json_object
*json_mac
= NULL
;
1557 struct mac_walk_ctx
*wctx
= ctxt
;
1558 char vni_str
[VNI_STR_LEN
];
1560 vty
= (struct vty
*)wctx
->vty
;
1561 json
= (struct json_object
*)wctx
->json
;
1563 zvni
= (zebra_vni_t
*)bucket
->data
;
1566 vty_out(vty
, "{}\n");
1571 /*We are iterating over a new VNI, set the count to 0*/
1574 num_macs
= num_valid_macs(zvni
);
1578 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1582 json_vni
= json_object_new_object();
1583 json_mac
= json_object_new_object();
1584 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1587 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1589 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1590 zvni
->vni
, num_macs
);
1592 json_object_int_add(json_vni
, "numMacs", num_macs
);
1594 /* assign per-vni to wctx->json object to fill macs
1595 * under the vni. Re-assign primary json object to fill
1596 * next vni information.
1598 wctx
->json
= json_mac
;
1599 if (wctx
->print_dup
)
1600 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1603 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1607 json_object_object_add(json_vni
, "macs", json_mac
);
1608 json_object_object_add(json
, vni_str
, json_vni
);
1612 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1614 struct nh_walk_ctx
*wctx
= NULL
;
1615 struct vty
*vty
= NULL
;
1616 struct json_object
*json_vni
= NULL
;
1617 struct json_object
*json_nh
= NULL
;
1618 zebra_neigh_t
*n
= NULL
;
1619 char buf1
[ETHER_ADDR_STRLEN
];
1620 char buf2
[INET6_ADDRSTRLEN
];
1622 wctx
= (struct nh_walk_ctx
*)ctx
;
1624 json_vni
= wctx
->json
;
1626 json_nh
= json_object_new_object();
1627 n
= (zebra_neigh_t
*)bucket
->data
;
1630 vty_out(vty
, "%-15s %-17s\n",
1631 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1632 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1634 json_object_string_add(json_nh
, "nexthopIp",
1635 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1636 json_object_string_add(
1637 json_nh
, "routerMac",
1638 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1639 json_object_object_add(json_vni
,
1640 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1645 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1648 struct vty
*vty
= NULL
;
1649 json_object
*json
= NULL
;
1650 json_object
*json_vni
= NULL
;
1651 zebra_l3vni_t
*zl3vni
= NULL
;
1652 uint32_t num_nh
= 0;
1653 struct nh_walk_ctx wctx
;
1654 char vni_str
[VNI_STR_LEN
];
1656 vty
= (struct vty
*)args
[0];
1657 json
= (struct json_object
*)args
[1];
1659 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1661 num_nh
= hashcount(zl3vni
->nh_table
);
1666 json_vni
= json_object_new_object();
1667 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1671 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1672 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1674 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1676 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1678 wctx
.json
= json_vni
;
1679 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1681 json_object_object_add(json
, vni_str
, json_vni
);
1684 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1687 struct vty
*vty
= NULL
;
1688 json_object
*json
= NULL
;
1689 json_object
*json_vni
= NULL
;
1690 zebra_l3vni_t
*zl3vni
= NULL
;
1692 struct rmac_walk_ctx wctx
;
1693 char vni_str
[VNI_STR_LEN
];
1695 vty
= (struct vty
*)args
[0];
1696 json
= (struct json_object
*)args
[1];
1698 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1700 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1705 json_vni
= json_object_new_object();
1706 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1710 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1711 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1713 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1715 /* assign per-vni to wctx->json object to fill macs
1716 * under the vni. Re-assign primary json object to fill
1717 * next vni information.
1719 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1721 wctx
.json
= json_vni
;
1722 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1724 json_object_object_add(json
, vni_str
, json_vni
);
1727 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1729 zebra_mac_t
*zrmac
= NULL
;
1730 struct rmac_walk_ctx
*wctx
= NULL
;
1731 struct vty
*vty
= NULL
;
1732 struct json_object
*json
= NULL
;
1733 struct json_object
*json_rmac
= NULL
;
1734 char buf
[ETHER_ADDR_STRLEN
];
1736 wctx
= (struct rmac_walk_ctx
*)ctx
;
1740 json_rmac
= json_object_new_object();
1741 zrmac
= (zebra_mac_t
*)bucket
->data
;
1744 vty_out(vty
, "%-17s %-21s\n",
1745 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1746 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1748 json_object_string_add(
1749 json_rmac
, "routerMac",
1750 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1751 json_object_string_add(json_rmac
, "vtepIp",
1752 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1753 json_object_object_add(
1754 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1759 /* print a specific L3 VNI entry */
1760 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1762 char buf
[ETHER_ADDR_STRLEN
];
1763 struct vty
*vty
= NULL
;
1764 json_object
*json
= NULL
;
1765 zebra_vni_t
*zvni
= NULL
;
1766 json_object
*json_vni_list
= NULL
;
1767 struct listnode
*node
= NULL
, *nnode
= NULL
;
1773 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1774 vty_out(vty
, " Type: %s\n", "L3");
1775 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1776 vty_out(vty
, " Local Vtep Ip: %s\n",
1777 inet_ntoa(zl3vni
->local_vtep_ip
));
1778 vty_out(vty
, " Vxlan-Intf: %s\n",
1779 zl3vni_vxlan_if_name(zl3vni
));
1780 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1781 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1782 vty_out(vty
, " VNI Filter: %s\n",
1783 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1784 ? "prefix-routes-only"
1786 vty_out(vty
, " Router MAC: %s\n",
1787 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1788 vty_out(vty
, " L2 VNIs: ");
1789 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1790 vty_out(vty
, "%u ", zvni
->vni
);
1793 json_vni_list
= json_object_new_array();
1794 json_object_int_add(json
, "vni", zl3vni
->vni
);
1795 json_object_string_add(json
, "type", "L3");
1796 json_object_string_add(json
, "localVtepIp",
1797 inet_ntoa(zl3vni
->local_vtep_ip
));
1798 json_object_string_add(json
, "vxlanIntf",
1799 zl3vni_vxlan_if_name(zl3vni
));
1800 json_object_string_add(json
, "sviIntf",
1801 zl3vni_svi_if_name(zl3vni
));
1802 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1803 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1804 json_object_string_add(
1806 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1807 json_object_string_add(
1809 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1810 ? "prefix-routes-only"
1812 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1813 json_object_array_add(json_vni_list
,
1814 json_object_new_int(zvni
->vni
));
1816 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1821 * Print a specific VNI entry.
1823 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1826 zebra_vtep_t
*zvtep
;
1829 json_object
*json
= NULL
;
1830 json_object
*json_vtep_list
= NULL
;
1831 json_object
*json_ip_str
= NULL
;
1837 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1838 vty_out(vty
, " Type: %s\n", "L2");
1839 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1841 json_object_int_add(json
, "vni", zvni
->vni
);
1842 json_object_string_add(json
, "type", "L2");
1843 json_object_string_add(json
, "vrf",
1844 vrf_id_to_name(zvni
->vrf_id
));
1847 if (!zvni
->vxlan_if
) { // unexpected
1849 vty_out(vty
, " VxLAN interface: unknown\n");
1852 num_macs
= num_valid_macs(zvni
);
1853 num_neigh
= hashcount(zvni
->neigh_table
);
1855 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1856 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1857 vty_out(vty
, " Local VTEP IP: %s\n",
1858 inet_ntoa(zvni
->local_vtep_ip
));
1860 json_object_string_add(json
, "vxlanInterface",
1861 zvni
->vxlan_if
->name
);
1862 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1863 json_object_string_add(json
, "vtepIp",
1864 inet_ntoa(zvni
->local_vtep_ip
));
1865 json_object_string_add(json
, "advertiseGatewayMacip",
1866 zvni
->advertise_gw_macip
? "Yes" : "No");
1867 json_object_int_add(json
, "numMacs", num_macs
);
1868 json_object_int_add(json
, "numArpNd", num_neigh
);
1872 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1875 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1877 json_vtep_list
= json_object_new_array();
1878 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1880 vty_out(vty
, " %s\n",
1881 inet_ntoa(zvtep
->vtep_ip
));
1883 json_ip_str
= json_object_new_string(
1884 inet_ntoa(zvtep
->vtep_ip
));
1885 json_object_array_add(json_vtep_list
,
1890 json_object_object_add(json
, "numRemoteVteps",
1895 " Number of MACs (local and remote) known for this VNI: %u\n",
1898 " Number of ARPs (IPv4 and IPv6, local and remote) "
1899 "known for this VNI: %u\n",
1901 vty_out(vty
, " Advertise-gw-macip: %s\n",
1902 zvni
->advertise_gw_macip
? "Yes" : "No");
1906 /* print a L3 VNI hash entry */
1907 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1909 struct vty
*vty
= NULL
;
1910 json_object
*json
= NULL
;
1911 json_object
*json_vni
= NULL
;
1912 zebra_l3vni_t
*zl3vni
= NULL
;
1914 vty
= (struct vty
*)ctx
[0];
1915 json
= (json_object
*)ctx
[1];
1917 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1920 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1921 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1922 hashcount(zl3vni
->rmac_table
),
1923 hashcount(zl3vni
->nh_table
), "n/a",
1924 zl3vni_vrf_name(zl3vni
));
1926 char vni_str
[VNI_STR_LEN
];
1928 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1929 json_vni
= json_object_new_object();
1930 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1931 json_object_string_add(json_vni
, "vxlanIf",
1932 zl3vni_vxlan_if_name(zl3vni
));
1933 json_object_int_add(json_vni
, "numMacs",
1934 hashcount(zl3vni
->rmac_table
));
1935 json_object_int_add(json_vni
, "numArpNd",
1936 hashcount(zl3vni
->nh_table
));
1937 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1938 json_object_string_add(json_vni
, "type", "L3");
1939 json_object_string_add(json_vni
, "tenantVrf",
1940 zl3vni_vrf_name(zl3vni
));
1941 json_object_object_add(json
, vni_str
, json_vni
);
1945 /* Private Structure to pass callback data for hash iterator */
1946 struct zvni_evpn_show
{
1949 struct zebra_vrf
*zvrf
;
1952 /* print a L3 VNI hash entry in detail*/
1953 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1955 struct vty
*vty
= NULL
;
1956 zebra_l3vni_t
*zl3vni
= NULL
;
1957 json_object
*json
= NULL
;
1958 bool use_json
= false;
1959 struct zvni_evpn_show
*zes
= data
;
1967 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1969 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1975 * Print a VNI hash entry - called for display of all VNIs.
1977 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
1981 zebra_vtep_t
*zvtep
;
1982 uint32_t num_vteps
= 0;
1983 uint32_t num_macs
= 0;
1984 uint32_t num_neigh
= 0;
1985 json_object
*json
= NULL
;
1986 json_object
*json_vni
= NULL
;
1987 json_object
*json_ip_str
= NULL
;
1988 json_object
*json_vtep_list
= NULL
;
1993 zvni
= (zebra_vni_t
*)bucket
->data
;
1995 zvtep
= zvni
->vteps
;
1998 zvtep
= zvtep
->next
;
2001 num_macs
= num_valid_macs(zvni
);
2002 num_neigh
= hashcount(zvni
->neigh_table
);
2004 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2006 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2007 num_macs
, num_neigh
, num_vteps
,
2008 vrf_id_to_name(zvni
->vrf_id
));
2010 char vni_str
[VNI_STR_LEN
];
2011 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2012 json_vni
= json_object_new_object();
2013 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2014 json_object_string_add(json_vni
, "type", "L2");
2015 json_object_string_add(json_vni
, "vxlanIf",
2016 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2018 json_object_int_add(json_vni
, "numMacs", num_macs
);
2019 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2020 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2021 json_object_string_add(json_vni
, "tenantVrf",
2022 vrf_id_to_name(zvni
->vrf_id
));
2024 json_vtep_list
= json_object_new_array();
2025 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2026 json_ip_str
= json_object_new_string(
2027 inet_ntoa(zvtep
->vtep_ip
));
2028 json_object_array_add(json_vtep_list
,
2031 json_object_object_add(json_vni
, "remoteVteps",
2034 json_object_object_add(json
, vni_str
, json_vni
);
2039 * Print a VNI hash entry in detail - called for display of all VNIs.
2041 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2045 json_object
*json
= NULL
;
2046 bool use_json
= false;
2047 struct zvni_evpn_show
*zes
= data
;
2055 zvni
= (zebra_vni_t
*)bucket
->data
;
2057 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2062 * Inform BGP about local MACIP.
2064 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2065 struct ipaddr
*ip
, uint8_t flags
,
2066 uint32_t seq
, int state
, uint16_t cmd
)
2068 char buf
[ETHER_ADDR_STRLEN
];
2069 char buf2
[INET6_ADDRSTRLEN
];
2071 struct zserv
*client
= NULL
;
2072 struct stream
*s
= NULL
;
2074 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2075 /* BGP may not be running. */
2079 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2081 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
2082 stream_putl(s
, vni
);
2083 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2086 if (IS_IPADDR_V4(ip
))
2087 ipa_len
= IPV4_MAX_BYTELEN
;
2088 else if (IS_IPADDR_V6(ip
))
2089 ipa_len
= IPV6_MAX_BYTELEN
;
2091 stream_putl(s
, ipa_len
); /* IP address length */
2093 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2095 stream_putl(s
, 0); /* Just MAC. */
2097 if (cmd
== ZEBRA_MACIP_ADD
) {
2098 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2099 stream_putl(s
, seq
); /* sequence number */
2101 stream_putl(s
, state
); /* state - active/inactive */
2105 /* Write packet size. */
2106 stream_putw_at(s
, 0, stream_get_endp(s
));
2108 if (IS_ZEBRA_DEBUG_VXLAN
)
2110 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2111 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2112 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2113 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2114 zebra_route_string(client
->proto
));
2116 if (cmd
== ZEBRA_MACIP_ADD
)
2117 client
->macipadd_cnt
++;
2119 client
->macipdel_cnt
++;
2121 return zserv_send_message(client
, s
);
2125 * Make hash key for neighbors.
2127 static unsigned int neigh_hash_keymake(void *p
)
2129 zebra_neigh_t
*n
= p
;
2130 struct ipaddr
*ip
= &n
->ip
;
2132 if (IS_IPADDR_V4(ip
))
2133 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2135 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2136 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2140 * Compare two neighbor hash structures.
2142 static bool neigh_cmp(const void *p1
, const void *p2
)
2144 const zebra_neigh_t
*n1
= p1
;
2145 const zebra_neigh_t
*n2
= p2
;
2147 if (n1
== NULL
&& n2
== NULL
)
2150 if (n1
== NULL
|| n2
== NULL
)
2153 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2156 static int neigh_list_cmp(void *p1
, void *p2
)
2158 const zebra_neigh_t
*n1
= p1
;
2159 const zebra_neigh_t
*n2
= p2
;
2161 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2165 * Callback to allocate neighbor hash entry.
2167 static void *zvni_neigh_alloc(void *p
)
2169 const zebra_neigh_t
*tmp_n
= p
;
2172 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2179 * Add neighbor entry.
2181 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2182 struct ethaddr
*mac
)
2184 zebra_neigh_t tmp_n
;
2185 zebra_neigh_t
*n
= NULL
;
2186 zebra_mac_t
*zmac
= NULL
;
2188 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2189 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2190 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2193 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2194 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2196 /* Associate the neigh to mac */
2197 zmac
= zvni_mac_lookup(zvni
, mac
);
2199 listnode_add_sort(zmac
->neigh_list
, n
);
2205 * Delete neighbor entry.
2207 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2209 zebra_neigh_t
*tmp_n
;
2210 zebra_mac_t
*zmac
= NULL
;
2212 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2214 listnode_delete(zmac
->neigh_list
, n
);
2216 /* Free the VNI hash entry and allocated memory. */
2217 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2218 XFREE(MTYPE_NEIGH
, tmp_n
);
2224 * Free neighbor hash entry (callback)
2226 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2228 struct neigh_walk_ctx
*wctx
= arg
;
2229 zebra_neigh_t
*n
= bucket
->data
;
2231 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2232 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2233 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2234 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2235 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2236 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2237 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2238 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2239 &n
->emac
, 0, n
->state
);
2241 if (wctx
->uninstall
)
2242 zvni_neigh_uninstall(wctx
->zvni
, n
);
2244 zvni_neigh_del(wctx
->zvni
, n
);
2251 * Delete all neighbor entries from specific VTEP for a particular VNI.
2253 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2254 struct in_addr
*r_vtep_ip
)
2256 struct neigh_walk_ctx wctx
;
2258 if (!zvni
->neigh_table
)
2261 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2263 wctx
.uninstall
= uninstall
;
2264 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2265 wctx
.r_vtep_ip
= *r_vtep_ip
;
2267 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2271 * Delete all neighbor entries for this VNI.
2273 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2276 struct neigh_walk_ctx wctx
;
2278 if (!zvni
->neigh_table
)
2281 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2283 wctx
.uninstall
= uninstall
;
2284 wctx
.upd_client
= upd_client
;
2287 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2291 * Look up neighbor hash entry.
2293 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2298 memset(&tmp
, 0, sizeof(tmp
));
2299 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2300 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2306 * Process all neighbors associated with a MAC upon the MAC being learnt
2307 * locally or undergoing any other change (such as sequence number).
2309 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2313 zebra_neigh_t
*n
= NULL
;
2314 struct listnode
*node
= NULL
;
2315 struct zebra_vrf
*zvrf
= NULL
;
2316 char buf
[ETHER_ADDR_STRLEN
];
2318 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2320 if (IS_ZEBRA_DEBUG_VXLAN
)
2321 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2322 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2323 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2325 /* Walk all neighbors and mark any inactive local neighbors as
2326 * active and/or update sequence number upon a move, and inform BGP.
2327 * The action for remote neighbors is TBD.
2328 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2329 * accidentally end up deleting a just-learnt local neighbor.
2331 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2332 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2333 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2334 ZEBRA_NEIGH_SET_ACTIVE(n
);
2335 n
->loc_seq
= zmac
->loc_seq
;
2336 if (!(zvrf
->dup_addr_detect
&&
2337 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2338 ZEBRA_NEIGH_DUPLICATE
)))
2339 zvni_neigh_send_add_to_client(
2340 zvni
->vni
, &n
->ip
, &n
->emac
,
2341 n
->flags
, n
->loc_seq
);
2348 * Process all neighbors associated with a local MAC upon the MAC being
2351 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2354 zebra_neigh_t
*n
= NULL
;
2355 struct listnode
*node
= NULL
;
2356 char buf
[ETHER_ADDR_STRLEN
];
2358 if (IS_ZEBRA_DEBUG_VXLAN
)
2359 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2360 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2363 /* Walk all local neighbors and mark as inactive and inform
2365 * TBD: There is currently no handling for remote neighbors. We
2366 * don't expect them to exist, if they do, do we install the MAC
2367 * as a remote MAC and the neighbor as remote?
2369 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2370 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2371 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2372 ZEBRA_NEIGH_SET_INACTIVE(n
);
2374 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2375 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2382 * Process all neighbors associated with a MAC upon the MAC being remotely
2385 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2388 zebra_neigh_t
*n
= NULL
;
2389 struct listnode
*node
= NULL
;
2390 char buf
[ETHER_ADDR_STRLEN
];
2392 if (IS_ZEBRA_DEBUG_VXLAN
)
2393 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2394 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2397 /* Walk all local neighbors and mark as inactive and inform
2400 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2401 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2402 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2403 ZEBRA_NEIGH_SET_INACTIVE(n
);
2405 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2406 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2413 * Process all neighbors associated with a remote MAC upon the MAC being
2416 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2419 /* NOTE: Currently a NO-OP. */
2422 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2424 zebra_neigh_t
*nbr
= NULL
;
2425 struct listnode
*node
= NULL
;
2427 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2428 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2429 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2430 zvni_neigh_probe(zvni
, nbr
);
2435 * Inform BGP about local neighbor addition.
2437 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2438 struct ethaddr
*macaddr
,
2439 uint8_t neigh_flags
,
2444 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2445 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2446 /* Set router flag (R-bit) based on local neigh entry add */
2447 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2448 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2450 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2451 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2455 * Inform BGP about local neighbor deletion.
2457 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2458 struct ethaddr
*macaddr
, uint8_t flags
,
2461 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2462 0, state
, ZEBRA_MACIP_DEL
);
2466 * Install remote neighbor into the kernel.
2468 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2470 struct zebra_if
*zif
;
2471 struct zebra_l2info_vxlan
*vxl
;
2472 struct interface
*vlan_if
;
2478 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2481 zif
= zvni
->vxlan_if
->info
;
2484 vxl
= &zif
->l2info
.vxl
;
2486 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2490 flags
= NTF_EXT_LEARNED
;
2491 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2492 flags
|= NTF_ROUTER
;
2493 ZEBRA_NEIGH_SET_ACTIVE(n
);
2494 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2500 * Uninstall remote neighbor from the kernel.
2502 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2504 struct zebra_if
*zif
;
2505 struct zebra_l2info_vxlan
*vxl
;
2506 struct interface
*vlan_if
;
2508 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2511 if (!zvni
->vxlan_if
) {
2512 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2517 zif
= zvni
->vxlan_if
->info
;
2520 vxl
= &zif
->l2info
.vxl
;
2521 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2525 ZEBRA_NEIGH_SET_INACTIVE(n
);
2527 return kernel_del_neigh(vlan_if
, &n
->ip
);
2531 * Probe neighbor from the kernel.
2533 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2535 struct zebra_if
*zif
;
2536 struct zebra_l2info_vxlan
*vxl
;
2537 struct interface
*vlan_if
;
2539 zif
= zvni
->vxlan_if
->info
;
2542 vxl
= &zif
->l2info
.vxl
;
2544 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2549 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2557 * Install neighbor hash entry - called upon access VLAN change.
2559 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2562 struct neigh_walk_ctx
*wctx
= ctxt
;
2564 n
= (zebra_neigh_t
*)bucket
->data
;
2566 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2567 zvni_neigh_install(wctx
->zvni
, n
);
2570 /* Get the VRR interface for SVI if any */
2571 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2573 struct zebra_vrf
*zvrf
= NULL
;
2574 struct interface
*tmp_if
= NULL
;
2575 struct zebra_if
*zif
= NULL
;
2577 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2580 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2585 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2588 if (zif
->link
== ifp
)
2595 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2597 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2598 struct connected
*c
= NULL
;
2599 struct ethaddr macaddr
;
2601 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2603 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2606 memset(&ip
, 0, sizeof(struct ipaddr
));
2607 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2610 if (c
->address
->family
== AF_INET
) {
2611 ip
.ipa_type
= IPADDR_V4
;
2612 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2613 sizeof(struct in_addr
));
2614 } else if (c
->address
->family
== AF_INET6
) {
2615 ip
.ipa_type
= IPADDR_V6
;
2616 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2617 sizeof(struct in6_addr
));
2622 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2628 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2630 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2631 struct connected
*c
= NULL
;
2632 struct ethaddr macaddr
;
2634 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2636 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2639 memset(&ip
, 0, sizeof(struct ipaddr
));
2640 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2643 if (c
->address
->family
== AF_INET
) {
2644 ip
.ipa_type
= IPADDR_V4
;
2645 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2646 sizeof(struct in_addr
));
2647 } else if (c
->address
->family
== AF_INET6
) {
2648 ip
.ipa_type
= IPADDR_V6
;
2649 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2650 sizeof(struct in6_addr
));
2655 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2661 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2664 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2665 struct connected
*c
= NULL
;
2666 struct ethaddr macaddr
;
2668 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2670 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2673 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2675 /* skip link local address */
2676 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2681 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2682 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2684 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2685 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2691 * zvni_gw_macip_add_to_client
2693 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2694 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2696 char buf
[ETHER_ADDR_STRLEN
];
2697 char buf2
[INET6_ADDRSTRLEN
];
2698 zebra_neigh_t
*n
= NULL
;
2699 zebra_mac_t
*mac
= NULL
;
2700 struct zebra_if
*zif
= NULL
;
2701 struct zebra_l2info_vxlan
*vxl
= NULL
;
2703 zif
= zvni
->vxlan_if
->info
;
2707 vxl
= &zif
->l2info
.vxl
;
2709 mac
= zvni_mac_lookup(zvni
, macaddr
);
2711 mac
= zvni_mac_add(zvni
, macaddr
);
2713 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2714 "Failed to add MAC %s intf %s(%u) VID %u",
2715 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2716 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2721 /* Set "local" forwarding info. */
2722 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2723 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2724 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2725 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2726 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2727 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2729 n
= zvni_neigh_lookup(zvni
, ip
);
2731 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2734 EC_ZEBRA_MAC_ADD_FAILED
,
2735 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2736 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2737 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2738 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2743 /* Set "local" forwarding info. */
2744 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2745 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2746 ZEBRA_NEIGH_SET_ACTIVE(n
);
2747 /* Set Router flag (R-bit) */
2748 if (ip
->ipa_type
== IPADDR_V6
)
2749 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2750 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2751 n
->ifindex
= ifp
->ifindex
;
2753 /* Only advertise in BGP if the knob is enabled */
2754 if (!advertise_gw_macip_enabled(zvni
))
2757 if (IS_ZEBRA_DEBUG_VXLAN
)
2759 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2760 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2761 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2762 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2764 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2765 n
->flags
, n
->loc_seq
);
2771 * zvni_gw_macip_del_from_client
2773 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2776 char buf1
[ETHER_ADDR_STRLEN
];
2777 char buf2
[INET6_ADDRSTRLEN
];
2778 zebra_neigh_t
*n
= NULL
;
2779 zebra_mac_t
*mac
= NULL
;
2781 /* If the neigh entry is not present nothing to do*/
2782 n
= zvni_neigh_lookup(zvni
, ip
);
2786 /* mac entry should be present */
2787 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2789 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2790 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2791 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2795 /* If the entry is not local nothing to do*/
2796 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2799 /* only need to delete the entry from bgp if we sent it before */
2800 if (IS_ZEBRA_DEBUG_VXLAN
)
2802 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2803 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2804 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2805 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2807 /* Remove neighbor from BGP. */
2808 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2809 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2811 /* Delete this neighbor entry. */
2812 zvni_neigh_del(zvni
, n
);
2814 /* see if the mac needs to be deleted as well*/
2816 zvni_deref_ip2mac(zvni
, mac
);
2821 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2824 zebra_vni_t
*zvni
= NULL
;
2825 struct zebra_if
*zif
= NULL
;
2826 struct zebra_l2info_vxlan zl2_info
;
2827 struct interface
*vlan_if
= NULL
;
2828 struct interface
*vrr_if
= NULL
;
2829 struct interface
*ifp
;
2831 /* Add primary SVI MAC*/
2832 zvni
= (zebra_vni_t
*)bucket
->data
;
2834 ifp
= zvni
->vxlan_if
;
2839 /* If down or not mapped to a bridge, we're done. */
2840 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2843 zl2_info
= zif
->l2info
.vxl
;
2846 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2850 /* Del primary MAC-IP */
2851 zvni_del_macip_for_intf(vlan_if
, zvni
);
2853 /* Del VRR MAC-IP - if any*/
2854 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2856 zvni_del_macip_for_intf(vrr_if
, zvni
);
2861 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2864 zebra_vni_t
*zvni
= NULL
;
2865 struct zebra_if
*zif
= NULL
;
2866 struct zebra_l2info_vxlan zl2_info
;
2867 struct interface
*vlan_if
= NULL
;
2868 struct interface
*vrr_if
= NULL
;
2869 struct interface
*ifp
= NULL
;
2871 zvni
= (zebra_vni_t
*)bucket
->data
;
2873 ifp
= zvni
->vxlan_if
;
2878 /* If down or not mapped to a bridge, we're done. */
2879 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2881 zl2_info
= zif
->l2info
.vxl
;
2884 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2888 /* Add primary SVI MAC-IP */
2889 zvni_add_macip_for_intf(vlan_if
, zvni
);
2891 if (advertise_gw_macip_enabled(zvni
)) {
2892 /* Add VRR MAC-IP - if any*/
2893 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2895 zvni_add_macip_for_intf(vrr_if
, zvni
);
2901 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2904 zebra_vni_t
*zvni
= NULL
;
2905 struct zebra_if
*zif
= NULL
;
2906 struct zebra_l2info_vxlan zl2_info
;
2907 struct interface
*vlan_if
= NULL
;
2908 struct interface
*ifp
;
2910 /* Add primary SVI MAC*/
2911 zvni
= (zebra_vni_t
*)bucket
->data
;
2915 ifp
= zvni
->vxlan_if
;
2920 /* If down or not mapped to a bridge, we're done. */
2921 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2924 zl2_info
= zif
->l2info
.vxl
;
2926 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2927 zif
->brslave_info
.br_if
);
2931 /* Del primary MAC-IP */
2932 zvni_del_macip_for_intf(vlan_if
, zvni
);
2937 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2938 struct interface
*ifp
,
2940 struct ethaddr
*macaddr
,
2943 char buf
[ETHER_ADDR_STRLEN
];
2944 char buf2
[INET6_ADDRSTRLEN
];
2945 struct zebra_vrf
*zvrf
;
2946 zebra_neigh_t
*n
= NULL
;
2947 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2948 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2949 bool upd_mac_seq
= false;
2950 bool neigh_mac_change
= false;
2951 bool neigh_on_hold
= false;
2952 bool neigh_was_remote
= false;
2953 bool do_dad
= false;
2954 struct in_addr vtep_ip
= {.s_addr
= 0};
2956 /* Check if the MAC exists. */
2957 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2959 /* create a dummy MAC if the MAC is not already present */
2960 if (IS_ZEBRA_DEBUG_VXLAN
)
2962 "AUTO MAC %s created for neigh %s on VNI %u",
2963 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2964 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2966 zmac
= zvni_mac_add(zvni
, macaddr
);
2968 zlog_debug("Failed to add MAC %s VNI %u",
2969 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2974 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2975 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2976 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2978 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2980 * We don't change the MAC to local upon a neighbor
2981 * learn event, we wait for the explicit local MAC
2982 * learn. However, we have to compute its sequence
2983 * number in preparation for when it actually turns
2990 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2994 /* Check if the neighbor exists. */
2995 n
= zvni_neigh_lookup(zvni
, ip
);
2997 /* New neighbor - create */
2998 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3001 EC_ZEBRA_MAC_ADD_FAILED
,
3002 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3003 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3004 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3005 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3008 /* Set "local" forwarding info. */
3009 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3010 n
->ifindex
= ifp
->ifindex
;
3012 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3016 /* Note any changes and see if of interest to BGP. */
3017 mac_different
= (memcmp(n
->emac
.octet
,
3018 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3019 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3020 ZEBRA_NEIGH_ROUTER_FLAG
);
3021 if (!mac_different
&& is_router
== cur_is_router
) {
3022 n
->ifindex
= ifp
->ifindex
;
3026 if (!mac_different
) {
3027 bool is_neigh_freezed
= false;
3029 /* Only the router flag has changed. */
3032 ZEBRA_NEIGH_ROUTER_FLAG
);
3034 UNSET_FLAG(n
->flags
,
3035 ZEBRA_NEIGH_ROUTER_FLAG
);
3037 /* Neigh is in freeze state and freeze action
3038 * is enabled, do not send update to client.
3040 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3042 CHECK_FLAG(n
->flags
,
3043 ZEBRA_NEIGH_DUPLICATE
));
3045 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3047 return zvni_neigh_send_add_to_client(
3048 zvni
->vni
, ip
, macaddr
,
3049 n
->flags
, n
->loc_seq
);
3053 /* The MAC has changed, need to issue a delete
3054 * first as this means a different MACIP route.
3055 * Also, need to do some unlinking/relinking.
3056 * We also need to update the MAC's sequence number
3057 * in different situations.
3059 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3060 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3061 &n
->emac
, 0, n
->state
);
3062 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3064 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3066 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3067 neigh_mac_change
= upd_mac_seq
= true;
3068 listnode_delete(old_zmac
->neigh_list
, n
);
3069 zvni_deref_ip2mac(zvni
, old_zmac
);
3072 /* Update the forwarding info. */
3073 n
->ifindex
= ifp
->ifindex
;
3074 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3076 /* Link to new MAC */
3077 listnode_add_sort(zmac
->neigh_list
, n
);
3078 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3080 * Neighbor has moved from remote to local. Its
3081 * MAC could have also changed as part of the move.
3083 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3085 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3087 old_mac_seq
= CHECK_FLAG(
3092 neigh_mac_change
= upd_mac_seq
= true;
3093 listnode_delete(old_zmac
->neigh_list
,
3095 zvni_deref_ip2mac(zvni
, old_zmac
);
3098 /* Link to new MAC */
3099 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3100 listnode_add_sort(zmac
->neigh_list
, n
);
3102 /* Based on Mobility event Scenario-B from the
3103 * draft, neigh's previous state was remote treat this
3106 neigh_was_remote
= true;
3107 vtep_ip
= n
->r_vtep_ip
;
3108 /* Mark appropriately */
3109 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3110 n
->r_vtep_ip
.s_addr
= 0;
3111 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3112 n
->ifindex
= ifp
->ifindex
;
3116 /* If MAC was previously remote, or the neighbor had a different
3117 * MAC earlier, recompute the sequence number.
3120 uint32_t seq1
, seq2
;
3122 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3123 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3124 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3125 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3126 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3129 /* Mark Router flag (R-bit) */
3131 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3133 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3135 /* Check old and/or new MAC detected as duplicate mark
3136 * the neigh as duplicate
3138 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3139 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3140 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3142 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3143 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3146 /* For IP Duplicate Address Detection (DAD) is trigger,
3147 * when the event is extended mobility based on scenario-B
3148 * from the draft, IP/Neigh's MAC binding changed and
3149 * neigh's previous state was remote.
3151 if (neigh_mac_change
&& neigh_was_remote
)
3154 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3155 &neigh_on_hold
, true);
3157 /* Before we program this in BGP, we need to check if MAC is locally
3158 * learnt. If not, force neighbor to be inactive and reset its seq.
3160 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3161 ZEBRA_NEIGH_SET_INACTIVE(n
);
3163 zmac
->loc_seq
= mac_new_seq
;
3167 /* If the MAC's sequence number has changed, inform the MAC and all
3168 * neighbors associated with the MAC to BGP, else just inform this
3171 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3172 if (IS_ZEBRA_DEBUG_VXLAN
)
3173 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3174 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3175 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3176 zmac
->loc_seq
= mac_new_seq
;
3177 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3178 zmac
->flags
, zmac
->loc_seq
))
3180 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3184 ZEBRA_NEIGH_SET_ACTIVE(n
);
3185 n
->loc_seq
= zmac
->loc_seq
;
3188 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3189 n
->flags
, n
->loc_seq
);
3193 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3194 struct interface
*ifp
,
3196 struct ethaddr
*macaddr
,
3199 char buf
[ETHER_ADDR_STRLEN
];
3200 char buf2
[INET6_ADDRSTRLEN
];
3201 zebra_neigh_t
*n
= NULL
;
3202 zebra_mac_t
*zmac
= NULL
;
3204 /* If the neighbor is unknown, there is no further action. */
3205 n
= zvni_neigh_lookup(zvni
, ip
);
3209 /* If a remote entry, see if it needs to be refreshed */
3210 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3212 if (state
& NUD_STALE
)
3213 zvni_neigh_install(zvni
, n
);
3216 /* We got a "remote" neighbor notification for an entry
3217 * we think is local. This can happen in a multihoming
3218 * scenario - but only if the MAC is already "remote".
3219 * Just mark our entry as "remote".
3221 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3222 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3224 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3225 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3226 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3231 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3232 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3233 ZEBRA_NEIGH_SET_ACTIVE(n
);
3234 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3241 * Make hash key for MAC.
3243 static unsigned int mac_hash_keymake(void *p
)
3245 zebra_mac_t
*pmac
= p
;
3246 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3248 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3252 * Compare two MAC addresses.
3254 static bool mac_cmp(const void *p1
, const void *p2
)
3256 const zebra_mac_t
*pmac1
= p1
;
3257 const zebra_mac_t
*pmac2
= p2
;
3259 if (pmac1
== NULL
&& pmac2
== NULL
)
3262 if (pmac1
== NULL
|| pmac2
== NULL
)
3265 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3270 * Callback to allocate MAC hash entry.
3272 static void *zvni_mac_alloc(void *p
)
3274 const zebra_mac_t
*tmp_mac
= p
;
3277 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3280 return ((void *)mac
);
3286 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3288 zebra_mac_t tmp_mac
;
3289 zebra_mac_t
*mac
= NULL
;
3291 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3292 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3293 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3296 mac
->neigh_list
= list_new();
3297 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3305 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3307 zebra_mac_t
*tmp_mac
;
3309 list_delete(&mac
->neigh_list
);
3311 /* Free the VNI hash entry and allocated memory. */
3312 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3313 XFREE(MTYPE_MAC
, tmp_mac
);
3319 * Free MAC hash entry (callback)
3321 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3323 struct mac_walk_ctx
*wctx
= arg
;
3324 zebra_mac_t
*mac
= bucket
->data
;
3326 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3327 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3328 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3329 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3330 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3331 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3332 &wctx
->r_vtep_ip
))) {
3333 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3334 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3338 if (wctx
->uninstall
)
3339 zvni_mac_uninstall(wctx
->zvni
, mac
);
3341 zvni_mac_del(wctx
->zvni
, mac
);
3348 * Delete all MAC entries from specific VTEP for a particular VNI.
3350 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3351 struct in_addr
*r_vtep_ip
)
3353 struct mac_walk_ctx wctx
;
3355 if (!zvni
->mac_table
)
3358 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3360 wctx
.uninstall
= uninstall
;
3361 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3362 wctx
.r_vtep_ip
= *r_vtep_ip
;
3364 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3368 * Delete all MAC entries for this VNI.
3370 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3373 struct mac_walk_ctx wctx
;
3375 if (!zvni
->mac_table
)
3378 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3380 wctx
.uninstall
= uninstall
;
3381 wctx
.upd_client
= upd_client
;
3384 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3388 * Look up MAC hash entry.
3390 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3395 memset(&tmp
, 0, sizeof(tmp
));
3396 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3397 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3403 * Inform BGP about local MAC addition.
3405 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3406 uint8_t mac_flags
, uint32_t seq
)
3410 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3411 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3412 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3413 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3415 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3416 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3420 * Inform BGP about local MAC deletion.
3422 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3424 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3425 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3429 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3430 * notifications, to see if they are of interest.
3432 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3433 struct interface
*br_if
, vlanid_t vid
)
3435 struct zebra_ns
*zns
;
3436 struct route_node
*rn
;
3437 struct interface
*tmp_if
= NULL
;
3438 struct zebra_if
*zif
;
3439 struct zebra_l2info_bridge
*br
;
3440 struct zebra_l2info_vxlan
*vxl
= NULL
;
3441 uint8_t bridge_vlan_aware
;
3445 /* Determine if bridge is VLAN-aware or not */
3448 br
= &zif
->l2info
.br
;
3449 bridge_vlan_aware
= br
->vlan_aware
;
3451 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3452 /* TODO: Optimize with a hash. */
3453 zns
= zebra_ns_lookup(NS_DEFAULT
);
3454 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3455 tmp_if
= (struct interface
*)rn
->info
;
3459 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3461 if (!if_is_operative(tmp_if
))
3463 vxl
= &zif
->l2info
.vxl
;
3465 if (zif
->brslave_info
.br_if
!= br_if
)
3468 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3477 zvni
= zvni_lookup(vxl
->vni
);
3482 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3483 * neighbor notifications, to see if they are of interest.
3485 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3486 struct interface
*br_if
)
3488 struct zebra_ns
*zns
;
3489 struct route_node
*rn
;
3490 struct interface
*tmp_if
= NULL
;
3491 struct zebra_if
*zif
;
3492 struct zebra_l2info_bridge
*br
;
3493 struct zebra_l2info_vxlan
*vxl
= NULL
;
3494 uint8_t bridge_vlan_aware
;
3502 /* Make sure the linked interface is a bridge. */
3503 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3506 /* Determine if bridge is VLAN-aware or not */
3509 br
= &zif
->l2info
.br
;
3510 bridge_vlan_aware
= br
->vlan_aware
;
3511 if (bridge_vlan_aware
) {
3512 struct zebra_l2info_vlan
*vl
;
3514 if (!IS_ZEBRA_IF_VLAN(ifp
))
3519 vl
= &zif
->l2info
.vl
;
3523 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3524 /* TODO: Optimize with a hash. */
3525 zns
= zebra_ns_lookup(NS_DEFAULT
);
3526 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3527 tmp_if
= (struct interface
*)rn
->info
;
3531 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3533 if (!if_is_operative(tmp_if
))
3535 vxl
= &zif
->l2info
.vxl
;
3537 if (zif
->brslave_info
.br_if
!= br_if
)
3540 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3549 zvni
= zvni_lookup(vxl
->vni
);
3553 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3555 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3556 * linked to the bridge
3557 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3560 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3562 struct zebra_ns
*zns
;
3563 struct route_node
*rn
;
3564 struct interface
*tmp_if
= NULL
;
3565 struct zebra_if
*zif
;
3566 struct zebra_l2info_bridge
*br
;
3567 struct zebra_l2info_vlan
*vl
;
3568 uint8_t bridge_vlan_aware
;
3571 /* Defensive check, caller expected to invoke only with valid bridge. */
3575 /* Determine if bridge is VLAN-aware or not */
3578 br
= &zif
->l2info
.br
;
3579 bridge_vlan_aware
= br
->vlan_aware
;
3581 /* Check oper status of the SVI. */
3582 if (!bridge_vlan_aware
)
3583 return if_is_operative(br_if
) ? br_if
: NULL
;
3585 /* Identify corresponding VLAN interface. */
3586 /* TODO: Optimize with a hash. */
3587 zns
= zebra_ns_lookup(NS_DEFAULT
);
3588 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3589 tmp_if
= (struct interface
*)rn
->info
;
3590 /* Check oper status of the SVI. */
3591 if (!tmp_if
|| !if_is_operative(tmp_if
))
3594 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3595 || zif
->link
!= br_if
)
3597 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3599 if (vl
->vid
== vid
) {
3605 return found
? tmp_if
: NULL
;
3609 * Install remote MAC into the kernel.
3611 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3613 struct zebra_if
*zif
;
3614 struct zebra_l2info_vxlan
*vxl
;
3617 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3620 zif
= zvni
->vxlan_if
->info
;
3623 vxl
= &zif
->l2info
.vxl
;
3625 sticky
= !!CHECK_FLAG(mac
->flags
,
3626 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3628 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3629 mac
->fwd_info
.r_vtep_ip
, sticky
);
3633 * Uninstall remote MAC from the kernel.
3635 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3637 struct zebra_if
*zif
;
3638 struct zebra_l2info_vxlan
*vxl
;
3639 struct in_addr vtep_ip
;
3640 struct interface
*ifp
;
3642 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3645 if (!zvni
->vxlan_if
) {
3646 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3651 zif
= zvni
->vxlan_if
->info
;
3654 vxl
= &zif
->l2info
.vxl
;
3656 ifp
= zvni
->vxlan_if
;
3657 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3659 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3663 * Install MAC hash entry - called upon access VLAN change.
3665 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3668 struct mac_walk_ctx
*wctx
= ctxt
;
3670 mac
= (zebra_mac_t
*)bucket
->data
;
3672 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3673 zvni_mac_install(wctx
->zvni
, mac
);
3677 * Count of remote neighbors referencing this MAC.
3679 static int remote_neigh_count(zebra_mac_t
*zmac
)
3681 zebra_neigh_t
*n
= NULL
;
3682 struct listnode
*node
= NULL
;
3685 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3686 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3694 * Decrement neighbor refcount of MAC; uninstall and free it if
3697 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3699 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3702 /* If all remote neighbors referencing a remote MAC go away,
3703 * we need to uninstall the MAC.
3705 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3706 remote_neigh_count(mac
) == 0) {
3707 zvni_mac_uninstall(zvni
, mac
);
3708 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3711 /* If no neighbors, delete the MAC. */
3712 if (list_isempty(mac
->neigh_list
))
3713 zvni_mac_del(zvni
, mac
);
3717 * Read and populate local MACs and neighbors corresponding to this VNI.
3719 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3721 struct zebra_ns
*zns
;
3722 struct zebra_if
*zif
;
3723 struct interface
*vlan_if
;
3724 struct zebra_l2info_vxlan
*vxl
;
3725 struct interface
*vrr_if
;
3728 vxl
= &zif
->l2info
.vxl
;
3729 zns
= zebra_ns_lookup(NS_DEFAULT
);
3731 if (IS_ZEBRA_DEBUG_VXLAN
)
3733 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3734 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3735 zif
->brslave_info
.bridge_ifindex
);
3737 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3738 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3741 /* Add SVI MAC-IP */
3742 zvni_add_macip_for_intf(vlan_if
, zvni
);
3744 /* Add VRR MAC-IP - if any*/
3745 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3747 zvni_add_macip_for_intf(vrr_if
, zvni
);
3749 neigh_read_for_vlan(zns
, vlan_if
);
3754 * Hash function for VNI.
3756 static unsigned int vni_hash_keymake(void *p
)
3758 const zebra_vni_t
*zvni
= p
;
3760 return (jhash_1word(zvni
->vni
, 0));
3764 * Compare 2 VNI hash entries.
3766 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3768 const zebra_vni_t
*zvni1
= p1
;
3769 const zebra_vni_t
*zvni2
= p2
;
3771 return (zvni1
->vni
== zvni2
->vni
);
3774 static int vni_list_cmp(void *p1
, void *p2
)
3776 const zebra_vni_t
*zvni1
= p1
;
3777 const zebra_vni_t
*zvni2
= p2
;
3779 if (zvni1
->vni
== zvni2
->vni
)
3781 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3785 * Callback to allocate VNI hash entry.
3787 static void *zvni_alloc(void *p
)
3789 const zebra_vni_t
*tmp_vni
= p
;
3792 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3793 zvni
->vni
= tmp_vni
->vni
;
3794 return ((void *)zvni
);
3798 * Look up VNI hash entry.
3800 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3802 struct zebra_vrf
*zvrf
;
3803 zebra_vni_t tmp_vni
;
3804 zebra_vni_t
*zvni
= NULL
;
3806 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3808 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3810 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3816 * Add VNI hash entry.
3818 static zebra_vni_t
*zvni_add(vni_t vni
)
3820 struct zebra_vrf
*zvrf
;
3821 zebra_vni_t tmp_zvni
;
3822 zebra_vni_t
*zvni
= NULL
;
3824 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3826 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3828 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3831 /* Create hash table for MAC */
3833 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3835 /* Create hash table for neighbors */
3836 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3837 "Zebra VNI Neighbor Table");
3843 * Delete VNI hash entry.
3845 static int zvni_del(zebra_vni_t
*zvni
)
3847 struct zebra_vrf
*zvrf
;
3848 zebra_vni_t
*tmp_zvni
;
3850 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3853 zvni
->vxlan_if
= NULL
;
3855 /* Free the neighbor hash table. */
3856 hash_free(zvni
->neigh_table
);
3857 zvni
->neigh_table
= NULL
;
3859 /* Free the MAC hash table. */
3860 hash_free(zvni
->mac_table
);
3861 zvni
->mac_table
= NULL
;
3863 /* Free the VNI hash entry and allocated memory. */
3864 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3865 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3871 * Inform BGP about local VNI addition.
3873 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3875 struct zserv
*client
;
3878 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3879 /* BGP may not be running. */
3883 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3885 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3886 stream_putl(s
, zvni
->vni
);
3887 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3888 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3890 /* Write packet size. */
3891 stream_putw_at(s
, 0, stream_get_endp(s
));
3893 if (IS_ZEBRA_DEBUG_VXLAN
)
3894 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3895 inet_ntoa(zvni
->local_vtep_ip
),
3896 vrf_id_to_name(zvni
->vrf_id
),
3897 zebra_route_string(client
->proto
));
3899 client
->vniadd_cnt
++;
3900 return zserv_send_message(client
, s
);
3904 * Inform BGP about local VNI deletion.
3906 static int zvni_send_del_to_client(vni_t vni
)
3908 struct zserv
*client
;
3911 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3912 /* BGP may not be running. */
3916 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3919 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3920 stream_putl(s
, vni
);
3922 /* Write packet size. */
3923 stream_putw_at(s
, 0, stream_get_endp(s
));
3925 if (IS_ZEBRA_DEBUG_VXLAN
)
3926 zlog_debug("Send VNI_DEL %u to %s", vni
,
3927 zebra_route_string(client
->proto
));
3929 client
->vnidel_cnt
++;
3930 return zserv_send_message(client
, s
);
3934 * Build the VNI hash table by going over the VxLAN interfaces. This
3935 * is called when EVPN (advertise-all-vni) is enabled.
3937 static void zvni_build_hash_table(void)
3939 struct zebra_ns
*zns
;
3940 struct route_node
*rn
;
3941 struct interface
*ifp
;
3943 /* Walk VxLAN interfaces and create VNI hash. */
3944 zns
= zebra_ns_lookup(NS_DEFAULT
);
3945 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3947 zebra_vni_t
*zvni
= NULL
;
3948 zebra_l3vni_t
*zl3vni
= NULL
;
3949 struct zebra_if
*zif
;
3950 struct zebra_l2info_vxlan
*vxl
;
3952 ifp
= (struct interface
*)rn
->info
;
3956 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3959 vxl
= &zif
->l2info
.vxl
;
3962 /* L3-VNI and L2-VNI are handled seperately */
3963 zl3vni
= zl3vni_lookup(vni
);
3966 if (IS_ZEBRA_DEBUG_VXLAN
)
3968 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3969 ifp
->name
, ifp
->ifindex
, vni
);
3971 /* associate with vxlan_if */
3972 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3973 zl3vni
->vxlan_if
= ifp
;
3976 * we need to associate with SVI.
3977 * we can associate with svi-if only after association
3978 * with vxlan-intf is complete
3980 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3982 if (is_l3vni_oper_up(zl3vni
))
3983 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3986 struct interface
*vlan_if
= NULL
;
3988 if (IS_ZEBRA_DEBUG_VXLAN
)
3990 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3991 ifp
->name
, ifp
->ifindex
, vni
,
3992 inet_ntoa(vxl
->vtep_ip
));
3994 /* VNI hash entry is not expected to exist. */
3995 zvni
= zvni_lookup(vni
);
3998 "VNI hash already present for IF %s(%u) L2-VNI %u",
3999 ifp
->name
, ifp
->ifindex
, vni
);
4003 zvni
= zvni_add(vni
);
4006 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4007 ifp
->name
, ifp
->ifindex
, vni
);
4011 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4012 zvni
->vxlan_if
= ifp
;
4013 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4014 zif
->brslave_info
.br_if
);
4016 zvni
->vrf_id
= vlan_if
->vrf_id
;
4017 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4019 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4023 /* Inform BGP if intf is up and mapped to bridge. */
4024 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4025 zvni_send_add_to_client(zvni
);
4031 * See if remote VTEP matches with prefix.
4033 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4035 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4039 * Locate remote VTEP in VNI hash table.
4041 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4043 zebra_vtep_t
*zvtep
;
4048 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4049 if (zvni_vtep_match(vtep_ip
, zvtep
))
4057 * Add remote VTEP to VNI hash table.
4059 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4061 zebra_vtep_t
*zvtep
;
4063 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4065 zvtep
->vtep_ip
= *vtep_ip
;
4068 zvni
->vteps
->prev
= zvtep
;
4069 zvtep
->next
= zvni
->vteps
;
4070 zvni
->vteps
= zvtep
;
4076 * Remove remote VTEP from VNI hash table.
4078 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4081 zvtep
->next
->prev
= zvtep
->prev
;
4083 zvtep
->prev
->next
= zvtep
->next
;
4085 zvni
->vteps
= zvtep
->next
;
4087 zvtep
->prev
= zvtep
->next
= NULL
;
4088 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4094 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4095 * uninstall from kernel if asked to.
4097 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4099 zebra_vtep_t
*zvtep
, *zvtep_next
;
4104 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4105 zvtep_next
= zvtep
->next
;
4107 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4108 zvni_vtep_del(zvni
, zvtep
);
4115 * Install remote VTEP into the kernel.
4117 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4119 if (is_vxlan_flooding_head_end())
4120 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4125 * Uninstall remote VTEP from the kernel.
4127 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4129 if (!zvni
->vxlan_if
) {
4130 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4135 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4139 * Install or uninstall flood entries in the kernel corresponding to
4140 * remote VTEPs. This is invoked upon change to BUM handling.
4142 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4146 zebra_vtep_t
*zvtep
;
4148 zvni
= (zebra_vni_t
*)bucket
->data
;
4152 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4153 if (is_vxlan_flooding_head_end())
4154 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4156 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4161 * Cleanup VNI/VTEP and update kernel
4163 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4165 zebra_vni_t
*zvni
= NULL
;
4166 zebra_l3vni_t
*zl3vni
= NULL
;
4167 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4169 zvni
= (zebra_vni_t
*)bucket
->data
;
4171 /* remove from l3-vni list */
4173 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4175 listnode_delete(zl3vni
->l2vnis
, zvni
);
4177 /* Free up all neighbors and MACs, if any. */
4178 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4179 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4181 /* Free up all remote VTEPs, if any. */
4182 zvni_vtep_del_all(zvni
, 1);
4184 /* Delete the hash entry. */
4189 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4191 zebra_l3vni_t
*zl3vni
= NULL
;
4193 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4195 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4198 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4199 struct prefix
*host
)
4201 struct host_rb_entry lookup
;
4202 struct host_rb_entry
*hle
;
4204 memset(&lookup
, 0, sizeof(lookup
));
4205 memcpy(&lookup
.p
, host
, sizeof(*host
));
4207 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4211 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4212 memcpy(hle
, &lookup
, sizeof(lookup
));
4214 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4217 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4219 struct host_rb_entry lookup
;
4220 struct host_rb_entry
*hle
;
4222 memset(&lookup
, 0, sizeof(lookup
));
4223 memcpy(&lookup
.p
, host
, sizeof(*host
));
4225 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4227 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4228 XFREE(MTYPE_HOST_PREFIX
, hle
);
4235 * Look up MAC hash entry.
4237 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4238 struct ethaddr
*rmac
)
4243 memset(&tmp
, 0, sizeof(tmp
));
4244 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4245 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4251 * Callback to allocate RMAC hash entry.
4253 static void *zl3vni_rmac_alloc(void *p
)
4255 const zebra_mac_t
*tmp_rmac
= p
;
4258 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4261 return ((void *)zrmac
);
4265 * Add RMAC entry to l3-vni
4267 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4269 zebra_mac_t tmp_rmac
;
4270 zebra_mac_t
*zrmac
= NULL
;
4272 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4273 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4274 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4277 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4279 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4280 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4288 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4290 zebra_mac_t
*tmp_rmac
;
4291 struct host_rb_entry
*hle
;
4293 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4294 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4296 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4297 XFREE(MTYPE_HOST_PREFIX
, hle
);
4300 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4301 XFREE(MTYPE_MAC
, tmp_rmac
);
4307 * Install remote RMAC into the kernel.
4309 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4311 struct zebra_if
*zif
= NULL
;
4312 struct zebra_l2info_vxlan
*vxl
= NULL
;
4314 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4315 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4318 zif
= zl3vni
->vxlan_if
->info
;
4322 vxl
= &zif
->l2info
.vxl
;
4324 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4325 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4329 * Uninstall remote RMAC from the kernel.
4331 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4333 char buf
[ETHER_ADDR_STRLEN
];
4334 struct zebra_if
*zif
= NULL
;
4335 struct zebra_l2info_vxlan
*vxl
= NULL
;
4337 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4338 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4341 if (!zl3vni
->vxlan_if
) {
4343 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4344 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4345 zl3vni
->vni
, zl3vni
);
4349 zif
= zl3vni
->vxlan_if
->info
;
4353 vxl
= &zif
->l2info
.vxl
;
4355 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4356 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4359 /* handle rmac add */
4360 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4361 struct ipaddr
*vtep_ip
,
4362 struct prefix
*host_prefix
)
4364 char buf
[ETHER_ADDR_STRLEN
];
4365 char buf1
[INET6_ADDRSTRLEN
];
4366 zebra_mac_t
*zrmac
= NULL
;
4368 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4371 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4374 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4375 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4377 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4380 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4381 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4383 /* install rmac in kernel */
4384 zl3vni_rmac_install(zl3vni
, zrmac
);
4387 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4393 /* handle rmac delete */
4394 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4395 struct prefix
*host_prefix
)
4397 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4399 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4400 /* uninstall from kernel */
4401 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4403 /* del the rmac entry */
4404 zl3vni_rmac_del(zl3vni
, zrmac
);
4409 * Look up nh hash entry on a l3-vni.
4411 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4416 memset(&tmp
, 0, sizeof(tmp
));
4417 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4418 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4425 * Callback to allocate NH hash entry on L3-VNI.
4427 static void *zl3vni_nh_alloc(void *p
)
4429 const zebra_neigh_t
*tmp_n
= p
;
4432 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4439 * Add neighbor entry.
4441 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4442 struct ethaddr
*mac
)
4444 zebra_neigh_t tmp_n
;
4445 zebra_neigh_t
*n
= NULL
;
4447 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4448 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4449 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4452 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4454 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4455 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4456 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4462 * Delete neighbor entry.
4464 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4466 zebra_neigh_t
*tmp_n
;
4467 struct host_rb_entry
*hle
;
4469 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4470 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4472 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4473 XFREE(MTYPE_HOST_PREFIX
, hle
);
4476 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4477 XFREE(MTYPE_NEIGH
, tmp_n
);
4483 * Install remote nh as neigh into the kernel.
4485 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4492 if (!is_l3vni_oper_up(zl3vni
))
4495 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4496 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4499 flags
= NTF_EXT_LEARNED
;
4500 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4501 flags
|= NTF_ROUTER
;
4502 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4508 * Uninstall remote nh from the kernel.
4510 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4512 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4513 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4516 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4519 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4522 /* add remote vtep as a neigh entry */
4523 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4524 struct ethaddr
*rmac
,
4525 struct prefix
*host_prefix
)
4527 char buf
[ETHER_ADDR_STRLEN
];
4528 char buf1
[INET6_ADDRSTRLEN
];
4529 zebra_neigh_t
*nh
= NULL
;
4531 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4533 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4537 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4538 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4539 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4544 /* install the nh neigh in kernel */
4545 zl3vni_nh_install(zl3vni
, nh
);
4548 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4553 /* handle nh neigh delete */
4554 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4555 struct prefix
*host_prefix
)
4557 rb_delete_host(&nh
->host_rb
, host_prefix
);
4559 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4560 /* uninstall from kernel */
4561 zl3vni_nh_uninstall(zl3vni
, nh
);
4563 /* delete the nh entry */
4564 zl3vni_nh_del(zl3vni
, nh
);
4568 /* handle neigh update from kernel - the only thing of interest is to
4569 * readd stale entries.
4571 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4575 zebra_neigh_t
*n
= NULL
;
4577 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4581 /* all next hop neigh are remote and installed by frr.
4582 * If the kernel has aged this entry, re-install.
4584 if (state
& NUD_STALE
)
4585 zl3vni_nh_install(zl3vni
, n
);
4590 /* handle neigh delete from kernel */
4591 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4593 zebra_neigh_t
*n
= NULL
;
4595 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4599 /* all next hop neigh are remote and installed by frr.
4600 * If we get an age out notification for these neigh entries, we have to
4603 zl3vni_nh_install(zl3vni
, n
);
4609 * Hash function for L3 VNI.
4611 static unsigned int l3vni_hash_keymake(void *p
)
4613 const zebra_l3vni_t
*zl3vni
= p
;
4615 return jhash_1word(zl3vni
->vni
, 0);
4619 * Compare 2 L3 VNI hash entries.
4621 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4623 const zebra_l3vni_t
*zl3vni1
= p1
;
4624 const zebra_l3vni_t
*zl3vni2
= p2
;
4626 return (zl3vni1
->vni
== zl3vni2
->vni
);
4630 * Callback to allocate L3 VNI hash entry.
4632 static void *zl3vni_alloc(void *p
)
4634 zebra_l3vni_t
*zl3vni
= NULL
;
4635 const zebra_l3vni_t
*tmp_l3vni
= p
;
4637 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4638 zl3vni
->vni
= tmp_l3vni
->vni
;
4639 return ((void *)zl3vni
);
4643 * Look up L3 VNI hash entry.
4645 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4647 zebra_l3vni_t tmp_l3vni
;
4648 zebra_l3vni_t
*zl3vni
= NULL
;
4650 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4651 tmp_l3vni
.vni
= vni
;
4652 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4658 * Add L3 VNI hash entry.
4660 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4662 zebra_l3vni_t tmp_zl3vni
;
4663 zebra_l3vni_t
*zl3vni
= NULL
;
4665 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4666 tmp_zl3vni
.vni
= vni
;
4668 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4671 zl3vni
->vrf_id
= vrf_id
;
4672 zl3vni
->svi_if
= NULL
;
4673 zl3vni
->vxlan_if
= NULL
;
4674 zl3vni
->l2vnis
= list_new();
4675 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4677 /* Create hash table for remote RMAC */
4678 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4679 "Zebra L3-VNI RMAC-Table");
4681 /* Create hash table for neighbors */
4682 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4683 "Zebra L3-VNI next-hop table");
4689 * Delete L3 VNI hash entry.
4691 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4693 zebra_l3vni_t
*tmp_zl3vni
;
4695 /* free the list of l2vnis */
4696 list_delete(&zl3vni
->l2vnis
);
4697 zl3vni
->l2vnis
= NULL
;
4699 /* Free the rmac table */
4700 hash_free(zl3vni
->rmac_table
);
4701 zl3vni
->rmac_table
= NULL
;
4703 /* Free the nh table */
4704 hash_free(zl3vni
->nh_table
);
4705 zl3vni
->nh_table
= NULL
;
4707 /* Free the VNI hash entry and allocated memory. */
4708 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4709 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4714 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4716 struct zebra_ns
*zns
= NULL
;
4717 struct route_node
*rn
= NULL
;
4718 struct interface
*ifp
= NULL
;
4720 /* loop through all vxlan-interface */
4721 zns
= zebra_ns_lookup(NS_DEFAULT
);
4722 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4724 struct zebra_if
*zif
= NULL
;
4725 struct zebra_l2info_vxlan
*vxl
= NULL
;
4727 ifp
= (struct interface
*)rn
->info
;
4732 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4735 vxl
= &zif
->l2info
.vxl
;
4736 if (vxl
->vni
== zl3vni
->vni
) {
4737 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4745 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4747 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4748 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4753 if (!zl3vni
->vxlan_if
)
4756 zif
= zl3vni
->vxlan_if
->info
;
4760 vxl
= &zif
->l2info
.vxl
;
4762 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4765 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4767 struct zebra_vrf
*zvrf
= NULL
;
4769 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4773 return zl3vni_lookup(zvrf
->l3vni
);
4777 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4778 * neighbor notifications, to see if they are of interest.
4780 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4781 struct interface
*br_if
)
4785 uint8_t bridge_vlan_aware
= 0;
4786 zebra_l3vni_t
*zl3vni
= NULL
;
4787 struct zebra_ns
*zns
= NULL
;
4788 struct route_node
*rn
= NULL
;
4789 struct zebra_if
*zif
= NULL
;
4790 struct interface
*tmp_if
= NULL
;
4791 struct zebra_l2info_bridge
*br
= NULL
;
4792 struct zebra_l2info_vxlan
*vxl
= NULL
;
4797 /* Make sure the linked interface is a bridge. */
4798 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4801 /* Determine if bridge is VLAN-aware or not */
4804 br
= &zif
->l2info
.br
;
4805 bridge_vlan_aware
= br
->vlan_aware
;
4806 if (bridge_vlan_aware
) {
4807 struct zebra_l2info_vlan
*vl
;
4809 if (!IS_ZEBRA_IF_VLAN(ifp
))
4814 vl
= &zif
->l2info
.vl
;
4818 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4819 /* TODO: Optimize with a hash. */
4820 zns
= zebra_ns_lookup(NS_DEFAULT
);
4821 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4822 tmp_if
= (struct interface
*)rn
->info
;
4826 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4828 if (!if_is_operative(tmp_if
))
4830 vxl
= &zif
->l2info
.vxl
;
4832 if (zif
->brslave_info
.br_if
!= br_if
)
4835 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4844 zl3vni
= zl3vni_lookup(vxl
->vni
);
4849 * Inform BGP about l3-vni.
4851 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4853 struct stream
*s
= NULL
;
4854 struct zserv
*client
= NULL
;
4855 struct ethaddr rmac
;
4856 char buf
[ETHER_ADDR_STRLEN
];
4858 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4859 /* BGP may not be running. */
4864 memset(&rmac
, 0, sizeof(struct ethaddr
));
4865 zl3vni_get_rmac(zl3vni
, &rmac
);
4867 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4869 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4870 stream_putl(s
, zl3vni
->vni
);
4871 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4872 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4873 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4875 /* Write packet size. */
4876 stream_putw_at(s
, 0, stream_get_endp(s
));
4878 if (IS_ZEBRA_DEBUG_VXLAN
)
4880 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4881 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4882 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4883 inet_ntoa(zl3vni
->local_vtep_ip
),
4884 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4885 ? "prefix-routes-only"
4887 zebra_route_string(client
->proto
));
4889 client
->l3vniadd_cnt
++;
4890 return zserv_send_message(client
, s
);
4894 * Inform BGP about local l3-VNI deletion.
4896 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4898 struct stream
*s
= NULL
;
4899 struct zserv
*client
= NULL
;
4901 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4902 /* BGP may not be running. */
4906 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4908 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4909 stream_putl(s
, zl3vni
->vni
);
4911 /* Write packet size. */
4912 stream_putw_at(s
, 0, stream_get_endp(s
));
4914 if (IS_ZEBRA_DEBUG_VXLAN
)
4915 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4916 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4917 zebra_route_string(client
->proto
));
4919 client
->l3vnidel_cnt
++;
4920 return zserv_send_message(client
, s
);
4923 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4928 /* send l3vni add to BGP */
4929 zl3vni_send_add_to_client(zl3vni
);
4932 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4937 /* send l3-vni del to BGP*/
4938 zl3vni_send_del_to_client(zl3vni
);
4941 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
4943 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
4944 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4946 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4947 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4951 * handle transition of vni from l2 to l3 and vice versa
4953 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4956 zebra_vni_t
*zvni
= NULL
;
4958 /* There is a possibility that VNI notification was already received
4959 * from kernel and we programmed it as L2-VNI
4960 * In such a case we need to delete this L2-VNI first, so
4961 * that it can be reprogrammed as L3-VNI in the system. It is also
4962 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4963 * interface is still present in kernel. In this case to keep it
4964 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4967 /* Locate hash entry */
4968 zvni
= zvni_lookup(vni
);
4972 if (IS_ZEBRA_DEBUG_VXLAN
)
4973 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4975 /* Delete VNI from BGP. */
4976 zvni_send_del_to_client(zvni
->vni
);
4978 /* Free up all neighbors and MAC, if any. */
4979 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4980 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4982 /* Free up all remote VTEPs, if any. */
4983 zvni_vtep_del_all(zvni
, 0);
4985 /* Delete the hash entry. */
4986 if (zvni_del(zvni
)) {
4987 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4988 "Failed to del VNI hash %p, VNI %u", zvni
,
4993 /* TODO_MITESH: This needs to be thought through. We don't have
4994 * enough information at this point to reprogram the vni as
4995 * l2-vni. One way is to store the required info in l3-vni and
4996 * used it solely for this purpose
5003 /* delete and uninstall rmac hash entry */
5004 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5006 zebra_mac_t
*zrmac
= NULL
;
5007 zebra_l3vni_t
*zl3vni
= NULL
;
5009 zrmac
= (zebra_mac_t
*)bucket
->data
;
5010 zl3vni
= (zebra_l3vni_t
*)ctx
;
5011 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5012 zl3vni_rmac_del(zl3vni
, zrmac
);
5015 /* delete and uninstall nh hash entry */
5016 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5018 zebra_neigh_t
*n
= NULL
;
5019 zebra_l3vni_t
*zl3vni
= NULL
;
5021 n
= (zebra_neigh_t
*)bucket
->data
;
5022 zl3vni
= (zebra_l3vni_t
*)ctx
;
5023 zl3vni_nh_uninstall(zl3vni
, n
);
5024 zl3vni_nh_del(zl3vni
, n
);
5027 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5030 struct zserv
*client
= NULL
;
5031 struct stream
*s
= NULL
;
5032 char buf
[PREFIX_STRLEN
];
5034 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5035 /* BGP may not be running. */
5039 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5041 zclient_create_header(s
, cmd
, vrf_id
);
5042 stream_put(s
, p
, sizeof(struct prefix
));
5044 /* Write packet size. */
5045 stream_putw_at(s
, 0, stream_get_endp(s
));
5047 if (IS_ZEBRA_DEBUG_VXLAN
)
5048 zlog_debug("Send ip prefix %s %s on vrf %s",
5049 prefix2str(p
, buf
, sizeof(buf
)),
5050 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5051 vrf_id_to_name(vrf_id
));
5053 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5054 client
->prefixadd_cnt
++;
5056 client
->prefixdel_cnt
++;
5058 return zserv_send_message(client
, s
);
5061 /* re-add remote rmac if needed */
5062 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5063 struct ethaddr
*rmac
)
5065 char buf
[ETHER_ADDR_STRLEN
];
5066 zebra_mac_t
*zrmac
= NULL
;
5068 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5072 if (IS_ZEBRA_DEBUG_VXLAN
)
5073 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5074 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5076 zl3vni_rmac_install(zl3vni
, zrmac
);
5080 /* Process a remote MACIP add from BGP. */
5081 static void process_remote_macip_add(vni_t vni
,
5082 struct ethaddr
*macaddr
,
5084 struct ipaddr
*ipaddr
,
5087 struct in_addr vtep_ip
)
5090 zebra_vtep_t
*zvtep
;
5091 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5092 zebra_neigh_t
*n
= NULL
;
5093 int update_mac
= 0, update_neigh
= 0;
5094 char buf
[ETHER_ADDR_STRLEN
];
5095 char buf1
[INET6_ADDRSTRLEN
];
5096 struct interface
*ifp
= NULL
;
5097 struct zebra_if
*zif
= NULL
;
5098 struct zebra_vrf
*zvrf
;
5103 bool do_dad
= false;
5104 bool is_dup_detect
= false;
5106 /* Locate VNI hash entry - expected to exist. */
5107 zvni
= zvni_lookup(vni
);
5109 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5113 ifp
= zvni
->vxlan_if
;
5117 !if_is_operative(ifp
) ||
5119 !zif
->brslave_info
.br_if
) {
5120 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5125 /* The remote VTEP specified should normally exist, but it is
5126 * possible that when peering comes up, peer may advertise MACIP
5127 * routes before advertising type-3 routes.
5129 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5131 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5133 EC_ZEBRA_VTEP_ADD_FAILED
,
5134 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5139 zvni_vtep_install(zvni
, &vtep_ip
);
5142 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5143 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5144 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5146 mac
= zvni_mac_lookup(zvni
, macaddr
);
5148 /* Ignore if the mac is already present as a gateway mac */
5150 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5151 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5152 if (IS_ZEBRA_DEBUG_VXLAN
)
5153 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5155 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5156 ipa_len
? " IP " : "",
5158 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5162 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5166 /* check if the remote MAC is unknown or has a change.
5167 * If so, that needs to be updated first. Note that client could
5168 * install MAC and MACIP separately or just install the latter.
5171 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5172 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5173 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5174 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5175 || seq
!= mac
->rem_seq
)
5180 mac
= zvni_mac_add(zvni
, macaddr
);
5183 "Failed to add MAC %s VNI %u Remote VTEP %s",
5184 prefix_mac2str(macaddr
, buf
,
5186 vni
, inet_ntoa(vtep_ip
));
5190 /* Is this MAC created for a MACIP? */
5192 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5194 const char *mac_type
;
5196 /* When host moves but changes its (MAC,IP)
5197 * binding, BGP may install a MACIP entry that
5198 * corresponds to "older" location of the host
5199 * in transient situations (because {IP1,M1}
5200 * is a different route from {IP1,M2}). Check
5201 * the sequence number and ignore this update
5204 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5205 tmp_seq
= mac
->loc_seq
;
5208 tmp_seq
= mac
->rem_seq
;
5209 mac_type
= "remote";
5211 if (seq
< tmp_seq
) {
5212 if (IS_ZEBRA_DEBUG_VXLAN
)
5213 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5215 prefix_mac2str(macaddr
,
5217 ipa_len
? " IP " : "",
5220 buf1
, sizeof(buf1
)) : "",
5227 /* Check MAC's curent state is local (this is the case
5228 * where MAC has moved from L->R) and check previous
5229 * detection started via local learning.
5230 * RFC-7432: A PE/VTEP that detects a MAC mobility
5231 * event via local learning starts an M-second timer.
5233 * VTEP-IP or seq. change alone is not considered
5234 * for dup. detection.
5236 * MAC is already marked duplicate set dad, then
5237 * is_dup_detect will be set to not install the entry.
5239 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5241 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5244 /* Remove local MAC from BGP. */
5245 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5246 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5248 /* Set "auto" and "remote" forwarding info. */
5249 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5250 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5251 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5252 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5255 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5257 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5260 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5262 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5264 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5265 mac
->fwd_info
.r_vtep_ip
,
5266 do_dad
, &is_dup_detect
,
5269 if (!is_dup_detect
) {
5270 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5271 /* Install the entry. */
5272 zvni_mac_install(zvni
, mac
);
5276 /* Update seq number. */
5279 /* If there is no IP, return after clearing AUTO flag of MAC. */
5281 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5288 /* Check if the remote neighbor itself is unknown or has a
5289 * change. If so, create or update and then install the entry.
5291 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5293 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5294 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5295 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5296 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5297 || seq
!= n
->rem_seq
)
5302 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5305 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5306 ipaddr2str(ipaddr
, buf1
,
5308 prefix_mac2str(macaddr
, buf
,
5310 vni
, inet_ntoa(vtep_ip
));
5317 /* When host moves but changes its (MAC,IP)
5318 * binding, BGP may install a MACIP entry that
5319 * corresponds to "older" location of the host
5320 * in transient situations (because {IP1,M1}
5321 * is a different route from {IP1,M2}). Check
5322 * the sequence number and ignore this update
5325 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5326 tmp_seq
= n
->loc_seq
;
5329 tmp_seq
= n
->rem_seq
;
5332 if (seq
< tmp_seq
) {
5333 if (IS_ZEBRA_DEBUG_VXLAN
)
5334 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5336 prefix_mac2str(macaddr
,
5339 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5344 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5345 /* MAC change, send a delete for old
5346 * neigh if learnt locally.
5348 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5349 IS_ZEBRA_NEIGH_ACTIVE(n
))
5350 zvni_neigh_send_del_to_client(
5352 &n
->emac
, 0, n
->state
);
5354 /* update neigh list for macs */
5355 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5357 listnode_delete(old_mac
->neigh_list
, n
);
5358 zvni_deref_ip2mac(zvni
, old_mac
);
5360 listnode_add_sort(mac
->neigh_list
, n
);
5361 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5363 /* Check Neigh's curent state is local
5364 * (this is the case where neigh/host has moved
5365 * from L->R) and check previous detction
5366 * started via local learning.
5368 * RFC-7432: A PE/VTEP that detects a MAC
5369 * mobilit event via local learning starts
5370 * an M-second timer.
5371 * VTEP-IP or seq. change along is not
5372 * considered for dup. detection.
5374 * Mobilty event scenario-B IP-MAC binding
5377 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5384 /* Set "remote" forwarding info. */
5385 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5386 n
->r_vtep_ip
= vtep_ip
;
5387 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5389 /* Set router flag (R-bit) to this Neighbor entry */
5390 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5391 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5393 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5395 /* Check old or new MAC detected as duplicate,
5396 * inherit duplicate flag to this neigh.
5398 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5400 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5401 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5403 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5404 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5407 /* Check duplicate address detection for IP */
5408 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5413 /* Install the entry. */
5415 zvni_neigh_install(zvni
, n
);
5418 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5420 /* Update seq number. */
5424 /* Process a remote MACIP delete from BGP. */
5425 static void process_remote_macip_del(vni_t vni
,
5426 struct ethaddr
*macaddr
,
5428 struct ipaddr
*ipaddr
,
5429 struct in_addr vtep_ip
)
5432 zebra_mac_t
*mac
= NULL
;
5433 zebra_neigh_t
*n
= NULL
;
5434 struct interface
*ifp
= NULL
;
5435 struct zebra_if
*zif
= NULL
;
5436 struct zebra_ns
*zns
;
5437 struct zebra_l2info_vxlan
*vxl
;
5438 struct zebra_vrf
*zvrf
;
5439 char buf
[ETHER_ADDR_STRLEN
];
5440 char buf1
[INET6_ADDRSTRLEN
];
5442 /* Locate VNI hash entry - expected to exist. */
5443 zvni
= zvni_lookup(vni
);
5445 if (IS_ZEBRA_DEBUG_VXLAN
)
5446 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5450 ifp
= zvni
->vxlan_if
;
5454 !if_is_operative(ifp
) ||
5456 !zif
->brslave_info
.br_if
) {
5457 if (IS_ZEBRA_DEBUG_VXLAN
)
5458 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5462 zns
= zebra_ns_lookup(NS_DEFAULT
);
5463 vxl
= &zif
->l2info
.vxl
;
5465 /* The remote VTEP specified is normally expected to exist, but
5466 * it is possible that the peer may delete the VTEP before deleting
5467 * any MACs referring to the VTEP, in which case the handler (see
5468 * remote_vtep_del) would have already deleted the MACs.
5470 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5473 mac
= zvni_mac_lookup(zvni
, macaddr
);
5475 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5478 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5479 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5480 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5484 /* If the remote mac or neighbor doesn't exist there is nothing
5485 * more to do. Otherwise, uninstall the entry and then remove it.
5490 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5492 /* Ignore the delete if this mac is a gateway mac-ip */
5493 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5494 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5496 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5498 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5499 ipa_len
? " IP " : "",
5501 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5505 /* Uninstall remote neighbor or MAC. */
5507 if (zvrf
->dad_freeze
&&
5508 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5509 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5510 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5511 struct interface
*vlan_if
;
5513 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5514 zif
->brslave_info
.br_if
);
5515 if (IS_ZEBRA_DEBUG_VXLAN
)
5516 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5517 __PRETTY_FUNCTION__
,
5518 ipaddr2str(ipaddr
, buf1
,
5519 sizeof(buf1
)), n
->flags
,
5521 neigh_read_specific_ip(ipaddr
, vlan_if
);
5524 /* When the MAC changes for an IP, it is possible the
5525 * client may update the new MAC before trying to delete the
5526 * "old" neighbor (as these are two different MACIP routes).
5527 * Do the delete only if the MAC matches.
5529 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5530 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5531 zvni_neigh_uninstall(zvni
, n
);
5532 zvni_neigh_del(zvni
, n
);
5533 zvni_deref_ip2mac(zvni
, mac
);
5536 /* DAD: when MAC is freeze state as remote learn event,
5537 * remote mac-ip delete event is received will result in freeze
5538 * entry removal, first fetch kernel for the same entry present
5539 * as LOCAL and reachable, avoid deleting this entry instead
5540 * use kerenel local entry to update during unfreeze time.
5542 if (zvrf
->dad_freeze
&&
5543 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5544 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5545 if (IS_ZEBRA_DEBUG_VXLAN
)
5546 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5547 __PRETTY_FUNCTION__
,
5548 prefix_mac2str(macaddr
, buf
,
5551 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5552 macaddr
, vxl
->access_vlan
);
5555 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5556 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5558 * the remote sequence number in the auto mac entry
5559 * needs to be reset to 0 as the mac entry may have
5560 * been removed on all VTEPs (including
5561 * the originating one)
5565 /* If all remote neighbors referencing a remote MAC
5566 * go away, we need to uninstall the MAC.
5568 if (remote_neigh_count(mac
) == 0) {
5569 zvni_mac_uninstall(zvni
, mac
);
5570 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5572 if (list_isempty(mac
->neigh_list
))
5573 zvni_mac_del(zvni
, mac
);
5575 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5581 /* Public functions */
5583 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5585 zebra_l3vni_t
*zl3vni
= NULL
;
5587 zl3vni
= zl3vni_lookup(vni
);
5591 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5594 /* handle evpn route in vrf table */
5595 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5596 struct ipaddr
*vtep_ip
,
5597 struct prefix
*host_prefix
)
5599 zebra_l3vni_t
*zl3vni
= NULL
;
5600 struct ipaddr ipv4_vtep
;
5602 zl3vni
= zl3vni_from_vrf(vrf_id
);
5603 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5607 * add the next hop neighbor -
5608 * neigh to be installed is the ipv6 nexthop neigh
5610 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5613 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5614 * address. Rmac is programmed against the ipv4 vtep because we only
5615 * support ipv4 tunnels in the h/w right now
5617 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5618 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5619 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5620 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5621 &(ipv4_vtep
.ipaddr_v4
));
5623 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5624 sizeof(struct in_addr
));
5627 * add the rmac - remote rmac to be installed is against the ipv4
5630 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5633 /* handle evpn vrf route delete */
5634 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5635 struct ipaddr
*vtep_ip
,
5636 struct prefix
*host_prefix
)
5638 zebra_l3vni_t
*zl3vni
= NULL
;
5639 zebra_neigh_t
*nh
= NULL
;
5640 zebra_mac_t
*zrmac
= NULL
;
5642 zl3vni
= zl3vni_from_vrf(vrf_id
);
5646 /* find the next hop entry and rmac entry */
5647 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5650 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5652 /* delete the next hop entry */
5653 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5655 /* delete the rmac entry */
5657 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5661 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5662 struct ethaddr
*rmac
, bool use_json
)
5664 zebra_l3vni_t
*zl3vni
= NULL
;
5665 zebra_mac_t
*zrmac
= NULL
;
5666 json_object
*json
= NULL
;
5668 if (!is_evpn_enabled()) {
5670 vty_out(vty
, "{}\n");
5675 json
= json_object_new_object();
5677 zl3vni
= zl3vni_lookup(l3vni
);
5680 vty_out(vty
, "{}\n");
5682 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5686 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5689 vty_out(vty
, "{}\n");
5692 "%% Requested RMAC doesn't exist in L3-VNI %u",
5697 zl3vni_print_rmac(zrmac
, vty
, json
);
5700 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5701 json
, JSON_C_TO_STRING_PRETTY
));
5702 json_object_free(json
);
5706 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5708 zebra_l3vni_t
*zl3vni
;
5710 struct rmac_walk_ctx wctx
;
5711 json_object
*json
= NULL
;
5713 if (!is_evpn_enabled())
5716 zl3vni
= zl3vni_lookup(l3vni
);
5719 vty_out(vty
, "{}\n");
5721 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5724 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5729 json
= json_object_new_object();
5731 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5735 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5737 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5739 json_object_int_add(json
, "numRmacs", num_rmacs
);
5741 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5744 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5745 json
, JSON_C_TO_STRING_PRETTY
));
5746 json_object_free(json
);
5750 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5752 json_object
*json
= NULL
;
5755 if (!is_evpn_enabled()) {
5757 vty_out(vty
, "{}\n");
5762 json
= json_object_new_object();
5766 hash_iterate(zrouter
.l3vni_table
,
5767 (void (*)(struct hash_bucket
*,
5768 void *))zl3vni_print_rmac_hash_all_vni
,
5772 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5773 json
, JSON_C_TO_STRING_PRETTY
));
5774 json_object_free(json
);
5778 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5779 struct ipaddr
*ip
, bool use_json
)
5781 zebra_l3vni_t
*zl3vni
= NULL
;
5782 zebra_neigh_t
*n
= NULL
;
5783 json_object
*json
= NULL
;
5785 if (!is_evpn_enabled()) {
5787 vty_out(vty
, "{}\n");
5792 json
= json_object_new_object();
5794 zl3vni
= zl3vni_lookup(l3vni
);
5797 vty_out(vty
, "{}\n");
5799 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5803 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5806 vty_out(vty
, "{}\n");
5809 "%% Requested next-hop not present for L3-VNI %u",
5814 zl3vni_print_nh(n
, vty
, json
);
5817 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5818 json
, JSON_C_TO_STRING_PRETTY
));
5819 json_object_free(json
);
5823 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5826 struct nh_walk_ctx wctx
;
5827 json_object
*json
= NULL
;
5828 zebra_l3vni_t
*zl3vni
= NULL
;
5830 if (!is_evpn_enabled())
5833 zl3vni
= zl3vni_lookup(l3vni
);
5836 vty_out(vty
, "{}\n");
5838 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5842 num_nh
= hashcount(zl3vni
->nh_table
);
5847 json
= json_object_new_object();
5852 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5854 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5856 json_object_int_add(json
, "numNextHops", num_nh
);
5858 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5861 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5862 json
, JSON_C_TO_STRING_PRETTY
));
5863 json_object_free(json
);
5867 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5869 json_object
*json
= NULL
;
5872 if (!is_evpn_enabled()) {
5874 vty_out(vty
, "{}\n");
5879 json
= json_object_new_object();
5883 hash_iterate(zrouter
.l3vni_table
,
5884 (void (*)(struct hash_bucket
*,
5885 void *))zl3vni_print_nh_hash_all_vni
,
5889 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5890 json
, JSON_C_TO_STRING_PRETTY
));
5891 json_object_free(json
);
5896 * Display L3 VNI information (VTY command handler).
5898 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5901 json_object
*json
= NULL
;
5902 zebra_l3vni_t
*zl3vni
= NULL
;
5904 if (!is_evpn_enabled()) {
5906 vty_out(vty
, "{}\n");
5910 zl3vni
= zl3vni_lookup(vni
);
5913 vty_out(vty
, "{}\n");
5915 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5920 json
= json_object_new_object();
5924 zl3vni_print(zl3vni
, (void *)args
);
5927 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5928 json
, JSON_C_TO_STRING_PRETTY
));
5929 json_object_free(json
);
5933 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5934 json_object
*json_vrfs
)
5936 char buf
[ETHER_ADDR_STRLEN
];
5937 zebra_l3vni_t
*zl3vni
= NULL
;
5939 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5944 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5945 zvrf_name(zvrf
), zl3vni
->vni
,
5946 zl3vni_vxlan_if_name(zl3vni
),
5947 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5948 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5950 json_object
*json_vrf
= NULL
;
5952 json_vrf
= json_object_new_object();
5953 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5954 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5955 json_object_string_add(json_vrf
, "vxlanIntf",
5956 zl3vni_vxlan_if_name(zl3vni
));
5957 json_object_string_add(json_vrf
, "sviIntf",
5958 zl3vni_svi_if_name(zl3vni
));
5959 json_object_string_add(json_vrf
, "state",
5960 zl3vni_state2str(zl3vni
));
5961 json_object_string_add(
5962 json_vrf
, "routerMac",
5963 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5964 json_object_array_add(json_vrfs
, json_vrf
);
5969 * Display Neighbors for a VNI (VTY command handler).
5971 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5972 vni_t vni
, bool use_json
)
5976 struct neigh_walk_ctx wctx
;
5977 json_object
*json
= NULL
;
5979 if (!is_evpn_enabled())
5981 zvni
= zvni_lookup(vni
);
5984 vty_out(vty
, "{}\n");
5986 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5989 num_neigh
= hashcount(zvni
->neigh_table
);
5994 json
= json_object_new_object();
5996 /* Since we have IPv6 addresses to deal with which can vary widely in
5997 * size, we try to be a bit more elegant in display by first computing
5998 * the maximum width.
6000 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6003 wctx
.addr_width
= 15;
6005 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6009 "Number of ARPs (local and remote) known for this VNI: %u\n",
6011 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6012 -wctx
.addr_width
, "IP", "Type",
6013 "State", "MAC", "Remote VTEP");
6015 json_object_int_add(json
, "numArpNd", num_neigh
);
6017 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6019 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6020 json
, JSON_C_TO_STRING_PRETTY
));
6021 json_object_free(json
);
6026 * Display neighbors across all VNIs (VTY command handler).
6028 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6029 bool print_dup
, bool use_json
)
6031 json_object
*json
= NULL
;
6034 if (!is_evpn_enabled())
6038 json
= json_object_new_object();
6042 args
[2] = (void *)(ptrdiff_t)print_dup
;
6044 hash_iterate(zvrf
->vni_table
,
6045 (void (*)(struct hash_bucket
*,
6046 void *))zvni_print_neigh_hash_all_vni
,
6049 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6050 json
, JSON_C_TO_STRING_PRETTY
));
6051 json_object_free(json
);
6056 * Display neighbors across all VNIs in detail(VTY command handler).
6058 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6059 struct zebra_vrf
*zvrf
,
6060 bool print_dup
, bool use_json
)
6062 json_object
*json
= NULL
;
6065 if (!is_evpn_enabled())
6069 json
= json_object_new_object();
6073 args
[2] = (void *)(ptrdiff_t)print_dup
;
6075 hash_iterate(zvrf
->vni_table
,
6076 (void (*)(struct hash_bucket
*,
6077 void *))zvni_print_neigh_hash_all_vni_detail
,
6080 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6081 json
, JSON_C_TO_STRING_PRETTY
));
6082 json_object_free(json
);
6087 * Display specific neighbor for a VNI, if present (VTY command handler).
6089 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6090 struct zebra_vrf
*zvrf
, vni_t vni
,
6091 struct ipaddr
*ip
, bool use_json
)
6095 json_object
*json
= NULL
;
6097 if (!is_evpn_enabled())
6099 zvni
= zvni_lookup(vni
);
6102 vty_out(vty
, "{}\n");
6104 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6107 n
= zvni_neigh_lookup(zvni
, ip
);
6111 "%% Requested neighbor does not exist in VNI %u\n",
6116 json
= json_object_new_object();
6118 zvni_print_neigh(n
, vty
, json
);
6121 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6122 json
, JSON_C_TO_STRING_PRETTY
));
6123 json_object_free(json
);
6128 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6129 * By definition, these are remote neighbors.
6131 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6132 vni_t vni
, struct in_addr vtep_ip
,
6137 struct neigh_walk_ctx wctx
;
6138 json_object
*json
= NULL
;
6140 if (!is_evpn_enabled())
6142 zvni
= zvni_lookup(vni
);
6145 vty_out(vty
, "{}\n");
6147 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6150 num_neigh
= hashcount(zvni
->neigh_table
);
6154 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6157 wctx
.addr_width
= 15;
6158 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6159 wctx
.r_vtep_ip
= vtep_ip
;
6161 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6162 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6165 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6166 json
, JSON_C_TO_STRING_PRETTY
));
6167 json_object_free(json
);
6172 * Display Duplicate detected Neighbors for a VNI
6173 * (VTY command handler).
6175 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6176 struct zebra_vrf
*zvrf
,
6182 struct neigh_walk_ctx wctx
;
6183 json_object
*json
= NULL
;
6185 if (!is_evpn_enabled())
6188 zvni
= zvni_lookup(vni
);
6190 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6194 num_neigh
= hashcount(zvni
->neigh_table
);
6198 num_neigh
= num_dup_detected_neighs(zvni
);
6203 json
= json_object_new_object();
6205 /* Since we have IPv6 addresses to deal with which can vary widely in
6206 * size, we try to be a bit more elegant in display by first computing
6207 * the maximum width.
6209 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6212 wctx
.addr_width
= 15;
6214 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6218 "Number of ARPs (local and remote) known for this VNI: %u\n",
6220 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6221 -wctx
.addr_width
, "IP", "Type",
6222 "State", "MAC", "Remote VTEP");
6224 json_object_int_add(json
, "numArpNd", num_neigh
);
6226 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6229 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6230 json
, JSON_C_TO_STRING_PRETTY
));
6231 json_object_free(json
);
6236 * Display MACs for a VNI (VTY command handler).
6238 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6239 vni_t vni
, bool use_json
)
6243 struct mac_walk_ctx wctx
;
6244 json_object
*json
= NULL
;
6245 json_object
*json_mac
= NULL
;
6247 if (!is_evpn_enabled())
6249 zvni
= zvni_lookup(vni
);
6252 vty_out(vty
, "{}\n");
6254 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6257 num_macs
= num_valid_macs(zvni
);
6262 json
= json_object_new_object();
6263 json_mac
= json_object_new_object();
6266 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6269 wctx
.json
= json_mac
;
6273 "Number of MACs (local and remote) known for this VNI: %u\n",
6275 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6276 "Intf/Remote VTEP", "VLAN");
6278 json_object_int_add(json
, "numMacs", num_macs
);
6280 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6283 json_object_object_add(json
, "macs", json_mac
);
6284 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6285 json
, JSON_C_TO_STRING_PRETTY
));
6286 json_object_free(json
);
6291 * Display MACs for all VNIs (VTY command handler).
6293 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6294 bool print_dup
, bool use_json
)
6296 struct mac_walk_ctx wctx
;
6297 json_object
*json
= NULL
;
6299 if (!is_evpn_enabled()) {
6301 vty_out(vty
, "{}\n");
6305 json
= json_object_new_object();
6307 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6310 wctx
.print_dup
= print_dup
;
6311 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6314 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6315 json
, JSON_C_TO_STRING_PRETTY
));
6316 json_object_free(json
);
6321 * Display MACs in detail for all VNIs (VTY command handler).
6323 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6324 struct zebra_vrf
*zvrf
,
6325 bool print_dup
, bool use_json
)
6327 struct mac_walk_ctx wctx
;
6328 json_object
*json
= NULL
;
6330 if (!is_evpn_enabled()) {
6332 vty_out(vty
, "{}\n");
6336 json
= json_object_new_object();
6338 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6341 wctx
.print_dup
= print_dup
;
6342 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6346 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6347 json
, JSON_C_TO_STRING_PRETTY
));
6348 json_object_free(json
);
6353 * Display MACs for all VNIs (VTY command handler).
6355 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6356 struct zebra_vrf
*zvrf
,
6357 struct in_addr vtep_ip
, bool use_json
)
6359 struct mac_walk_ctx wctx
;
6360 json_object
*json
= NULL
;
6362 if (!is_evpn_enabled())
6366 json
= json_object_new_object();
6368 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6370 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6371 wctx
.r_vtep_ip
= vtep_ip
;
6373 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6376 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6377 json
, JSON_C_TO_STRING_PRETTY
));
6378 json_object_free(json
);
6383 * Display specific MAC for a VNI, if present (VTY command handler).
6385 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6386 vni_t vni
, struct ethaddr
*macaddr
,
6391 json_object
*json
= NULL
;
6393 if (!is_evpn_enabled())
6396 zvni
= zvni_lookup(vni
);
6399 vty_out(vty
, "{}\n");
6401 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6404 mac
= zvni_mac_lookup(zvni
, macaddr
);
6407 vty_out(vty
, "{}\n");
6410 "%% Requested MAC does not exist in VNI %u\n",
6416 json
= json_object_new_object();
6418 zvni_print_mac(mac
, vty
, json
);
6420 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6421 json
, JSON_C_TO_STRING_PRETTY
));
6422 json_object_free(json
);
6426 /* Print Duplicate MACs per VNI */
6427 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6428 struct zebra_vrf
*zvrf
,
6429 vni_t vni
, bool use_json
)
6432 struct mac_walk_ctx wctx
;
6434 json_object
*json
= NULL
;
6435 json_object
*json_mac
= NULL
;
6437 if (!is_evpn_enabled())
6440 zvni
= zvni_lookup(vni
);
6442 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6446 num_macs
= num_valid_macs(zvni
);
6450 num_macs
= num_dup_detected_macs(zvni
);
6455 json
= json_object_new_object();
6456 json_mac
= json_object_new_object();
6459 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6462 wctx
.json
= json_mac
;
6466 "Number of MACs (local and remote) known for this VNI: %u\n",
6468 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6469 "Intf/Remote VTEP", "VLAN");
6471 json_object_int_add(json
, "numMacs", num_macs
);
6473 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6476 json_object_object_add(json
, "macs", json_mac
);
6477 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6478 json
, JSON_C_TO_STRING_PRETTY
));
6479 json_object_free(json
);
6484 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6485 struct zebra_vrf
*zvrf
,
6486 vni_t vni
, struct ethaddr
*macaddr
)
6490 struct listnode
*node
= NULL
;
6491 zebra_neigh_t
*nbr
= NULL
;
6493 if (!is_evpn_enabled())
6496 zvni
= zvni_lookup(vni
);
6498 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6502 mac
= zvni_mac_lookup(zvni
, macaddr
);
6504 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6509 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6510 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6514 /* Remove all IPs as duplicate associcated with this MAC */
6515 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6516 /* For local neigh mark inactive so MACIP update is generated
6517 * to BGP. This is a scenario where MAC update received
6518 * and detected as duplicate which marked neigh as duplicate.
6519 * Later local neigh update did not get a chance to relay
6520 * to BGP. Similarly remote macip update, neigh needs to be
6521 * installed locally.
6523 if (zvrf
->dad_freeze
&&
6524 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6525 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6526 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6527 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6528 zvni_neigh_install(zvni
, nbr
);
6531 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6533 nbr
->detect_start_time
.tv_sec
= 0;
6534 nbr
->dad_dup_detect_time
= 0;
6537 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6539 mac
->detect_start_time
.tv_sec
= 0;
6540 mac
->detect_start_time
.tv_usec
= 0;
6541 mac
->dad_dup_detect_time
= 0;
6542 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6544 /* warn-only action return */
6545 if (!zvrf
->dad_freeze
)
6548 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6549 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6551 if (zvni_mac_send_add_to_client(zvni
->vni
,
6557 /* Process all neighbors associated with this MAC. */
6558 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6560 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6561 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6563 /* Install the entry. */
6564 zvni_mac_install(zvni
, mac
);
6570 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6571 struct zebra_vrf
*zvrf
,
6572 vni_t vni
, struct ipaddr
*ip
)
6577 char buf
[INET6_ADDRSTRLEN
];
6578 char buf2
[ETHER_ADDR_STRLEN
];
6580 if (!is_evpn_enabled())
6583 zvni
= zvni_lookup(vni
);
6585 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6589 nbr
= zvni_neigh_lookup(zvni
, ip
);
6592 "%% Requested host IP does not exist in VNI %u\n",
6597 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6599 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6601 "%% Requsted host IP %s is not duplicate detected\n",
6606 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6608 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6610 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6611 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6612 return CMD_WARNING_CONFIG_FAILED
;
6615 if (IS_ZEBRA_DEBUG_VXLAN
)
6616 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6617 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6620 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6622 nbr
->detect_start_time
.tv_sec
= 0;
6623 nbr
->detect_start_time
.tv_usec
= 0;
6624 nbr
->dad_dup_detect_time
= 0;
6625 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6627 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6628 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6630 nbr
->flags
, nbr
->loc_seq
);
6631 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6632 zvni_neigh_install(zvni
, nbr
);
6638 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6640 struct mac_walk_ctx
*wctx
= ctxt
;
6643 struct listnode
*node
= NULL
;
6644 zebra_neigh_t
*nbr
= NULL
;
6646 mac
= (zebra_mac_t
*)bucket
->data
;
6652 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6655 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6657 mac
->detect_start_time
.tv_sec
= 0;
6658 mac
->detect_start_time
.tv_usec
= 0;
6659 mac
->dad_dup_detect_time
= 0;
6660 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6662 /* Remove all IPs as duplicate associcated with this MAC */
6663 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6664 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6666 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6668 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6670 nbr
->detect_start_time
.tv_sec
= 0;
6671 nbr
->dad_dup_detect_time
= 0;
6674 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6675 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6677 if (zvni_mac_send_add_to_client(zvni
->vni
,
6679 mac
->flags
, mac
->loc_seq
))
6682 /* Process all neighbors associated with this MAC. */
6683 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6685 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6686 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6688 /* Install the entry. */
6689 zvni_mac_install(zvni
, mac
);
6693 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6695 struct neigh_walk_ctx
*wctx
= ctxt
;
6698 char buf
[INET6_ADDRSTRLEN
];
6700 nbr
= (zebra_neigh_t
*)bucket
->data
;
6706 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6709 if (IS_ZEBRA_DEBUG_VXLAN
) {
6710 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6712 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6713 __PRETTY_FUNCTION__
, buf
,
6714 nbr
->flags
, nbr
->loc_seq
);
6717 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6719 nbr
->detect_start_time
.tv_sec
= 0;
6720 nbr
->detect_start_time
.tv_usec
= 0;
6721 nbr
->dad_dup_detect_time
= 0;
6722 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6724 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6725 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6727 nbr
->flags
, nbr
->loc_seq
);
6728 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6729 zvni_neigh_install(zvni
, nbr
);
6733 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6738 struct zebra_vrf
*zvrf
;
6739 struct mac_walk_ctx m_wctx
;
6740 struct neigh_walk_ctx n_wctx
;
6742 zvni
= (zebra_vni_t
*)bucket
->data
;
6746 vty
= (struct vty
*)args
[0];
6747 zvrf
= (struct zebra_vrf
*)args
[1];
6749 if (hashcount(zvni
->neigh_table
)) {
6750 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6754 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6758 if (num_valid_macs(zvni
)) {
6759 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6763 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6768 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6769 struct zebra_vrf
*zvrf
)
6773 if (!is_evpn_enabled())
6779 hash_iterate(zvrf
->vni_table
,
6780 (void (*)(struct hash_bucket
*, void *))
6781 zvni_clear_dup_detect_hash_vni_all
, args
);
6786 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6787 struct zebra_vrf
*zvrf
,
6791 struct mac_walk_ctx m_wctx
;
6792 struct neigh_walk_ctx n_wctx
;
6794 if (!is_evpn_enabled())
6797 zvni
= zvni_lookup(vni
);
6799 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6803 if (hashcount(zvni
->neigh_table
)) {
6804 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6808 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6812 if (num_valid_macs(zvni
)) {
6813 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6817 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6824 * Display MACs for a VNI from specific VTEP (VTY command handler).
6826 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6827 vni_t vni
, struct in_addr vtep_ip
,
6832 struct mac_walk_ctx wctx
;
6833 json_object
*json
= NULL
;
6834 json_object
*json_mac
= NULL
;
6836 if (!is_evpn_enabled())
6838 zvni
= zvni_lookup(vni
);
6841 vty_out(vty
, "{}\n");
6843 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6846 num_macs
= num_valid_macs(zvni
);
6851 json
= json_object_new_object();
6852 json_mac
= json_object_new_object();
6855 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6858 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6859 wctx
.r_vtep_ip
= vtep_ip
;
6860 wctx
.json
= json_mac
;
6861 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6864 json_object_int_add(json
, "numMacs", wctx
.count
);
6866 json_object_object_add(json
, "macs", json_mac
);
6867 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6868 json
, JSON_C_TO_STRING_PRETTY
));
6869 json_object_free(json
);
6875 * Display VNI information (VTY command handler).
6877 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6880 json_object
*json
= NULL
;
6882 zebra_l3vni_t
*zl3vni
= NULL
;
6883 zebra_vni_t
*zvni
= NULL
;
6885 if (!is_evpn_enabled())
6889 json
= json_object_new_object();
6893 zl3vni
= zl3vni_lookup(vni
);
6895 zl3vni_print(zl3vni
, (void *)args
);
6897 zvni
= zvni_lookup(vni
);
6900 vty_out(vty
, "{}\n");
6902 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6906 zvni_print(zvni
, (void *)args
);
6910 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6911 json
, JSON_C_TO_STRING_PRETTY
));
6912 json_object_free(json
);
6916 /* Display all global details for EVPN */
6917 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6922 json_object
*json
= NULL
;
6923 struct zebra_vrf
*zvrf
= NULL
;
6925 if (!is_evpn_enabled())
6928 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6932 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6933 num_l2vnis
= hashcount(zvrf
->vni_table
);
6934 num_vnis
= num_l2vnis
+ num_l3vnis
;
6937 json
= json_object_new_object();
6938 json_object_string_add(json
, "advertiseGatewayMacip",
6939 zvrf
->advertise_gw_macip
? "Yes" : "No");
6940 json_object_int_add(json
, "numVnis", num_vnis
);
6941 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6942 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6943 if (zvrf
->dup_addr_detect
)
6944 json_object_boolean_true_add(json
,
6945 "isDuplicateAddrDetection");
6947 json_object_boolean_false_add(json
,
6948 "isDuplicateAddrDetection");
6949 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6950 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6951 json_object_int_add(json
, "detectionFreezeTime",
6952 zvrf
->dad_freeze_time
);
6955 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6956 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6957 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6958 zvrf
->advertise_gw_macip
? "Yes" : "No");
6959 vty_out(vty
, "Advertise svi mac-ip: %s\n",
6960 zvrf
->advertise_svi_macip
? "Yes" : "No");
6961 vty_out(vty
, "Duplicate address detection: %s\n",
6962 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6963 vty_out(vty
, " Detection max-moves %u, time %d\n",
6964 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6965 if (zvrf
->dad_freeze
) {
6966 if (zvrf
->dad_freeze_time
)
6967 vty_out(vty
, " Detection freeze %u\n",
6968 zvrf
->dad_freeze_time
);
6970 vty_out(vty
, " Detection freeze %s\n",
6976 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6977 json
, JSON_C_TO_STRING_PRETTY
));
6978 json_object_free(json
);
6983 * Display VNI hash table (VTY command handler).
6985 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6988 json_object
*json
= NULL
;
6991 if (!is_evpn_enabled())
6995 json
= json_object_new_object();
6997 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6998 "Type", "VxLAN IF", "# MACs", "# ARPs",
6999 "# Remote VTEPs", "Tenant VRF");
7004 /* Display all L2-VNIs */
7005 hash_iterate(zvrf
->vni_table
,
7006 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7009 /* Display all L3-VNIs */
7010 hash_iterate(zrouter
.l3vni_table
,
7011 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7015 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7016 json
, JSON_C_TO_STRING_PRETTY
));
7017 json_object_free(json
);
7021 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7025 uint32_t max_moves
= 0;
7026 uint32_t freeze_time
= 0;
7027 bool dup_addr_detect
= false;
7028 bool freeze
= false;
7031 STREAM_GETL(s
, dup_addr_detect
);
7032 STREAM_GETL(s
, time
);
7033 STREAM_GETL(s
, max_moves
);
7034 STREAM_GETL(s
, freeze
);
7035 STREAM_GETL(s
, freeze_time
);
7037 /* DAD previous state was enabled, and new state is disable,
7038 * clear all duplicate detected addresses.
7040 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7041 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7043 zvrf
->dup_addr_detect
= dup_addr_detect
;
7044 zvrf
->dad_time
= time
;
7045 zvrf
->dad_max_moves
= max_moves
;
7046 zvrf
->dad_freeze
= freeze
;
7047 zvrf
->dad_freeze_time
= freeze_time
;
7049 if (IS_ZEBRA_DEBUG_VXLAN
)
7051 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7052 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7053 zvrf
->dup_addr_detect
? "enable" : "disable",
7054 zvrf
->dad_max_moves
,
7056 zvrf
->dad_freeze
? "enable" : "disable",
7057 zvrf
->dad_freeze_time
);
7064 * Display VNI hash table in detail(VTY command handler).
7066 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7069 json_object
*json
= NULL
;
7070 struct zebra_ns
*zns
= NULL
;
7071 struct zvni_evpn_show zes
;
7073 if (!is_evpn_enabled())
7076 zns
= zebra_ns_lookup(NS_DEFAULT
);
7082 json
= json_object_new_object();
7088 /* Display all L2-VNIs */
7089 hash_iterate(zvrf
->vni_table
, (void (*)(struct hash_bucket
*,
7090 void *))zvni_print_hash_detail
,
7093 /* Display all L3-VNIs */
7094 hash_iterate(zrouter
.l3vni_table
,
7095 (void (*)(struct hash_bucket
*,
7096 void *))zl3vni_print_hash_detail
,
7100 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7101 json
, JSON_C_TO_STRING_PRETTY
));
7102 json_object_free(json
);
7107 * Handle neighbor delete notification from the kernel (on a VLAN device
7108 * / L3 interface). This may result in either the neighbor getting deleted
7109 * from our database or being re-added to the kernel (if it is a valid
7112 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7113 struct interface
*link_if
,
7116 char buf
[INET6_ADDRSTRLEN
];
7117 char buf2
[ETHER_ADDR_STRLEN
];
7118 zebra_neigh_t
*n
= NULL
;
7119 zebra_vni_t
*zvni
= NULL
;
7120 zebra_mac_t
*zmac
= NULL
;
7121 zebra_l3vni_t
*zl3vni
= NULL
;
7122 struct zebra_vrf
*zvrf
;
7124 /* check if this is a remote neigh entry corresponding to remote
7127 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7129 return zl3vni_local_nh_del(zl3vni
, ip
);
7131 /* We are only interested in neighbors on an SVI that resides on top
7132 * of a VxLAN bridge.
7134 zvni
= zvni_from_svi(ifp
, link_if
);
7138 if (!zvni
->vxlan_if
) {
7140 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7145 if (IS_ZEBRA_DEBUG_VXLAN
)
7146 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7147 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7148 ifp
->ifindex
, zvni
->vni
);
7150 /* If entry doesn't exist, nothing to do. */
7151 n
= zvni_neigh_lookup(zvni
, ip
);
7155 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7157 if (IS_ZEBRA_DEBUG_VXLAN
)
7159 "Trying to del a neigh %s without a mac %s on VNI %u",
7160 ipaddr2str(ip
, buf
, sizeof(buf
)),
7161 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7167 /* If it is a remote entry, the kernel has aged this out or someone has
7168 * deleted it, it needs to be re-installed as Quagga is the owner.
7170 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7171 zvni_neigh_install(zvni
, n
);
7175 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7177 zlog_debug("%s: VNI %u vrf lookup failed.",
7178 __PRETTY_FUNCTION__
, zvni
->vni
);
7182 /* In case of feeze action, if local neigh is in duplicate state,
7183 * Mark the Neigh as inactive before sending delete request to BGPd,
7184 * If BGPd has remote entry, it will re-install
7186 if (zvrf
->dad_freeze
&&
7187 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7188 ZEBRA_NEIGH_SET_INACTIVE(n
);
7190 /* Remove neighbor from BGP. */
7191 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7193 /* Delete this neighbor entry. */
7194 zvni_neigh_del(zvni
, n
);
7196 /* see if the AUTO mac needs to be deleted */
7197 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7198 && !listcount(zmac
->neigh_list
))
7199 zvni_mac_del(zvni
, zmac
);
7205 * Handle neighbor add or update notification from the kernel (on a VLAN
7206 * device / L3 interface). This is typically for a local neighbor but can
7207 * also be for a remote neighbor (e.g., ageout notification). It could
7208 * also be a "move" scenario.
7210 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7211 struct interface
*link_if
,
7213 struct ethaddr
*macaddr
,
7218 char buf
[ETHER_ADDR_STRLEN
];
7219 char buf2
[INET6_ADDRSTRLEN
];
7220 zebra_vni_t
*zvni
= NULL
;
7221 zebra_l3vni_t
*zl3vni
= NULL
;
7223 /* check if this is a remote neigh entry corresponding to remote
7226 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7228 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7230 /* We are only interested in neighbors on an SVI that resides on top
7231 * of a VxLAN bridge.
7233 zvni
= zvni_from_svi(ifp
, link_if
);
7237 if (IS_ZEBRA_DEBUG_VXLAN
)
7239 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7240 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7241 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7242 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7243 is_router
? "router " : "",
7246 /* Is this about a local neighbor or a remote one? */
7248 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7251 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7256 * Handle message from client to delete a remote MACIP for a VNI.
7258 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7262 struct ethaddr macaddr
;
7264 struct in_addr vtep_ip
;
7265 uint16_t l
= 0, ipa_len
;
7266 char buf
[ETHER_ADDR_STRLEN
];
7267 char buf1
[INET6_ADDRSTRLEN
];
7269 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7270 memset(&ip
, 0, sizeof(struct ipaddr
));
7271 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7275 while (l
< hdr
->length
) {
7276 /* Obtain each remote MACIP and process. */
7277 /* Message contains VNI, followed by MAC followed by IP (if any)
7278 * followed by remote VTEP IP.
7280 memset(&ip
, 0, sizeof(ip
));
7281 STREAM_GETL(s
, vni
);
7282 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7283 STREAM_GETL(s
, ipa_len
);
7285 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7287 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7289 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7290 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7291 l
+= IPV4_MAX_BYTELEN
;
7293 if (IS_ZEBRA_DEBUG_VXLAN
)
7295 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7297 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7298 ipa_len
? " IP " : "",
7300 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7302 zebra_route_string(client
->proto
));
7304 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7312 * Handle message from client to add a remote MACIP for a VNI. This
7313 * could be just the add of a MAC address or the add of a neighbor
7316 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7320 struct ethaddr macaddr
;
7322 struct in_addr vtep_ip
;
7323 uint16_t l
= 0, ipa_len
;
7326 char buf
[ETHER_ADDR_STRLEN
];
7327 char buf1
[INET6_ADDRSTRLEN
];
7329 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7330 memset(&ip
, 0, sizeof(struct ipaddr
));
7331 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7333 if (!EVPN_ENABLED(zvrf
)) {
7334 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7340 while (l
< hdr
->length
) {
7341 /* Obtain each remote MACIP and process. */
7342 /* Message contains VNI, followed by MAC followed by IP (if any)
7343 * followed by remote VTEP IP.
7345 memset(&ip
, 0, sizeof(ip
));
7346 STREAM_GETL(s
, vni
);
7347 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7348 STREAM_GETL(s
, ipa_len
);
7350 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7352 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7354 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7355 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7356 l
+= IPV4_MAX_BYTELEN
;
7358 /* Get flags - sticky mac and/or gateway mac */
7359 STREAM_GETC(s
, flags
);
7361 STREAM_GETL(s
, seq
);
7364 if (IS_ZEBRA_DEBUG_VXLAN
)
7366 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7368 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7369 ipa_len
? " IP " : "",
7371 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7372 flags
, seq
, inet_ntoa(vtep_ip
),
7373 zebra_route_string(client
->proto
));
7375 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7376 flags
, seq
, vtep_ip
);
7384 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7385 * us, this must involve a multihoming scenario. Treat this as implicit delete
7386 * of any prior local MAC.
7388 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7389 struct interface
*br_if
,
7390 struct ethaddr
*macaddr
, vlanid_t vid
)
7392 struct zebra_if
*zif
;
7393 struct zebra_l2info_vxlan
*vxl
;
7397 char buf
[ETHER_ADDR_STRLEN
];
7401 vxl
= &zif
->l2info
.vxl
;
7404 /* Check if EVPN is enabled. */
7405 if (!is_evpn_enabled())
7408 /* Locate hash entry; it is expected to exist. */
7409 zvni
= zvni_lookup(vni
);
7413 /* If entry doesn't exist, nothing to do. */
7414 mac
= zvni_mac_lookup(zvni
, macaddr
);
7418 /* Is it a local entry? */
7419 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7422 if (IS_ZEBRA_DEBUG_VXLAN
)
7424 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7425 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7428 /* Remove MAC from BGP. */
7429 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7432 * If there are no neigh associated with the mac delete the mac
7433 * else mark it as AUTO for forward reference
7435 if (!listcount(mac
->neigh_list
)) {
7436 zvni_mac_del(zvni
, mac
);
7438 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7439 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7446 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7447 * This can happen because the remote MAC entries are also added as "dynamic",
7448 * so the kernel can ageout the entry.
7450 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7451 struct interface
*br_if
,
7452 struct ethaddr
*macaddr
, vlanid_t vid
)
7454 struct zebra_if
*zif
= NULL
;
7455 struct zebra_l2info_vxlan
*vxl
= NULL
;
7457 zebra_vni_t
*zvni
= NULL
;
7458 zebra_l3vni_t
*zl3vni
= NULL
;
7459 zebra_mac_t
*mac
= NULL
;
7460 char buf
[ETHER_ADDR_STRLEN
];
7464 vxl
= &zif
->l2info
.vxl
;
7467 /* Check if EVPN is enabled. */
7468 if (!is_evpn_enabled())
7471 /* check if this is a remote RMAC and readd simillar to remote macs */
7472 zl3vni
= zl3vni_lookup(vni
);
7474 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7476 /* Locate hash entry; it is expected to exist. */
7477 zvni
= zvni_lookup(vni
);
7481 /* If entry doesn't exist, nothing to do. */
7482 mac
= zvni_mac_lookup(zvni
, macaddr
);
7486 /* Is it a remote entry? */
7487 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7490 if (IS_ZEBRA_DEBUG_VXLAN
)
7491 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7492 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7495 zvni_mac_install(zvni
, mac
);
7500 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7502 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7503 struct ethaddr
*macaddr
, vlanid_t vid
)
7507 char buf
[ETHER_ADDR_STRLEN
];
7509 /* We are interested in MACs only on ports or (port, VLAN) that
7512 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7515 if (!zvni
->vxlan_if
) {
7517 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7522 if (IS_ZEBRA_DEBUG_VXLAN
)
7523 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7524 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7525 ifp
->ifindex
, vid
, zvni
->vni
);
7527 /* If entry doesn't exist, nothing to do. */
7528 mac
= zvni_mac_lookup(zvni
, macaddr
);
7532 /* Is it a local entry? */
7533 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7536 /* Update all the neigh entries associated with this mac */
7537 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7539 /* Remove MAC from BGP. */
7540 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7543 * If there are no neigh associated with the mac delete the mac
7544 * else mark it as AUTO for forward reference
7546 if (!listcount(mac
->neigh_list
)) {
7547 zvni_mac_del(zvni
, mac
);
7549 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7550 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7557 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7559 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7560 struct interface
*br_if
,
7561 struct ethaddr
*macaddr
, vlanid_t vid
,
7566 struct zebra_vrf
*zvrf
;
7567 char buf
[ETHER_ADDR_STRLEN
];
7568 bool mac_sticky
= false;
7569 bool inform_client
= false;
7570 bool upd_neigh
= false;
7571 bool is_dup_detect
= false;
7572 struct in_addr vtep_ip
= {.s_addr
= 0};
7574 /* We are interested in MACs only on ports or (port, VLAN) that
7577 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7579 if (IS_ZEBRA_DEBUG_VXLAN
)
7581 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7582 sticky
? "sticky " : "",
7583 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7584 ifp
->name
, ifp
->ifindex
, vid
);
7588 if (!zvni
->vxlan_if
) {
7590 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7595 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7599 /* Check if we need to create or update or it is a NO-OP. */
7600 mac
= zvni_mac_lookup(zvni
, macaddr
);
7602 if (IS_ZEBRA_DEBUG_VXLAN
)
7604 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7605 sticky
? "sticky " : "",
7606 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7607 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7609 mac
= zvni_mac_add(zvni
, macaddr
);
7612 EC_ZEBRA_MAC_ADD_FAILED
,
7613 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7614 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7615 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7618 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7619 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7620 mac
->fwd_info
.local
.vid
= vid
;
7622 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7623 inform_client
= true;
7626 if (IS_ZEBRA_DEBUG_VXLAN
)
7628 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7629 sticky
? "sticky " : "",
7630 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7631 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7634 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7635 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7639 * Update any changes and if changes are relevant to
7642 if (mac_sticky
== sticky
7643 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7644 && mac
->fwd_info
.local
.vid
== vid
) {
7645 if (IS_ZEBRA_DEBUG_VXLAN
)
7647 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7648 "entry exists and has not changed ",
7649 sticky
? "sticky " : "",
7650 prefix_mac2str(macaddr
, buf
,
7652 ifp
->name
, ifp
->ifindex
, vid
,
7656 if (mac_sticky
!= sticky
) {
7658 SET_FLAG(mac
->flags
,
7661 UNSET_FLAG(mac
->flags
,
7663 inform_client
= true;
7666 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7667 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7668 mac
->fwd_info
.local
.vid
= vid
;
7670 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7671 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7672 bool do_dad
= false;
7675 * MAC has either moved or was "internally" created due
7676 * to a neighbor learn and is now actually learnt. If
7677 * it was learnt as a remote sticky MAC, this is an
7680 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7682 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7683 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7684 prefix_mac2str(macaddr
, buf
,
7686 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7691 /* If an actual move, compute MAC's seq number */
7692 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7693 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7695 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7696 /* Trigger DAD for remote MAC */
7700 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7701 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7702 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7703 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7704 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7705 mac
->fwd_info
.local
.vid
= vid
;
7707 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7709 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7711 * We have to inform BGP of this MAC as well as process
7714 inform_client
= true;
7717 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7721 if (is_dup_detect
) {
7722 inform_client
= false;
7728 /* Inform BGP if required. */
7729 if (inform_client
) {
7730 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7731 mac
->flags
, mac
->loc_seq
))
7735 /* Process all neighbors associated with this MAC, if required. */
7737 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7743 * Handle message from client to delete a remote VTEP for a VNI.
7745 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7748 unsigned short l
= 0;
7750 struct in_addr vtep_ip
;
7752 zebra_vtep_t
*zvtep
;
7753 struct interface
*ifp
;
7754 struct zebra_if
*zif
;
7756 if (!is_evpn_enabled()) {
7758 "%s: EVPN is not enabled yet we have received a vtep del command",
7759 __PRETTY_FUNCTION__
);
7763 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7764 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7771 while (l
< hdr
->length
) {
7772 /* Obtain each remote VTEP and process. */
7773 STREAM_GETL(s
, vni
);
7775 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7776 l
+= IPV4_MAX_BYTELEN
;
7778 if (IS_ZEBRA_DEBUG_VXLAN
)
7779 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7780 inet_ntoa(vtep_ip
), vni
,
7781 zebra_route_string(client
->proto
));
7783 /* Locate VNI hash entry - expected to exist. */
7784 zvni
= zvni_lookup(vni
);
7786 if (IS_ZEBRA_DEBUG_VXLAN
)
7788 "Failed to locate VNI hash upon remote VTEP DEL, "
7794 ifp
= zvni
->vxlan_if
;
7797 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7803 /* If down or not mapped to a bridge, we're done. */
7804 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7807 /* If the remote VTEP does not exist, there's nothing more to
7809 * Otherwise, uninstall any remote MACs pointing to this VTEP
7811 * then, the VTEP entry itself and remove it.
7813 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7817 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7818 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7819 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7820 zvni_vtep_del(zvni
, zvtep
);
7828 * Handle message from client to add a remote VTEP for a VNI.
7830 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7833 unsigned short l
= 0;
7835 struct in_addr vtep_ip
;
7837 struct interface
*ifp
;
7838 struct zebra_if
*zif
;
7840 if (!is_evpn_enabled()) {
7842 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7843 __PRETTY_FUNCTION__
);
7847 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7848 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7855 while (l
< hdr
->length
) {
7856 /* Obtain each remote VTEP and process. */
7857 STREAM_GETL(s
, vni
);
7859 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7860 l
+= IPV4_MAX_BYTELEN
;
7862 if (IS_ZEBRA_DEBUG_VXLAN
)
7863 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7864 inet_ntoa(vtep_ip
), vni
,
7865 zebra_route_string(client
->proto
));
7867 /* Locate VNI hash entry - expected to exist. */
7868 zvni
= zvni_lookup(vni
);
7871 EC_ZEBRA_VTEP_ADD_FAILED
,
7872 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7877 ifp
= zvni
->vxlan_if
;
7880 EC_ZEBRA_VTEP_ADD_FAILED
,
7881 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7888 /* If down or not mapped to a bridge, we're done. */
7889 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7892 /* If the remote VTEP already exists,
7893 there's nothing more to do. */
7894 if (zvni_vtep_find(zvni
, &vtep_ip
))
7897 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7898 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7899 "Failed to add remote VTEP, VNI %u zvni %p",
7904 zvni_vtep_install(zvni
, &vtep_ip
);
7912 * Add/Del gateway macip to evpn
7914 * 1. SVI interface on a vlan aware bridge
7915 * 2. SVI interface on a vlan unaware bridge
7916 * 3. vrr interface (MACVLAN) associated to a SVI
7917 * We advertise macip routes for an interface if it is associated to VxLan vlan
7919 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7923 struct ethaddr macaddr
;
7924 zebra_vni_t
*zvni
= NULL
;
7926 memset(&ip
, 0, sizeof(struct ipaddr
));
7927 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7929 /* Check if EVPN is enabled. */
7930 if (!is_evpn_enabled())
7933 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7934 struct interface
*svi_if
=
7935 NULL
; /* SVI corresponding to the MACVLAN */
7936 struct zebra_if
*ifp_zif
=
7937 NULL
; /* Zebra daemon specific info for MACVLAN */
7938 struct zebra_if
*svi_if_zif
=
7939 NULL
; /* Zebra daemon specific info for SVI*/
7941 ifp_zif
= ifp
->info
;
7946 * for a MACVLAN interface the link represents the svi_if
7948 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7949 ifp_zif
->link_ifindex
);
7951 zlog_debug("MACVLAN %s(%u) without link information",
7952 ifp
->name
, ifp
->ifindex
);
7956 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7958 * If it is a vlan aware bridge then the link gives the
7959 * bridge information
7961 struct interface
*svi_if_link
= NULL
;
7963 svi_if_zif
= svi_if
->info
;
7965 svi_if_link
= if_lookup_by_index_per_ns(
7966 zebra_ns_lookup(NS_DEFAULT
),
7967 svi_if_zif
->link_ifindex
);
7968 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7970 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7972 * If it is a vlan unaware bridge then svi is the bridge
7975 zvni
= zvni_from_svi(svi_if
, svi_if
);
7977 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7978 struct zebra_if
*svi_if_zif
=
7979 NULL
; /* Zebra daemon specific info for SVI */
7980 struct interface
*svi_if_link
=
7981 NULL
; /* link info for the SVI = bridge info */
7983 svi_if_zif
= ifp
->info
;
7985 svi_if_link
= if_lookup_by_index_per_ns(
7986 zebra_ns_lookup(NS_DEFAULT
),
7987 svi_if_zif
->link_ifindex
);
7989 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7991 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7992 zvni
= zvni_from_svi(ifp
, ifp
);
7998 if (!zvni
->vxlan_if
) {
7999 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8005 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8007 if (p
->family
== AF_INET
) {
8008 ip
.ipa_type
= IPADDR_V4
;
8009 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8010 sizeof(struct in_addr
));
8011 } else if (p
->family
== AF_INET6
) {
8012 ip
.ipa_type
= IPADDR_V6
;
8013 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8014 sizeof(struct in6_addr
));
8019 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8021 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8027 * Handle SVI interface going down.
8028 * SVI can be associated to either L3-VNI or L2-VNI.
8029 * For L2-VNI: At this point, this is a NOP since
8030 * the kernel deletes the neighbor entries on this SVI (if any).
8031 * We only need to update the vrf corresponding to zvni.
8032 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8035 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8037 zebra_l3vni_t
*zl3vni
= NULL
;
8039 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8042 /* process l3-vni down */
8043 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8045 /* remove association with svi-if */
8046 zl3vni
->svi_if
= NULL
;
8048 zebra_vni_t
*zvni
= NULL
;
8050 /* since we dont have svi corresponding to zvni, we associate it
8051 * to default vrf. Note: the corresponding neigh entries on the
8052 * SVI would have already been deleted */
8053 zvni
= zvni_from_svi(ifp
, link_if
);
8055 zvni
->vrf_id
= VRF_DEFAULT
;
8057 /* update the tenant vrf in BGP */
8058 zvni_send_add_to_client(zvni
);
8065 * Handle SVI interface coming up.
8066 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8068 * For L2-VNI: we need to install any remote neighbors entried (used for
8070 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8072 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8074 zebra_vni_t
*zvni
= NULL
;
8075 zebra_l3vni_t
*zl3vni
= NULL
;
8077 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8080 /* associate with svi */
8081 zl3vni
->svi_if
= ifp
;
8083 /* process oper-up */
8084 if (is_l3vni_oper_up(zl3vni
))
8085 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8088 /* process SVI up for l2-vni */
8089 struct neigh_walk_ctx n_wctx
;
8091 zvni
= zvni_from_svi(ifp
, link_if
);
8095 if (!zvni
->vxlan_if
) {
8097 "VNI %u hash %p doesn't have intf upon SVI up",
8102 if (IS_ZEBRA_DEBUG_VXLAN
)
8104 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8105 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8106 vrf_id_to_name(ifp
->vrf_id
));
8108 /* update the vrf information for l2-vni and inform bgp */
8109 zvni
->vrf_id
= ifp
->vrf_id
;
8110 zvni_send_add_to_client(zvni
);
8112 /* Install any remote neighbors for this VNI. */
8113 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8115 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8123 * Handle VxLAN interface down
8125 int zebra_vxlan_if_down(struct interface
*ifp
)
8128 struct zebra_if
*zif
= NULL
;
8129 struct zebra_l2info_vxlan
*vxl
= NULL
;
8130 zebra_l3vni_t
*zl3vni
= NULL
;
8133 /* Check if EVPN is enabled. */
8134 if (!is_evpn_enabled())
8139 vxl
= &zif
->l2info
.vxl
;
8142 zl3vni
= zl3vni_lookup(vni
);
8144 /* process-if-down for l3-vni */
8145 if (IS_ZEBRA_DEBUG_VXLAN
)
8146 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8149 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8151 /* process if-down for l2-vni */
8152 if (IS_ZEBRA_DEBUG_VXLAN
)
8153 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8156 /* Locate hash entry; it is expected to exist. */
8157 zvni
= zvni_lookup(vni
);
8160 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8161 ifp
->name
, ifp
->ifindex
, vni
);
8165 assert(zvni
->vxlan_if
== ifp
);
8167 /* Delete this VNI from BGP. */
8168 zvni_send_del_to_client(zvni
->vni
);
8170 /* Free up all neighbors and MACs, if any. */
8171 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8172 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8174 /* Free up all remote VTEPs, if any. */
8175 zvni_vtep_del_all(zvni
, 1);
8181 * Handle VxLAN interface up - update BGP if required.
8183 int zebra_vxlan_if_up(struct interface
*ifp
)
8186 struct zebra_if
*zif
= NULL
;
8187 struct zebra_l2info_vxlan
*vxl
= NULL
;
8188 zebra_vni_t
*zvni
= NULL
;
8189 zebra_l3vni_t
*zl3vni
= NULL
;
8191 /* Check if EVPN is enabled. */
8192 if (!is_evpn_enabled())
8197 vxl
= &zif
->l2info
.vxl
;
8200 zl3vni
= zl3vni_lookup(vni
);
8203 if (IS_ZEBRA_DEBUG_VXLAN
)
8204 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8207 /* we need to associate with SVI, if any, we can associate with
8208 * svi-if only after association with vxlan-intf is complete
8210 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8212 if (is_l3vni_oper_up(zl3vni
))
8213 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8215 /* Handle L2-VNI add */
8216 struct interface
*vlan_if
= NULL
;
8218 if (IS_ZEBRA_DEBUG_VXLAN
)
8219 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8222 /* Locate hash entry; it is expected to exist. */
8223 zvni
= zvni_lookup(vni
);
8226 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8227 ifp
->name
, ifp
->ifindex
, vni
);
8231 assert(zvni
->vxlan_if
== ifp
);
8232 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8233 zif
->brslave_info
.br_if
);
8235 zvni
->vrf_id
= vlan_if
->vrf_id
;
8236 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8238 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8241 /* If part of a bridge, inform BGP about this VNI. */
8242 /* Also, read and populate local MACs and neighbors. */
8243 if (zif
->brslave_info
.br_if
) {
8244 zvni_send_add_to_client(zvni
);
8245 zvni_read_mac_neigh(zvni
, ifp
);
8253 * Handle VxLAN interface delete. Locate and remove entry in hash table
8254 * and update BGP, if required.
8256 int zebra_vxlan_if_del(struct interface
*ifp
)
8259 struct zebra_if
*zif
= NULL
;
8260 struct zebra_l2info_vxlan
*vxl
= NULL
;
8261 zebra_vni_t
*zvni
= NULL
;
8262 zebra_l3vni_t
*zl3vni
= NULL
;
8264 /* Check if EVPN is enabled. */
8265 if (!is_evpn_enabled())
8270 vxl
= &zif
->l2info
.vxl
;
8273 zl3vni
= zl3vni_lookup(vni
);
8276 if (IS_ZEBRA_DEBUG_VXLAN
)
8277 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8280 /* process oper-down for l3-vni */
8281 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8283 /* remove the association with vxlan_if */
8284 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8285 zl3vni
->vxlan_if
= NULL
;
8288 /* process if-del for l2-vni*/
8289 if (IS_ZEBRA_DEBUG_VXLAN
)
8290 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8293 /* Locate hash entry; it is expected to exist. */
8294 zvni
= zvni_lookup(vni
);
8297 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8298 ifp
->name
, ifp
->ifindex
, vni
);
8302 /* remove from l3-vni list */
8303 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8305 listnode_delete(zl3vni
->l2vnis
, zvni
);
8307 /* Delete VNI from BGP. */
8308 zvni_send_del_to_client(zvni
->vni
);
8310 /* Free up all neighbors and MAC, if any. */
8311 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8312 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8314 /* Free up all remote VTEPs, if any. */
8315 zvni_vtep_del_all(zvni
, 0);
8317 /* Delete the hash entry. */
8318 if (zvni_del(zvni
)) {
8319 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8320 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8321 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8329 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8331 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8334 struct zebra_if
*zif
= NULL
;
8335 struct zebra_l2info_vxlan
*vxl
= NULL
;
8336 zebra_vni_t
*zvni
= NULL
;
8337 zebra_l3vni_t
*zl3vni
= NULL
;
8339 /* Check if EVPN is enabled. */
8340 if (!is_evpn_enabled())
8345 vxl
= &zif
->l2info
.vxl
;
8348 zl3vni
= zl3vni_lookup(vni
);
8351 if (IS_ZEBRA_DEBUG_VXLAN
)
8353 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8354 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8355 inet_ntoa(vxl
->vtep_ip
),
8356 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8358 /* Removed from bridge? Cleanup and return */
8359 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8360 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8361 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8365 /* access-vlan change - process oper down, associate with new
8366 * svi_if and then process oper up again
8368 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8369 if (if_is_operative(ifp
)) {
8370 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8371 zl3vni
->svi_if
= NULL
;
8372 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8373 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8374 if (is_l3vni_oper_up(zl3vni
))
8375 zebra_vxlan_process_l3vni_oper_up(
8381 * local-ip change - process oper down, associate with new
8382 * local-ip and then process oper up again
8384 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8385 if (if_is_operative(ifp
)) {
8386 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8387 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8388 if (is_l3vni_oper_up(zl3vni
))
8389 zebra_vxlan_process_l3vni_oper_up(
8394 /* Update local tunnel IP. */
8395 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8397 /* if we have a valid new master, process l3-vni oper up */
8398 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8399 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8400 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8404 /* Update VNI hash. */
8405 zvni
= zvni_lookup(vni
);
8408 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8409 ifp
->name
, ifp
->ifindex
, vni
);
8413 if (IS_ZEBRA_DEBUG_VXLAN
)
8415 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8416 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8417 inet_ntoa(vxl
->vtep_ip
),
8418 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8420 /* Removed from bridge? Cleanup and return */
8421 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8422 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8423 /* Delete from client, remove all remote VTEPs */
8424 /* Also, free up all MACs and neighbors. */
8425 zvni_send_del_to_client(zvni
->vni
);
8426 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8427 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8428 zvni_vtep_del_all(zvni
, 1);
8432 /* Handle other changes. */
8433 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8434 /* Remove all existing local neigh and MACs for this VNI
8435 * (including from BGP)
8437 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8438 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8441 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8442 zvni
->vxlan_if
= ifp
;
8444 /* Take further actions needed.
8445 * Note that if we are here, there is a change of interest.
8447 /* If down or not mapped to a bridge, we're done. */
8448 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8451 /* Inform BGP, if there is a change of interest. */
8453 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8454 zvni_send_add_to_client(zvni
);
8456 /* If there is a valid new master or a VLAN mapping change,
8457 * read and populate local MACs and neighbors.
8458 * Also, reinstall any remote MACs and neighbors
8459 * for this VNI (based on new VLAN).
8461 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8462 zvni_read_mac_neigh(zvni
, ifp
);
8463 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8464 struct mac_walk_ctx m_wctx
;
8465 struct neigh_walk_ctx n_wctx
;
8467 zvni_read_mac_neigh(zvni
, ifp
);
8469 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8471 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8474 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8476 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8485 * Handle VxLAN interface add.
8487 int zebra_vxlan_if_add(struct interface
*ifp
)
8490 struct zebra_if
*zif
= NULL
;
8491 struct zebra_l2info_vxlan
*vxl
= NULL
;
8492 zebra_vni_t
*zvni
= NULL
;
8493 zebra_l3vni_t
*zl3vni
= NULL
;
8495 /* Check if EVPN is enabled. */
8496 if (!is_evpn_enabled())
8501 vxl
= &zif
->l2info
.vxl
;
8504 zl3vni
= zl3vni_lookup(vni
);
8507 /* process if-add for l3-vni*/
8508 if (IS_ZEBRA_DEBUG_VXLAN
)
8510 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8511 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8512 inet_ntoa(vxl
->vtep_ip
),
8513 zif
->brslave_info
.bridge_ifindex
);
8515 /* associate with vxlan_if */
8516 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8517 zl3vni
->vxlan_if
= ifp
;
8519 /* Associate with SVI, if any. We can associate with svi-if only
8520 * after association with vxlan_if is complete */
8521 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8523 if (is_l3vni_oper_up(zl3vni
))
8524 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8527 /* process if-add for l2-vni */
8528 struct interface
*vlan_if
= NULL
;
8530 /* Create or update VNI hash. */
8531 zvni
= zvni_lookup(vni
);
8533 zvni
= zvni_add(vni
);
8536 EC_ZEBRA_VNI_ADD_FAILED
,
8537 "Failed to add VNI hash, IF %s(%u) VNI %u",
8538 ifp
->name
, ifp
->ifindex
, vni
);
8543 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8544 zvni
->vxlan_if
= ifp
;
8545 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8546 zif
->brslave_info
.br_if
);
8548 zvni
->vrf_id
= vlan_if
->vrf_id
;
8549 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8551 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8554 if (IS_ZEBRA_DEBUG_VXLAN
)
8556 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8558 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8560 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8561 inet_ntoa(vxl
->vtep_ip
),
8562 zif
->brslave_info
.bridge_ifindex
);
8564 /* If down or not mapped to a bridge, we're done. */
8565 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8569 zvni_send_add_to_client(zvni
);
8571 /* Read and populate local MACs and neighbors */
8572 zvni_read_mac_neigh(zvni
, ifp
);
8578 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8579 char *err
, int err_str_sz
, int filter
,
8582 zebra_l3vni_t
*zl3vni
= NULL
;
8583 struct zebra_vrf
*zvrf_default
= NULL
;
8585 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8589 if (IS_ZEBRA_DEBUG_VXLAN
)
8590 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8591 add
? "ADD" : "DEL");
8595 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8597 /* check if the vni is already present under zvrf */
8599 snprintf(err
, err_str_sz
,
8600 "VNI is already configured under the vrf");
8604 /* check if this VNI is already present in the system */
8605 zl3vni
= zl3vni_lookup(vni
);
8607 snprintf(err
, err_str_sz
,
8608 "VNI is already configured as L3-VNI");
8612 /* add the L3-VNI to the global table */
8613 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8615 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8619 /* associate the vrf with vni */
8622 /* set the filter in l3vni to denote if we are using l3vni only
8626 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8628 /* associate with vxlan-intf;
8629 * we need to associate with the vxlan-intf first
8631 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8633 /* associate with corresponding SVI interface, we can associate
8634 * with svi-if only after vxlan interface association is
8637 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8639 /* formulate l2vni list */
8640 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8643 if (is_l3vni_oper_up(zl3vni
))
8644 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8647 zl3vni
= zl3vni_lookup(vni
);
8649 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8653 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8654 snprintf(err
, ERR_STR_SZ
,
8655 "prefix-routes-only is not set for the vni");
8659 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8661 /* delete and uninstall all rmacs */
8662 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8665 /* delete and uninstall all next-hops */
8666 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8672 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8677 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8679 zebra_l3vni_t
*zl3vni
= NULL
;
8682 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8686 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8687 if (is_l3vni_oper_up(zl3vni
))
8688 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8692 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8694 zebra_l3vni_t
*zl3vni
= NULL
;
8697 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8701 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8702 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8706 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8708 zebra_l3vni_t
*zl3vni
= NULL
;
8712 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8718 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8724 * Handle message from client to specify the flooding mechanism for
8725 * BUM packets. The default is to do head-end (ingress) replication
8726 * and the other supported option is to disable it. This applies to
8727 * all BUM traffic and disabling it applies to both the transmit and
8728 * receive direction.
8730 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8733 enum vxlan_flood_control flood_ctrl
;
8735 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8736 zlog_err("EVPN flood control for non-default VRF %u",
8742 STREAM_GETC(s
, flood_ctrl
);
8744 if (IS_ZEBRA_DEBUG_VXLAN
)
8745 zlog_debug("EVPN flood control %u, currently %u",
8746 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8748 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8751 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8753 /* Install or uninstall flood entries corresponding to
8756 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8764 * Handle message from client to enable/disable advertisement of svi macip
8767 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8772 zebra_vni_t
*zvni
= NULL
;
8773 struct interface
*ifp
= NULL
;
8775 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8776 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8782 STREAM_GETC(s
, advertise
);
8783 STREAM_GETL(s
, vni
);
8786 if (IS_ZEBRA_DEBUG_VXLAN
)
8787 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8788 advertise
? "enabled" : "disabled",
8789 advertise_gw_macip_enabled(NULL
)
8793 if (zvrf
->advertise_svi_macip
== advertise
)
8798 zvrf
->advertise_svi_macip
= advertise
;
8799 hash_iterate(zvrf
->vni_table
,
8800 zvni_gw_macip_add_for_vni_hash
, NULL
);
8802 hash_iterate(zvrf
->vni_table
,
8803 zvni_svi_macip_del_for_vni_hash
, NULL
);
8804 zvrf
->advertise_svi_macip
= advertise
;
8808 struct zebra_if
*zif
= NULL
;
8809 struct zebra_l2info_vxlan zl2_info
;
8810 struct interface
*vlan_if
= NULL
;
8812 zvni
= zvni_lookup(vni
);
8816 if (IS_ZEBRA_DEBUG_VXLAN
)
8818 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8819 advertise
? "enabled" : "disabled", vni
,
8820 advertise_svi_macip_enabled(zvni
)
8824 if (zvni
->advertise_svi_macip
== advertise
)
8827 ifp
= zvni
->vxlan_if
;
8833 /* If down or not mapped to a bridge, we're done. */
8834 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8837 zl2_info
= zif
->l2info
.vxl
;
8839 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8840 zif
->brslave_info
.br_if
);
8845 zvni
->advertise_svi_macip
= advertise
;
8846 /* Add primary SVI MAC-IP */
8847 zvni_add_macip_for_intf(vlan_if
, zvni
);
8849 /* Del primary MAC-IP */
8850 zvni_del_macip_for_intf(vlan_if
, zvni
);
8851 zvni
->advertise_svi_macip
= advertise
;
8860 * Handle message from client to enable/disable advertisement of g/w macip
8863 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8868 zebra_vni_t
*zvni
= NULL
;
8869 struct interface
*ifp
= NULL
;
8870 struct zebra_if
*zif
= NULL
;
8871 struct zebra_l2info_vxlan zl2_info
;
8872 struct interface
*vlan_if
= NULL
;
8874 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8875 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8881 STREAM_GETC(s
, advertise
);
8882 vni
= stream_get3(s
);
8884 zvni
= zvni_lookup(vni
);
8888 if (zvni
->advertise_subnet
== advertise
)
8891 if (IS_ZEBRA_DEBUG_VXLAN
)
8892 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8893 advertise
? "enabled" : "disabled", vni
,
8894 zvni
->advertise_subnet
? "enabled" : "disabled");
8897 zvni
->advertise_subnet
= advertise
;
8899 ifp
= zvni
->vxlan_if
;
8905 /* If down or not mapped to a bridge, we're done. */
8906 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8909 zl2_info
= zif
->l2info
.vxl
;
8912 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8916 if (zvni
->advertise_subnet
)
8917 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8919 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8926 * Handle message from client to enable/disable advertisement of g/w macip
8929 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8934 zebra_vni_t
*zvni
= NULL
;
8935 struct interface
*ifp
= NULL
;
8937 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8938 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8944 STREAM_GETC(s
, advertise
);
8945 STREAM_GETL(s
, vni
);
8948 if (IS_ZEBRA_DEBUG_VXLAN
)
8949 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8950 advertise
? "enabled" : "disabled",
8951 advertise_gw_macip_enabled(NULL
)
8955 if (zvrf
->advertise_gw_macip
== advertise
)
8958 zvrf
->advertise_gw_macip
= advertise
;
8960 if (advertise_gw_macip_enabled(zvni
))
8961 hash_iterate(zvrf
->vni_table
,
8962 zvni_gw_macip_add_for_vni_hash
, NULL
);
8964 hash_iterate(zvrf
->vni_table
,
8965 zvni_gw_macip_del_for_vni_hash
, NULL
);
8968 struct zebra_if
*zif
= NULL
;
8969 struct zebra_l2info_vxlan zl2_info
;
8970 struct interface
*vlan_if
= NULL
;
8971 struct interface
*vrr_if
= NULL
;
8973 zvni
= zvni_lookup(vni
);
8977 if (IS_ZEBRA_DEBUG_VXLAN
)
8979 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8980 advertise
? "enabled" : "disabled", vni
,
8981 advertise_gw_macip_enabled(zvni
) ? "enabled"
8984 if (zvni
->advertise_gw_macip
== advertise
)
8987 zvni
->advertise_gw_macip
= advertise
;
8989 ifp
= zvni
->vxlan_if
;
8995 /* If down or not mapped to a bridge, we're done. */
8996 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8999 zl2_info
= zif
->l2info
.vxl
;
9001 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9002 zif
->brslave_info
.br_if
);
9006 if (advertise_gw_macip_enabled(zvni
)) {
9007 /* Add primary SVI MAC-IP */
9008 zvni_add_macip_for_intf(vlan_if
, zvni
);
9010 /* Add VRR MAC-IP - if any*/
9011 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9013 zvni_add_macip_for_intf(vrr_if
, zvni
);
9015 /* Del primary MAC-IP */
9016 zvni_del_macip_for_intf(vlan_if
, zvni
);
9018 /* Del VRR MAC-IP - if any*/
9019 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9021 zvni_del_macip_for_intf(vrr_if
, zvni
);
9031 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9032 * When enabled, the VNI hash table will be built and MAC FDB table read;
9033 * when disabled, the entries should be deleted and remote VTEPs and MACs
9034 * uninstalled from the kernel.
9035 * This also informs the setting for BUM handling at the time this change
9036 * occurs; it is relevant only when specifying "learn".
9038 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9040 struct stream
*s
= NULL
;
9042 enum vxlan_flood_control flood_ctrl
;
9044 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
9045 zlog_debug("EVPN VNI Adv for non-default VRF %u",
9051 STREAM_GETC(s
, advertise
);
9052 STREAM_GETC(s
, flood_ctrl
);
9054 if (IS_ZEBRA_DEBUG_VXLAN
)
9055 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
9056 advertise
? "enabled" : "disabled",
9057 is_evpn_enabled() ? "enabled" : "disabled",
9060 if (zvrf
->advertise_all_vni
== advertise
)
9063 zvrf
->advertise_all_vni
= advertise
;
9064 if (is_evpn_enabled()) {
9065 /* Note BUM handling */
9066 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9068 /* Build VNI hash table and inform BGP. */
9069 zvni_build_hash_table();
9071 /* Add all SVI (L3 GW) MACs to BGP*/
9072 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9075 /* Read the MAC FDB */
9076 macfdb_read(zvrf
->zns
);
9078 /* Read neighbors */
9079 neigh_read(zvrf
->zns
);
9081 /* Cleanup VTEPs for all VNIs - uninstall from
9082 * kernel and free entries.
9084 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9086 /* cleanup all l3vnis */
9087 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9095 * Allocate VNI hash table for this VRF and do other initialization.
9096 * NOTE: Currently supported only for default VRF.
9098 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9102 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9103 "Zebra VRF VNI Table");
9106 /* Cleanup VNI info, but don't free the table. */
9107 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9111 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9114 /* Close all VNI handling */
9115 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9119 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9120 hash_free(zvrf
->vni_table
);
9123 /* init the l3vni table */
9124 void zebra_vxlan_init(void)
9126 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9127 "Zebra VRF L3 VNI table");
9130 /* free l3vni table */
9131 void zebra_vxlan_disable(void)
9133 hash_free(zrouter
.l3vni_table
);
9136 /* get the l3vni svi ifindex */
9137 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9139 zebra_l3vni_t
*zl3vni
= NULL
;
9141 zl3vni
= zl3vni_from_vrf(vrf_id
);
9142 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9145 return zl3vni
->svi_if
->ifindex
;
9148 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9150 struct zebra_vrf
*zvrf
= NULL
;
9151 zebra_neigh_t
*nbr
= NULL
;
9152 zebra_vni_t
*zvni
= NULL
;
9153 char buf1
[INET6_ADDRSTRLEN
];
9154 char buf2
[ETHER_ADDR_STRLEN
];
9156 nbr
= THREAD_ARG(t
);
9158 /* since this is asynchronous we need sanity checks*/
9159 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9163 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9167 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
9171 if (IS_ZEBRA_DEBUG_VXLAN
)
9172 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9173 __PRETTY_FUNCTION__
,
9174 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
9175 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
9177 nbr
->dad_count
, zvni
->vni
);
9179 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9181 nbr
->detect_start_time
.tv_sec
= 0;
9182 nbr
->detect_start_time
.tv_usec
= 0;
9183 nbr
->dad_dup_detect_time
= 0;
9184 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9187 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9188 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9189 nbr
->flags
, nbr
->loc_seq
);
9190 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9191 zvni_neigh_install(zvni
, nbr
);
9197 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9199 struct zebra_vrf
*zvrf
= NULL
;
9200 zebra_mac_t
*mac
= NULL
;
9201 zebra_vni_t
*zvni
= NULL
;
9202 struct listnode
*node
= NULL
;
9203 zebra_neigh_t
*nbr
= NULL
;
9204 char buf
[ETHER_ADDR_STRLEN
];
9206 mac
= THREAD_ARG(t
);
9208 /* since this is asynchronous we need sanity checks*/
9209 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9213 zvni
= zvni_lookup(mac
->zvni
->vni
);
9217 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
9221 if (IS_ZEBRA_DEBUG_VXLAN
)
9222 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9223 __PRETTY_FUNCTION__
,
9224 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9227 listcount(mac
->neigh_list
));
9229 /* Remove all IPs as duplicate associcated with this MAC */
9230 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9231 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9232 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9233 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9234 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9235 zvni_neigh_install(zvni
, nbr
);
9238 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9240 nbr
->detect_start_time
.tv_sec
= 0;
9241 nbr
->dad_dup_detect_time
= 0;
9244 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9246 mac
->detect_start_time
.tv_sec
= 0;
9247 mac
->detect_start_time
.tv_usec
= 0;
9248 mac
->dad_dup_detect_time
= 0;
9249 mac
->dad_mac_auto_recovery_timer
= NULL
;
9251 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9253 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9254 mac
->flags
, mac
->loc_seq
))
9257 /* Process all neighbors associated with this MAC. */
9258 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9260 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9261 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9263 /* Install the entry. */
9264 zvni_mac_install(zvni
, mac
);