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
);
2219 XFREE(MTYPE_NEIGH
, tmp_n
);
2225 * Free neighbor hash entry (callback)
2227 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2229 struct neigh_walk_ctx
*wctx
= arg
;
2230 zebra_neigh_t
*n
= bucket
->data
;
2232 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2233 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2234 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2235 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2236 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2237 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2238 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2239 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2240 &n
->emac
, 0, n
->state
);
2242 if (wctx
->uninstall
)
2243 zvni_neigh_uninstall(wctx
->zvni
, n
);
2245 zvni_neigh_del(wctx
->zvni
, n
);
2252 * Delete all neighbor entries from specific VTEP for a particular VNI.
2254 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2255 struct in_addr
*r_vtep_ip
)
2257 struct neigh_walk_ctx wctx
;
2259 if (!zvni
->neigh_table
)
2262 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2264 wctx
.uninstall
= uninstall
;
2265 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2266 wctx
.r_vtep_ip
= *r_vtep_ip
;
2268 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2272 * Delete all neighbor entries for this VNI.
2274 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2277 struct neigh_walk_ctx wctx
;
2279 if (!zvni
->neigh_table
)
2282 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2284 wctx
.uninstall
= uninstall
;
2285 wctx
.upd_client
= upd_client
;
2288 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2292 * Look up neighbor hash entry.
2294 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2299 memset(&tmp
, 0, sizeof(tmp
));
2300 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2301 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2307 * Process all neighbors associated with a MAC upon the MAC being learnt
2308 * locally or undergoing any other change (such as sequence number).
2310 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2314 zebra_neigh_t
*n
= NULL
;
2315 struct listnode
*node
= NULL
;
2316 struct zebra_vrf
*zvrf
= NULL
;
2317 char buf
[ETHER_ADDR_STRLEN
];
2319 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2321 if (IS_ZEBRA_DEBUG_VXLAN
)
2322 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2323 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2324 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2326 /* Walk all neighbors and mark any inactive local neighbors as
2327 * active and/or update sequence number upon a move, and inform BGP.
2328 * The action for remote neighbors is TBD.
2329 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2330 * accidentally end up deleting a just-learnt local neighbor.
2332 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2333 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2334 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2335 ZEBRA_NEIGH_SET_ACTIVE(n
);
2336 n
->loc_seq
= zmac
->loc_seq
;
2337 if (!(zvrf
->dup_addr_detect
&&
2338 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2339 ZEBRA_NEIGH_DUPLICATE
)))
2340 zvni_neigh_send_add_to_client(
2341 zvni
->vni
, &n
->ip
, &n
->emac
,
2342 n
->flags
, n
->loc_seq
);
2349 * Process all neighbors associated with a local MAC upon the MAC being
2352 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2355 zebra_neigh_t
*n
= NULL
;
2356 struct listnode
*node
= NULL
;
2357 char buf
[ETHER_ADDR_STRLEN
];
2359 if (IS_ZEBRA_DEBUG_VXLAN
)
2360 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2361 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2364 /* Walk all local neighbors and mark as inactive and inform
2366 * TBD: There is currently no handling for remote neighbors. We
2367 * don't expect them to exist, if they do, do we install the MAC
2368 * as a remote MAC and the neighbor as remote?
2370 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2371 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2372 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2373 ZEBRA_NEIGH_SET_INACTIVE(n
);
2375 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2376 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2383 * Process all neighbors associated with a MAC upon the MAC being remotely
2386 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2389 zebra_neigh_t
*n
= NULL
;
2390 struct listnode
*node
= NULL
;
2391 char buf
[ETHER_ADDR_STRLEN
];
2393 if (IS_ZEBRA_DEBUG_VXLAN
)
2394 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2395 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2398 /* Walk all local neighbors and mark as inactive and inform
2401 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2402 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2403 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2404 ZEBRA_NEIGH_SET_INACTIVE(n
);
2406 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2407 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2414 * Process all neighbors associated with a remote MAC upon the MAC being
2417 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2420 /* NOTE: Currently a NO-OP. */
2423 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2425 zebra_neigh_t
*nbr
= NULL
;
2426 struct listnode
*node
= NULL
;
2428 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2429 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2430 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2431 zvni_neigh_probe(zvni
, nbr
);
2436 * Inform BGP about local neighbor addition.
2438 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2439 struct ethaddr
*macaddr
,
2440 uint8_t neigh_flags
,
2445 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2446 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2447 /* Set router flag (R-bit) based on local neigh entry add */
2448 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2449 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2451 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2452 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2456 * Inform BGP about local neighbor deletion.
2458 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2459 struct ethaddr
*macaddr
, uint8_t flags
,
2462 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2463 0, state
, ZEBRA_MACIP_DEL
);
2467 * Install remote neighbor into the kernel.
2469 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2471 struct zebra_if
*zif
;
2472 struct zebra_l2info_vxlan
*vxl
;
2473 struct interface
*vlan_if
;
2479 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2482 zif
= zvni
->vxlan_if
->info
;
2485 vxl
= &zif
->l2info
.vxl
;
2487 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2491 flags
= NTF_EXT_LEARNED
;
2492 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2493 flags
|= NTF_ROUTER
;
2494 ZEBRA_NEIGH_SET_ACTIVE(n
);
2495 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2501 * Uninstall remote neighbor from the kernel.
2503 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2505 struct zebra_if
*zif
;
2506 struct zebra_l2info_vxlan
*vxl
;
2507 struct interface
*vlan_if
;
2509 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2512 if (!zvni
->vxlan_if
) {
2513 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2518 zif
= zvni
->vxlan_if
->info
;
2521 vxl
= &zif
->l2info
.vxl
;
2522 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2526 ZEBRA_NEIGH_SET_INACTIVE(n
);
2528 return kernel_del_neigh(vlan_if
, &n
->ip
);
2532 * Probe neighbor from the kernel.
2534 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2536 struct zebra_if
*zif
;
2537 struct zebra_l2info_vxlan
*vxl
;
2538 struct interface
*vlan_if
;
2540 zif
= zvni
->vxlan_if
->info
;
2543 vxl
= &zif
->l2info
.vxl
;
2545 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2550 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2558 * Install neighbor hash entry - called upon access VLAN change.
2560 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2563 struct neigh_walk_ctx
*wctx
= ctxt
;
2565 n
= (zebra_neigh_t
*)bucket
->data
;
2567 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2568 zvni_neigh_install(wctx
->zvni
, n
);
2571 /* Get the VRR interface for SVI if any */
2572 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2574 struct zebra_vrf
*zvrf
= NULL
;
2575 struct interface
*tmp_if
= NULL
;
2576 struct zebra_if
*zif
= NULL
;
2578 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2581 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2586 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2589 if (zif
->link
== ifp
)
2596 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2598 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2599 struct connected
*c
= NULL
;
2600 struct ethaddr macaddr
;
2602 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2604 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2607 memset(&ip
, 0, sizeof(struct ipaddr
));
2608 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2611 if (c
->address
->family
== AF_INET
) {
2612 ip
.ipa_type
= IPADDR_V4
;
2613 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2614 sizeof(struct in_addr
));
2615 } else if (c
->address
->family
== AF_INET6
) {
2616 ip
.ipa_type
= IPADDR_V6
;
2617 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2618 sizeof(struct in6_addr
));
2623 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2629 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2631 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2632 struct connected
*c
= NULL
;
2633 struct ethaddr macaddr
;
2635 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2637 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2640 memset(&ip
, 0, sizeof(struct ipaddr
));
2641 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2644 if (c
->address
->family
== AF_INET
) {
2645 ip
.ipa_type
= IPADDR_V4
;
2646 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2647 sizeof(struct in_addr
));
2648 } else if (c
->address
->family
== AF_INET6
) {
2649 ip
.ipa_type
= IPADDR_V6
;
2650 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2651 sizeof(struct in6_addr
));
2656 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2662 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2665 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2666 struct connected
*c
= NULL
;
2667 struct ethaddr macaddr
;
2669 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2671 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2674 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2676 /* skip link local address */
2677 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2682 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2683 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2685 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2686 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2692 * zvni_gw_macip_add_to_client
2694 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2695 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2697 char buf
[ETHER_ADDR_STRLEN
];
2698 char buf2
[INET6_ADDRSTRLEN
];
2699 zebra_neigh_t
*n
= NULL
;
2700 zebra_mac_t
*mac
= NULL
;
2701 struct zebra_if
*zif
= NULL
;
2702 struct zebra_l2info_vxlan
*vxl
= NULL
;
2704 zif
= zvni
->vxlan_if
->info
;
2708 vxl
= &zif
->l2info
.vxl
;
2710 mac
= zvni_mac_lookup(zvni
, macaddr
);
2712 mac
= zvni_mac_add(zvni
, macaddr
);
2714 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2715 "Failed to add MAC %s intf %s(%u) VID %u",
2716 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2717 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2722 /* Set "local" forwarding info. */
2723 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2724 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2725 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2726 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2727 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2728 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2730 n
= zvni_neigh_lookup(zvni
, ip
);
2732 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2735 EC_ZEBRA_MAC_ADD_FAILED
,
2736 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2737 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2738 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2739 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2744 /* Set "local" forwarding info. */
2745 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2746 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2747 ZEBRA_NEIGH_SET_ACTIVE(n
);
2748 /* Set Router flag (R-bit) */
2749 if (ip
->ipa_type
== IPADDR_V6
)
2750 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2751 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2752 n
->ifindex
= ifp
->ifindex
;
2754 /* Only advertise in BGP if the knob is enabled */
2755 if (!advertise_gw_macip_enabled(zvni
))
2758 if (IS_ZEBRA_DEBUG_VXLAN
)
2760 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2761 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2762 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2763 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2765 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2766 n
->flags
, n
->loc_seq
);
2772 * zvni_gw_macip_del_from_client
2774 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2777 char buf1
[ETHER_ADDR_STRLEN
];
2778 char buf2
[INET6_ADDRSTRLEN
];
2779 zebra_neigh_t
*n
= NULL
;
2780 zebra_mac_t
*mac
= NULL
;
2782 /* If the neigh entry is not present nothing to do*/
2783 n
= zvni_neigh_lookup(zvni
, ip
);
2787 /* mac entry should be present */
2788 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2790 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2791 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2792 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2796 /* If the entry is not local nothing to do*/
2797 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2800 /* only need to delete the entry from bgp if we sent it before */
2801 if (IS_ZEBRA_DEBUG_VXLAN
)
2803 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2804 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2805 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2806 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2808 /* Remove neighbor from BGP. */
2809 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2810 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2812 /* Delete this neighbor entry. */
2813 zvni_neigh_del(zvni
, n
);
2815 /* see if the mac needs to be deleted as well*/
2817 zvni_deref_ip2mac(zvni
, mac
);
2822 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2825 zebra_vni_t
*zvni
= NULL
;
2826 struct zebra_if
*zif
= NULL
;
2827 struct zebra_l2info_vxlan zl2_info
;
2828 struct interface
*vlan_if
= NULL
;
2829 struct interface
*vrr_if
= NULL
;
2830 struct interface
*ifp
;
2832 /* Add primary SVI MAC*/
2833 zvni
= (zebra_vni_t
*)bucket
->data
;
2835 ifp
= zvni
->vxlan_if
;
2840 /* If down or not mapped to a bridge, we're done. */
2841 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2844 zl2_info
= zif
->l2info
.vxl
;
2847 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2851 /* Del primary MAC-IP */
2852 zvni_del_macip_for_intf(vlan_if
, zvni
);
2854 /* Del VRR MAC-IP - if any*/
2855 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2857 zvni_del_macip_for_intf(vrr_if
, zvni
);
2862 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2865 zebra_vni_t
*zvni
= NULL
;
2866 struct zebra_if
*zif
= NULL
;
2867 struct zebra_l2info_vxlan zl2_info
;
2868 struct interface
*vlan_if
= NULL
;
2869 struct interface
*vrr_if
= NULL
;
2870 struct interface
*ifp
= NULL
;
2872 zvni
= (zebra_vni_t
*)bucket
->data
;
2874 ifp
= zvni
->vxlan_if
;
2879 /* If down or not mapped to a bridge, we're done. */
2880 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2882 zl2_info
= zif
->l2info
.vxl
;
2885 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2889 /* Add primary SVI MAC-IP */
2890 zvni_add_macip_for_intf(vlan_if
, zvni
);
2892 if (advertise_gw_macip_enabled(zvni
)) {
2893 /* Add VRR MAC-IP - if any*/
2894 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2896 zvni_add_macip_for_intf(vrr_if
, zvni
);
2902 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2905 zebra_vni_t
*zvni
= NULL
;
2906 struct zebra_if
*zif
= NULL
;
2907 struct zebra_l2info_vxlan zl2_info
;
2908 struct interface
*vlan_if
= NULL
;
2909 struct interface
*ifp
;
2911 /* Add primary SVI MAC*/
2912 zvni
= (zebra_vni_t
*)bucket
->data
;
2916 ifp
= zvni
->vxlan_if
;
2921 /* If down or not mapped to a bridge, we're done. */
2922 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2925 zl2_info
= zif
->l2info
.vxl
;
2927 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2928 zif
->brslave_info
.br_if
);
2932 /* Del primary MAC-IP */
2933 zvni_del_macip_for_intf(vlan_if
, zvni
);
2938 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2939 struct interface
*ifp
,
2941 struct ethaddr
*macaddr
,
2944 char buf
[ETHER_ADDR_STRLEN
];
2945 char buf2
[INET6_ADDRSTRLEN
];
2946 struct zebra_vrf
*zvrf
;
2947 zebra_neigh_t
*n
= NULL
;
2948 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2949 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2950 bool upd_mac_seq
= false;
2951 bool neigh_mac_change
= false;
2952 bool neigh_on_hold
= false;
2953 bool neigh_was_remote
= false;
2954 bool do_dad
= false;
2955 struct in_addr vtep_ip
= {.s_addr
= 0};
2957 /* Check if the MAC exists. */
2958 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2960 /* create a dummy MAC if the MAC is not already present */
2961 if (IS_ZEBRA_DEBUG_VXLAN
)
2963 "AUTO MAC %s created for neigh %s on VNI %u",
2964 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2965 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2967 zmac
= zvni_mac_add(zvni
, macaddr
);
2969 zlog_debug("Failed to add MAC %s VNI %u",
2970 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2975 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2976 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2977 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2979 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2981 * We don't change the MAC to local upon a neighbor
2982 * learn event, we wait for the explicit local MAC
2983 * learn. However, we have to compute its sequence
2984 * number in preparation for when it actually turns
2991 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2995 /* Check if the neighbor exists. */
2996 n
= zvni_neigh_lookup(zvni
, ip
);
2998 /* New neighbor - create */
2999 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3002 EC_ZEBRA_MAC_ADD_FAILED
,
3003 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3004 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3005 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3006 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3009 /* Set "local" forwarding info. */
3010 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3011 n
->ifindex
= ifp
->ifindex
;
3013 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3017 /* Note any changes and see if of interest to BGP. */
3018 mac_different
= (memcmp(n
->emac
.octet
,
3019 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3020 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3021 ZEBRA_NEIGH_ROUTER_FLAG
);
3022 if (!mac_different
&& is_router
== cur_is_router
) {
3023 n
->ifindex
= ifp
->ifindex
;
3027 if (!mac_different
) {
3028 bool is_neigh_freezed
= false;
3030 /* Only the router flag has changed. */
3033 ZEBRA_NEIGH_ROUTER_FLAG
);
3035 UNSET_FLAG(n
->flags
,
3036 ZEBRA_NEIGH_ROUTER_FLAG
);
3038 /* Neigh is in freeze state and freeze action
3039 * is enabled, do not send update to client.
3041 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3043 CHECK_FLAG(n
->flags
,
3044 ZEBRA_NEIGH_DUPLICATE
));
3046 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3048 return zvni_neigh_send_add_to_client(
3049 zvni
->vni
, ip
, macaddr
,
3050 n
->flags
, n
->loc_seq
);
3054 /* The MAC has changed, need to issue a delete
3055 * first as this means a different MACIP route.
3056 * Also, need to do some unlinking/relinking.
3057 * We also need to update the MAC's sequence number
3058 * in different situations.
3060 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3061 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3062 &n
->emac
, 0, n
->state
);
3063 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3065 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3067 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3068 neigh_mac_change
= upd_mac_seq
= true;
3069 listnode_delete(old_zmac
->neigh_list
, n
);
3070 zvni_deref_ip2mac(zvni
, old_zmac
);
3073 /* Update the forwarding info. */
3074 n
->ifindex
= ifp
->ifindex
;
3075 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3077 /* Link to new MAC */
3078 listnode_add_sort(zmac
->neigh_list
, n
);
3079 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3081 * Neighbor has moved from remote to local. Its
3082 * MAC could have also changed as part of the move.
3084 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3086 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3088 old_mac_seq
= CHECK_FLAG(
3093 neigh_mac_change
= upd_mac_seq
= true;
3094 listnode_delete(old_zmac
->neigh_list
,
3096 zvni_deref_ip2mac(zvni
, old_zmac
);
3099 /* Link to new MAC */
3100 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3101 listnode_add_sort(zmac
->neigh_list
, n
);
3103 /* Based on Mobility event Scenario-B from the
3104 * draft, neigh's previous state was remote treat this
3107 neigh_was_remote
= true;
3108 vtep_ip
= n
->r_vtep_ip
;
3109 /* Mark appropriately */
3110 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3111 n
->r_vtep_ip
.s_addr
= 0;
3112 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3113 n
->ifindex
= ifp
->ifindex
;
3117 /* If MAC was previously remote, or the neighbor had a different
3118 * MAC earlier, recompute the sequence number.
3121 uint32_t seq1
, seq2
;
3123 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3124 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3125 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3126 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3127 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3130 /* Mark Router flag (R-bit) */
3132 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3134 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3136 /* Check old and/or new MAC detected as duplicate mark
3137 * the neigh as duplicate
3139 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3140 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3141 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3143 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3144 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3147 /* For IP Duplicate Address Detection (DAD) is trigger,
3148 * when the event is extended mobility based on scenario-B
3149 * from the draft, IP/Neigh's MAC binding changed and
3150 * neigh's previous state was remote.
3152 if (neigh_mac_change
&& neigh_was_remote
)
3155 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3156 &neigh_on_hold
, true);
3158 /* Before we program this in BGP, we need to check if MAC is locally
3159 * learnt. If not, force neighbor to be inactive and reset its seq.
3161 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3162 ZEBRA_NEIGH_SET_INACTIVE(n
);
3164 zmac
->loc_seq
= mac_new_seq
;
3168 /* If the MAC's sequence number has changed, inform the MAC and all
3169 * neighbors associated with the MAC to BGP, else just inform this
3172 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3173 if (IS_ZEBRA_DEBUG_VXLAN
)
3174 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3175 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3176 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3177 zmac
->loc_seq
= mac_new_seq
;
3178 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3179 zmac
->flags
, zmac
->loc_seq
))
3181 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3185 ZEBRA_NEIGH_SET_ACTIVE(n
);
3186 n
->loc_seq
= zmac
->loc_seq
;
3189 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3190 n
->flags
, n
->loc_seq
);
3194 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3195 struct interface
*ifp
,
3197 struct ethaddr
*macaddr
,
3200 char buf
[ETHER_ADDR_STRLEN
];
3201 char buf2
[INET6_ADDRSTRLEN
];
3202 zebra_neigh_t
*n
= NULL
;
3203 zebra_mac_t
*zmac
= NULL
;
3205 /* If the neighbor is unknown, there is no further action. */
3206 n
= zvni_neigh_lookup(zvni
, ip
);
3210 /* If a remote entry, see if it needs to be refreshed */
3211 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3213 if (state
& NUD_STALE
)
3214 zvni_neigh_install(zvni
, n
);
3217 /* We got a "remote" neighbor notification for an entry
3218 * we think is local. This can happen in a multihoming
3219 * scenario - but only if the MAC is already "remote".
3220 * Just mark our entry as "remote".
3222 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3223 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3225 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3226 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3227 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3232 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3233 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3234 ZEBRA_NEIGH_SET_ACTIVE(n
);
3235 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3242 * Make hash key for MAC.
3244 static unsigned int mac_hash_keymake(void *p
)
3246 zebra_mac_t
*pmac
= p
;
3247 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3249 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3253 * Compare two MAC addresses.
3255 static bool mac_cmp(const void *p1
, const void *p2
)
3257 const zebra_mac_t
*pmac1
= p1
;
3258 const zebra_mac_t
*pmac2
= p2
;
3260 if (pmac1
== NULL
&& pmac2
== NULL
)
3263 if (pmac1
== NULL
|| pmac2
== NULL
)
3266 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3271 * Callback to allocate MAC hash entry.
3273 static void *zvni_mac_alloc(void *p
)
3275 const zebra_mac_t
*tmp_mac
= p
;
3278 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3281 return ((void *)mac
);
3287 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3289 zebra_mac_t tmp_mac
;
3290 zebra_mac_t
*mac
= NULL
;
3292 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3293 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3294 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3297 mac
->neigh_list
= list_new();
3298 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3306 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3308 zebra_mac_t
*tmp_mac
;
3310 list_delete(&mac
->neigh_list
);
3312 /* Free the VNI hash entry and allocated memory. */
3313 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3315 XFREE(MTYPE_MAC
, tmp_mac
);
3321 * Free MAC hash entry (callback)
3323 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3325 struct mac_walk_ctx
*wctx
= arg
;
3326 zebra_mac_t
*mac
= bucket
->data
;
3328 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3329 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3330 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3331 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3332 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3333 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3334 &wctx
->r_vtep_ip
))) {
3335 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3336 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3340 if (wctx
->uninstall
)
3341 zvni_mac_uninstall(wctx
->zvni
, mac
);
3343 zvni_mac_del(wctx
->zvni
, mac
);
3350 * Delete all MAC entries from specific VTEP for a particular VNI.
3352 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3353 struct in_addr
*r_vtep_ip
)
3355 struct mac_walk_ctx wctx
;
3357 if (!zvni
->mac_table
)
3360 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3362 wctx
.uninstall
= uninstall
;
3363 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3364 wctx
.r_vtep_ip
= *r_vtep_ip
;
3366 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3370 * Delete all MAC entries for this VNI.
3372 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3375 struct mac_walk_ctx wctx
;
3377 if (!zvni
->mac_table
)
3380 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3382 wctx
.uninstall
= uninstall
;
3383 wctx
.upd_client
= upd_client
;
3386 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3390 * Look up MAC hash entry.
3392 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3397 memset(&tmp
, 0, sizeof(tmp
));
3398 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3399 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3405 * Inform BGP about local MAC addition.
3407 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3408 uint8_t mac_flags
, uint32_t seq
)
3412 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3413 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3414 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3415 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3417 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3418 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3422 * Inform BGP about local MAC deletion.
3424 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3426 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3427 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3431 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3432 * notifications, to see if they are of interest.
3434 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3435 struct interface
*br_if
, vlanid_t vid
)
3437 struct zebra_ns
*zns
;
3438 struct route_node
*rn
;
3439 struct interface
*tmp_if
= NULL
;
3440 struct zebra_if
*zif
;
3441 struct zebra_l2info_bridge
*br
;
3442 struct zebra_l2info_vxlan
*vxl
= NULL
;
3443 uint8_t bridge_vlan_aware
;
3447 /* Determine if bridge is VLAN-aware or not */
3450 br
= &zif
->l2info
.br
;
3451 bridge_vlan_aware
= br
->vlan_aware
;
3453 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3454 /* TODO: Optimize with a hash. */
3455 zns
= zebra_ns_lookup(NS_DEFAULT
);
3456 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3457 tmp_if
= (struct interface
*)rn
->info
;
3461 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3463 if (!if_is_operative(tmp_if
))
3465 vxl
= &zif
->l2info
.vxl
;
3467 if (zif
->brslave_info
.br_if
!= br_if
)
3470 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3479 zvni
= zvni_lookup(vxl
->vni
);
3484 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3485 * neighbor notifications, to see if they are of interest.
3487 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3488 struct interface
*br_if
)
3490 struct zebra_ns
*zns
;
3491 struct route_node
*rn
;
3492 struct interface
*tmp_if
= NULL
;
3493 struct zebra_if
*zif
;
3494 struct zebra_l2info_bridge
*br
;
3495 struct zebra_l2info_vxlan
*vxl
= NULL
;
3496 uint8_t bridge_vlan_aware
;
3504 /* Make sure the linked interface is a bridge. */
3505 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3508 /* Determine if bridge is VLAN-aware or not */
3511 br
= &zif
->l2info
.br
;
3512 bridge_vlan_aware
= br
->vlan_aware
;
3513 if (bridge_vlan_aware
) {
3514 struct zebra_l2info_vlan
*vl
;
3516 if (!IS_ZEBRA_IF_VLAN(ifp
))
3521 vl
= &zif
->l2info
.vl
;
3525 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3526 /* TODO: Optimize with a hash. */
3527 zns
= zebra_ns_lookup(NS_DEFAULT
);
3528 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3529 tmp_if
= (struct interface
*)rn
->info
;
3533 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3535 if (!if_is_operative(tmp_if
))
3537 vxl
= &zif
->l2info
.vxl
;
3539 if (zif
->brslave_info
.br_if
!= br_if
)
3542 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3551 zvni
= zvni_lookup(vxl
->vni
);
3555 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3557 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3558 * linked to the bridge
3559 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3562 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3564 struct zebra_ns
*zns
;
3565 struct route_node
*rn
;
3566 struct interface
*tmp_if
= NULL
;
3567 struct zebra_if
*zif
;
3568 struct zebra_l2info_bridge
*br
;
3569 struct zebra_l2info_vlan
*vl
;
3570 uint8_t bridge_vlan_aware
;
3573 /* Defensive check, caller expected to invoke only with valid bridge. */
3577 /* Determine if bridge is VLAN-aware or not */
3580 br
= &zif
->l2info
.br
;
3581 bridge_vlan_aware
= br
->vlan_aware
;
3583 /* Check oper status of the SVI. */
3584 if (!bridge_vlan_aware
)
3585 return if_is_operative(br_if
) ? br_if
: NULL
;
3587 /* Identify corresponding VLAN interface. */
3588 /* TODO: Optimize with a hash. */
3589 zns
= zebra_ns_lookup(NS_DEFAULT
);
3590 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3591 tmp_if
= (struct interface
*)rn
->info
;
3592 /* Check oper status of the SVI. */
3593 if (!tmp_if
|| !if_is_operative(tmp_if
))
3596 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3597 || zif
->link
!= br_if
)
3599 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3601 if (vl
->vid
== vid
) {
3607 return found
? tmp_if
: NULL
;
3611 * Install remote MAC into the kernel.
3613 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3615 struct zebra_if
*zif
;
3616 struct zebra_l2info_vxlan
*vxl
;
3619 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3622 zif
= zvni
->vxlan_if
->info
;
3625 vxl
= &zif
->l2info
.vxl
;
3627 sticky
= !!CHECK_FLAG(mac
->flags
,
3628 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3630 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3631 mac
->fwd_info
.r_vtep_ip
, sticky
);
3635 * Uninstall remote MAC from the kernel.
3637 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3639 struct zebra_if
*zif
;
3640 struct zebra_l2info_vxlan
*vxl
;
3641 struct in_addr vtep_ip
;
3642 struct interface
*ifp
;
3644 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3647 if (!zvni
->vxlan_if
) {
3648 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3653 zif
= zvni
->vxlan_if
->info
;
3656 vxl
= &zif
->l2info
.vxl
;
3658 ifp
= zvni
->vxlan_if
;
3659 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3661 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3665 * Install MAC hash entry - called upon access VLAN change.
3667 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3670 struct mac_walk_ctx
*wctx
= ctxt
;
3672 mac
= (zebra_mac_t
*)bucket
->data
;
3674 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3675 zvni_mac_install(wctx
->zvni
, mac
);
3679 * Count of remote neighbors referencing this MAC.
3681 static int remote_neigh_count(zebra_mac_t
*zmac
)
3683 zebra_neigh_t
*n
= NULL
;
3684 struct listnode
*node
= NULL
;
3687 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3688 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3696 * Decrement neighbor refcount of MAC; uninstall and free it if
3699 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3701 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3704 /* If all remote neighbors referencing a remote MAC go away,
3705 * we need to uninstall the MAC.
3707 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3708 remote_neigh_count(mac
) == 0) {
3709 zvni_mac_uninstall(zvni
, mac
);
3710 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3713 /* If no neighbors, delete the MAC. */
3714 if (list_isempty(mac
->neigh_list
))
3715 zvni_mac_del(zvni
, mac
);
3719 * Read and populate local MACs and neighbors corresponding to this VNI.
3721 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3723 struct zebra_ns
*zns
;
3724 struct zebra_if
*zif
;
3725 struct interface
*vlan_if
;
3726 struct zebra_l2info_vxlan
*vxl
;
3727 struct interface
*vrr_if
;
3730 vxl
= &zif
->l2info
.vxl
;
3731 zns
= zebra_ns_lookup(NS_DEFAULT
);
3733 if (IS_ZEBRA_DEBUG_VXLAN
)
3735 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3736 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3737 zif
->brslave_info
.bridge_ifindex
);
3739 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3740 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3743 /* Add SVI MAC-IP */
3744 zvni_add_macip_for_intf(vlan_if
, zvni
);
3746 /* Add VRR MAC-IP - if any*/
3747 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3749 zvni_add_macip_for_intf(vrr_if
, zvni
);
3751 neigh_read_for_vlan(zns
, vlan_if
);
3756 * Hash function for VNI.
3758 static unsigned int vni_hash_keymake(void *p
)
3760 const zebra_vni_t
*zvni
= p
;
3762 return (jhash_1word(zvni
->vni
, 0));
3766 * Compare 2 VNI hash entries.
3768 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3770 const zebra_vni_t
*zvni1
= p1
;
3771 const zebra_vni_t
*zvni2
= p2
;
3773 return (zvni1
->vni
== zvni2
->vni
);
3776 static int vni_list_cmp(void *p1
, void *p2
)
3778 const zebra_vni_t
*zvni1
= p1
;
3779 const zebra_vni_t
*zvni2
= p2
;
3781 if (zvni1
->vni
== zvni2
->vni
)
3783 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3787 * Callback to allocate VNI hash entry.
3789 static void *zvni_alloc(void *p
)
3791 const zebra_vni_t
*tmp_vni
= p
;
3794 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3795 zvni
->vni
= tmp_vni
->vni
;
3796 return ((void *)zvni
);
3800 * Look up VNI hash entry.
3802 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3804 struct zebra_vrf
*zvrf
;
3805 zebra_vni_t tmp_vni
;
3806 zebra_vni_t
*zvni
= NULL
;
3808 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3810 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3812 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3818 * Add VNI hash entry.
3820 static zebra_vni_t
*zvni_add(vni_t vni
)
3822 struct zebra_vrf
*zvrf
;
3823 zebra_vni_t tmp_zvni
;
3824 zebra_vni_t
*zvni
= NULL
;
3826 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3828 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3830 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3833 /* Create hash table for MAC */
3835 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3837 /* Create hash table for neighbors */
3838 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3839 "Zebra VNI Neighbor Table");
3845 * Delete VNI hash entry.
3847 static int zvni_del(zebra_vni_t
*zvni
)
3849 struct zebra_vrf
*zvrf
;
3850 zebra_vni_t
*tmp_zvni
;
3852 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3855 zvni
->vxlan_if
= NULL
;
3857 /* Free the neighbor hash table. */
3858 hash_free(zvni
->neigh_table
);
3859 zvni
->neigh_table
= NULL
;
3861 /* Free the MAC hash table. */
3862 hash_free(zvni
->mac_table
);
3863 zvni
->mac_table
= NULL
;
3865 /* Free the VNI hash entry and allocated memory. */
3866 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3868 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3874 * Inform BGP about local VNI addition.
3876 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3878 struct zserv
*client
;
3881 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3882 /* BGP may not be running. */
3886 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3888 zclient_create_header(s
, ZEBRA_VNI_ADD
, VRF_DEFAULT
);
3889 stream_putl(s
, zvni
->vni
);
3890 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3891 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3893 /* Write packet size. */
3894 stream_putw_at(s
, 0, stream_get_endp(s
));
3896 if (IS_ZEBRA_DEBUG_VXLAN
)
3897 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3898 inet_ntoa(zvni
->local_vtep_ip
),
3899 vrf_id_to_name(zvni
->vrf_id
),
3900 zebra_route_string(client
->proto
));
3902 client
->vniadd_cnt
++;
3903 return zserv_send_message(client
, s
);
3907 * Inform BGP about local VNI deletion.
3909 static int zvni_send_del_to_client(vni_t vni
)
3911 struct zserv
*client
;
3914 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3915 /* BGP may not be running. */
3919 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3922 zclient_create_header(s
, ZEBRA_VNI_DEL
, VRF_DEFAULT
);
3923 stream_putl(s
, vni
);
3925 /* Write packet size. */
3926 stream_putw_at(s
, 0, stream_get_endp(s
));
3928 if (IS_ZEBRA_DEBUG_VXLAN
)
3929 zlog_debug("Send VNI_DEL %u to %s", vni
,
3930 zebra_route_string(client
->proto
));
3932 client
->vnidel_cnt
++;
3933 return zserv_send_message(client
, s
);
3937 * Build the VNI hash table by going over the VxLAN interfaces. This
3938 * is called when EVPN (advertise-all-vni) is enabled.
3940 static void zvni_build_hash_table(void)
3942 struct zebra_ns
*zns
;
3943 struct route_node
*rn
;
3944 struct interface
*ifp
;
3946 /* Walk VxLAN interfaces and create VNI hash. */
3947 zns
= zebra_ns_lookup(NS_DEFAULT
);
3948 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3950 zebra_vni_t
*zvni
= NULL
;
3951 zebra_l3vni_t
*zl3vni
= NULL
;
3952 struct zebra_if
*zif
;
3953 struct zebra_l2info_vxlan
*vxl
;
3955 ifp
= (struct interface
*)rn
->info
;
3959 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3962 vxl
= &zif
->l2info
.vxl
;
3965 /* L3-VNI and L2-VNI are handled seperately */
3966 zl3vni
= zl3vni_lookup(vni
);
3969 if (IS_ZEBRA_DEBUG_VXLAN
)
3971 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3972 ifp
->name
, ifp
->ifindex
, vni
);
3974 /* associate with vxlan_if */
3975 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3976 zl3vni
->vxlan_if
= ifp
;
3979 * we need to associate with SVI.
3980 * we can associate with svi-if only after association
3981 * with vxlan-intf is complete
3983 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3985 if (is_l3vni_oper_up(zl3vni
))
3986 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3989 struct interface
*vlan_if
= NULL
;
3991 if (IS_ZEBRA_DEBUG_VXLAN
)
3993 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3994 ifp
->name
, ifp
->ifindex
, vni
,
3995 inet_ntoa(vxl
->vtep_ip
));
3997 /* VNI hash entry is not expected to exist. */
3998 zvni
= zvni_lookup(vni
);
4001 "VNI hash already present for IF %s(%u) L2-VNI %u",
4002 ifp
->name
, ifp
->ifindex
, vni
);
4006 zvni
= zvni_add(vni
);
4009 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4010 ifp
->name
, ifp
->ifindex
, vni
);
4014 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4015 zvni
->vxlan_if
= ifp
;
4016 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4017 zif
->brslave_info
.br_if
);
4019 zvni
->vrf_id
= vlan_if
->vrf_id
;
4020 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4022 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4026 /* Inform BGP if intf is up and mapped to bridge. */
4027 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4028 zvni_send_add_to_client(zvni
);
4034 * See if remote VTEP matches with prefix.
4036 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4038 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4042 * Locate remote VTEP in VNI hash table.
4044 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4046 zebra_vtep_t
*zvtep
;
4051 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4052 if (zvni_vtep_match(vtep_ip
, zvtep
))
4060 * Add remote VTEP to VNI hash table.
4062 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4064 zebra_vtep_t
*zvtep
;
4066 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4068 zvtep
->vtep_ip
= *vtep_ip
;
4071 zvni
->vteps
->prev
= zvtep
;
4072 zvtep
->next
= zvni
->vteps
;
4073 zvni
->vteps
= zvtep
;
4079 * Remove remote VTEP from VNI hash table.
4081 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4084 zvtep
->next
->prev
= zvtep
->prev
;
4086 zvtep
->prev
->next
= zvtep
->next
;
4088 zvni
->vteps
= zvtep
->next
;
4090 zvtep
->prev
= zvtep
->next
= NULL
;
4091 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4097 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4098 * uninstall from kernel if asked to.
4100 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4102 zebra_vtep_t
*zvtep
, *zvtep_next
;
4107 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4108 zvtep_next
= zvtep
->next
;
4110 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4111 zvni_vtep_del(zvni
, zvtep
);
4118 * Install remote VTEP into the kernel.
4120 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4122 if (is_vxlan_flooding_head_end())
4123 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4128 * Uninstall remote VTEP from the kernel.
4130 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4132 if (!zvni
->vxlan_if
) {
4133 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4138 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4142 * Install or uninstall flood entries in the kernel corresponding to
4143 * remote VTEPs. This is invoked upon change to BUM handling.
4145 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4149 zebra_vtep_t
*zvtep
;
4151 zvni
= (zebra_vni_t
*)bucket
->data
;
4155 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4156 if (is_vxlan_flooding_head_end())
4157 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4159 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4164 * Cleanup VNI/VTEP and update kernel
4166 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4168 zebra_vni_t
*zvni
= NULL
;
4169 zebra_l3vni_t
*zl3vni
= NULL
;
4170 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4172 zvni
= (zebra_vni_t
*)bucket
->data
;
4174 /* remove from l3-vni list */
4176 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4178 listnode_delete(zl3vni
->l2vnis
, zvni
);
4180 /* Free up all neighbors and MACs, if any. */
4181 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4182 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4184 /* Free up all remote VTEPs, if any. */
4185 zvni_vtep_del_all(zvni
, 1);
4187 /* Delete the hash entry. */
4192 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4194 zebra_l3vni_t
*zl3vni
= NULL
;
4196 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4198 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4201 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4202 struct prefix
*host
)
4204 struct host_rb_entry lookup
;
4205 struct host_rb_entry
*hle
;
4207 memset(&lookup
, 0, sizeof(lookup
));
4208 memcpy(&lookup
.p
, host
, sizeof(*host
));
4210 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4214 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4215 memcpy(hle
, &lookup
, sizeof(lookup
));
4217 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4220 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4222 struct host_rb_entry lookup
;
4223 struct host_rb_entry
*hle
;
4225 memset(&lookup
, 0, sizeof(lookup
));
4226 memcpy(&lookup
.p
, host
, sizeof(*host
));
4228 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4230 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4231 XFREE(MTYPE_HOST_PREFIX
, hle
);
4238 * Look up MAC hash entry.
4240 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4241 struct ethaddr
*rmac
)
4246 memset(&tmp
, 0, sizeof(tmp
));
4247 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4248 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4254 * Callback to allocate RMAC hash entry.
4256 static void *zl3vni_rmac_alloc(void *p
)
4258 const zebra_mac_t
*tmp_rmac
= p
;
4261 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4264 return ((void *)zrmac
);
4268 * Add RMAC entry to l3-vni
4270 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4272 zebra_mac_t tmp_rmac
;
4273 zebra_mac_t
*zrmac
= NULL
;
4275 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4276 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4277 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4280 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4282 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4283 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4291 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4293 zebra_mac_t
*tmp_rmac
;
4294 struct host_rb_entry
*hle
;
4296 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4297 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4299 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4300 XFREE(MTYPE_HOST_PREFIX
, hle
);
4303 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4305 XFREE(MTYPE_MAC
, tmp_rmac
);
4311 * Install remote RMAC into the kernel.
4313 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4315 struct zebra_if
*zif
= NULL
;
4316 struct zebra_l2info_vxlan
*vxl
= NULL
;
4318 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4319 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4322 zif
= zl3vni
->vxlan_if
->info
;
4326 vxl
= &zif
->l2info
.vxl
;
4328 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4329 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4333 * Uninstall remote RMAC from the kernel.
4335 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4337 char buf
[ETHER_ADDR_STRLEN
];
4338 struct zebra_if
*zif
= NULL
;
4339 struct zebra_l2info_vxlan
*vxl
= NULL
;
4341 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4342 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4345 if (!zl3vni
->vxlan_if
) {
4347 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4348 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4349 zl3vni
->vni
, zl3vni
);
4353 zif
= zl3vni
->vxlan_if
->info
;
4357 vxl
= &zif
->l2info
.vxl
;
4359 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4360 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4363 /* handle rmac add */
4364 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4365 struct ipaddr
*vtep_ip
,
4366 struct prefix
*host_prefix
)
4368 char buf
[ETHER_ADDR_STRLEN
];
4369 char buf1
[INET6_ADDRSTRLEN
];
4370 zebra_mac_t
*zrmac
= NULL
;
4372 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4375 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4378 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4379 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4381 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4384 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4385 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4387 /* install rmac in kernel */
4388 zl3vni_rmac_install(zl3vni
, zrmac
);
4391 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4397 /* handle rmac delete */
4398 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4399 struct prefix
*host_prefix
)
4401 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4403 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4404 /* uninstall from kernel */
4405 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4407 /* del the rmac entry */
4408 zl3vni_rmac_del(zl3vni
, zrmac
);
4413 * Look up nh hash entry on a l3-vni.
4415 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4420 memset(&tmp
, 0, sizeof(tmp
));
4421 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4422 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4429 * Callback to allocate NH hash entry on L3-VNI.
4431 static void *zl3vni_nh_alloc(void *p
)
4433 const zebra_neigh_t
*tmp_n
= p
;
4436 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4443 * Add neighbor entry.
4445 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4446 struct ethaddr
*mac
)
4448 zebra_neigh_t tmp_n
;
4449 zebra_neigh_t
*n
= NULL
;
4451 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4452 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4453 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4456 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4458 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4459 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4460 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4466 * Delete neighbor entry.
4468 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4470 zebra_neigh_t
*tmp_n
;
4471 struct host_rb_entry
*hle
;
4473 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4474 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4476 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4477 XFREE(MTYPE_HOST_PREFIX
, hle
);
4480 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4482 XFREE(MTYPE_NEIGH
, tmp_n
);
4488 * Install remote nh as neigh into the kernel.
4490 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4497 if (!is_l3vni_oper_up(zl3vni
))
4500 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4501 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4504 flags
= NTF_EXT_LEARNED
;
4505 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4506 flags
|= NTF_ROUTER
;
4507 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4513 * Uninstall remote nh from the kernel.
4515 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4517 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4518 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4521 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4524 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4527 /* add remote vtep as a neigh entry */
4528 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4529 struct ethaddr
*rmac
,
4530 struct prefix
*host_prefix
)
4532 char buf
[ETHER_ADDR_STRLEN
];
4533 char buf1
[INET6_ADDRSTRLEN
];
4534 zebra_neigh_t
*nh
= NULL
;
4536 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4538 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4542 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4543 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4544 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4549 /* install the nh neigh in kernel */
4550 zl3vni_nh_install(zl3vni
, nh
);
4553 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4558 /* handle nh neigh delete */
4559 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4560 struct prefix
*host_prefix
)
4562 rb_delete_host(&nh
->host_rb
, host_prefix
);
4564 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4565 /* uninstall from kernel */
4566 zl3vni_nh_uninstall(zl3vni
, nh
);
4568 /* delete the nh entry */
4569 zl3vni_nh_del(zl3vni
, nh
);
4573 /* handle neigh update from kernel - the only thing of interest is to
4574 * readd stale entries.
4576 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4580 zebra_neigh_t
*n
= NULL
;
4582 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4586 /* all next hop neigh are remote and installed by frr.
4587 * If the kernel has aged this entry, re-install.
4589 if (state
& NUD_STALE
)
4590 zl3vni_nh_install(zl3vni
, n
);
4595 /* handle neigh delete from kernel */
4596 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4598 zebra_neigh_t
*n
= NULL
;
4600 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4604 /* all next hop neigh are remote and installed by frr.
4605 * If we get an age out notification for these neigh entries, we have to
4608 zl3vni_nh_install(zl3vni
, n
);
4614 * Hash function for L3 VNI.
4616 static unsigned int l3vni_hash_keymake(void *p
)
4618 const zebra_l3vni_t
*zl3vni
= p
;
4620 return jhash_1word(zl3vni
->vni
, 0);
4624 * Compare 2 L3 VNI hash entries.
4626 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4628 const zebra_l3vni_t
*zl3vni1
= p1
;
4629 const zebra_l3vni_t
*zl3vni2
= p2
;
4631 return (zl3vni1
->vni
== zl3vni2
->vni
);
4635 * Callback to allocate L3 VNI hash entry.
4637 static void *zl3vni_alloc(void *p
)
4639 zebra_l3vni_t
*zl3vni
= NULL
;
4640 const zebra_l3vni_t
*tmp_l3vni
= p
;
4642 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4643 zl3vni
->vni
= tmp_l3vni
->vni
;
4644 return ((void *)zl3vni
);
4648 * Look up L3 VNI hash entry.
4650 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4652 zebra_l3vni_t tmp_l3vni
;
4653 zebra_l3vni_t
*zl3vni
= NULL
;
4655 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4656 tmp_l3vni
.vni
= vni
;
4657 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4663 * Add L3 VNI hash entry.
4665 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4667 zebra_l3vni_t tmp_zl3vni
;
4668 zebra_l3vni_t
*zl3vni
= NULL
;
4670 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4671 tmp_zl3vni
.vni
= vni
;
4673 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4676 zl3vni
->vrf_id
= vrf_id
;
4677 zl3vni
->svi_if
= NULL
;
4678 zl3vni
->vxlan_if
= NULL
;
4679 zl3vni
->l2vnis
= list_new();
4680 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4682 /* Create hash table for remote RMAC */
4683 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4684 "Zebra L3-VNI RMAC-Table");
4686 /* Create hash table for neighbors */
4687 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4688 "Zebra L3-VNI next-hop table");
4694 * Delete L3 VNI hash entry.
4696 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4698 zebra_l3vni_t
*tmp_zl3vni
;
4700 /* free the list of l2vnis */
4701 list_delete(&zl3vni
->l2vnis
);
4702 zl3vni
->l2vnis
= NULL
;
4704 /* Free the rmac table */
4705 hash_free(zl3vni
->rmac_table
);
4706 zl3vni
->rmac_table
= NULL
;
4708 /* Free the nh table */
4709 hash_free(zl3vni
->nh_table
);
4710 zl3vni
->nh_table
= NULL
;
4712 /* Free the VNI hash entry and allocated memory. */
4713 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4715 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4720 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4722 struct zebra_ns
*zns
= NULL
;
4723 struct route_node
*rn
= NULL
;
4724 struct interface
*ifp
= NULL
;
4726 /* loop through all vxlan-interface */
4727 zns
= zebra_ns_lookup(NS_DEFAULT
);
4728 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4730 struct zebra_if
*zif
= NULL
;
4731 struct zebra_l2info_vxlan
*vxl
= NULL
;
4733 ifp
= (struct interface
*)rn
->info
;
4738 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4741 vxl
= &zif
->l2info
.vxl
;
4742 if (vxl
->vni
== zl3vni
->vni
) {
4743 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4751 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4753 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4754 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4759 if (!zl3vni
->vxlan_if
)
4762 zif
= zl3vni
->vxlan_if
->info
;
4766 vxl
= &zif
->l2info
.vxl
;
4768 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4771 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4773 struct zebra_vrf
*zvrf
= NULL
;
4775 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4779 return zl3vni_lookup(zvrf
->l3vni
);
4783 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4784 * neighbor notifications, to see if they are of interest.
4786 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4787 struct interface
*br_if
)
4791 uint8_t bridge_vlan_aware
= 0;
4792 zebra_l3vni_t
*zl3vni
= NULL
;
4793 struct zebra_ns
*zns
= NULL
;
4794 struct route_node
*rn
= NULL
;
4795 struct zebra_if
*zif
= NULL
;
4796 struct interface
*tmp_if
= NULL
;
4797 struct zebra_l2info_bridge
*br
= NULL
;
4798 struct zebra_l2info_vxlan
*vxl
= NULL
;
4803 /* Make sure the linked interface is a bridge. */
4804 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4807 /* Determine if bridge is VLAN-aware or not */
4810 br
= &zif
->l2info
.br
;
4811 bridge_vlan_aware
= br
->vlan_aware
;
4812 if (bridge_vlan_aware
) {
4813 struct zebra_l2info_vlan
*vl
;
4815 if (!IS_ZEBRA_IF_VLAN(ifp
))
4820 vl
= &zif
->l2info
.vl
;
4824 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4825 /* TODO: Optimize with a hash. */
4826 zns
= zebra_ns_lookup(NS_DEFAULT
);
4827 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4828 tmp_if
= (struct interface
*)rn
->info
;
4832 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4834 if (!if_is_operative(tmp_if
))
4836 vxl
= &zif
->l2info
.vxl
;
4838 if (zif
->brslave_info
.br_if
!= br_if
)
4841 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4850 zl3vni
= zl3vni_lookup(vxl
->vni
);
4855 * Inform BGP about l3-vni.
4857 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4859 struct stream
*s
= NULL
;
4860 struct zserv
*client
= NULL
;
4861 struct ethaddr rmac
;
4862 char buf
[ETHER_ADDR_STRLEN
];
4864 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4865 /* BGP may not be running. */
4870 memset(&rmac
, 0, sizeof(struct ethaddr
));
4871 zl3vni_get_rmac(zl3vni
, &rmac
);
4873 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4875 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4876 stream_putl(s
, zl3vni
->vni
);
4877 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4878 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4879 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4881 /* Write packet size. */
4882 stream_putw_at(s
, 0, stream_get_endp(s
));
4884 if (IS_ZEBRA_DEBUG_VXLAN
)
4886 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4887 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4888 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4889 inet_ntoa(zl3vni
->local_vtep_ip
),
4890 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4891 ? "prefix-routes-only"
4893 zebra_route_string(client
->proto
));
4895 client
->l3vniadd_cnt
++;
4896 return zserv_send_message(client
, s
);
4900 * Inform BGP about local l3-VNI deletion.
4902 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4904 struct stream
*s
= NULL
;
4905 struct zserv
*client
= NULL
;
4907 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4908 /* BGP may not be running. */
4912 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4914 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4915 stream_putl(s
, zl3vni
->vni
);
4917 /* Write packet size. */
4918 stream_putw_at(s
, 0, stream_get_endp(s
));
4920 if (IS_ZEBRA_DEBUG_VXLAN
)
4921 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4922 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4923 zebra_route_string(client
->proto
));
4925 client
->l3vnidel_cnt
++;
4926 return zserv_send_message(client
, s
);
4929 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4934 /* send l3vni add to BGP */
4935 zl3vni_send_add_to_client(zl3vni
);
4938 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4943 /* send l3-vni del to BGP*/
4944 zl3vni_send_del_to_client(zl3vni
);
4947 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
4949 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
4950 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4952 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4953 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4957 * handle transition of vni from l2 to l3 and vice versa
4959 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4962 zebra_vni_t
*zvni
= NULL
;
4964 /* There is a possibility that VNI notification was already received
4965 * from kernel and we programmed it as L2-VNI
4966 * In such a case we need to delete this L2-VNI first, so
4967 * that it can be reprogrammed as L3-VNI in the system. It is also
4968 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4969 * interface is still present in kernel. In this case to keep it
4970 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4973 /* Locate hash entry */
4974 zvni
= zvni_lookup(vni
);
4978 if (IS_ZEBRA_DEBUG_VXLAN
)
4979 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4981 /* Delete VNI from BGP. */
4982 zvni_send_del_to_client(zvni
->vni
);
4984 /* Free up all neighbors and MAC, if any. */
4985 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4986 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4988 /* Free up all remote VTEPs, if any. */
4989 zvni_vtep_del_all(zvni
, 0);
4991 /* Delete the hash entry. */
4992 if (zvni_del(zvni
)) {
4993 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4994 "Failed to del VNI hash %p, VNI %u", zvni
,
4999 /* TODO_MITESH: This needs to be thought through. We don't have
5000 * enough information at this point to reprogram the vni as
5001 * l2-vni. One way is to store the required info in l3-vni and
5002 * used it solely for this purpose
5009 /* delete and uninstall rmac hash entry */
5010 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5012 zebra_mac_t
*zrmac
= NULL
;
5013 zebra_l3vni_t
*zl3vni
= NULL
;
5015 zrmac
= (zebra_mac_t
*)bucket
->data
;
5016 zl3vni
= (zebra_l3vni_t
*)ctx
;
5017 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5018 zl3vni_rmac_del(zl3vni
, zrmac
);
5021 /* delete and uninstall nh hash entry */
5022 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5024 zebra_neigh_t
*n
= NULL
;
5025 zebra_l3vni_t
*zl3vni
= NULL
;
5027 n
= (zebra_neigh_t
*)bucket
->data
;
5028 zl3vni
= (zebra_l3vni_t
*)ctx
;
5029 zl3vni_nh_uninstall(zl3vni
, n
);
5030 zl3vni_nh_del(zl3vni
, n
);
5033 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5036 struct zserv
*client
= NULL
;
5037 struct stream
*s
= NULL
;
5038 char buf
[PREFIX_STRLEN
];
5040 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5041 /* BGP may not be running. */
5045 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5047 zclient_create_header(s
, cmd
, vrf_id
);
5048 stream_put(s
, p
, sizeof(struct prefix
));
5050 /* Write packet size. */
5051 stream_putw_at(s
, 0, stream_get_endp(s
));
5053 if (IS_ZEBRA_DEBUG_VXLAN
)
5054 zlog_debug("Send ip prefix %s %s on vrf %s",
5055 prefix2str(p
, buf
, sizeof(buf
)),
5056 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5057 vrf_id_to_name(vrf_id
));
5059 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5060 client
->prefixadd_cnt
++;
5062 client
->prefixdel_cnt
++;
5064 return zserv_send_message(client
, s
);
5067 /* re-add remote rmac if needed */
5068 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5069 struct ethaddr
*rmac
)
5071 char buf
[ETHER_ADDR_STRLEN
];
5072 zebra_mac_t
*zrmac
= NULL
;
5074 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5078 if (IS_ZEBRA_DEBUG_VXLAN
)
5079 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5080 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5082 zl3vni_rmac_install(zl3vni
, zrmac
);
5086 /* Process a remote MACIP add from BGP. */
5087 static void process_remote_macip_add(vni_t vni
,
5088 struct ethaddr
*macaddr
,
5090 struct ipaddr
*ipaddr
,
5093 struct in_addr vtep_ip
)
5096 zebra_vtep_t
*zvtep
;
5097 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5098 zebra_neigh_t
*n
= NULL
;
5099 int update_mac
= 0, update_neigh
= 0;
5100 char buf
[ETHER_ADDR_STRLEN
];
5101 char buf1
[INET6_ADDRSTRLEN
];
5102 struct interface
*ifp
= NULL
;
5103 struct zebra_if
*zif
= NULL
;
5104 struct zebra_vrf
*zvrf
;
5109 bool do_dad
= false;
5110 bool is_dup_detect
= false;
5112 /* Locate VNI hash entry - expected to exist. */
5113 zvni
= zvni_lookup(vni
);
5115 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5119 ifp
= zvni
->vxlan_if
;
5123 !if_is_operative(ifp
) ||
5125 !zif
->brslave_info
.br_if
) {
5126 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5131 /* The remote VTEP specified should normally exist, but it is
5132 * possible that when peering comes up, peer may advertise MACIP
5133 * routes before advertising type-3 routes.
5135 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5137 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5139 EC_ZEBRA_VTEP_ADD_FAILED
,
5140 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5145 zvni_vtep_install(zvni
, &vtep_ip
);
5148 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5149 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5150 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5152 mac
= zvni_mac_lookup(zvni
, macaddr
);
5154 /* Ignore if the mac is already present as a gateway mac */
5156 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5157 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5158 if (IS_ZEBRA_DEBUG_VXLAN
)
5159 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5161 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5162 ipa_len
? " IP " : "",
5164 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5168 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5172 /* check if the remote MAC is unknown or has a change.
5173 * If so, that needs to be updated first. Note that client could
5174 * install MAC and MACIP separately or just install the latter.
5177 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5178 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5179 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5180 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5181 || seq
!= mac
->rem_seq
)
5186 mac
= zvni_mac_add(zvni
, macaddr
);
5189 "Failed to add MAC %s VNI %u Remote VTEP %s",
5190 prefix_mac2str(macaddr
, buf
,
5192 vni
, inet_ntoa(vtep_ip
));
5196 /* Is this MAC created for a MACIP? */
5198 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5200 const char *mac_type
;
5202 /* When host moves but changes its (MAC,IP)
5203 * binding, BGP may install a MACIP entry that
5204 * corresponds to "older" location of the host
5205 * in transient situations (because {IP1,M1}
5206 * is a different route from {IP1,M2}). Check
5207 * the sequence number and ignore this update
5210 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5211 tmp_seq
= mac
->loc_seq
;
5214 tmp_seq
= mac
->rem_seq
;
5215 mac_type
= "remote";
5217 if (seq
< tmp_seq
) {
5218 if (IS_ZEBRA_DEBUG_VXLAN
)
5219 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5221 prefix_mac2str(macaddr
,
5223 ipa_len
? " IP " : "",
5226 buf1
, sizeof(buf1
)) : "",
5233 /* Check MAC's curent state is local (this is the case
5234 * where MAC has moved from L->R) and check previous
5235 * detection started via local learning.
5236 * RFC-7432: A PE/VTEP that detects a MAC mobility
5237 * event via local learning starts an M-second timer.
5239 * VTEP-IP or seq. change alone is not considered
5240 * for dup. detection.
5242 * MAC is already marked duplicate set dad, then
5243 * is_dup_detect will be set to not install the entry.
5245 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5247 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5250 /* Remove local MAC from BGP. */
5251 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5252 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5254 /* Set "auto" and "remote" forwarding info. */
5255 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5256 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5257 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5258 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5261 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5263 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5266 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5268 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5270 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5271 mac
->fwd_info
.r_vtep_ip
,
5272 do_dad
, &is_dup_detect
,
5275 if (!is_dup_detect
) {
5276 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5277 /* Install the entry. */
5278 zvni_mac_install(zvni
, mac
);
5282 /* Update seq number. */
5285 /* If there is no IP, return after clearing AUTO flag of MAC. */
5287 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5294 /* Check if the remote neighbor itself is unknown or has a
5295 * change. If so, create or update and then install the entry.
5297 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5299 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5300 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5301 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5302 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5303 || seq
!= n
->rem_seq
)
5308 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5311 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5312 ipaddr2str(ipaddr
, buf1
,
5314 prefix_mac2str(macaddr
, buf
,
5316 vni
, inet_ntoa(vtep_ip
));
5323 /* When host moves but changes its (MAC,IP)
5324 * binding, BGP may install a MACIP entry that
5325 * corresponds to "older" location of the host
5326 * in transient situations (because {IP1,M1}
5327 * is a different route from {IP1,M2}). Check
5328 * the sequence number and ignore this update
5331 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5332 tmp_seq
= n
->loc_seq
;
5335 tmp_seq
= n
->rem_seq
;
5338 if (seq
< tmp_seq
) {
5339 if (IS_ZEBRA_DEBUG_VXLAN
)
5340 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5342 prefix_mac2str(macaddr
,
5345 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5350 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5351 /* MAC change, send a delete for old
5352 * neigh if learnt locally.
5354 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5355 IS_ZEBRA_NEIGH_ACTIVE(n
))
5356 zvni_neigh_send_del_to_client(
5358 &n
->emac
, 0, n
->state
);
5360 /* update neigh list for macs */
5361 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5363 listnode_delete(old_mac
->neigh_list
, n
);
5364 zvni_deref_ip2mac(zvni
, old_mac
);
5366 listnode_add_sort(mac
->neigh_list
, n
);
5367 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5369 /* Check Neigh's curent state is local
5370 * (this is the case where neigh/host has moved
5371 * from L->R) and check previous detction
5372 * started via local learning.
5374 * RFC-7432: A PE/VTEP that detects a MAC
5375 * mobilit event via local learning starts
5376 * an M-second timer.
5377 * VTEP-IP or seq. change along is not
5378 * considered for dup. detection.
5380 * Mobilty event scenario-B IP-MAC binding
5383 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5390 /* Set "remote" forwarding info. */
5391 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5392 n
->r_vtep_ip
= vtep_ip
;
5393 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5395 /* Set router flag (R-bit) to this Neighbor entry */
5396 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5397 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5399 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5401 /* Check old or new MAC detected as duplicate,
5402 * inherit duplicate flag to this neigh.
5404 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5406 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5407 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5409 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5410 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5413 /* Check duplicate address detection for IP */
5414 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5419 /* Install the entry. */
5421 zvni_neigh_install(zvni
, n
);
5424 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5426 /* Update seq number. */
5430 /* Process a remote MACIP delete from BGP. */
5431 static void process_remote_macip_del(vni_t vni
,
5432 struct ethaddr
*macaddr
,
5434 struct ipaddr
*ipaddr
,
5435 struct in_addr vtep_ip
)
5438 zebra_mac_t
*mac
= NULL
;
5439 zebra_neigh_t
*n
= NULL
;
5440 struct interface
*ifp
= NULL
;
5441 struct zebra_if
*zif
= NULL
;
5442 struct zebra_ns
*zns
;
5443 struct zebra_l2info_vxlan
*vxl
;
5444 struct zebra_vrf
*zvrf
;
5445 char buf
[ETHER_ADDR_STRLEN
];
5446 char buf1
[INET6_ADDRSTRLEN
];
5448 /* Locate VNI hash entry - expected to exist. */
5449 zvni
= zvni_lookup(vni
);
5451 if (IS_ZEBRA_DEBUG_VXLAN
)
5452 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5456 ifp
= zvni
->vxlan_if
;
5460 !if_is_operative(ifp
) ||
5462 !zif
->brslave_info
.br_if
) {
5463 if (IS_ZEBRA_DEBUG_VXLAN
)
5464 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5468 zns
= zebra_ns_lookup(NS_DEFAULT
);
5469 vxl
= &zif
->l2info
.vxl
;
5471 /* The remote VTEP specified is normally expected to exist, but
5472 * it is possible that the peer may delete the VTEP before deleting
5473 * any MACs referring to the VTEP, in which case the handler (see
5474 * remote_vtep_del) would have already deleted the MACs.
5476 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5479 mac
= zvni_mac_lookup(zvni
, macaddr
);
5481 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5484 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5485 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5486 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5490 /* If the remote mac or neighbor doesn't exist there is nothing
5491 * more to do. Otherwise, uninstall the entry and then remove it.
5496 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5498 /* Ignore the delete if this mac is a gateway mac-ip */
5499 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5500 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5502 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5504 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5505 ipa_len
? " IP " : "",
5507 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5511 /* Uninstall remote neighbor or MAC. */
5513 if (zvrf
->dad_freeze
&&
5514 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5515 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5516 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5517 struct interface
*vlan_if
;
5519 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5520 zif
->brslave_info
.br_if
);
5521 if (IS_ZEBRA_DEBUG_VXLAN
)
5522 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5523 __PRETTY_FUNCTION__
,
5524 ipaddr2str(ipaddr
, buf1
,
5525 sizeof(buf1
)), n
->flags
,
5527 neigh_read_specific_ip(ipaddr
, vlan_if
);
5530 /* When the MAC changes for an IP, it is possible the
5531 * client may update the new MAC before trying to delete the
5532 * "old" neighbor (as these are two different MACIP routes).
5533 * Do the delete only if the MAC matches.
5535 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5536 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5537 zvni_neigh_uninstall(zvni
, n
);
5538 zvni_neigh_del(zvni
, n
);
5539 zvni_deref_ip2mac(zvni
, mac
);
5542 /* DAD: when MAC is freeze state as remote learn event,
5543 * remote mac-ip delete event is received will result in freeze
5544 * entry removal, first fetch kernel for the same entry present
5545 * as LOCAL and reachable, avoid deleting this entry instead
5546 * use kerenel local entry to update during unfreeze time.
5548 if (zvrf
->dad_freeze
&&
5549 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5550 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5551 if (IS_ZEBRA_DEBUG_VXLAN
)
5552 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5553 __PRETTY_FUNCTION__
,
5554 prefix_mac2str(macaddr
, buf
,
5557 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5558 macaddr
, vxl
->access_vlan
);
5561 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5562 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5564 * the remote sequence number in the auto mac entry
5565 * needs to be reset to 0 as the mac entry may have
5566 * been removed on all VTEPs (including
5567 * the originating one)
5571 /* If all remote neighbors referencing a remote MAC
5572 * go away, we need to uninstall the MAC.
5574 if (remote_neigh_count(mac
) == 0) {
5575 zvni_mac_uninstall(zvni
, mac
);
5576 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5578 if (list_isempty(mac
->neigh_list
))
5579 zvni_mac_del(zvni
, mac
);
5581 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5587 /* Public functions */
5589 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5591 zebra_l3vni_t
*zl3vni
= NULL
;
5593 zl3vni
= zl3vni_lookup(vni
);
5597 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5600 /* handle evpn route in vrf table */
5601 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5602 struct ipaddr
*vtep_ip
,
5603 struct prefix
*host_prefix
)
5605 zebra_l3vni_t
*zl3vni
= NULL
;
5606 struct ipaddr ipv4_vtep
;
5608 zl3vni
= zl3vni_from_vrf(vrf_id
);
5609 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5613 * add the next hop neighbor -
5614 * neigh to be installed is the ipv6 nexthop neigh
5616 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5619 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5620 * address. Rmac is programmed against the ipv4 vtep because we only
5621 * support ipv4 tunnels in the h/w right now
5623 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5624 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5625 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5626 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5627 &(ipv4_vtep
.ipaddr_v4
));
5629 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5630 sizeof(struct in_addr
));
5633 * add the rmac - remote rmac to be installed is against the ipv4
5636 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5639 /* handle evpn vrf route delete */
5640 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5641 struct ipaddr
*vtep_ip
,
5642 struct prefix
*host_prefix
)
5644 zebra_l3vni_t
*zl3vni
= NULL
;
5645 zebra_neigh_t
*nh
= NULL
;
5646 zebra_mac_t
*zrmac
= NULL
;
5648 zl3vni
= zl3vni_from_vrf(vrf_id
);
5652 /* find the next hop entry and rmac entry */
5653 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5656 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5658 /* delete the next hop entry */
5659 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5661 /* delete the rmac entry */
5663 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5667 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5668 struct ethaddr
*rmac
, bool use_json
)
5670 zebra_l3vni_t
*zl3vni
= NULL
;
5671 zebra_mac_t
*zrmac
= NULL
;
5672 json_object
*json
= NULL
;
5674 if (!is_evpn_enabled()) {
5676 vty_out(vty
, "{}\n");
5681 json
= json_object_new_object();
5683 zl3vni
= zl3vni_lookup(l3vni
);
5686 vty_out(vty
, "{}\n");
5688 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5692 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5695 vty_out(vty
, "{}\n");
5698 "%% Requested RMAC doesn't exist in L3-VNI %u",
5703 zl3vni_print_rmac(zrmac
, vty
, json
);
5706 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5707 json
, JSON_C_TO_STRING_PRETTY
));
5708 json_object_free(json
);
5712 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5714 zebra_l3vni_t
*zl3vni
;
5716 struct rmac_walk_ctx wctx
;
5717 json_object
*json
= NULL
;
5719 if (!is_evpn_enabled())
5722 zl3vni
= zl3vni_lookup(l3vni
);
5725 vty_out(vty
, "{}\n");
5727 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5730 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5735 json
= json_object_new_object();
5737 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5741 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5743 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5745 json_object_int_add(json
, "numRmacs", num_rmacs
);
5747 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5750 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5751 json
, JSON_C_TO_STRING_PRETTY
));
5752 json_object_free(json
);
5756 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5758 json_object
*json
= NULL
;
5761 if (!is_evpn_enabled()) {
5763 vty_out(vty
, "{}\n");
5768 json
= json_object_new_object();
5772 hash_iterate(zrouter
.l3vni_table
,
5773 (void (*)(struct hash_bucket
*,
5774 void *))zl3vni_print_rmac_hash_all_vni
,
5778 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5779 json
, JSON_C_TO_STRING_PRETTY
));
5780 json_object_free(json
);
5784 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5785 struct ipaddr
*ip
, bool use_json
)
5787 zebra_l3vni_t
*zl3vni
= NULL
;
5788 zebra_neigh_t
*n
= NULL
;
5789 json_object
*json
= NULL
;
5791 if (!is_evpn_enabled()) {
5793 vty_out(vty
, "{}\n");
5798 json
= json_object_new_object();
5800 zl3vni
= zl3vni_lookup(l3vni
);
5803 vty_out(vty
, "{}\n");
5805 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5809 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5812 vty_out(vty
, "{}\n");
5815 "%% Requested next-hop not present for L3-VNI %u",
5820 zl3vni_print_nh(n
, vty
, json
);
5823 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5824 json
, JSON_C_TO_STRING_PRETTY
));
5825 json_object_free(json
);
5829 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5832 struct nh_walk_ctx wctx
;
5833 json_object
*json
= NULL
;
5834 zebra_l3vni_t
*zl3vni
= NULL
;
5836 if (!is_evpn_enabled())
5839 zl3vni
= zl3vni_lookup(l3vni
);
5842 vty_out(vty
, "{}\n");
5844 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5848 num_nh
= hashcount(zl3vni
->nh_table
);
5853 json
= json_object_new_object();
5858 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5860 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5862 json_object_int_add(json
, "numNextHops", num_nh
);
5864 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5867 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5868 json
, JSON_C_TO_STRING_PRETTY
));
5869 json_object_free(json
);
5873 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5875 json_object
*json
= NULL
;
5878 if (!is_evpn_enabled()) {
5880 vty_out(vty
, "{}\n");
5885 json
= json_object_new_object();
5889 hash_iterate(zrouter
.l3vni_table
,
5890 (void (*)(struct hash_bucket
*,
5891 void *))zl3vni_print_nh_hash_all_vni
,
5895 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5896 json
, JSON_C_TO_STRING_PRETTY
));
5897 json_object_free(json
);
5902 * Display L3 VNI information (VTY command handler).
5904 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5907 json_object
*json
= NULL
;
5908 zebra_l3vni_t
*zl3vni
= NULL
;
5910 if (!is_evpn_enabled()) {
5912 vty_out(vty
, "{}\n");
5916 zl3vni
= zl3vni_lookup(vni
);
5919 vty_out(vty
, "{}\n");
5921 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5926 json
= json_object_new_object();
5930 zl3vni_print(zl3vni
, (void *)args
);
5933 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5934 json
, JSON_C_TO_STRING_PRETTY
));
5935 json_object_free(json
);
5939 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5940 json_object
*json_vrfs
)
5942 char buf
[ETHER_ADDR_STRLEN
];
5943 zebra_l3vni_t
*zl3vni
= NULL
;
5945 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5950 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5951 zvrf_name(zvrf
), zl3vni
->vni
,
5952 zl3vni_vxlan_if_name(zl3vni
),
5953 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5954 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5956 json_object
*json_vrf
= NULL
;
5958 json_vrf
= json_object_new_object();
5959 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5960 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5961 json_object_string_add(json_vrf
, "vxlanIntf",
5962 zl3vni_vxlan_if_name(zl3vni
));
5963 json_object_string_add(json_vrf
, "sviIntf",
5964 zl3vni_svi_if_name(zl3vni
));
5965 json_object_string_add(json_vrf
, "state",
5966 zl3vni_state2str(zl3vni
));
5967 json_object_string_add(
5968 json_vrf
, "routerMac",
5969 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5970 json_object_array_add(json_vrfs
, json_vrf
);
5975 * Display Neighbors for a VNI (VTY command handler).
5977 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5978 vni_t vni
, bool use_json
)
5982 struct neigh_walk_ctx wctx
;
5983 json_object
*json
= NULL
;
5985 if (!is_evpn_enabled())
5987 zvni
= zvni_lookup(vni
);
5990 vty_out(vty
, "{}\n");
5992 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5995 num_neigh
= hashcount(zvni
->neigh_table
);
6000 json
= json_object_new_object();
6002 /* Since we have IPv6 addresses to deal with which can vary widely in
6003 * size, we try to be a bit more elegant in display by first computing
6004 * the maximum width.
6006 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6009 wctx
.addr_width
= 15;
6011 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6015 "Number of ARPs (local and remote) known for this VNI: %u\n",
6017 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6018 -wctx
.addr_width
, "IP", "Type",
6019 "State", "MAC", "Remote VTEP");
6021 json_object_int_add(json
, "numArpNd", num_neigh
);
6023 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6025 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6026 json
, JSON_C_TO_STRING_PRETTY
));
6027 json_object_free(json
);
6032 * Display neighbors across all VNIs (VTY command handler).
6034 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6035 bool print_dup
, bool use_json
)
6037 json_object
*json
= NULL
;
6040 if (!is_evpn_enabled())
6044 json
= json_object_new_object();
6048 args
[2] = (void *)(ptrdiff_t)print_dup
;
6050 hash_iterate(zvrf
->vni_table
,
6051 (void (*)(struct hash_bucket
*,
6052 void *))zvni_print_neigh_hash_all_vni
,
6055 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6056 json
, JSON_C_TO_STRING_PRETTY
));
6057 json_object_free(json
);
6062 * Display neighbors across all VNIs in detail(VTY command handler).
6064 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6065 struct zebra_vrf
*zvrf
,
6066 bool print_dup
, bool use_json
)
6068 json_object
*json
= NULL
;
6071 if (!is_evpn_enabled())
6075 json
= json_object_new_object();
6079 args
[2] = (void *)(ptrdiff_t)print_dup
;
6081 hash_iterate(zvrf
->vni_table
,
6082 (void (*)(struct hash_bucket
*,
6083 void *))zvni_print_neigh_hash_all_vni_detail
,
6086 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6087 json
, JSON_C_TO_STRING_PRETTY
));
6088 json_object_free(json
);
6093 * Display specific neighbor for a VNI, if present (VTY command handler).
6095 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6096 struct zebra_vrf
*zvrf
, vni_t vni
,
6097 struct ipaddr
*ip
, bool use_json
)
6101 json_object
*json
= NULL
;
6103 if (!is_evpn_enabled())
6105 zvni
= zvni_lookup(vni
);
6108 vty_out(vty
, "{}\n");
6110 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6113 n
= zvni_neigh_lookup(zvni
, ip
);
6117 "%% Requested neighbor does not exist in VNI %u\n",
6122 json
= json_object_new_object();
6124 zvni_print_neigh(n
, vty
, json
);
6127 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6128 json
, JSON_C_TO_STRING_PRETTY
));
6129 json_object_free(json
);
6134 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6135 * By definition, these are remote neighbors.
6137 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6138 vni_t vni
, struct in_addr vtep_ip
,
6143 struct neigh_walk_ctx wctx
;
6144 json_object
*json
= NULL
;
6146 if (!is_evpn_enabled())
6148 zvni
= zvni_lookup(vni
);
6151 vty_out(vty
, "{}\n");
6153 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6156 num_neigh
= hashcount(zvni
->neigh_table
);
6160 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6163 wctx
.addr_width
= 15;
6164 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6165 wctx
.r_vtep_ip
= vtep_ip
;
6167 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6168 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6171 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6172 json
, JSON_C_TO_STRING_PRETTY
));
6173 json_object_free(json
);
6178 * Display Duplicate detected Neighbors for a VNI
6179 * (VTY command handler).
6181 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6182 struct zebra_vrf
*zvrf
,
6188 struct neigh_walk_ctx wctx
;
6189 json_object
*json
= NULL
;
6191 if (!is_evpn_enabled())
6194 zvni
= zvni_lookup(vni
);
6196 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6200 num_neigh
= hashcount(zvni
->neigh_table
);
6204 num_neigh
= num_dup_detected_neighs(zvni
);
6209 json
= json_object_new_object();
6211 /* Since we have IPv6 addresses to deal with which can vary widely in
6212 * size, we try to be a bit more elegant in display by first computing
6213 * the maximum width.
6215 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6218 wctx
.addr_width
= 15;
6220 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6224 "Number of ARPs (local and remote) known for this VNI: %u\n",
6226 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6227 -wctx
.addr_width
, "IP", "Type",
6228 "State", "MAC", "Remote VTEP");
6230 json_object_int_add(json
, "numArpNd", num_neigh
);
6232 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6235 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6236 json
, JSON_C_TO_STRING_PRETTY
));
6237 json_object_free(json
);
6242 * Display MACs for a VNI (VTY command handler).
6244 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6245 vni_t vni
, bool use_json
)
6249 struct mac_walk_ctx wctx
;
6250 json_object
*json
= NULL
;
6251 json_object
*json_mac
= NULL
;
6253 if (!is_evpn_enabled())
6255 zvni
= zvni_lookup(vni
);
6258 vty_out(vty
, "{}\n");
6260 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6263 num_macs
= num_valid_macs(zvni
);
6268 json
= json_object_new_object();
6269 json_mac
= json_object_new_object();
6272 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6275 wctx
.json
= json_mac
;
6279 "Number of MACs (local and remote) known for this VNI: %u\n",
6281 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6282 "Intf/Remote VTEP", "VLAN");
6284 json_object_int_add(json
, "numMacs", num_macs
);
6286 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6289 json_object_object_add(json
, "macs", json_mac
);
6290 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6291 json
, JSON_C_TO_STRING_PRETTY
));
6292 json_object_free(json
);
6297 * Display MACs for all VNIs (VTY command handler).
6299 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6300 bool print_dup
, bool use_json
)
6302 struct mac_walk_ctx wctx
;
6303 json_object
*json
= NULL
;
6305 if (!is_evpn_enabled()) {
6307 vty_out(vty
, "{}\n");
6311 json
= json_object_new_object();
6313 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6316 wctx
.print_dup
= print_dup
;
6317 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6320 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6321 json
, JSON_C_TO_STRING_PRETTY
));
6322 json_object_free(json
);
6327 * Display MACs in detail for all VNIs (VTY command handler).
6329 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6330 struct zebra_vrf
*zvrf
,
6331 bool print_dup
, bool use_json
)
6333 struct mac_walk_ctx wctx
;
6334 json_object
*json
= NULL
;
6336 if (!is_evpn_enabled()) {
6338 vty_out(vty
, "{}\n");
6342 json
= json_object_new_object();
6344 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6347 wctx
.print_dup
= print_dup
;
6348 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6352 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6353 json
, JSON_C_TO_STRING_PRETTY
));
6354 json_object_free(json
);
6359 * Display MACs for all VNIs (VTY command handler).
6361 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6362 struct zebra_vrf
*zvrf
,
6363 struct in_addr vtep_ip
, bool use_json
)
6365 struct mac_walk_ctx wctx
;
6366 json_object
*json
= NULL
;
6368 if (!is_evpn_enabled())
6372 json
= json_object_new_object();
6374 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6376 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6377 wctx
.r_vtep_ip
= vtep_ip
;
6379 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6382 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6383 json
, JSON_C_TO_STRING_PRETTY
));
6384 json_object_free(json
);
6389 * Display specific MAC for a VNI, if present (VTY command handler).
6391 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6392 vni_t vni
, struct ethaddr
*macaddr
,
6397 json_object
*json
= NULL
;
6399 if (!is_evpn_enabled())
6402 zvni
= zvni_lookup(vni
);
6405 vty_out(vty
, "{}\n");
6407 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6410 mac
= zvni_mac_lookup(zvni
, macaddr
);
6413 vty_out(vty
, "{}\n");
6416 "%% Requested MAC does not exist in VNI %u\n",
6422 json
= json_object_new_object();
6424 zvni_print_mac(mac
, vty
, json
);
6426 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6427 json
, JSON_C_TO_STRING_PRETTY
));
6428 json_object_free(json
);
6432 /* Print Duplicate MACs per VNI */
6433 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6434 struct zebra_vrf
*zvrf
,
6435 vni_t vni
, bool use_json
)
6438 struct mac_walk_ctx wctx
;
6440 json_object
*json
= NULL
;
6441 json_object
*json_mac
= NULL
;
6443 if (!is_evpn_enabled())
6446 zvni
= zvni_lookup(vni
);
6448 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6452 num_macs
= num_valid_macs(zvni
);
6456 num_macs
= num_dup_detected_macs(zvni
);
6461 json
= json_object_new_object();
6462 json_mac
= json_object_new_object();
6465 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6468 wctx
.json
= json_mac
;
6472 "Number of MACs (local and remote) known for this VNI: %u\n",
6474 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6475 "Intf/Remote VTEP", "VLAN");
6477 json_object_int_add(json
, "numMacs", num_macs
);
6479 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6482 json_object_object_add(json
, "macs", json_mac
);
6483 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6484 json
, JSON_C_TO_STRING_PRETTY
));
6485 json_object_free(json
);
6490 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6491 struct zebra_vrf
*zvrf
,
6492 vni_t vni
, struct ethaddr
*macaddr
)
6496 struct listnode
*node
= NULL
;
6497 zebra_neigh_t
*nbr
= NULL
;
6499 if (!is_evpn_enabled())
6502 zvni
= zvni_lookup(vni
);
6504 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6508 mac
= zvni_mac_lookup(zvni
, macaddr
);
6510 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6515 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6516 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6520 /* Remove all IPs as duplicate associcated with this MAC */
6521 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6522 /* For local neigh mark inactive so MACIP update is generated
6523 * to BGP. This is a scenario where MAC update received
6524 * and detected as duplicate which marked neigh as duplicate.
6525 * Later local neigh update did not get a chance to relay
6526 * to BGP. Similarly remote macip update, neigh needs to be
6527 * installed locally.
6529 if (zvrf
->dad_freeze
&&
6530 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6531 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6532 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6533 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6534 zvni_neigh_install(zvni
, nbr
);
6537 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6539 nbr
->detect_start_time
.tv_sec
= 0;
6540 nbr
->dad_dup_detect_time
= 0;
6543 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6545 mac
->detect_start_time
.tv_sec
= 0;
6546 mac
->detect_start_time
.tv_usec
= 0;
6547 mac
->dad_dup_detect_time
= 0;
6548 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6550 /* warn-only action return */
6551 if (!zvrf
->dad_freeze
)
6554 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6555 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6557 if (zvni_mac_send_add_to_client(zvni
->vni
,
6563 /* Process all neighbors associated with this MAC. */
6564 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6566 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6567 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6569 /* Install the entry. */
6570 zvni_mac_install(zvni
, mac
);
6576 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6577 struct zebra_vrf
*zvrf
,
6578 vni_t vni
, struct ipaddr
*ip
)
6583 char buf
[INET6_ADDRSTRLEN
];
6584 char buf2
[ETHER_ADDR_STRLEN
];
6586 if (!is_evpn_enabled())
6589 zvni
= zvni_lookup(vni
);
6591 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6595 nbr
= zvni_neigh_lookup(zvni
, ip
);
6598 "%% Requested host IP does not exist in VNI %u\n",
6603 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6605 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6607 "%% Requsted host IP %s is not duplicate detected\n",
6612 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6614 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6616 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6617 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6618 return CMD_WARNING_CONFIG_FAILED
;
6621 if (IS_ZEBRA_DEBUG_VXLAN
)
6622 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6623 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6626 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6628 nbr
->detect_start_time
.tv_sec
= 0;
6629 nbr
->detect_start_time
.tv_usec
= 0;
6630 nbr
->dad_dup_detect_time
= 0;
6631 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6633 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6634 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6636 nbr
->flags
, nbr
->loc_seq
);
6637 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6638 zvni_neigh_install(zvni
, nbr
);
6644 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6646 struct mac_walk_ctx
*wctx
= ctxt
;
6649 struct listnode
*node
= NULL
;
6650 zebra_neigh_t
*nbr
= NULL
;
6652 mac
= (zebra_mac_t
*)bucket
->data
;
6658 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6661 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6663 mac
->detect_start_time
.tv_sec
= 0;
6664 mac
->detect_start_time
.tv_usec
= 0;
6665 mac
->dad_dup_detect_time
= 0;
6666 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6668 /* Remove all IPs as duplicate associcated with this MAC */
6669 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6670 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6672 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6674 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6676 nbr
->detect_start_time
.tv_sec
= 0;
6677 nbr
->dad_dup_detect_time
= 0;
6680 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6681 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6683 if (zvni_mac_send_add_to_client(zvni
->vni
,
6685 mac
->flags
, mac
->loc_seq
))
6688 /* Process all neighbors associated with this MAC. */
6689 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6691 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6692 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6694 /* Install the entry. */
6695 zvni_mac_install(zvni
, mac
);
6699 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6701 struct neigh_walk_ctx
*wctx
= ctxt
;
6704 char buf
[INET6_ADDRSTRLEN
];
6706 nbr
= (zebra_neigh_t
*)bucket
->data
;
6712 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6715 if (IS_ZEBRA_DEBUG_VXLAN
) {
6716 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6718 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6719 __PRETTY_FUNCTION__
, buf
,
6720 nbr
->flags
, nbr
->loc_seq
);
6723 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6725 nbr
->detect_start_time
.tv_sec
= 0;
6726 nbr
->detect_start_time
.tv_usec
= 0;
6727 nbr
->dad_dup_detect_time
= 0;
6728 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6730 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6731 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6733 nbr
->flags
, nbr
->loc_seq
);
6734 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6735 zvni_neigh_install(zvni
, nbr
);
6739 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6744 struct zebra_vrf
*zvrf
;
6745 struct mac_walk_ctx m_wctx
;
6746 struct neigh_walk_ctx n_wctx
;
6748 zvni
= (zebra_vni_t
*)bucket
->data
;
6752 vty
= (struct vty
*)args
[0];
6753 zvrf
= (struct zebra_vrf
*)args
[1];
6755 if (hashcount(zvni
->neigh_table
)) {
6756 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6760 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6764 if (num_valid_macs(zvni
)) {
6765 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6769 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6774 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6775 struct zebra_vrf
*zvrf
)
6779 if (!is_evpn_enabled())
6785 hash_iterate(zvrf
->vni_table
,
6786 (void (*)(struct hash_bucket
*, void *))
6787 zvni_clear_dup_detect_hash_vni_all
, args
);
6792 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6793 struct zebra_vrf
*zvrf
,
6797 struct mac_walk_ctx m_wctx
;
6798 struct neigh_walk_ctx n_wctx
;
6800 if (!is_evpn_enabled())
6803 zvni
= zvni_lookup(vni
);
6805 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6809 if (hashcount(zvni
->neigh_table
)) {
6810 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6814 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6818 if (num_valid_macs(zvni
)) {
6819 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6823 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6830 * Display MACs for a VNI from specific VTEP (VTY command handler).
6832 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6833 vni_t vni
, struct in_addr vtep_ip
,
6838 struct mac_walk_ctx wctx
;
6839 json_object
*json
= NULL
;
6840 json_object
*json_mac
= NULL
;
6842 if (!is_evpn_enabled())
6844 zvni
= zvni_lookup(vni
);
6847 vty_out(vty
, "{}\n");
6849 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6852 num_macs
= num_valid_macs(zvni
);
6857 json
= json_object_new_object();
6858 json_mac
= json_object_new_object();
6861 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6864 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6865 wctx
.r_vtep_ip
= vtep_ip
;
6866 wctx
.json
= json_mac
;
6867 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6870 json_object_int_add(json
, "numMacs", wctx
.count
);
6872 json_object_object_add(json
, "macs", json_mac
);
6873 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6874 json
, JSON_C_TO_STRING_PRETTY
));
6875 json_object_free(json
);
6881 * Display VNI information (VTY command handler).
6883 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6886 json_object
*json
= NULL
;
6888 zebra_l3vni_t
*zl3vni
= NULL
;
6889 zebra_vni_t
*zvni
= NULL
;
6891 if (!is_evpn_enabled())
6895 json
= json_object_new_object();
6899 zl3vni
= zl3vni_lookup(vni
);
6901 zl3vni_print(zl3vni
, (void *)args
);
6903 zvni
= zvni_lookup(vni
);
6906 vty_out(vty
, "{}\n");
6908 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6912 zvni_print(zvni
, (void *)args
);
6916 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6917 json
, JSON_C_TO_STRING_PRETTY
));
6918 json_object_free(json
);
6922 /* Display all global details for EVPN */
6923 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6928 json_object
*json
= NULL
;
6929 struct zebra_vrf
*zvrf
= NULL
;
6931 if (!is_evpn_enabled())
6934 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
6938 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6939 num_l2vnis
= hashcount(zvrf
->vni_table
);
6940 num_vnis
= num_l2vnis
+ num_l3vnis
;
6943 json
= json_object_new_object();
6944 json_object_string_add(json
, "advertiseGatewayMacip",
6945 zvrf
->advertise_gw_macip
? "Yes" : "No");
6946 json_object_int_add(json
, "numVnis", num_vnis
);
6947 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6948 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6949 if (zvrf
->dup_addr_detect
)
6950 json_object_boolean_true_add(json
,
6951 "isDuplicateAddrDetection");
6953 json_object_boolean_false_add(json
,
6954 "isDuplicateAddrDetection");
6955 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6956 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6957 json_object_int_add(json
, "detectionFreezeTime",
6958 zvrf
->dad_freeze_time
);
6961 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6962 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6963 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6964 zvrf
->advertise_gw_macip
? "Yes" : "No");
6965 vty_out(vty
, "Advertise svi mac-ip: %s\n",
6966 zvrf
->advertise_svi_macip
? "Yes" : "No");
6967 vty_out(vty
, "Duplicate address detection: %s\n",
6968 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6969 vty_out(vty
, " Detection max-moves %u, time %d\n",
6970 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6971 if (zvrf
->dad_freeze
) {
6972 if (zvrf
->dad_freeze_time
)
6973 vty_out(vty
, " Detection freeze %u\n",
6974 zvrf
->dad_freeze_time
);
6976 vty_out(vty
, " Detection freeze %s\n",
6982 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6983 json
, JSON_C_TO_STRING_PRETTY
));
6984 json_object_free(json
);
6989 * Display VNI hash table (VTY command handler).
6991 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6994 json_object
*json
= NULL
;
6997 if (!is_evpn_enabled())
7001 json
= json_object_new_object();
7003 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7004 "Type", "VxLAN IF", "# MACs", "# ARPs",
7005 "# Remote VTEPs", "Tenant VRF");
7010 /* Display all L2-VNIs */
7011 hash_iterate(zvrf
->vni_table
,
7012 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7015 /* Display all L3-VNIs */
7016 hash_iterate(zrouter
.l3vni_table
,
7017 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7021 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7022 json
, JSON_C_TO_STRING_PRETTY
));
7023 json_object_free(json
);
7027 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7031 uint32_t max_moves
= 0;
7032 uint32_t freeze_time
= 0;
7033 bool dup_addr_detect
= false;
7034 bool freeze
= false;
7037 STREAM_GETL(s
, dup_addr_detect
);
7038 STREAM_GETL(s
, time
);
7039 STREAM_GETL(s
, max_moves
);
7040 STREAM_GETL(s
, freeze
);
7041 STREAM_GETL(s
, freeze_time
);
7043 /* DAD previous state was enabled, and new state is disable,
7044 * clear all duplicate detected addresses.
7046 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7047 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7049 zvrf
->dup_addr_detect
= dup_addr_detect
;
7050 zvrf
->dad_time
= time
;
7051 zvrf
->dad_max_moves
= max_moves
;
7052 zvrf
->dad_freeze
= freeze
;
7053 zvrf
->dad_freeze_time
= freeze_time
;
7055 if (IS_ZEBRA_DEBUG_VXLAN
)
7057 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7058 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7059 zvrf
->dup_addr_detect
? "enable" : "disable",
7060 zvrf
->dad_max_moves
,
7062 zvrf
->dad_freeze
? "enable" : "disable",
7063 zvrf
->dad_freeze_time
);
7070 * Display VNI hash table in detail(VTY command handler).
7072 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7075 json_object
*json
= NULL
;
7076 struct zebra_ns
*zns
= NULL
;
7077 struct zvni_evpn_show zes
;
7079 if (!is_evpn_enabled())
7082 zns
= zebra_ns_lookup(NS_DEFAULT
);
7088 json
= json_object_new_object();
7094 /* Display all L2-VNIs */
7095 hash_iterate(zvrf
->vni_table
, (void (*)(struct hash_bucket
*,
7096 void *))zvni_print_hash_detail
,
7099 /* Display all L3-VNIs */
7100 hash_iterate(zrouter
.l3vni_table
,
7101 (void (*)(struct hash_bucket
*,
7102 void *))zl3vni_print_hash_detail
,
7106 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7107 json
, JSON_C_TO_STRING_PRETTY
));
7108 json_object_free(json
);
7113 * Handle neighbor delete notification from the kernel (on a VLAN device
7114 * / L3 interface). This may result in either the neighbor getting deleted
7115 * from our database or being re-added to the kernel (if it is a valid
7118 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7119 struct interface
*link_if
,
7122 char buf
[INET6_ADDRSTRLEN
];
7123 char buf2
[ETHER_ADDR_STRLEN
];
7124 zebra_neigh_t
*n
= NULL
;
7125 zebra_vni_t
*zvni
= NULL
;
7126 zebra_mac_t
*zmac
= NULL
;
7127 zebra_l3vni_t
*zl3vni
= NULL
;
7128 struct zebra_vrf
*zvrf
;
7130 /* check if this is a remote neigh entry corresponding to remote
7133 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7135 return zl3vni_local_nh_del(zl3vni
, ip
);
7137 /* We are only interested in neighbors on an SVI that resides on top
7138 * of a VxLAN bridge.
7140 zvni
= zvni_from_svi(ifp
, link_if
);
7144 if (!zvni
->vxlan_if
) {
7146 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7151 if (IS_ZEBRA_DEBUG_VXLAN
)
7152 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7153 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7154 ifp
->ifindex
, zvni
->vni
);
7156 /* If entry doesn't exist, nothing to do. */
7157 n
= zvni_neigh_lookup(zvni
, ip
);
7161 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7163 if (IS_ZEBRA_DEBUG_VXLAN
)
7165 "Trying to del a neigh %s without a mac %s on VNI %u",
7166 ipaddr2str(ip
, buf
, sizeof(buf
)),
7167 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7173 /* If it is a remote entry, the kernel has aged this out or someone has
7174 * deleted it, it needs to be re-installed as Quagga is the owner.
7176 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7177 zvni_neigh_install(zvni
, n
);
7181 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7183 zlog_debug("%s: VNI %u vrf lookup failed.",
7184 __PRETTY_FUNCTION__
, zvni
->vni
);
7188 /* In case of feeze action, if local neigh is in duplicate state,
7189 * Mark the Neigh as inactive before sending delete request to BGPd,
7190 * If BGPd has remote entry, it will re-install
7192 if (zvrf
->dad_freeze
&&
7193 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7194 ZEBRA_NEIGH_SET_INACTIVE(n
);
7196 /* Remove neighbor from BGP. */
7197 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7199 /* Delete this neighbor entry. */
7200 zvni_neigh_del(zvni
, n
);
7202 /* see if the AUTO mac needs to be deleted */
7203 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7204 && !listcount(zmac
->neigh_list
))
7205 zvni_mac_del(zvni
, zmac
);
7211 * Handle neighbor add or update notification from the kernel (on a VLAN
7212 * device / L3 interface). This is typically for a local neighbor but can
7213 * also be for a remote neighbor (e.g., ageout notification). It could
7214 * also be a "move" scenario.
7216 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7217 struct interface
*link_if
,
7219 struct ethaddr
*macaddr
,
7224 char buf
[ETHER_ADDR_STRLEN
];
7225 char buf2
[INET6_ADDRSTRLEN
];
7226 zebra_vni_t
*zvni
= NULL
;
7227 zebra_l3vni_t
*zl3vni
= NULL
;
7229 /* check if this is a remote neigh entry corresponding to remote
7232 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7234 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7236 /* We are only interested in neighbors on an SVI that resides on top
7237 * of a VxLAN bridge.
7239 zvni
= zvni_from_svi(ifp
, link_if
);
7243 if (IS_ZEBRA_DEBUG_VXLAN
)
7245 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7246 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7247 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7248 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7249 is_router
? "router " : "",
7252 /* Is this about a local neighbor or a remote one? */
7254 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7257 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7262 * Handle message from client to delete a remote MACIP for a VNI.
7264 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7268 struct ethaddr macaddr
;
7270 struct in_addr vtep_ip
;
7271 uint16_t l
= 0, ipa_len
;
7272 char buf
[ETHER_ADDR_STRLEN
];
7273 char buf1
[INET6_ADDRSTRLEN
];
7275 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7276 memset(&ip
, 0, sizeof(struct ipaddr
));
7277 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7281 while (l
< hdr
->length
) {
7282 /* Obtain each remote MACIP and process. */
7283 /* Message contains VNI, followed by MAC followed by IP (if any)
7284 * followed by remote VTEP IP.
7286 memset(&ip
, 0, sizeof(ip
));
7287 STREAM_GETL(s
, vni
);
7288 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7289 STREAM_GETL(s
, ipa_len
);
7291 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7293 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7295 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7296 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7297 l
+= IPV4_MAX_BYTELEN
;
7299 if (IS_ZEBRA_DEBUG_VXLAN
)
7301 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7303 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7304 ipa_len
? " IP " : "",
7306 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7308 zebra_route_string(client
->proto
));
7310 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7318 * Handle message from client to add a remote MACIP for a VNI. This
7319 * could be just the add of a MAC address or the add of a neighbor
7322 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7326 struct ethaddr macaddr
;
7328 struct in_addr vtep_ip
;
7329 uint16_t l
= 0, ipa_len
;
7332 char buf
[ETHER_ADDR_STRLEN
];
7333 char buf1
[INET6_ADDRSTRLEN
];
7335 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7336 memset(&ip
, 0, sizeof(struct ipaddr
));
7337 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7339 if (!EVPN_ENABLED(zvrf
)) {
7340 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7346 while (l
< hdr
->length
) {
7347 /* Obtain each remote MACIP and process. */
7348 /* Message contains VNI, followed by MAC followed by IP (if any)
7349 * followed by remote VTEP IP.
7351 memset(&ip
, 0, sizeof(ip
));
7352 STREAM_GETL(s
, vni
);
7353 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7354 STREAM_GETL(s
, ipa_len
);
7356 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7358 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7360 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7361 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7362 l
+= IPV4_MAX_BYTELEN
;
7364 /* Get flags - sticky mac and/or gateway mac */
7365 STREAM_GETC(s
, flags
);
7367 STREAM_GETL(s
, seq
);
7370 if (IS_ZEBRA_DEBUG_VXLAN
)
7372 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7374 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7375 ipa_len
? " IP " : "",
7377 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7378 flags
, seq
, inet_ntoa(vtep_ip
),
7379 zebra_route_string(client
->proto
));
7381 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7382 flags
, seq
, vtep_ip
);
7390 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7391 * us, this must involve a multihoming scenario. Treat this as implicit delete
7392 * of any prior local MAC.
7394 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7395 struct interface
*br_if
,
7396 struct ethaddr
*macaddr
, vlanid_t vid
)
7398 struct zebra_if
*zif
;
7399 struct zebra_l2info_vxlan
*vxl
;
7403 char buf
[ETHER_ADDR_STRLEN
];
7407 vxl
= &zif
->l2info
.vxl
;
7410 /* Check if EVPN is enabled. */
7411 if (!is_evpn_enabled())
7414 /* Locate hash entry; it is expected to exist. */
7415 zvni
= zvni_lookup(vni
);
7419 /* If entry doesn't exist, nothing to do. */
7420 mac
= zvni_mac_lookup(zvni
, macaddr
);
7424 /* Is it a local entry? */
7425 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7428 if (IS_ZEBRA_DEBUG_VXLAN
)
7430 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7431 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7434 /* Remove MAC from BGP. */
7435 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7438 * If there are no neigh associated with the mac delete the mac
7439 * else mark it as AUTO for forward reference
7441 if (!listcount(mac
->neigh_list
)) {
7442 zvni_mac_del(zvni
, mac
);
7444 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7445 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7452 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7453 * This can happen because the remote MAC entries are also added as "dynamic",
7454 * so the kernel can ageout the entry.
7456 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7457 struct interface
*br_if
,
7458 struct ethaddr
*macaddr
, vlanid_t vid
)
7460 struct zebra_if
*zif
= NULL
;
7461 struct zebra_l2info_vxlan
*vxl
= NULL
;
7463 zebra_vni_t
*zvni
= NULL
;
7464 zebra_l3vni_t
*zl3vni
= NULL
;
7465 zebra_mac_t
*mac
= NULL
;
7466 char buf
[ETHER_ADDR_STRLEN
];
7470 vxl
= &zif
->l2info
.vxl
;
7473 /* Check if EVPN is enabled. */
7474 if (!is_evpn_enabled())
7477 /* check if this is a remote RMAC and readd simillar to remote macs */
7478 zl3vni
= zl3vni_lookup(vni
);
7480 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7482 /* Locate hash entry; it is expected to exist. */
7483 zvni
= zvni_lookup(vni
);
7487 /* If entry doesn't exist, nothing to do. */
7488 mac
= zvni_mac_lookup(zvni
, macaddr
);
7492 /* Is it a remote entry? */
7493 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7496 if (IS_ZEBRA_DEBUG_VXLAN
)
7497 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7498 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7501 zvni_mac_install(zvni
, mac
);
7506 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7508 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7509 struct ethaddr
*macaddr
, vlanid_t vid
)
7513 char buf
[ETHER_ADDR_STRLEN
];
7515 /* We are interested in MACs only on ports or (port, VLAN) that
7518 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7521 if (!zvni
->vxlan_if
) {
7523 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7528 if (IS_ZEBRA_DEBUG_VXLAN
)
7529 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7530 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7531 ifp
->ifindex
, vid
, zvni
->vni
);
7533 /* If entry doesn't exist, nothing to do. */
7534 mac
= zvni_mac_lookup(zvni
, macaddr
);
7538 /* Is it a local entry? */
7539 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7542 /* Update all the neigh entries associated with this mac */
7543 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7545 /* Remove MAC from BGP. */
7546 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7549 * If there are no neigh associated with the mac delete the mac
7550 * else mark it as AUTO for forward reference
7552 if (!listcount(mac
->neigh_list
)) {
7553 zvni_mac_del(zvni
, mac
);
7555 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7556 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7563 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7565 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7566 struct interface
*br_if
,
7567 struct ethaddr
*macaddr
, vlanid_t vid
,
7572 struct zebra_vrf
*zvrf
;
7573 char buf
[ETHER_ADDR_STRLEN
];
7574 bool mac_sticky
= false;
7575 bool inform_client
= false;
7576 bool upd_neigh
= false;
7577 bool is_dup_detect
= false;
7578 struct in_addr vtep_ip
= {.s_addr
= 0};
7580 /* We are interested in MACs only on ports or (port, VLAN) that
7583 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7585 if (IS_ZEBRA_DEBUG_VXLAN
)
7587 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7588 sticky
? "sticky " : "",
7589 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7590 ifp
->name
, ifp
->ifindex
, vid
);
7594 if (!zvni
->vxlan_if
) {
7596 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7601 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7605 /* Check if we need to create or update or it is a NO-OP. */
7606 mac
= zvni_mac_lookup(zvni
, macaddr
);
7608 if (IS_ZEBRA_DEBUG_VXLAN
)
7610 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7611 sticky
? "sticky " : "",
7612 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7613 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7615 mac
= zvni_mac_add(zvni
, macaddr
);
7618 EC_ZEBRA_MAC_ADD_FAILED
,
7619 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7620 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7621 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7624 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7625 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7626 mac
->fwd_info
.local
.vid
= vid
;
7628 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7629 inform_client
= true;
7632 if (IS_ZEBRA_DEBUG_VXLAN
)
7634 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7635 sticky
? "sticky " : "",
7636 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7637 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7640 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7641 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7645 * Update any changes and if changes are relevant to
7648 if (mac_sticky
== sticky
7649 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7650 && mac
->fwd_info
.local
.vid
== vid
) {
7651 if (IS_ZEBRA_DEBUG_VXLAN
)
7653 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7654 "entry exists and has not changed ",
7655 sticky
? "sticky " : "",
7656 prefix_mac2str(macaddr
, buf
,
7658 ifp
->name
, ifp
->ifindex
, vid
,
7662 if (mac_sticky
!= sticky
) {
7664 SET_FLAG(mac
->flags
,
7667 UNSET_FLAG(mac
->flags
,
7669 inform_client
= true;
7672 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7673 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7674 mac
->fwd_info
.local
.vid
= vid
;
7676 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7677 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7678 bool do_dad
= false;
7681 * MAC has either moved or was "internally" created due
7682 * to a neighbor learn and is now actually learnt. If
7683 * it was learnt as a remote sticky MAC, this is an
7686 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7688 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7689 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7690 prefix_mac2str(macaddr
, buf
,
7692 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7697 /* If an actual move, compute MAC's seq number */
7698 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7699 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7701 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7702 /* Trigger DAD for remote MAC */
7706 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7707 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7708 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7709 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7710 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7711 mac
->fwd_info
.local
.vid
= vid
;
7713 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7715 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7717 * We have to inform BGP of this MAC as well as process
7720 inform_client
= true;
7723 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7727 if (is_dup_detect
) {
7728 inform_client
= false;
7734 /* Inform BGP if required. */
7735 if (inform_client
) {
7736 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7737 mac
->flags
, mac
->loc_seq
))
7741 /* Process all neighbors associated with this MAC, if required. */
7743 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7749 * Handle message from client to delete a remote VTEP for a VNI.
7751 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7754 unsigned short l
= 0;
7756 struct in_addr vtep_ip
;
7758 zebra_vtep_t
*zvtep
;
7759 struct interface
*ifp
;
7760 struct zebra_if
*zif
;
7762 if (!is_evpn_enabled()) {
7764 "%s: EVPN is not enabled yet we have received a vtep del command",
7765 __PRETTY_FUNCTION__
);
7769 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7770 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7777 while (l
< hdr
->length
) {
7778 /* Obtain each remote VTEP and process. */
7779 STREAM_GETL(s
, vni
);
7781 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7782 l
+= IPV4_MAX_BYTELEN
;
7784 if (IS_ZEBRA_DEBUG_VXLAN
)
7785 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7786 inet_ntoa(vtep_ip
), vni
,
7787 zebra_route_string(client
->proto
));
7789 /* Locate VNI hash entry - expected to exist. */
7790 zvni
= zvni_lookup(vni
);
7792 if (IS_ZEBRA_DEBUG_VXLAN
)
7794 "Failed to locate VNI hash upon remote VTEP DEL, "
7800 ifp
= zvni
->vxlan_if
;
7803 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7809 /* If down or not mapped to a bridge, we're done. */
7810 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7813 /* If the remote VTEP does not exist, there's nothing more to
7815 * Otherwise, uninstall any remote MACs pointing to this VTEP
7817 * then, the VTEP entry itself and remove it.
7819 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7823 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7824 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7825 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7826 zvni_vtep_del(zvni
, zvtep
);
7834 * Handle message from client to add a remote VTEP for a VNI.
7836 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7839 unsigned short l
= 0;
7841 struct in_addr vtep_ip
;
7843 struct interface
*ifp
;
7844 struct zebra_if
*zif
;
7846 if (!is_evpn_enabled()) {
7848 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7849 __PRETTY_FUNCTION__
);
7853 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
7854 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7861 while (l
< hdr
->length
) {
7862 /* Obtain each remote VTEP and process. */
7863 STREAM_GETL(s
, vni
);
7865 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7866 l
+= IPV4_MAX_BYTELEN
;
7868 if (IS_ZEBRA_DEBUG_VXLAN
)
7869 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7870 inet_ntoa(vtep_ip
), vni
,
7871 zebra_route_string(client
->proto
));
7873 /* Locate VNI hash entry - expected to exist. */
7874 zvni
= zvni_lookup(vni
);
7877 EC_ZEBRA_VTEP_ADD_FAILED
,
7878 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7883 ifp
= zvni
->vxlan_if
;
7886 EC_ZEBRA_VTEP_ADD_FAILED
,
7887 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7894 /* If down or not mapped to a bridge, we're done. */
7895 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7898 /* If the remote VTEP already exists,
7899 there's nothing more to do. */
7900 if (zvni_vtep_find(zvni
, &vtep_ip
))
7903 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7904 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7905 "Failed to add remote VTEP, VNI %u zvni %p",
7910 zvni_vtep_install(zvni
, &vtep_ip
);
7918 * Add/Del gateway macip to evpn
7920 * 1. SVI interface on a vlan aware bridge
7921 * 2. SVI interface on a vlan unaware bridge
7922 * 3. vrr interface (MACVLAN) associated to a SVI
7923 * We advertise macip routes for an interface if it is associated to VxLan vlan
7925 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7929 struct ethaddr macaddr
;
7930 zebra_vni_t
*zvni
= NULL
;
7932 memset(&ip
, 0, sizeof(struct ipaddr
));
7933 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7935 /* Check if EVPN is enabled. */
7936 if (!is_evpn_enabled())
7939 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7940 struct interface
*svi_if
=
7941 NULL
; /* SVI corresponding to the MACVLAN */
7942 struct zebra_if
*ifp_zif
=
7943 NULL
; /* Zebra daemon specific info for MACVLAN */
7944 struct zebra_if
*svi_if_zif
=
7945 NULL
; /* Zebra daemon specific info for SVI*/
7947 ifp_zif
= ifp
->info
;
7952 * for a MACVLAN interface the link represents the svi_if
7954 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7955 ifp_zif
->link_ifindex
);
7957 zlog_debug("MACVLAN %s(%u) without link information",
7958 ifp
->name
, ifp
->ifindex
);
7962 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7964 * If it is a vlan aware bridge then the link gives the
7965 * bridge information
7967 struct interface
*svi_if_link
= NULL
;
7969 svi_if_zif
= svi_if
->info
;
7971 svi_if_link
= if_lookup_by_index_per_ns(
7972 zebra_ns_lookup(NS_DEFAULT
),
7973 svi_if_zif
->link_ifindex
);
7974 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7976 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7978 * If it is a vlan unaware bridge then svi is the bridge
7981 zvni
= zvni_from_svi(svi_if
, svi_if
);
7983 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7984 struct zebra_if
*svi_if_zif
=
7985 NULL
; /* Zebra daemon specific info for SVI */
7986 struct interface
*svi_if_link
=
7987 NULL
; /* link info for the SVI = bridge info */
7989 svi_if_zif
= ifp
->info
;
7991 svi_if_link
= if_lookup_by_index_per_ns(
7992 zebra_ns_lookup(NS_DEFAULT
),
7993 svi_if_zif
->link_ifindex
);
7995 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7997 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7998 zvni
= zvni_from_svi(ifp
, ifp
);
8004 if (!zvni
->vxlan_if
) {
8005 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8011 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8013 if (p
->family
== AF_INET
) {
8014 ip
.ipa_type
= IPADDR_V4
;
8015 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8016 sizeof(struct in_addr
));
8017 } else if (p
->family
== AF_INET6
) {
8018 ip
.ipa_type
= IPADDR_V6
;
8019 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8020 sizeof(struct in6_addr
));
8025 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8027 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8033 * Handle SVI interface going down.
8034 * SVI can be associated to either L3-VNI or L2-VNI.
8035 * For L2-VNI: At this point, this is a NOP since
8036 * the kernel deletes the neighbor entries on this SVI (if any).
8037 * We only need to update the vrf corresponding to zvni.
8038 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8041 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8043 zebra_l3vni_t
*zl3vni
= NULL
;
8045 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8048 /* process l3-vni down */
8049 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8051 /* remove association with svi-if */
8052 zl3vni
->svi_if
= NULL
;
8054 zebra_vni_t
*zvni
= NULL
;
8056 /* since we dont have svi corresponding to zvni, we associate it
8057 * to default vrf. Note: the corresponding neigh entries on the
8058 * SVI would have already been deleted */
8059 zvni
= zvni_from_svi(ifp
, link_if
);
8061 zvni
->vrf_id
= VRF_DEFAULT
;
8063 /* update the tenant vrf in BGP */
8064 zvni_send_add_to_client(zvni
);
8071 * Handle SVI interface coming up.
8072 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8074 * For L2-VNI: we need to install any remote neighbors entried (used for
8076 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8078 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8080 zebra_vni_t
*zvni
= NULL
;
8081 zebra_l3vni_t
*zl3vni
= NULL
;
8083 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8086 /* associate with svi */
8087 zl3vni
->svi_if
= ifp
;
8089 /* process oper-up */
8090 if (is_l3vni_oper_up(zl3vni
))
8091 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8094 /* process SVI up for l2-vni */
8095 struct neigh_walk_ctx n_wctx
;
8097 zvni
= zvni_from_svi(ifp
, link_if
);
8101 if (!zvni
->vxlan_if
) {
8103 "VNI %u hash %p doesn't have intf upon SVI up",
8108 if (IS_ZEBRA_DEBUG_VXLAN
)
8110 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8111 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8112 vrf_id_to_name(ifp
->vrf_id
));
8114 /* update the vrf information for l2-vni and inform bgp */
8115 zvni
->vrf_id
= ifp
->vrf_id
;
8116 zvni_send_add_to_client(zvni
);
8118 /* Install any remote neighbors for this VNI. */
8119 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8121 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8129 * Handle VxLAN interface down
8131 int zebra_vxlan_if_down(struct interface
*ifp
)
8134 struct zebra_if
*zif
= NULL
;
8135 struct zebra_l2info_vxlan
*vxl
= NULL
;
8136 zebra_l3vni_t
*zl3vni
= NULL
;
8139 /* Check if EVPN is enabled. */
8140 if (!is_evpn_enabled())
8145 vxl
= &zif
->l2info
.vxl
;
8148 zl3vni
= zl3vni_lookup(vni
);
8150 /* process-if-down for l3-vni */
8151 if (IS_ZEBRA_DEBUG_VXLAN
)
8152 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8155 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8157 /* process if-down for l2-vni */
8158 if (IS_ZEBRA_DEBUG_VXLAN
)
8159 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8162 /* Locate hash entry; it is expected to exist. */
8163 zvni
= zvni_lookup(vni
);
8166 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8167 ifp
->name
, ifp
->ifindex
, vni
);
8171 assert(zvni
->vxlan_if
== ifp
);
8173 /* Delete this VNI from BGP. */
8174 zvni_send_del_to_client(zvni
->vni
);
8176 /* Free up all neighbors and MACs, if any. */
8177 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8178 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8180 /* Free up all remote VTEPs, if any. */
8181 zvni_vtep_del_all(zvni
, 1);
8187 * Handle VxLAN interface up - update BGP if required.
8189 int zebra_vxlan_if_up(struct interface
*ifp
)
8192 struct zebra_if
*zif
= NULL
;
8193 struct zebra_l2info_vxlan
*vxl
= NULL
;
8194 zebra_vni_t
*zvni
= NULL
;
8195 zebra_l3vni_t
*zl3vni
= NULL
;
8197 /* Check if EVPN is enabled. */
8198 if (!is_evpn_enabled())
8203 vxl
= &zif
->l2info
.vxl
;
8206 zl3vni
= zl3vni_lookup(vni
);
8209 if (IS_ZEBRA_DEBUG_VXLAN
)
8210 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8213 /* we need to associate with SVI, if any, we can associate with
8214 * svi-if only after association with vxlan-intf is complete
8216 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8218 if (is_l3vni_oper_up(zl3vni
))
8219 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8221 /* Handle L2-VNI add */
8222 struct interface
*vlan_if
= NULL
;
8224 if (IS_ZEBRA_DEBUG_VXLAN
)
8225 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8228 /* Locate hash entry; it is expected to exist. */
8229 zvni
= zvni_lookup(vni
);
8232 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8233 ifp
->name
, ifp
->ifindex
, vni
);
8237 assert(zvni
->vxlan_if
== ifp
);
8238 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8239 zif
->brslave_info
.br_if
);
8241 zvni
->vrf_id
= vlan_if
->vrf_id
;
8242 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8244 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8247 /* If part of a bridge, inform BGP about this VNI. */
8248 /* Also, read and populate local MACs and neighbors. */
8249 if (zif
->brslave_info
.br_if
) {
8250 zvni_send_add_to_client(zvni
);
8251 zvni_read_mac_neigh(zvni
, ifp
);
8259 * Handle VxLAN interface delete. Locate and remove entry in hash table
8260 * and update BGP, if required.
8262 int zebra_vxlan_if_del(struct interface
*ifp
)
8265 struct zebra_if
*zif
= NULL
;
8266 struct zebra_l2info_vxlan
*vxl
= NULL
;
8267 zebra_vni_t
*zvni
= NULL
;
8268 zebra_l3vni_t
*zl3vni
= NULL
;
8270 /* Check if EVPN is enabled. */
8271 if (!is_evpn_enabled())
8276 vxl
= &zif
->l2info
.vxl
;
8279 zl3vni
= zl3vni_lookup(vni
);
8282 if (IS_ZEBRA_DEBUG_VXLAN
)
8283 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8286 /* process oper-down for l3-vni */
8287 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8289 /* remove the association with vxlan_if */
8290 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8291 zl3vni
->vxlan_if
= NULL
;
8294 /* process if-del for l2-vni*/
8295 if (IS_ZEBRA_DEBUG_VXLAN
)
8296 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8299 /* Locate hash entry; it is expected to exist. */
8300 zvni
= zvni_lookup(vni
);
8303 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8304 ifp
->name
, ifp
->ifindex
, vni
);
8308 /* remove from l3-vni list */
8309 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8311 listnode_delete(zl3vni
->l2vnis
, zvni
);
8313 /* Delete VNI from BGP. */
8314 zvni_send_del_to_client(zvni
->vni
);
8316 /* Free up all neighbors and MAC, if any. */
8317 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8318 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8320 /* Free up all remote VTEPs, if any. */
8321 zvni_vtep_del_all(zvni
, 0);
8323 /* Delete the hash entry. */
8324 if (zvni_del(zvni
)) {
8325 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8326 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8327 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8335 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8337 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8340 struct zebra_if
*zif
= NULL
;
8341 struct zebra_l2info_vxlan
*vxl
= NULL
;
8342 zebra_vni_t
*zvni
= NULL
;
8343 zebra_l3vni_t
*zl3vni
= NULL
;
8345 /* Check if EVPN is enabled. */
8346 if (!is_evpn_enabled())
8351 vxl
= &zif
->l2info
.vxl
;
8354 zl3vni
= zl3vni_lookup(vni
);
8357 if (IS_ZEBRA_DEBUG_VXLAN
)
8359 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8360 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8361 inet_ntoa(vxl
->vtep_ip
),
8362 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8364 /* Removed from bridge? Cleanup and return */
8365 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8366 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8367 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8371 /* access-vlan change - process oper down, associate with new
8372 * svi_if and then process oper up again
8374 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8375 if (if_is_operative(ifp
)) {
8376 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8377 zl3vni
->svi_if
= NULL
;
8378 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8379 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8380 if (is_l3vni_oper_up(zl3vni
))
8381 zebra_vxlan_process_l3vni_oper_up(
8387 * local-ip change - process oper down, associate with new
8388 * local-ip and then process oper up again
8390 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8391 if (if_is_operative(ifp
)) {
8392 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8393 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8394 if (is_l3vni_oper_up(zl3vni
))
8395 zebra_vxlan_process_l3vni_oper_up(
8400 /* Update local tunnel IP. */
8401 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8403 /* if we have a valid new master, process l3-vni oper up */
8404 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8405 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8406 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8410 /* Update VNI hash. */
8411 zvni
= zvni_lookup(vni
);
8414 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8415 ifp
->name
, ifp
->ifindex
, vni
);
8419 if (IS_ZEBRA_DEBUG_VXLAN
)
8421 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8422 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8423 inet_ntoa(vxl
->vtep_ip
),
8424 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8426 /* Removed from bridge? Cleanup and return */
8427 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8428 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8429 /* Delete from client, remove all remote VTEPs */
8430 /* Also, free up all MACs and neighbors. */
8431 zvni_send_del_to_client(zvni
->vni
);
8432 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8433 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8434 zvni_vtep_del_all(zvni
, 1);
8438 /* Handle other changes. */
8439 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8440 /* Remove all existing local neigh and MACs for this VNI
8441 * (including from BGP)
8443 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8444 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8447 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8448 zvni
->vxlan_if
= ifp
;
8450 /* Take further actions needed.
8451 * Note that if we are here, there is a change of interest.
8453 /* If down or not mapped to a bridge, we're done. */
8454 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8457 /* Inform BGP, if there is a change of interest. */
8459 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8460 zvni_send_add_to_client(zvni
);
8462 /* If there is a valid new master or a VLAN mapping change,
8463 * read and populate local MACs and neighbors.
8464 * Also, reinstall any remote MACs and neighbors
8465 * for this VNI (based on new VLAN).
8467 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8468 zvni_read_mac_neigh(zvni
, ifp
);
8469 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8470 struct mac_walk_ctx m_wctx
;
8471 struct neigh_walk_ctx n_wctx
;
8473 zvni_read_mac_neigh(zvni
, ifp
);
8475 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8477 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8480 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8482 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8491 * Handle VxLAN interface add.
8493 int zebra_vxlan_if_add(struct interface
*ifp
)
8496 struct zebra_if
*zif
= NULL
;
8497 struct zebra_l2info_vxlan
*vxl
= NULL
;
8498 zebra_vni_t
*zvni
= NULL
;
8499 zebra_l3vni_t
*zl3vni
= NULL
;
8501 /* Check if EVPN is enabled. */
8502 if (!is_evpn_enabled())
8507 vxl
= &zif
->l2info
.vxl
;
8510 zl3vni
= zl3vni_lookup(vni
);
8513 /* process if-add for l3-vni*/
8514 if (IS_ZEBRA_DEBUG_VXLAN
)
8516 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8517 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8518 inet_ntoa(vxl
->vtep_ip
),
8519 zif
->brslave_info
.bridge_ifindex
);
8521 /* associate with vxlan_if */
8522 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8523 zl3vni
->vxlan_if
= ifp
;
8525 /* Associate with SVI, if any. We can associate with svi-if only
8526 * after association with vxlan_if is complete */
8527 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8529 if (is_l3vni_oper_up(zl3vni
))
8530 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8533 /* process if-add for l2-vni */
8534 struct interface
*vlan_if
= NULL
;
8536 /* Create or update VNI hash. */
8537 zvni
= zvni_lookup(vni
);
8539 zvni
= zvni_add(vni
);
8542 EC_ZEBRA_VNI_ADD_FAILED
,
8543 "Failed to add VNI hash, IF %s(%u) VNI %u",
8544 ifp
->name
, ifp
->ifindex
, vni
);
8549 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8550 zvni
->vxlan_if
= ifp
;
8551 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8552 zif
->brslave_info
.br_if
);
8554 zvni
->vrf_id
= vlan_if
->vrf_id
;
8555 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8557 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8560 if (IS_ZEBRA_DEBUG_VXLAN
)
8562 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8564 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8566 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8567 inet_ntoa(vxl
->vtep_ip
),
8568 zif
->brslave_info
.bridge_ifindex
);
8570 /* If down or not mapped to a bridge, we're done. */
8571 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8575 zvni_send_add_to_client(zvni
);
8577 /* Read and populate local MACs and neighbors */
8578 zvni_read_mac_neigh(zvni
, ifp
);
8584 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8585 char *err
, int err_str_sz
, int filter
,
8588 zebra_l3vni_t
*zl3vni
= NULL
;
8589 struct zebra_vrf
*zvrf_default
= NULL
;
8591 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
8595 if (IS_ZEBRA_DEBUG_VXLAN
)
8596 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8597 add
? "ADD" : "DEL");
8601 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8603 /* check if the vni is already present under zvrf */
8605 snprintf(err
, err_str_sz
,
8606 "VNI is already configured under the vrf");
8610 /* check if this VNI is already present in the system */
8611 zl3vni
= zl3vni_lookup(vni
);
8613 snprintf(err
, err_str_sz
,
8614 "VNI is already configured as L3-VNI");
8618 /* add the L3-VNI to the global table */
8619 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8621 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8625 /* associate the vrf with vni */
8628 /* set the filter in l3vni to denote if we are using l3vni only
8632 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8634 /* associate with vxlan-intf;
8635 * we need to associate with the vxlan-intf first
8637 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8639 /* associate with corresponding SVI interface, we can associate
8640 * with svi-if only after vxlan interface association is
8643 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8645 /* formulate l2vni list */
8646 hash_iterate(zvrf_default
->vni_table
, zvni_add_to_l3vni_list
,
8649 if (is_l3vni_oper_up(zl3vni
))
8650 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8653 zl3vni
= zl3vni_lookup(vni
);
8655 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8659 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8660 snprintf(err
, ERR_STR_SZ
,
8661 "prefix-routes-only is not set for the vni");
8665 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8667 /* delete and uninstall all rmacs */
8668 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8671 /* delete and uninstall all next-hops */
8672 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8678 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8683 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8685 zebra_l3vni_t
*zl3vni
= NULL
;
8688 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8692 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8693 if (is_l3vni_oper_up(zl3vni
))
8694 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8698 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8700 zebra_l3vni_t
*zl3vni
= NULL
;
8703 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8707 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8708 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8712 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8714 zebra_l3vni_t
*zl3vni
= NULL
;
8718 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8724 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8730 * Handle message from client to specify the flooding mechanism for
8731 * BUM packets. The default is to do head-end (ingress) replication
8732 * and the other supported option is to disable it. This applies to
8733 * all BUM traffic and disabling it applies to both the transmit and
8734 * receive direction.
8736 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8739 enum vxlan_flood_control flood_ctrl
;
8741 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8742 zlog_err("EVPN flood control for non-default VRF %u",
8748 STREAM_GETC(s
, flood_ctrl
);
8750 if (IS_ZEBRA_DEBUG_VXLAN
)
8751 zlog_debug("EVPN flood control %u, currently %u",
8752 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8754 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8757 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8759 /* Install or uninstall flood entries corresponding to
8762 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8770 * Handle message from client to enable/disable advertisement of svi macip
8773 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8778 zebra_vni_t
*zvni
= NULL
;
8779 struct interface
*ifp
= NULL
;
8781 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8782 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8788 STREAM_GETC(s
, advertise
);
8789 STREAM_GETL(s
, vni
);
8792 if (IS_ZEBRA_DEBUG_VXLAN
)
8793 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8794 advertise
? "enabled" : "disabled",
8795 advertise_gw_macip_enabled(NULL
)
8799 if (zvrf
->advertise_svi_macip
== advertise
)
8804 zvrf
->advertise_svi_macip
= advertise
;
8805 hash_iterate(zvrf
->vni_table
,
8806 zvni_gw_macip_add_for_vni_hash
, NULL
);
8808 hash_iterate(zvrf
->vni_table
,
8809 zvni_svi_macip_del_for_vni_hash
, NULL
);
8810 zvrf
->advertise_svi_macip
= advertise
;
8814 struct zebra_if
*zif
= NULL
;
8815 struct zebra_l2info_vxlan zl2_info
;
8816 struct interface
*vlan_if
= NULL
;
8818 zvni
= zvni_lookup(vni
);
8822 if (IS_ZEBRA_DEBUG_VXLAN
)
8824 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8825 advertise
? "enabled" : "disabled", vni
,
8826 advertise_svi_macip_enabled(zvni
)
8830 if (zvni
->advertise_svi_macip
== advertise
)
8833 ifp
= zvni
->vxlan_if
;
8839 /* If down or not mapped to a bridge, we're done. */
8840 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8843 zl2_info
= zif
->l2info
.vxl
;
8845 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8846 zif
->brslave_info
.br_if
);
8851 zvni
->advertise_svi_macip
= advertise
;
8852 /* Add primary SVI MAC-IP */
8853 zvni_add_macip_for_intf(vlan_if
, zvni
);
8855 /* Del primary MAC-IP */
8856 zvni_del_macip_for_intf(vlan_if
, zvni
);
8857 zvni
->advertise_svi_macip
= advertise
;
8866 * Handle message from client to enable/disable advertisement of g/w macip
8869 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8874 zebra_vni_t
*zvni
= NULL
;
8875 struct interface
*ifp
= NULL
;
8876 struct zebra_if
*zif
= NULL
;
8877 struct zebra_l2info_vxlan zl2_info
;
8878 struct interface
*vlan_if
= NULL
;
8880 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8881 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8887 STREAM_GETC(s
, advertise
);
8888 vni
= stream_get3(s
);
8890 zvni
= zvni_lookup(vni
);
8894 if (zvni
->advertise_subnet
== advertise
)
8897 if (IS_ZEBRA_DEBUG_VXLAN
)
8898 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8899 advertise
? "enabled" : "disabled", vni
,
8900 zvni
->advertise_subnet
? "enabled" : "disabled");
8903 zvni
->advertise_subnet
= advertise
;
8905 ifp
= zvni
->vxlan_if
;
8911 /* If down or not mapped to a bridge, we're done. */
8912 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8915 zl2_info
= zif
->l2info
.vxl
;
8918 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8922 if (zvni
->advertise_subnet
)
8923 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8925 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8932 * Handle message from client to enable/disable advertisement of g/w macip
8935 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8940 zebra_vni_t
*zvni
= NULL
;
8941 struct interface
*ifp
= NULL
;
8943 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
8944 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8950 STREAM_GETC(s
, advertise
);
8951 STREAM_GETL(s
, vni
);
8954 if (IS_ZEBRA_DEBUG_VXLAN
)
8955 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8956 advertise
? "enabled" : "disabled",
8957 advertise_gw_macip_enabled(NULL
)
8961 if (zvrf
->advertise_gw_macip
== advertise
)
8964 zvrf
->advertise_gw_macip
= advertise
;
8966 if (advertise_gw_macip_enabled(zvni
))
8967 hash_iterate(zvrf
->vni_table
,
8968 zvni_gw_macip_add_for_vni_hash
, NULL
);
8970 hash_iterate(zvrf
->vni_table
,
8971 zvni_gw_macip_del_for_vni_hash
, NULL
);
8974 struct zebra_if
*zif
= NULL
;
8975 struct zebra_l2info_vxlan zl2_info
;
8976 struct interface
*vlan_if
= NULL
;
8977 struct interface
*vrr_if
= NULL
;
8979 zvni
= zvni_lookup(vni
);
8983 if (IS_ZEBRA_DEBUG_VXLAN
)
8985 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8986 advertise
? "enabled" : "disabled", vni
,
8987 advertise_gw_macip_enabled(zvni
) ? "enabled"
8990 if (zvni
->advertise_gw_macip
== advertise
)
8993 zvni
->advertise_gw_macip
= advertise
;
8995 ifp
= zvni
->vxlan_if
;
9001 /* If down or not mapped to a bridge, we're done. */
9002 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9005 zl2_info
= zif
->l2info
.vxl
;
9007 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9008 zif
->brslave_info
.br_if
);
9012 if (advertise_gw_macip_enabled(zvni
)) {
9013 /* Add primary SVI MAC-IP */
9014 zvni_add_macip_for_intf(vlan_if
, zvni
);
9016 /* Add VRR MAC-IP - if any*/
9017 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9019 zvni_add_macip_for_intf(vrr_if
, zvni
);
9021 /* Del primary MAC-IP */
9022 zvni_del_macip_for_intf(vlan_if
, zvni
);
9024 /* Del VRR MAC-IP - if any*/
9025 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9027 zvni_del_macip_for_intf(vrr_if
, zvni
);
9037 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9038 * When enabled, the VNI hash table will be built and MAC FDB table read;
9039 * when disabled, the entries should be deleted and remote VTEPs and MACs
9040 * uninstalled from the kernel.
9041 * This also informs the setting for BUM handling at the time this change
9042 * occurs; it is relevant only when specifying "learn".
9044 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9046 struct stream
*s
= NULL
;
9048 enum vxlan_flood_control flood_ctrl
;
9050 if (zvrf_id(zvrf
) != VRF_DEFAULT
) {
9051 zlog_debug("EVPN VNI Adv for non-default VRF %u",
9057 STREAM_GETC(s
, advertise
);
9058 STREAM_GETC(s
, flood_ctrl
);
9060 if (IS_ZEBRA_DEBUG_VXLAN
)
9061 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
9062 advertise
? "enabled" : "disabled",
9063 is_evpn_enabled() ? "enabled" : "disabled",
9066 if (zvrf
->advertise_all_vni
== advertise
)
9069 zvrf
->advertise_all_vni
= advertise
;
9070 if (is_evpn_enabled()) {
9071 /* Note BUM handling */
9072 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9074 /* Build VNI hash table and inform BGP. */
9075 zvni_build_hash_table();
9077 /* Add all SVI (L3 GW) MACs to BGP*/
9078 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9081 /* Read the MAC FDB */
9082 macfdb_read(zvrf
->zns
);
9084 /* Read neighbors */
9085 neigh_read(zvrf
->zns
);
9087 /* Cleanup VTEPs for all VNIs - uninstall from
9088 * kernel and free entries.
9090 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9092 /* cleanup all l3vnis */
9093 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9101 * Allocate VNI hash table for this VRF and do other initialization.
9102 * NOTE: Currently supported only for default VRF.
9104 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9108 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9109 "Zebra VRF VNI Table");
9112 /* Cleanup VNI info, but don't free the table. */
9113 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9117 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9120 /* Close all VNI handling */
9121 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9125 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9126 hash_free(zvrf
->vni_table
);
9129 /* init the l3vni table */
9130 void zebra_vxlan_init(void)
9132 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9133 "Zebra VRF L3 VNI table");
9136 /* free l3vni table */
9137 void zebra_vxlan_disable(void)
9139 hash_free(zrouter
.l3vni_table
);
9142 /* get the l3vni svi ifindex */
9143 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9145 zebra_l3vni_t
*zl3vni
= NULL
;
9147 zl3vni
= zl3vni_from_vrf(vrf_id
);
9148 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9151 return zl3vni
->svi_if
->ifindex
;
9154 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9156 struct zebra_vrf
*zvrf
= NULL
;
9157 zebra_neigh_t
*nbr
= NULL
;
9158 zebra_vni_t
*zvni
= NULL
;
9159 char buf1
[INET6_ADDRSTRLEN
];
9160 char buf2
[ETHER_ADDR_STRLEN
];
9162 nbr
= THREAD_ARG(t
);
9164 /* since this is asynchronous we need sanity checks*/
9165 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9169 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9173 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
9177 if (IS_ZEBRA_DEBUG_VXLAN
)
9178 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9179 __PRETTY_FUNCTION__
,
9180 prefix_mac2str(&nbr
->emac
, buf1
, sizeof(buf1
)),
9181 ipaddr2str(&nbr
->ip
, buf2
, sizeof(buf2
)),
9183 nbr
->dad_count
, zvni
->vni
);
9185 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9187 nbr
->detect_start_time
.tv_sec
= 0;
9188 nbr
->detect_start_time
.tv_usec
= 0;
9189 nbr
->dad_dup_detect_time
= 0;
9190 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9193 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9194 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9195 nbr
->flags
, nbr
->loc_seq
);
9196 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9197 zvni_neigh_install(zvni
, nbr
);
9203 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9205 struct zebra_vrf
*zvrf
= NULL
;
9206 zebra_mac_t
*mac
= NULL
;
9207 zebra_vni_t
*zvni
= NULL
;
9208 struct listnode
*node
= NULL
;
9209 zebra_neigh_t
*nbr
= NULL
;
9210 char buf
[ETHER_ADDR_STRLEN
];
9212 mac
= THREAD_ARG(t
);
9214 /* since this is asynchronous we need sanity checks*/
9215 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9219 zvni
= zvni_lookup(mac
->zvni
->vni
);
9223 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
9227 if (IS_ZEBRA_DEBUG_VXLAN
)
9228 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9229 __PRETTY_FUNCTION__
,
9230 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9233 listcount(mac
->neigh_list
));
9235 /* Remove all IPs as duplicate associcated with this MAC */
9236 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9237 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9238 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9239 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9240 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9241 zvni_neigh_install(zvni
, nbr
);
9244 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9246 nbr
->detect_start_time
.tv_sec
= 0;
9247 nbr
->dad_dup_detect_time
= 0;
9250 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9252 mac
->detect_start_time
.tv_sec
= 0;
9253 mac
->detect_start_time
.tv_usec
= 0;
9254 mac
->dad_dup_detect_time
= 0;
9255 mac
->dad_mac_auto_recovery_timer
= NULL
;
9257 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9259 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9260 mac
->flags
, mac
->loc_seq
))
9263 /* Process all neighbors associated with this MAC. */
9264 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9266 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9267 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9269 /* Install the entry. */
9270 zvni_mac_install(zvni
, mac
);