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
= zebra_vrf_get_evpn();
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
= zebra_vrf_get_evpn();
342 if (zvrf
&& zvrf
->advertise_svi_macip
)
345 if (zvni
&& zvni
->advertise_svi_macip
)
351 /* As part Duplicate Address Detection (DAD) for IP mobility
352 * MAC binding changes, ensure to inherit duplicate flag
355 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
356 zebra_mac_t
*old_zmac
,
357 zebra_mac_t
*new_zmac
,
360 bool is_old_mac_dup
= false;
361 bool is_new_mac_dup
= false;
363 if (!zvrf
->dup_addr_detect
)
365 /* Check old or new MAC is detected as duplicate
366 * mark this neigh as duplicate
369 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
370 ZEBRA_MAC_DUPLICATE
);
372 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
373 ZEBRA_MAC_DUPLICATE
);
374 /* Old and/or new MAC can be in duplicate state,
375 * based on that IP/Neigh Inherits the flag.
376 * If New MAC is marked duplicate, inherit to the IP.
377 * If old MAC is duplicate but new MAC is not, clear
378 * duplicate flag for IP and reset detection params
379 * and let IP DAD retrigger.
381 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
382 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
383 /* Capture Duplicate detection time */
384 nbr
->dad_dup_detect_time
= monotime(NULL
);
386 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
387 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
389 nbr
->detect_start_time
.tv_sec
= 0;
390 nbr
->detect_start_time
.tv_usec
= 0;
395 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
397 struct in_addr vtep_ip
,
403 struct listnode
*node
= NULL
;
404 struct timeval elapsed
= {0, 0};
405 char buf
[ETHER_ADDR_STRLEN
];
406 char buf1
[INET6_ADDRSTRLEN
];
407 bool reset_params
= false;
409 if (!(zvrf
->dup_addr_detect
&& do_dad
))
412 /* MAC is detected as duplicate,
413 * Local MAC event -> hold on advertising to BGP.
414 * Remote MAC event -> hold on installing it.
416 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
417 if (IS_ZEBRA_DEBUG_VXLAN
)
419 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
421 prefix_mac2str(&mac
->macaddr
, buf
,
423 mac
->flags
, mac
->dad_count
,
424 zvrf
->dad_freeze_time
);
426 /* For duplicate MAC do not update
427 * client but update neigh due to
430 if (zvrf
->dad_freeze
)
431 *is_dup_detect
= true;
436 /* Check if detection time (M-secs) expired.
437 * Reset learn count and detection start time.
439 monotime_since(&mac
->detect_start_time
, &elapsed
);
440 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
441 if (is_local
&& !reset_params
) {
442 /* RFC-7432: A PE/VTEP that detects a MAC mobility
443 * event via LOCAL learning starts an M-second timer.
445 * NOTE: This is the START of the probe with count is
446 * 0 during LOCAL learn event.
447 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
449 reset_params
= !mac
->dad_count
;
453 if (IS_ZEBRA_DEBUG_VXLAN
)
455 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
456 , __PRETTY_FUNCTION__
,
457 prefix_mac2str(&mac
->macaddr
, buf
,
459 mac
->flags
, mac
->dad_count
);
462 /* Start dup. addr detection (DAD) start time,
463 * ONLY during LOCAL learn.
466 monotime(&mac
->detect_start_time
);
468 } else if (!is_local
) {
469 /* For REMOTE MAC, increment detection count
470 * ONLY while in probe window, once window passed,
471 * next local learn event should trigger DAD.
476 /* For LOCAL MAC learn event, once count is reset above via either
477 * initial/start detection time or passed the probe time, the count
478 * needs to be incremented.
483 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
484 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
485 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
487 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
488 is_local
? "local update, last" :
489 "remote update, from", inet_ntoa(vtep_ip
));
491 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
493 /* Capture Duplicate detection time */
494 mac
->dad_dup_detect_time
= monotime(NULL
);
496 /* Mark all IPs/Neighs as duplicate
497 * associcated with this MAC
499 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
501 /* Ony Mark IPs which are Local */
502 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
505 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
507 nbr
->dad_dup_detect_time
= monotime(NULL
);
509 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
510 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
512 prefix_mac2str(&mac
->macaddr
,
514 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
515 is_local
? "local" : "remote");
518 /* Start auto recovery timer for this MAC */
519 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
520 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
521 if (IS_ZEBRA_DEBUG_VXLAN
)
523 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
524 , __PRETTY_FUNCTION__
,
525 prefix_mac2str(&mac
->macaddr
, buf
,
527 mac
->flags
, zvrf
->dad_freeze_time
);
529 thread_add_timer(zrouter
.master
,
530 zebra_vxlan_dad_mac_auto_recovery_exp
,
531 mac
, zvrf
->dad_freeze_time
,
532 &mac
->dad_mac_auto_recovery_timer
);
535 /* In case of local update, do not inform to client (BGPd),
536 * upd_neigh for neigh sequence change.
538 if (zvrf
->dad_freeze
)
539 *is_dup_detect
= true;
543 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
545 struct in_addr vtep_ip
,
551 struct timeval elapsed
= {0, 0};
552 char buf
[ETHER_ADDR_STRLEN
];
553 char buf1
[INET6_ADDRSTRLEN
];
554 bool reset_params
= false;
556 if (!zvrf
->dup_addr_detect
)
559 /* IP is detected as duplicate or inherit dup
560 * state, hold on to install as remote entry
561 * only if freeze is enabled.
563 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
564 if (IS_ZEBRA_DEBUG_VXLAN
)
566 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
568 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
569 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
570 nbr
->flags
, nbr
->dad_count
,
571 zvrf
->dad_freeze_time
);
573 if (zvrf
->dad_freeze
)
574 *is_dup_detect
= true;
576 /* warn-only action, neigh will be installed.
577 * freeze action, it wil not be installed.
585 /* Check if detection time (M-secs) expired.
586 * Reset learn count and detection start time.
587 * During remote mac add, count should already be 1
588 * via local learning.
590 monotime_since(&nbr
->detect_start_time
, &elapsed
);
591 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
593 if (is_local
&& !reset_params
) {
594 /* RFC-7432: A PE/VTEP that detects a MAC mobility
595 * event via LOCAL learning starts an M-second timer.
597 * NOTE: This is the START of the probe with count is
598 * 0 during LOCAL learn event.
600 reset_params
= !nbr
->dad_count
;
604 if (IS_ZEBRA_DEBUG_VXLAN
)
606 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
608 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
609 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
610 nbr
->flags
, nbr
->dad_count
);
611 /* Reset learn count but do not start detection
612 * during REMOTE learn event.
615 /* Start dup. addr detection (DAD) start time,
616 * ONLY during LOCAL learn.
619 monotime(&nbr
->detect_start_time
);
621 } else if (!is_local
) {
622 /* For REMOTE IP/Neigh, increment detection count
623 * ONLY while in probe window, once window passed,
624 * next local learn event should trigger DAD.
629 /* For LOCAL IP/Neigh learn event, once count is reset above via either
630 * initial/start detection time or passed the probe time, the count
631 * needs to be incremented.
636 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
637 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
638 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
640 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
641 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
642 is_local
? "local update, last" :
643 "remote update, from",
646 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
648 /* Capture Duplicate detection time */
649 nbr
->dad_dup_detect_time
= monotime(NULL
);
651 /* Start auto recovery timer for this IP */
652 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
653 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
654 if (IS_ZEBRA_DEBUG_VXLAN
)
656 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
658 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
659 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
660 nbr
->flags
, zvrf
->dad_freeze_time
);
662 thread_add_timer(zrouter
.master
,
663 zebra_vxlan_dad_ip_auto_recovery_exp
,
664 nbr
, zvrf
->dad_freeze_time
,
665 &nbr
->dad_ip_auto_recovery_timer
);
667 if (zvrf
->dad_freeze
)
668 *is_dup_detect
= true;
673 * Helper function to determine maximum width of neighbor IP address for
674 * display - just because we're dealing with IPv6 addresses that can
677 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
680 char buf
[INET6_ADDRSTRLEN
];
681 struct neigh_walk_ctx
*wctx
= ctxt
;
684 n
= (zebra_neigh_t
*)bucket
->data
;
686 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
688 if (width
> wctx
->addr_width
)
689 wctx
->addr_width
= width
;
694 * Print a specific neighbor entry.
696 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
699 char buf1
[ETHER_ADDR_STRLEN
];
700 char buf2
[INET6_ADDRSTRLEN
];
701 const char *type_str
;
702 const char *state_str
;
703 bool flags_present
= false;
704 struct zebra_vrf
*zvrf
= NULL
;
705 struct timeval detect_start_time
= {0, 0};
707 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
711 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
712 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
713 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
714 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
716 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
717 vty
= (struct vty
*)ctxt
;
719 vty_out(vty
, "IP: %s\n",
720 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
721 vty_out(vty
, " Type: %s\n", type_str
);
722 vty_out(vty
, " State: %s\n", state_str
);
723 vty_out(vty
, " MAC: %s\n",
724 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
726 json_object_string_add(json
, "ip", buf2
);
727 json_object_string_add(json
, "type", type_str
);
728 json_object_string_add(json
, "state", state_str
);
729 json_object_string_add(json
, "mac", buf1
);
731 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
733 vty_out(vty
, " Remote VTEP: %s\n",
734 inet_ntoa(n
->r_vtep_ip
));
736 json_object_string_add(json
, "remoteVtep",
737 inet_ntoa(n
->r_vtep_ip
));
739 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
741 vty_out(vty
, " Flags: Default-gateway");
742 flags_present
= true;
744 json_object_boolean_true_add(json
, "defaultGateway");
746 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
749 flags_present
? " ,Router" : " Flags: Router");
750 flags_present
= true;
756 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
757 n
->loc_seq
, n
->rem_seq
);
759 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
760 vty_out(vty
, " Duplicate, detected at %s",
761 time_to_string(n
->dad_dup_detect_time
));
762 } else if (n
->dad_count
) {
763 monotime_since(&n
->detect_start_time
,
765 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
766 char *buf
= time_to_string(
767 n
->detect_start_time
.tv_sec
);
770 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
772 " Duplicate detection started at %s, detection count %u\n",
773 tmp_buf
, n
->dad_count
);
777 json_object_int_add(json
, "localSequence", n
->loc_seq
);
778 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
779 json_object_int_add(json
, "detectionCount",
781 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
782 json_object_boolean_true_add(json
, "isDuplicate");
784 json_object_boolean_false_add(json
, "isDuplicate");
791 * Print neighbor hash entry - called for display of all neighbors.
793 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
796 json_object
*json_vni
= NULL
, *json_row
= NULL
;
798 char buf1
[ETHER_ADDR_STRLEN
];
799 char buf2
[INET6_ADDRSTRLEN
];
800 struct neigh_walk_ctx
*wctx
= ctxt
;
801 const char *state_str
;
804 json_vni
= wctx
->json
;
805 n
= (zebra_neigh_t
*)bucket
->data
;
808 json_row
= json_object_new_object();
810 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
811 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
812 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
813 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
814 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
817 if (json_vni
== NULL
) {
818 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
819 -wctx
->addr_width
, buf2
, "local",
822 json_object_string_add(json_row
, "type", "local");
823 json_object_string_add(json_row
, "state", state_str
);
824 json_object_string_add(json_row
, "mac", buf1
);
825 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
826 json_object_boolean_true_add(
827 json_row
, "defaultGateway");
828 json_object_int_add(json_row
, "localSequence",
830 json_object_int_add(json_row
, "remoteSequence",
832 json_object_int_add(json_row
, "detectionCount",
834 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
835 json_object_boolean_true_add(json_row
,
838 json_object_boolean_false_add(json_row
,
842 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
843 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
844 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
847 if (json_vni
== NULL
) {
848 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
851 "%*s %-6s %-8s %-17s %-21s\n",
852 -wctx
->addr_width
, "Neighbor", "Type",
853 "State", "MAC", "Remote VTEP");
854 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
855 -wctx
->addr_width
, buf2
, "remote", state_str
,
856 buf1
, inet_ntoa(n
->r_vtep_ip
));
858 json_object_string_add(json_row
, "type", "remote");
859 json_object_string_add(json_row
, "state", state_str
);
860 json_object_string_add(json_row
, "mac", buf1
);
861 json_object_string_add(json_row
, "remoteVtep",
862 inet_ntoa(n
->r_vtep_ip
));
863 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
864 json_object_boolean_true_add(json_row
,
866 json_object_int_add(json_row
, "localSequence",
868 json_object_int_add(json_row
, "remoteSequence",
870 json_object_int_add(json_row
, "detectionCount",
872 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
873 json_object_boolean_true_add(json_row
,
876 json_object_boolean_false_add(json_row
,
883 json_object_object_add(json_vni
, buf2
, json_row
);
887 * Print neighbor hash entry in detail - called for display of all neighbors.
889 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
892 json_object
*json_vni
= NULL
, *json_row
= NULL
;
894 char buf
[INET6_ADDRSTRLEN
];
895 struct neigh_walk_ctx
*wctx
= ctxt
;
898 json_vni
= wctx
->json
;
899 n
= (zebra_neigh_t
*)bucket
->data
;
903 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
905 json_row
= json_object_new_object();
907 zvni_print_neigh(n
, vty
, json_row
);
910 json_object_object_add(json_vni
, buf
, json_row
);
914 * Print neighbors for all VNI.
916 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
920 json_object
*json
= NULL
, *json_vni
= NULL
;
923 struct neigh_walk_ctx wctx
;
924 char vni_str
[VNI_STR_LEN
];
927 vty
= (struct vty
*)args
[0];
928 json
= (json_object
*)args
[1];
929 print_dup
= (uint32_t)(uintptr_t)args
[2];
931 zvni
= (zebra_vni_t
*)bucket
->data
;
933 num_neigh
= hashcount(zvni
->neigh_table
);
936 num_neigh
= num_dup_detected_neighs(zvni
);
940 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
941 zvni
->vni
, num_neigh
);
943 json_vni
= json_object_new_object();
944 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
945 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
950 json_object_object_add(json
, vni_str
, json_vni
);
954 /* Since we have IPv6 addresses to deal with which can vary widely in
955 * size, we try to be a bit more elegant in display by first computing
958 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
961 wctx
.addr_width
= 15;
962 wctx
.json
= json_vni
;
963 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
966 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
967 -wctx
.addr_width
, "IP", "Type",
968 "State", "MAC", "Remote VTEP");
971 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
974 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
977 json_object_object_add(json
, vni_str
, json_vni
);
980 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
984 nbr
= (zebra_neigh_t
*)bucket
->data
;
988 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
989 zvni_print_neigh_hash(bucket
, ctxt
);
992 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
997 nbr
= (zebra_neigh_t
*)bucket
->data
;
1001 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1002 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1006 * Print neighbors for all VNIs in detail.
1008 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1012 json_object
*json
= NULL
, *json_vni
= NULL
;
1015 struct neigh_walk_ctx wctx
;
1016 char vni_str
[VNI_STR_LEN
];
1019 vty
= (struct vty
*)args
[0];
1020 json
= (json_object
*)args
[1];
1021 print_dup
= (uint32_t)(uintptr_t)args
[2];
1023 zvni
= (zebra_vni_t
*)bucket
->data
;
1026 vty_out(vty
, "{}\n");
1029 num_neigh
= hashcount(zvni
->neigh_table
);
1031 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1036 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1037 zvni
->vni
, num_neigh
);
1039 json_vni
= json_object_new_object();
1040 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1041 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1045 json_object_object_add(json
, vni_str
, json_vni
);
1049 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1052 wctx
.addr_width
= 15;
1053 wctx
.json
= json_vni
;
1056 hash_iterate(zvni
->neigh_table
,
1057 zvni_print_dad_neigh_hash_detail
, &wctx
);
1059 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1063 json_object_object_add(json
, vni_str
, json_vni
);
1066 /* print a specific next hop for an l3vni */
1067 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1070 char buf1
[ETHER_ADDR_STRLEN
];
1071 char buf2
[INET6_ADDRSTRLEN
];
1072 json_object
*json_hosts
= NULL
;
1073 struct host_rb_entry
*hle
;
1076 vty_out(vty
, "Ip: %s\n",
1077 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1078 vty_out(vty
, " RMAC: %s\n",
1079 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1080 vty_out(vty
, " Refcount: %d\n",
1081 rb_host_count(&n
->host_rb
));
1082 vty_out(vty
, " Prefixes:\n");
1083 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1084 vty_out(vty
, " %s\n",
1085 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1087 json_hosts
= json_object_new_array();
1088 json_object_string_add(
1089 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1090 json_object_string_add(
1092 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1093 json_object_int_add(json
, "refCount",
1094 rb_host_count(&n
->host_rb
));
1095 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1096 json_object_array_add(json_hosts
,
1097 json_object_new_string(prefix2str(
1098 &hle
->p
, buf2
, sizeof(buf2
))));
1099 json_object_object_add(json
, "prefixList", json_hosts
);
1103 /* Print a specific RMAC entry */
1104 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1107 char buf1
[ETHER_ADDR_STRLEN
];
1108 char buf2
[PREFIX_STRLEN
];
1109 json_object
*json_hosts
= NULL
;
1110 struct host_rb_entry
*hle
;
1113 vty_out(vty
, "MAC: %s\n",
1114 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1115 vty_out(vty
, " Remote VTEP: %s\n",
1116 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1117 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1118 vty_out(vty
, " Prefixes:\n");
1119 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1120 vty_out(vty
, " %s\n",
1121 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1123 json_hosts
= json_object_new_array();
1124 json_object_string_add(
1126 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1127 json_object_string_add(json
, "vtepIp",
1128 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1129 json_object_int_add(json
, "refCount",
1130 rb_host_count(&zrmac
->host_rb
));
1131 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1132 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1133 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1134 json_object_array_add(
1136 json_object_new_string(prefix2str(
1137 &hle
->p
, buf2
, sizeof(buf2
))));
1138 json_object_object_add(json
, "prefixList", json_hosts
);
1143 * Print a specific MAC entry.
1145 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1148 zebra_neigh_t
*n
= NULL
;
1149 struct listnode
*node
= NULL
;
1150 char buf1
[ETHER_ADDR_STRLEN
];
1151 char buf2
[INET6_ADDRSTRLEN
];
1152 struct zebra_vrf
*zvrf
;
1153 struct timeval detect_start_time
= {0, 0};
1155 zvrf
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
1157 vty
= (struct vty
*)ctxt
;
1158 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1161 json_object
*json_mac
= json_object_new_object();
1163 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1164 struct zebra_ns
*zns
;
1165 struct interface
*ifp
;
1168 ifindex
= mac
->fwd_info
.local
.ifindex
;
1169 zns
= zebra_ns_lookup(NS_DEFAULT
);
1170 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1173 json_object_string_add(json_mac
, "type", "local");
1174 json_object_string_add(json_mac
, "intf", ifp
->name
);
1175 json_object_int_add(json_mac
, "ifindex", ifindex
);
1176 if (mac
->fwd_info
.local
.vid
)
1177 json_object_int_add(json_mac
, "vlan",
1178 mac
->fwd_info
.local
.vid
);
1179 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1180 json_object_string_add(json_mac
, "type", "remote");
1181 json_object_string_add(
1182 json_mac
, "remoteVtep",
1183 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1184 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1185 json_object_string_add(json_mac
, "type", "auto");
1187 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1188 json_object_boolean_true_add(json_mac
, "stickyMac");
1190 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1191 json_object_boolean_true_add(json_mac
,
1194 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1195 json_object_boolean_true_add(json_mac
,
1196 "remoteGatewayMac");
1198 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1199 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1201 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1202 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1203 json_object_boolean_true_add(json_mac
, "isDuplicate");
1205 json_object_boolean_false_add(json_mac
, "isDuplicate");
1207 /* print all the associated neigh */
1208 if (!listcount(mac
->neigh_list
))
1209 json_object_string_add(json_mac
, "neighbors", "none");
1211 json_object
*json_active_nbrs
= json_object_new_array();
1212 json_object
*json_inactive_nbrs
=
1213 json_object_new_array();
1214 json_object
*json_nbrs
= json_object_new_object();
1216 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1217 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1218 json_object_array_add(
1220 json_object_new_string(
1225 json_object_array_add(
1227 json_object_new_string(
1233 json_object_object_add(json_nbrs
, "active",
1235 json_object_object_add(json_nbrs
, "inactive",
1236 json_inactive_nbrs
);
1237 json_object_object_add(json_mac
, "neighbors",
1241 json_object_object_add(json
, buf1
, json_mac
);
1243 vty_out(vty
, "MAC: %s\n", buf1
);
1245 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1246 struct zebra_ns
*zns
;
1247 struct interface
*ifp
;
1250 ifindex
= mac
->fwd_info
.local
.ifindex
;
1251 zns
= zebra_ns_lookup(NS_DEFAULT
);
1252 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1255 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1256 if (mac
->fwd_info
.local
.vid
)
1257 vty_out(vty
, " VLAN: %u",
1258 mac
->fwd_info
.local
.vid
);
1259 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1260 vty_out(vty
, " Remote VTEP: %s",
1261 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1262 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1263 vty_out(vty
, " Auto Mac ");
1266 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1267 vty_out(vty
, " Sticky Mac ");
1269 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1270 vty_out(vty
, " Default-gateway Mac ");
1272 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1273 vty_out(vty
, " Remote-gateway Mac ");
1276 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1280 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1281 vty_out(vty
, " Duplicate, detected at %s",
1282 time_to_string(mac
->dad_dup_detect_time
));
1283 } else if (mac
->dad_count
) {
1284 monotime_since(&mac
->detect_start_time
,
1285 &detect_start_time
);
1286 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1287 char *buf
= time_to_string(
1288 mac
->detect_start_time
.tv_sec
);
1291 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1293 " Duplicate detection started at %s, detection count %u\n",
1294 tmp_buf
, mac
->dad_count
);
1298 /* print all the associated neigh */
1299 vty_out(vty
, " Neighbors:\n");
1300 if (!listcount(mac
->neigh_list
))
1301 vty_out(vty
, " No Neighbors\n");
1303 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1304 vty_out(vty
, " %s %s\n",
1305 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1306 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1317 * Print MAC hash entry - called for display of all MACs.
1319 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1322 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1324 char buf1
[ETHER_ADDR_STRLEN
];
1325 struct mac_walk_ctx
*wctx
= ctxt
;
1328 json_mac_hdr
= wctx
->json
;
1329 mac
= (zebra_mac_t
*)bucket
->data
;
1331 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1334 json_mac
= json_object_new_object();
1336 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1337 struct zebra_ns
*zns
;
1339 struct interface
*ifp
;
1342 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1345 zns
= zebra_ns_lookup(NS_DEFAULT
);
1346 ifindex
= mac
->fwd_info
.local
.ifindex
;
1347 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1348 if (!ifp
) // unexpected
1350 vid
= mac
->fwd_info
.local
.vid
;
1351 if (json_mac_hdr
== NULL
)
1352 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1355 json_object_string_add(json_mac
, "type", "local");
1356 json_object_string_add(json_mac
, "intf", ifp
->name
);
1359 if (json_mac_hdr
== NULL
)
1360 vty_out(vty
, " %-5u", vid
);
1362 json_object_int_add(json_mac
, "vlan", vid
);
1364 if (json_mac_hdr
== NULL
) {
1367 json_object_int_add(json_mac
, "localSequence",
1369 json_object_int_add(json_mac
, "remoteSequence",
1371 json_object_int_add(json_mac
, "detectionCount",
1373 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1374 json_object_boolean_true_add(json_mac
,
1377 json_object_boolean_false_add(json_mac
,
1379 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1384 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1386 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1387 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1391 if (json_mac_hdr
== NULL
) {
1392 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1393 (wctx
->count
== 0)) {
1394 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1395 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1396 "Type", "Intf/Remote VTEP", "VLAN");
1398 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1399 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1401 json_object_string_add(json_mac
, "type", "remote");
1402 json_object_string_add(json_mac
, "remoteVtep",
1403 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1404 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1405 json_object_int_add(json_mac
, "localSequence",
1407 json_object_int_add(json_mac
, "remoteSequence",
1409 json_object_int_add(json_mac
, "detectionCount",
1411 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1412 json_object_boolean_true_add(json_mac
,
1415 json_object_boolean_false_add(json_mac
,
1424 /* Print Duplicate MAC */
1425 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1429 mac
= (zebra_mac_t
*)bucket
->data
;
1433 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1434 zvni_print_mac_hash(bucket
, ctxt
);
1438 * Print MAC hash entry in detail - called for display of all MACs.
1440 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1443 json_object
*json_mac_hdr
= NULL
;
1445 struct mac_walk_ctx
*wctx
= ctxt
;
1446 char buf1
[ETHER_ADDR_STRLEN
];
1449 json_mac_hdr
= wctx
->json
;
1450 mac
= (zebra_mac_t
*)bucket
->data
;
1455 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1457 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1460 /* Print Duplicate MAC in detail */
1461 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1466 mac
= (zebra_mac_t
*)bucket
->data
;
1470 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1471 zvni_print_mac_hash_detail(bucket
, ctxt
);
1475 * Print MACs for all VNI.
1477 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1480 json_object
*json
= NULL
, *json_vni
= NULL
;
1481 json_object
*json_mac
= NULL
;
1484 struct mac_walk_ctx
*wctx
= ctxt
;
1485 char vni_str
[VNI_STR_LEN
];
1487 vty
= (struct vty
*)wctx
->vty
;
1488 json
= (struct json_object
*)wctx
->json
;
1490 zvni
= (zebra_vni_t
*)bucket
->data
;
1493 /*We are iterating over a new VNI, set the count to 0*/
1496 num_macs
= num_valid_macs(zvni
);
1500 if (wctx
->print_dup
)
1501 num_macs
= num_dup_detected_macs(zvni
);
1504 json_vni
= json_object_new_object();
1505 json_mac
= json_object_new_object();
1506 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1509 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1511 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1512 zvni
->vni
, num_macs
);
1513 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1514 "Intf/Remote VTEP", "VLAN");
1516 json_object_int_add(json_vni
, "numMacs", num_macs
);
1521 json_object_int_add(json_vni
, "numMacs", num_macs
);
1522 json_object_object_add(json
, vni_str
, json_vni
);
1527 /* assign per-vni to wctx->json object to fill macs
1528 * under the vni. Re-assign primary json object to fill
1529 * next vni information.
1531 wctx
->json
= json_mac
;
1532 if (wctx
->print_dup
)
1533 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1535 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1539 json_object_object_add(json_vni
, "macs", json_mac
);
1540 json_object_object_add(json
, vni_str
, json_vni
);
1545 * Print MACs in detail for all VNI.
1547 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1551 json_object
*json
= NULL
, *json_vni
= NULL
;
1552 json_object
*json_mac
= NULL
;
1555 struct mac_walk_ctx
*wctx
= ctxt
;
1556 char vni_str
[VNI_STR_LEN
];
1558 vty
= (struct vty
*)wctx
->vty
;
1559 json
= (struct json_object
*)wctx
->json
;
1561 zvni
= (zebra_vni_t
*)bucket
->data
;
1564 vty_out(vty
, "{}\n");
1569 /*We are iterating over a new VNI, set the count to 0*/
1572 num_macs
= num_valid_macs(zvni
);
1576 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1580 json_vni
= json_object_new_object();
1581 json_mac
= json_object_new_object();
1582 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1585 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1587 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1588 zvni
->vni
, num_macs
);
1590 json_object_int_add(json_vni
, "numMacs", num_macs
);
1592 /* assign per-vni to wctx->json object to fill macs
1593 * under the vni. Re-assign primary json object to fill
1594 * next vni information.
1596 wctx
->json
= json_mac
;
1597 if (wctx
->print_dup
)
1598 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1601 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1605 json_object_object_add(json_vni
, "macs", json_mac
);
1606 json_object_object_add(json
, vni_str
, json_vni
);
1610 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1612 struct nh_walk_ctx
*wctx
= NULL
;
1613 struct vty
*vty
= NULL
;
1614 struct json_object
*json_vni
= NULL
;
1615 struct json_object
*json_nh
= NULL
;
1616 zebra_neigh_t
*n
= NULL
;
1617 char buf1
[ETHER_ADDR_STRLEN
];
1618 char buf2
[INET6_ADDRSTRLEN
];
1620 wctx
= (struct nh_walk_ctx
*)ctx
;
1622 json_vni
= wctx
->json
;
1624 json_nh
= json_object_new_object();
1625 n
= (zebra_neigh_t
*)bucket
->data
;
1628 vty_out(vty
, "%-15s %-17s\n",
1629 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1630 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1632 json_object_string_add(json_nh
, "nexthopIp",
1633 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1634 json_object_string_add(
1635 json_nh
, "routerMac",
1636 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1637 json_object_object_add(json_vni
,
1638 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1643 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1646 struct vty
*vty
= NULL
;
1647 json_object
*json
= NULL
;
1648 json_object
*json_vni
= NULL
;
1649 zebra_l3vni_t
*zl3vni
= NULL
;
1650 uint32_t num_nh
= 0;
1651 struct nh_walk_ctx wctx
;
1652 char vni_str
[VNI_STR_LEN
];
1654 vty
= (struct vty
*)args
[0];
1655 json
= (struct json_object
*)args
[1];
1657 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1659 num_nh
= hashcount(zl3vni
->nh_table
);
1664 json_vni
= json_object_new_object();
1665 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1669 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1670 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1672 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1674 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1676 wctx
.json
= json_vni
;
1677 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1679 json_object_object_add(json
, vni_str
, json_vni
);
1682 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1685 struct vty
*vty
= NULL
;
1686 json_object
*json
= NULL
;
1687 json_object
*json_vni
= NULL
;
1688 zebra_l3vni_t
*zl3vni
= NULL
;
1690 struct rmac_walk_ctx wctx
;
1691 char vni_str
[VNI_STR_LEN
];
1693 vty
= (struct vty
*)args
[0];
1694 json
= (struct json_object
*)args
[1];
1696 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1698 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1703 json_vni
= json_object_new_object();
1704 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1708 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1709 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1711 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1713 /* assign per-vni to wctx->json object to fill macs
1714 * under the vni. Re-assign primary json object to fill
1715 * next vni information.
1717 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1719 wctx
.json
= json_vni
;
1720 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1722 json_object_object_add(json
, vni_str
, json_vni
);
1725 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1727 zebra_mac_t
*zrmac
= NULL
;
1728 struct rmac_walk_ctx
*wctx
= NULL
;
1729 struct vty
*vty
= NULL
;
1730 struct json_object
*json
= NULL
;
1731 struct json_object
*json_rmac
= NULL
;
1732 char buf
[ETHER_ADDR_STRLEN
];
1734 wctx
= (struct rmac_walk_ctx
*)ctx
;
1738 json_rmac
= json_object_new_object();
1739 zrmac
= (zebra_mac_t
*)bucket
->data
;
1742 vty_out(vty
, "%-17s %-21s\n",
1743 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1744 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1746 json_object_string_add(
1747 json_rmac
, "routerMac",
1748 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1749 json_object_string_add(json_rmac
, "vtepIp",
1750 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1751 json_object_object_add(
1752 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1757 /* print a specific L3 VNI entry */
1758 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1760 char buf
[ETHER_ADDR_STRLEN
];
1761 struct vty
*vty
= NULL
;
1762 json_object
*json
= NULL
;
1763 zebra_vni_t
*zvni
= NULL
;
1764 json_object
*json_vni_list
= NULL
;
1765 struct listnode
*node
= NULL
, *nnode
= NULL
;
1771 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1772 vty_out(vty
, " Type: %s\n", "L3");
1773 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1774 vty_out(vty
, " Local Vtep Ip: %s\n",
1775 inet_ntoa(zl3vni
->local_vtep_ip
));
1776 vty_out(vty
, " Vxlan-Intf: %s\n",
1777 zl3vni_vxlan_if_name(zl3vni
));
1778 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1779 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1780 vty_out(vty
, " VNI Filter: %s\n",
1781 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1782 ? "prefix-routes-only"
1784 vty_out(vty
, " Router MAC: %s\n",
1785 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1786 vty_out(vty
, " L2 VNIs: ");
1787 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1788 vty_out(vty
, "%u ", zvni
->vni
);
1791 json_vni_list
= json_object_new_array();
1792 json_object_int_add(json
, "vni", zl3vni
->vni
);
1793 json_object_string_add(json
, "type", "L3");
1794 json_object_string_add(json
, "localVtepIp",
1795 inet_ntoa(zl3vni
->local_vtep_ip
));
1796 json_object_string_add(json
, "vxlanIntf",
1797 zl3vni_vxlan_if_name(zl3vni
));
1798 json_object_string_add(json
, "sviIntf",
1799 zl3vni_svi_if_name(zl3vni
));
1800 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1801 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1802 json_object_string_add(
1804 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1805 json_object_string_add(
1807 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1808 ? "prefix-routes-only"
1810 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1811 json_object_array_add(json_vni_list
,
1812 json_object_new_int(zvni
->vni
));
1814 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1819 * Print a specific VNI entry.
1821 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1824 zebra_vtep_t
*zvtep
;
1827 json_object
*json
= NULL
;
1828 json_object
*json_vtep_list
= NULL
;
1829 json_object
*json_ip_str
= NULL
;
1835 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1836 vty_out(vty
, " Type: %s\n", "L2");
1837 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1839 json_object_int_add(json
, "vni", zvni
->vni
);
1840 json_object_string_add(json
, "type", "L2");
1841 json_object_string_add(json
, "vrf",
1842 vrf_id_to_name(zvni
->vrf_id
));
1845 if (!zvni
->vxlan_if
) { // unexpected
1847 vty_out(vty
, " VxLAN interface: unknown\n");
1850 num_macs
= num_valid_macs(zvni
);
1851 num_neigh
= hashcount(zvni
->neigh_table
);
1853 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1854 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1855 vty_out(vty
, " Local VTEP IP: %s\n",
1856 inet_ntoa(zvni
->local_vtep_ip
));
1858 json_object_string_add(json
, "vxlanInterface",
1859 zvni
->vxlan_if
->name
);
1860 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1861 json_object_string_add(json
, "vtepIp",
1862 inet_ntoa(zvni
->local_vtep_ip
));
1863 json_object_string_add(json
, "advertiseGatewayMacip",
1864 zvni
->advertise_gw_macip
? "Yes" : "No");
1865 json_object_int_add(json
, "numMacs", num_macs
);
1866 json_object_int_add(json
, "numArpNd", num_neigh
);
1870 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1873 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1875 json_vtep_list
= json_object_new_array();
1876 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1878 vty_out(vty
, " %s\n",
1879 inet_ntoa(zvtep
->vtep_ip
));
1881 json_ip_str
= json_object_new_string(
1882 inet_ntoa(zvtep
->vtep_ip
));
1883 json_object_array_add(json_vtep_list
,
1888 json_object_object_add(json
, "numRemoteVteps",
1893 " Number of MACs (local and remote) known for this VNI: %u\n",
1896 " Number of ARPs (IPv4 and IPv6, local and remote) "
1897 "known for this VNI: %u\n",
1899 vty_out(vty
, " Advertise-gw-macip: %s\n",
1900 zvni
->advertise_gw_macip
? "Yes" : "No");
1904 /* print a L3 VNI hash entry */
1905 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1907 struct vty
*vty
= NULL
;
1908 json_object
*json
= NULL
;
1909 json_object
*json_vni
= NULL
;
1910 zebra_l3vni_t
*zl3vni
= NULL
;
1912 vty
= (struct vty
*)ctx
[0];
1913 json
= (json_object
*)ctx
[1];
1915 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1918 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1919 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1920 hashcount(zl3vni
->rmac_table
),
1921 hashcount(zl3vni
->nh_table
), "n/a",
1922 zl3vni_vrf_name(zl3vni
));
1924 char vni_str
[VNI_STR_LEN
];
1926 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1927 json_vni
= json_object_new_object();
1928 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1929 json_object_string_add(json_vni
, "vxlanIf",
1930 zl3vni_vxlan_if_name(zl3vni
));
1931 json_object_int_add(json_vni
, "numMacs",
1932 hashcount(zl3vni
->rmac_table
));
1933 json_object_int_add(json_vni
, "numArpNd",
1934 hashcount(zl3vni
->nh_table
));
1935 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1936 json_object_string_add(json_vni
, "type", "L3");
1937 json_object_string_add(json_vni
, "tenantVrf",
1938 zl3vni_vrf_name(zl3vni
));
1939 json_object_object_add(json
, vni_str
, json_vni
);
1943 /* Private Structure to pass callback data for hash iterator */
1944 struct zvni_evpn_show
{
1947 struct zebra_vrf
*zvrf
;
1950 /* print a L3 VNI hash entry in detail*/
1951 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1953 struct vty
*vty
= NULL
;
1954 zebra_l3vni_t
*zl3vni
= NULL
;
1955 json_object
*json
= NULL
;
1956 bool use_json
= false;
1957 struct zvni_evpn_show
*zes
= data
;
1965 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1967 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1973 * Print a VNI hash entry - called for display of all VNIs.
1975 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
1979 zebra_vtep_t
*zvtep
;
1980 uint32_t num_vteps
= 0;
1981 uint32_t num_macs
= 0;
1982 uint32_t num_neigh
= 0;
1983 json_object
*json
= NULL
;
1984 json_object
*json_vni
= NULL
;
1985 json_object
*json_ip_str
= NULL
;
1986 json_object
*json_vtep_list
= NULL
;
1991 zvni
= (zebra_vni_t
*)bucket
->data
;
1993 zvtep
= zvni
->vteps
;
1996 zvtep
= zvtep
->next
;
1999 num_macs
= num_valid_macs(zvni
);
2000 num_neigh
= hashcount(zvni
->neigh_table
);
2002 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2004 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2005 num_macs
, num_neigh
, num_vteps
,
2006 vrf_id_to_name(zvni
->vrf_id
));
2008 char vni_str
[VNI_STR_LEN
];
2009 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2010 json_vni
= json_object_new_object();
2011 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2012 json_object_string_add(json_vni
, "type", "L2");
2013 json_object_string_add(json_vni
, "vxlanIf",
2014 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2016 json_object_int_add(json_vni
, "numMacs", num_macs
);
2017 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2018 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2019 json_object_string_add(json_vni
, "tenantVrf",
2020 vrf_id_to_name(zvni
->vrf_id
));
2022 json_vtep_list
= json_object_new_array();
2023 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2024 json_ip_str
= json_object_new_string(
2025 inet_ntoa(zvtep
->vtep_ip
));
2026 json_object_array_add(json_vtep_list
,
2029 json_object_object_add(json_vni
, "remoteVteps",
2032 json_object_object_add(json
, vni_str
, json_vni
);
2037 * Print a VNI hash entry in detail - called for display of all VNIs.
2039 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2043 json_object
*json
= NULL
;
2044 bool use_json
= false;
2045 struct zvni_evpn_show
*zes
= data
;
2053 zvni
= (zebra_vni_t
*)bucket
->data
;
2055 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2060 * Inform BGP about local MACIP.
2062 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2063 struct ipaddr
*ip
, uint8_t flags
,
2064 uint32_t seq
, int state
, uint16_t cmd
)
2066 char buf
[ETHER_ADDR_STRLEN
];
2067 char buf2
[INET6_ADDRSTRLEN
];
2069 struct zserv
*client
= NULL
;
2070 struct stream
*s
= NULL
;
2072 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2073 /* BGP may not be running. */
2077 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2079 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2080 stream_putl(s
, vni
);
2081 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2084 if (IS_IPADDR_V4(ip
))
2085 ipa_len
= IPV4_MAX_BYTELEN
;
2086 else if (IS_IPADDR_V6(ip
))
2087 ipa_len
= IPV6_MAX_BYTELEN
;
2089 stream_putl(s
, ipa_len
); /* IP address length */
2091 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2093 stream_putl(s
, 0); /* Just MAC. */
2095 if (cmd
== ZEBRA_MACIP_ADD
) {
2096 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2097 stream_putl(s
, seq
); /* sequence number */
2099 stream_putl(s
, state
); /* state - active/inactive */
2103 /* Write packet size. */
2104 stream_putw_at(s
, 0, stream_get_endp(s
));
2106 if (IS_ZEBRA_DEBUG_VXLAN
)
2108 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2109 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2110 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2111 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2112 zebra_route_string(client
->proto
));
2114 if (cmd
== ZEBRA_MACIP_ADD
)
2115 client
->macipadd_cnt
++;
2117 client
->macipdel_cnt
++;
2119 return zserv_send_message(client
, s
);
2123 * Make hash key for neighbors.
2125 static unsigned int neigh_hash_keymake(void *p
)
2127 zebra_neigh_t
*n
= p
;
2128 struct ipaddr
*ip
= &n
->ip
;
2130 if (IS_IPADDR_V4(ip
))
2131 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2133 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2134 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2138 * Compare two neighbor hash structures.
2140 static bool neigh_cmp(const void *p1
, const void *p2
)
2142 const zebra_neigh_t
*n1
= p1
;
2143 const zebra_neigh_t
*n2
= p2
;
2145 if (n1
== NULL
&& n2
== NULL
)
2148 if (n1
== NULL
|| n2
== NULL
)
2151 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2154 static int neigh_list_cmp(void *p1
, void *p2
)
2156 const zebra_neigh_t
*n1
= p1
;
2157 const zebra_neigh_t
*n2
= p2
;
2159 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2163 * Callback to allocate neighbor hash entry.
2165 static void *zvni_neigh_alloc(void *p
)
2167 const zebra_neigh_t
*tmp_n
= p
;
2170 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2177 * Add neighbor entry.
2179 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2180 struct ethaddr
*mac
)
2182 zebra_neigh_t tmp_n
;
2183 zebra_neigh_t
*n
= NULL
;
2184 zebra_mac_t
*zmac
= NULL
;
2186 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2187 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2188 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2191 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2192 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2194 /* Associate the neigh to mac */
2195 zmac
= zvni_mac_lookup(zvni
, mac
);
2197 listnode_add_sort(zmac
->neigh_list
, n
);
2203 * Delete neighbor entry.
2205 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2207 zebra_neigh_t
*tmp_n
;
2208 zebra_mac_t
*zmac
= NULL
;
2210 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2212 listnode_delete(zmac
->neigh_list
, n
);
2214 /* Free the VNI hash entry and allocated memory. */
2215 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2216 XFREE(MTYPE_NEIGH
, tmp_n
);
2222 * Free neighbor hash entry (callback)
2224 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2226 struct neigh_walk_ctx
*wctx
= arg
;
2227 zebra_neigh_t
*n
= bucket
->data
;
2229 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2230 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2231 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2232 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2233 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2234 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2235 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2236 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2237 &n
->emac
, 0, n
->state
);
2239 if (wctx
->uninstall
)
2240 zvni_neigh_uninstall(wctx
->zvni
, n
);
2242 zvni_neigh_del(wctx
->zvni
, n
);
2249 * Delete all neighbor entries from specific VTEP for a particular VNI.
2251 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2252 struct in_addr
*r_vtep_ip
)
2254 struct neigh_walk_ctx wctx
;
2256 if (!zvni
->neigh_table
)
2259 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2261 wctx
.uninstall
= uninstall
;
2262 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2263 wctx
.r_vtep_ip
= *r_vtep_ip
;
2265 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2269 * Delete all neighbor entries for this VNI.
2271 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2274 struct neigh_walk_ctx wctx
;
2276 if (!zvni
->neigh_table
)
2279 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2281 wctx
.uninstall
= uninstall
;
2282 wctx
.upd_client
= upd_client
;
2285 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2289 * Look up neighbor hash entry.
2291 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2296 memset(&tmp
, 0, sizeof(tmp
));
2297 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2298 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2304 * Process all neighbors associated with a MAC upon the MAC being learnt
2305 * locally or undergoing any other change (such as sequence number).
2307 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2311 zebra_neigh_t
*n
= NULL
;
2312 struct listnode
*node
= NULL
;
2313 struct zebra_vrf
*zvrf
= NULL
;
2314 char buf
[ETHER_ADDR_STRLEN
];
2316 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2318 if (IS_ZEBRA_DEBUG_VXLAN
)
2319 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2320 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2321 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2323 /* Walk all neighbors and mark any inactive local neighbors as
2324 * active and/or update sequence number upon a move, and inform BGP.
2325 * The action for remote neighbors is TBD.
2326 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2327 * accidentally end up deleting a just-learnt local neighbor.
2329 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2330 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2331 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2332 ZEBRA_NEIGH_SET_ACTIVE(n
);
2333 n
->loc_seq
= zmac
->loc_seq
;
2334 if (!(zvrf
->dup_addr_detect
&&
2335 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2336 ZEBRA_NEIGH_DUPLICATE
)))
2337 zvni_neigh_send_add_to_client(
2338 zvni
->vni
, &n
->ip
, &n
->emac
,
2339 n
->flags
, n
->loc_seq
);
2346 * Process all neighbors associated with a local MAC upon the MAC being
2349 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2352 zebra_neigh_t
*n
= NULL
;
2353 struct listnode
*node
= NULL
;
2354 char buf
[ETHER_ADDR_STRLEN
];
2356 if (IS_ZEBRA_DEBUG_VXLAN
)
2357 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2358 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2361 /* Walk all local neighbors and mark as inactive and inform
2363 * TBD: There is currently no handling for remote neighbors. We
2364 * don't expect them to exist, if they do, do we install the MAC
2365 * as a remote MAC and the neighbor as remote?
2367 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2368 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2369 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2370 ZEBRA_NEIGH_SET_INACTIVE(n
);
2372 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2373 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2380 * Process all neighbors associated with a MAC upon the MAC being remotely
2383 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2386 zebra_neigh_t
*n
= NULL
;
2387 struct listnode
*node
= NULL
;
2388 char buf
[ETHER_ADDR_STRLEN
];
2390 if (IS_ZEBRA_DEBUG_VXLAN
)
2391 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2392 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2395 /* Walk all local neighbors and mark as inactive and inform
2398 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2399 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2400 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2401 ZEBRA_NEIGH_SET_INACTIVE(n
);
2403 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2404 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2411 * Process all neighbors associated with a remote MAC upon the MAC being
2414 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2417 /* NOTE: Currently a NO-OP. */
2420 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2422 zebra_neigh_t
*nbr
= NULL
;
2423 struct listnode
*node
= NULL
;
2425 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2426 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2427 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2428 zvni_neigh_probe(zvni
, nbr
);
2433 * Inform BGP about local neighbor addition.
2435 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2436 struct ethaddr
*macaddr
,
2437 uint8_t neigh_flags
,
2442 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2443 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2444 /* Set router flag (R-bit) based on local neigh entry add */
2445 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2446 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2448 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2449 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2453 * Inform BGP about local neighbor deletion.
2455 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2456 struct ethaddr
*macaddr
, uint8_t flags
,
2459 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2460 0, state
, ZEBRA_MACIP_DEL
);
2464 * Install remote neighbor into the kernel.
2466 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2468 struct zebra_if
*zif
;
2469 struct zebra_l2info_vxlan
*vxl
;
2470 struct interface
*vlan_if
;
2476 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2479 zif
= zvni
->vxlan_if
->info
;
2482 vxl
= &zif
->l2info
.vxl
;
2484 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2488 flags
= NTF_EXT_LEARNED
;
2489 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2490 flags
|= NTF_ROUTER
;
2491 ZEBRA_NEIGH_SET_ACTIVE(n
);
2492 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2498 * Uninstall remote neighbor from the kernel.
2500 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2502 struct zebra_if
*zif
;
2503 struct zebra_l2info_vxlan
*vxl
;
2504 struct interface
*vlan_if
;
2506 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2509 if (!zvni
->vxlan_if
) {
2510 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2515 zif
= zvni
->vxlan_if
->info
;
2518 vxl
= &zif
->l2info
.vxl
;
2519 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2523 ZEBRA_NEIGH_SET_INACTIVE(n
);
2525 return kernel_del_neigh(vlan_if
, &n
->ip
);
2529 * Probe neighbor from the kernel.
2531 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2533 struct zebra_if
*zif
;
2534 struct zebra_l2info_vxlan
*vxl
;
2535 struct interface
*vlan_if
;
2537 zif
= zvni
->vxlan_if
->info
;
2540 vxl
= &zif
->l2info
.vxl
;
2542 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2547 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2555 * Install neighbor hash entry - called upon access VLAN change.
2557 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2560 struct neigh_walk_ctx
*wctx
= ctxt
;
2562 n
= (zebra_neigh_t
*)bucket
->data
;
2564 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2565 zvni_neigh_install(wctx
->zvni
, n
);
2568 /* Get the VRR interface for SVI if any */
2569 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2571 struct zebra_vrf
*zvrf
= NULL
;
2572 struct interface
*tmp_if
= NULL
;
2573 struct zebra_if
*zif
= NULL
;
2575 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2578 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2583 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2586 if (zif
->link
== ifp
)
2593 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2595 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2596 struct connected
*c
= NULL
;
2597 struct ethaddr macaddr
;
2599 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2601 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2604 memset(&ip
, 0, sizeof(struct ipaddr
));
2605 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2608 if (c
->address
->family
== AF_INET
) {
2609 ip
.ipa_type
= IPADDR_V4
;
2610 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2611 sizeof(struct in_addr
));
2612 } else if (c
->address
->family
== AF_INET6
) {
2613 ip
.ipa_type
= IPADDR_V6
;
2614 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2615 sizeof(struct in6_addr
));
2620 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2626 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2628 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2629 struct connected
*c
= NULL
;
2630 struct ethaddr macaddr
;
2632 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2634 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2637 memset(&ip
, 0, sizeof(struct ipaddr
));
2638 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2641 if (c
->address
->family
== AF_INET
) {
2642 ip
.ipa_type
= IPADDR_V4
;
2643 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2644 sizeof(struct in_addr
));
2645 } else if (c
->address
->family
== AF_INET6
) {
2646 ip
.ipa_type
= IPADDR_V6
;
2647 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2648 sizeof(struct in6_addr
));
2653 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2659 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2662 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2663 struct connected
*c
= NULL
;
2664 struct ethaddr macaddr
;
2666 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2668 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2671 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2673 /* skip link local address */
2674 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2679 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2680 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2682 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2683 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2689 * zvni_gw_macip_add_to_client
2691 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2692 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2694 char buf
[ETHER_ADDR_STRLEN
];
2695 char buf2
[INET6_ADDRSTRLEN
];
2696 zebra_neigh_t
*n
= NULL
;
2697 zebra_mac_t
*mac
= NULL
;
2698 struct zebra_if
*zif
= NULL
;
2699 struct zebra_l2info_vxlan
*vxl
= NULL
;
2701 zif
= zvni
->vxlan_if
->info
;
2705 vxl
= &zif
->l2info
.vxl
;
2707 mac
= zvni_mac_lookup(zvni
, macaddr
);
2709 mac
= zvni_mac_add(zvni
, macaddr
);
2711 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2712 "Failed to add MAC %s intf %s(%u) VID %u",
2713 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2714 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2719 /* Set "local" forwarding info. */
2720 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2721 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2722 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2723 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2724 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2725 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2727 n
= zvni_neigh_lookup(zvni
, ip
);
2729 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2732 EC_ZEBRA_MAC_ADD_FAILED
,
2733 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2734 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2735 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2736 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2741 /* Set "local" forwarding info. */
2742 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2743 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2744 ZEBRA_NEIGH_SET_ACTIVE(n
);
2745 /* Set Router flag (R-bit) */
2746 if (ip
->ipa_type
== IPADDR_V6
)
2747 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2748 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2749 n
->ifindex
= ifp
->ifindex
;
2751 /* Only advertise in BGP if the knob is enabled */
2752 if (!advertise_gw_macip_enabled(zvni
))
2755 if (IS_ZEBRA_DEBUG_VXLAN
)
2757 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2758 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2759 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2760 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2762 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2763 n
->flags
, n
->loc_seq
);
2769 * zvni_gw_macip_del_from_client
2771 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2774 char buf1
[ETHER_ADDR_STRLEN
];
2775 char buf2
[INET6_ADDRSTRLEN
];
2776 zebra_neigh_t
*n
= NULL
;
2777 zebra_mac_t
*mac
= NULL
;
2779 /* If the neigh entry is not present nothing to do*/
2780 n
= zvni_neigh_lookup(zvni
, ip
);
2784 /* mac entry should be present */
2785 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2787 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2788 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2789 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2793 /* If the entry is not local nothing to do*/
2794 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2797 /* only need to delete the entry from bgp if we sent it before */
2798 if (IS_ZEBRA_DEBUG_VXLAN
)
2800 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2801 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2802 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2803 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2805 /* Remove neighbor from BGP. */
2806 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2807 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2809 /* Delete this neighbor entry. */
2810 zvni_neigh_del(zvni
, n
);
2812 /* see if the mac needs to be deleted as well*/
2814 zvni_deref_ip2mac(zvni
, mac
);
2819 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2822 zebra_vni_t
*zvni
= NULL
;
2823 struct zebra_if
*zif
= NULL
;
2824 struct zebra_l2info_vxlan zl2_info
;
2825 struct interface
*vlan_if
= NULL
;
2826 struct interface
*vrr_if
= NULL
;
2827 struct interface
*ifp
;
2829 /* Add primary SVI MAC*/
2830 zvni
= (zebra_vni_t
*)bucket
->data
;
2832 ifp
= zvni
->vxlan_if
;
2837 /* If down or not mapped to a bridge, we're done. */
2838 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2841 zl2_info
= zif
->l2info
.vxl
;
2844 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2848 /* Del primary MAC-IP */
2849 zvni_del_macip_for_intf(vlan_if
, zvni
);
2851 /* Del VRR MAC-IP - if any*/
2852 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2854 zvni_del_macip_for_intf(vrr_if
, zvni
);
2859 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2862 zebra_vni_t
*zvni
= NULL
;
2863 struct zebra_if
*zif
= NULL
;
2864 struct zebra_l2info_vxlan zl2_info
;
2865 struct interface
*vlan_if
= NULL
;
2866 struct interface
*vrr_if
= NULL
;
2867 struct interface
*ifp
= NULL
;
2869 zvni
= (zebra_vni_t
*)bucket
->data
;
2871 ifp
= zvni
->vxlan_if
;
2876 /* If down or not mapped to a bridge, we're done. */
2877 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2879 zl2_info
= zif
->l2info
.vxl
;
2882 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2886 /* Add primary SVI MAC-IP */
2887 zvni_add_macip_for_intf(vlan_if
, zvni
);
2889 if (advertise_gw_macip_enabled(zvni
)) {
2890 /* Add VRR MAC-IP - if any*/
2891 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2893 zvni_add_macip_for_intf(vrr_if
, zvni
);
2899 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2902 zebra_vni_t
*zvni
= NULL
;
2903 struct zebra_if
*zif
= NULL
;
2904 struct zebra_l2info_vxlan zl2_info
;
2905 struct interface
*vlan_if
= NULL
;
2906 struct interface
*ifp
;
2908 /* Add primary SVI MAC*/
2909 zvni
= (zebra_vni_t
*)bucket
->data
;
2913 ifp
= zvni
->vxlan_if
;
2918 /* If down or not mapped to a bridge, we're done. */
2919 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2922 zl2_info
= zif
->l2info
.vxl
;
2924 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2925 zif
->brslave_info
.br_if
);
2929 /* Del primary MAC-IP */
2930 zvni_del_macip_for_intf(vlan_if
, zvni
);
2935 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2936 struct interface
*ifp
,
2938 struct ethaddr
*macaddr
,
2941 char buf
[ETHER_ADDR_STRLEN
];
2942 char buf2
[INET6_ADDRSTRLEN
];
2943 struct zebra_vrf
*zvrf
;
2944 zebra_neigh_t
*n
= NULL
;
2945 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2946 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2947 bool upd_mac_seq
= false;
2948 bool neigh_mac_change
= false;
2949 bool neigh_on_hold
= false;
2950 bool neigh_was_remote
= false;
2951 bool do_dad
= false;
2952 struct in_addr vtep_ip
= {.s_addr
= 0};
2954 /* Check if the MAC exists. */
2955 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2957 /* create a dummy MAC if the MAC is not already present */
2958 if (IS_ZEBRA_DEBUG_VXLAN
)
2960 "AUTO MAC %s created for neigh %s on VNI %u",
2961 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2962 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2964 zmac
= zvni_mac_add(zvni
, macaddr
);
2966 zlog_debug("Failed to add MAC %s VNI %u",
2967 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2972 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2973 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2974 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2976 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2978 * We don't change the MAC to local upon a neighbor
2979 * learn event, we wait for the explicit local MAC
2980 * learn. However, we have to compute its sequence
2981 * number in preparation for when it actually turns
2988 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2992 /* Check if the neighbor exists. */
2993 n
= zvni_neigh_lookup(zvni
, ip
);
2995 /* New neighbor - create */
2996 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2999 EC_ZEBRA_MAC_ADD_FAILED
,
3000 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3001 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3002 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3003 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3006 /* Set "local" forwarding info. */
3007 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3008 n
->ifindex
= ifp
->ifindex
;
3010 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3014 /* Note any changes and see if of interest to BGP. */
3015 mac_different
= (memcmp(n
->emac
.octet
,
3016 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3017 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3018 ZEBRA_NEIGH_ROUTER_FLAG
);
3019 if (!mac_different
&& is_router
== cur_is_router
) {
3020 n
->ifindex
= ifp
->ifindex
;
3024 if (!mac_different
) {
3025 bool is_neigh_freezed
= false;
3027 /* Only the router flag has changed. */
3030 ZEBRA_NEIGH_ROUTER_FLAG
);
3032 UNSET_FLAG(n
->flags
,
3033 ZEBRA_NEIGH_ROUTER_FLAG
);
3035 /* Neigh is in freeze state and freeze action
3036 * is enabled, do not send update to client.
3038 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3040 CHECK_FLAG(n
->flags
,
3041 ZEBRA_NEIGH_DUPLICATE
));
3043 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3045 return zvni_neigh_send_add_to_client(
3046 zvni
->vni
, ip
, macaddr
,
3047 n
->flags
, n
->loc_seq
);
3051 /* The MAC has changed, need to issue a delete
3052 * first as this means a different MACIP route.
3053 * Also, need to do some unlinking/relinking.
3054 * We also need to update the MAC's sequence number
3055 * in different situations.
3057 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3058 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3059 &n
->emac
, 0, n
->state
);
3060 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3062 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3064 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3065 neigh_mac_change
= upd_mac_seq
= true;
3066 listnode_delete(old_zmac
->neigh_list
, n
);
3067 zvni_deref_ip2mac(zvni
, old_zmac
);
3070 /* Update the forwarding info. */
3071 n
->ifindex
= ifp
->ifindex
;
3072 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3074 /* Link to new MAC */
3075 listnode_add_sort(zmac
->neigh_list
, n
);
3076 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3078 * Neighbor has moved from remote to local. Its
3079 * MAC could have also changed as part of the move.
3081 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3083 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3085 old_mac_seq
= CHECK_FLAG(
3090 neigh_mac_change
= upd_mac_seq
= true;
3091 listnode_delete(old_zmac
->neigh_list
,
3093 zvni_deref_ip2mac(zvni
, old_zmac
);
3096 /* Link to new MAC */
3097 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3098 listnode_add_sort(zmac
->neigh_list
, n
);
3100 /* Based on Mobility event Scenario-B from the
3101 * draft, neigh's previous state was remote treat this
3104 neigh_was_remote
= true;
3105 vtep_ip
= n
->r_vtep_ip
;
3106 /* Mark appropriately */
3107 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3108 n
->r_vtep_ip
.s_addr
= 0;
3109 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3110 n
->ifindex
= ifp
->ifindex
;
3114 /* If MAC was previously remote, or the neighbor had a different
3115 * MAC earlier, recompute the sequence number.
3118 uint32_t seq1
, seq2
;
3120 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3121 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3122 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3123 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3124 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3127 /* Mark Router flag (R-bit) */
3129 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3131 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3133 /* Check old and/or new MAC detected as duplicate mark
3134 * the neigh as duplicate
3136 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3137 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3138 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3140 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3141 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3144 /* For IP Duplicate Address Detection (DAD) is trigger,
3145 * when the event is extended mobility based on scenario-B
3146 * from the draft, IP/Neigh's MAC binding changed and
3147 * neigh's previous state was remote.
3149 if (neigh_mac_change
&& neigh_was_remote
)
3152 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3153 &neigh_on_hold
, true);
3155 /* Before we program this in BGP, we need to check if MAC is locally
3156 * learnt. If not, force neighbor to be inactive and reset its seq.
3158 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3159 ZEBRA_NEIGH_SET_INACTIVE(n
);
3161 zmac
->loc_seq
= mac_new_seq
;
3165 /* If the MAC's sequence number has changed, inform the MAC and all
3166 * neighbors associated with the MAC to BGP, else just inform this
3169 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3170 if (IS_ZEBRA_DEBUG_VXLAN
)
3171 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3172 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3173 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3174 zmac
->loc_seq
= mac_new_seq
;
3175 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3176 zmac
->flags
, zmac
->loc_seq
))
3178 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3182 ZEBRA_NEIGH_SET_ACTIVE(n
);
3183 n
->loc_seq
= zmac
->loc_seq
;
3186 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3187 n
->flags
, n
->loc_seq
);
3191 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3192 struct interface
*ifp
,
3194 struct ethaddr
*macaddr
,
3197 char buf
[ETHER_ADDR_STRLEN
];
3198 char buf2
[INET6_ADDRSTRLEN
];
3199 zebra_neigh_t
*n
= NULL
;
3200 zebra_mac_t
*zmac
= NULL
;
3202 /* If the neighbor is unknown, there is no further action. */
3203 n
= zvni_neigh_lookup(zvni
, ip
);
3207 /* If a remote entry, see if it needs to be refreshed */
3208 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3210 if (state
& NUD_STALE
)
3211 zvni_neigh_install(zvni
, n
);
3214 /* We got a "remote" neighbor notification for an entry
3215 * we think is local. This can happen in a multihoming
3216 * scenario - but only if the MAC is already "remote".
3217 * Just mark our entry as "remote".
3219 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3220 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3222 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3223 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3224 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3229 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3230 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3231 ZEBRA_NEIGH_SET_ACTIVE(n
);
3232 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3239 * Make hash key for MAC.
3241 static unsigned int mac_hash_keymake(void *p
)
3243 zebra_mac_t
*pmac
= p
;
3244 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3246 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3250 * Compare two MAC addresses.
3252 static bool mac_cmp(const void *p1
, const void *p2
)
3254 const zebra_mac_t
*pmac1
= p1
;
3255 const zebra_mac_t
*pmac2
= p2
;
3257 if (pmac1
== NULL
&& pmac2
== NULL
)
3260 if (pmac1
== NULL
|| pmac2
== NULL
)
3263 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3268 * Callback to allocate MAC hash entry.
3270 static void *zvni_mac_alloc(void *p
)
3272 const zebra_mac_t
*tmp_mac
= p
;
3275 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3278 return ((void *)mac
);
3284 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3286 zebra_mac_t tmp_mac
;
3287 zebra_mac_t
*mac
= NULL
;
3289 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3290 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3291 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3294 mac
->neigh_list
= list_new();
3295 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3303 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3305 zebra_mac_t
*tmp_mac
;
3307 list_delete(&mac
->neigh_list
);
3309 /* Free the VNI hash entry and allocated memory. */
3310 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3311 XFREE(MTYPE_MAC
, tmp_mac
);
3317 * Free MAC hash entry (callback)
3319 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3321 struct mac_walk_ctx
*wctx
= arg
;
3322 zebra_mac_t
*mac
= bucket
->data
;
3324 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3325 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3326 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3327 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3328 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3329 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3330 &wctx
->r_vtep_ip
))) {
3331 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3332 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3336 if (wctx
->uninstall
)
3337 zvni_mac_uninstall(wctx
->zvni
, mac
);
3339 zvni_mac_del(wctx
->zvni
, mac
);
3346 * Delete all MAC entries from specific VTEP for a particular VNI.
3348 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3349 struct in_addr
*r_vtep_ip
)
3351 struct mac_walk_ctx wctx
;
3353 if (!zvni
->mac_table
)
3356 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3358 wctx
.uninstall
= uninstall
;
3359 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3360 wctx
.r_vtep_ip
= *r_vtep_ip
;
3362 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3366 * Delete all MAC entries for this VNI.
3368 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3371 struct mac_walk_ctx wctx
;
3373 if (!zvni
->mac_table
)
3376 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3378 wctx
.uninstall
= uninstall
;
3379 wctx
.upd_client
= upd_client
;
3382 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3386 * Look up MAC hash entry.
3388 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3393 memset(&tmp
, 0, sizeof(tmp
));
3394 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3395 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3401 * Inform BGP about local MAC addition.
3403 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3404 uint8_t mac_flags
, uint32_t seq
)
3408 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3409 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3410 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3411 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3413 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3414 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3418 * Inform BGP about local MAC deletion.
3420 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3422 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3423 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3427 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3428 * notifications, to see if they are of interest.
3430 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3431 struct interface
*br_if
, vlanid_t vid
)
3433 struct zebra_ns
*zns
;
3434 struct route_node
*rn
;
3435 struct interface
*tmp_if
= NULL
;
3436 struct zebra_if
*zif
;
3437 struct zebra_l2info_bridge
*br
;
3438 struct zebra_l2info_vxlan
*vxl
= NULL
;
3439 uint8_t bridge_vlan_aware
;
3443 /* Determine if bridge is VLAN-aware or not */
3446 br
= &zif
->l2info
.br
;
3447 bridge_vlan_aware
= br
->vlan_aware
;
3449 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3450 /* TODO: Optimize with a hash. */
3451 zns
= zebra_ns_lookup(NS_DEFAULT
);
3452 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3453 tmp_if
= (struct interface
*)rn
->info
;
3457 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3459 if (!if_is_operative(tmp_if
))
3461 vxl
= &zif
->l2info
.vxl
;
3463 if (zif
->brslave_info
.br_if
!= br_if
)
3466 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3475 zvni
= zvni_lookup(vxl
->vni
);
3480 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3481 * neighbor notifications, to see if they are of interest.
3483 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3484 struct interface
*br_if
)
3486 struct zebra_ns
*zns
;
3487 struct route_node
*rn
;
3488 struct interface
*tmp_if
= NULL
;
3489 struct zebra_if
*zif
;
3490 struct zebra_l2info_bridge
*br
;
3491 struct zebra_l2info_vxlan
*vxl
= NULL
;
3492 uint8_t bridge_vlan_aware
;
3500 /* Make sure the linked interface is a bridge. */
3501 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3504 /* Determine if bridge is VLAN-aware or not */
3507 br
= &zif
->l2info
.br
;
3508 bridge_vlan_aware
= br
->vlan_aware
;
3509 if (bridge_vlan_aware
) {
3510 struct zebra_l2info_vlan
*vl
;
3512 if (!IS_ZEBRA_IF_VLAN(ifp
))
3517 vl
= &zif
->l2info
.vl
;
3521 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3522 /* TODO: Optimize with a hash. */
3523 zns
= zebra_ns_lookup(NS_DEFAULT
);
3524 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3525 tmp_if
= (struct interface
*)rn
->info
;
3529 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3531 if (!if_is_operative(tmp_if
))
3533 vxl
= &zif
->l2info
.vxl
;
3535 if (zif
->brslave_info
.br_if
!= br_if
)
3538 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3547 zvni
= zvni_lookup(vxl
->vni
);
3551 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3553 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3554 * linked to the bridge
3555 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3558 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3560 struct zebra_ns
*zns
;
3561 struct route_node
*rn
;
3562 struct interface
*tmp_if
= NULL
;
3563 struct zebra_if
*zif
;
3564 struct zebra_l2info_bridge
*br
;
3565 struct zebra_l2info_vlan
*vl
;
3566 uint8_t bridge_vlan_aware
;
3569 /* Defensive check, caller expected to invoke only with valid bridge. */
3573 /* Determine if bridge is VLAN-aware or not */
3576 br
= &zif
->l2info
.br
;
3577 bridge_vlan_aware
= br
->vlan_aware
;
3579 /* Check oper status of the SVI. */
3580 if (!bridge_vlan_aware
)
3581 return if_is_operative(br_if
) ? br_if
: NULL
;
3583 /* Identify corresponding VLAN interface. */
3584 /* TODO: Optimize with a hash. */
3585 zns
= zebra_ns_lookup(NS_DEFAULT
);
3586 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3587 tmp_if
= (struct interface
*)rn
->info
;
3588 /* Check oper status of the SVI. */
3589 if (!tmp_if
|| !if_is_operative(tmp_if
))
3592 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3593 || zif
->link
!= br_if
)
3595 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3597 if (vl
->vid
== vid
) {
3603 return found
? tmp_if
: NULL
;
3607 * Install remote MAC into the kernel.
3609 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3611 struct zebra_if
*zif
;
3612 struct zebra_l2info_vxlan
*vxl
;
3615 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3618 zif
= zvni
->vxlan_if
->info
;
3621 vxl
= &zif
->l2info
.vxl
;
3623 sticky
= !!CHECK_FLAG(mac
->flags
,
3624 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3626 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3627 mac
->fwd_info
.r_vtep_ip
, sticky
);
3631 * Uninstall remote MAC from the kernel.
3633 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3635 struct zebra_if
*zif
;
3636 struct zebra_l2info_vxlan
*vxl
;
3637 struct in_addr vtep_ip
;
3638 struct interface
*ifp
;
3640 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3643 if (!zvni
->vxlan_if
) {
3644 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3649 zif
= zvni
->vxlan_if
->info
;
3652 vxl
= &zif
->l2info
.vxl
;
3654 ifp
= zvni
->vxlan_if
;
3655 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3657 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3661 * Install MAC hash entry - called upon access VLAN change.
3663 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3666 struct mac_walk_ctx
*wctx
= ctxt
;
3668 mac
= (zebra_mac_t
*)bucket
->data
;
3670 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3671 zvni_mac_install(wctx
->zvni
, mac
);
3675 * Count of remote neighbors referencing this MAC.
3677 static int remote_neigh_count(zebra_mac_t
*zmac
)
3679 zebra_neigh_t
*n
= NULL
;
3680 struct listnode
*node
= NULL
;
3683 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3684 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3692 * Decrement neighbor refcount of MAC; uninstall and free it if
3695 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3697 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3700 /* If all remote neighbors referencing a remote MAC go away,
3701 * we need to uninstall the MAC.
3703 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3704 remote_neigh_count(mac
) == 0) {
3705 zvni_mac_uninstall(zvni
, mac
);
3706 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3709 /* If no neighbors, delete the MAC. */
3710 if (list_isempty(mac
->neigh_list
))
3711 zvni_mac_del(zvni
, mac
);
3715 * Read and populate local MACs and neighbors corresponding to this VNI.
3717 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3719 struct zebra_ns
*zns
;
3720 struct zebra_if
*zif
;
3721 struct interface
*vlan_if
;
3722 struct zebra_l2info_vxlan
*vxl
;
3723 struct interface
*vrr_if
;
3726 vxl
= &zif
->l2info
.vxl
;
3727 zns
= zebra_ns_lookup(NS_DEFAULT
);
3729 if (IS_ZEBRA_DEBUG_VXLAN
)
3731 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3732 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3733 zif
->brslave_info
.bridge_ifindex
);
3735 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3736 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3739 /* Add SVI MAC-IP */
3740 zvni_add_macip_for_intf(vlan_if
, zvni
);
3742 /* Add VRR MAC-IP - if any*/
3743 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3745 zvni_add_macip_for_intf(vrr_if
, zvni
);
3747 neigh_read_for_vlan(zns
, vlan_if
);
3752 * Hash function for VNI.
3754 static unsigned int vni_hash_keymake(void *p
)
3756 const zebra_vni_t
*zvni
= p
;
3758 return (jhash_1word(zvni
->vni
, 0));
3762 * Compare 2 VNI hash entries.
3764 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3766 const zebra_vni_t
*zvni1
= p1
;
3767 const zebra_vni_t
*zvni2
= p2
;
3769 return (zvni1
->vni
== zvni2
->vni
);
3772 static int vni_list_cmp(void *p1
, void *p2
)
3774 const zebra_vni_t
*zvni1
= p1
;
3775 const zebra_vni_t
*zvni2
= p2
;
3777 if (zvni1
->vni
== zvni2
->vni
)
3779 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3783 * Callback to allocate VNI hash entry.
3785 static void *zvni_alloc(void *p
)
3787 const zebra_vni_t
*tmp_vni
= p
;
3790 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3791 zvni
->vni
= tmp_vni
->vni
;
3792 return ((void *)zvni
);
3796 * Look up VNI hash entry.
3798 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3800 struct zebra_vrf
*zvrf
;
3801 zebra_vni_t tmp_vni
;
3802 zebra_vni_t
*zvni
= NULL
;
3804 zvrf
= zebra_vrf_get_evpn();
3806 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3808 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3814 * Add VNI hash entry.
3816 static zebra_vni_t
*zvni_add(vni_t vni
)
3818 struct zebra_vrf
*zvrf
;
3819 zebra_vni_t tmp_zvni
;
3820 zebra_vni_t
*zvni
= NULL
;
3822 zvrf
= zebra_vrf_get_evpn();
3824 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3826 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3829 /* Create hash table for MAC */
3831 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3833 /* Create hash table for neighbors */
3834 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3835 "Zebra VNI Neighbor Table");
3841 * Delete VNI hash entry.
3843 static int zvni_del(zebra_vni_t
*zvni
)
3845 struct zebra_vrf
*zvrf
;
3846 zebra_vni_t
*tmp_zvni
;
3848 zvrf
= zebra_vrf_get_evpn();
3851 zvni
->vxlan_if
= NULL
;
3853 /* Free the neighbor hash table. */
3854 hash_free(zvni
->neigh_table
);
3855 zvni
->neigh_table
= NULL
;
3857 /* Free the MAC hash table. */
3858 hash_free(zvni
->mac_table
);
3859 zvni
->mac_table
= NULL
;
3861 /* Free the VNI hash entry and allocated memory. */
3862 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3863 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3869 * Inform BGP about local VNI addition.
3871 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3873 struct zserv
*client
;
3876 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3877 /* BGP may not be running. */
3881 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3883 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3884 stream_putl(s
, zvni
->vni
);
3885 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3886 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3888 /* Write packet size. */
3889 stream_putw_at(s
, 0, stream_get_endp(s
));
3891 if (IS_ZEBRA_DEBUG_VXLAN
)
3892 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3893 inet_ntoa(zvni
->local_vtep_ip
),
3894 vrf_id_to_name(zvni
->vrf_id
),
3895 zebra_route_string(client
->proto
));
3897 client
->vniadd_cnt
++;
3898 return zserv_send_message(client
, s
);
3902 * Inform BGP about local VNI deletion.
3904 static int zvni_send_del_to_client(vni_t vni
)
3906 struct zserv
*client
;
3909 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3910 /* BGP may not be running. */
3914 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3917 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3918 stream_putl(s
, vni
);
3920 /* Write packet size. */
3921 stream_putw_at(s
, 0, stream_get_endp(s
));
3923 if (IS_ZEBRA_DEBUG_VXLAN
)
3924 zlog_debug("Send VNI_DEL %u to %s", vni
,
3925 zebra_route_string(client
->proto
));
3927 client
->vnidel_cnt
++;
3928 return zserv_send_message(client
, s
);
3932 * Build the VNI hash table by going over the VxLAN interfaces. This
3933 * is called when EVPN (advertise-all-vni) is enabled.
3935 static void zvni_build_hash_table(void)
3937 struct zebra_ns
*zns
;
3938 struct route_node
*rn
;
3939 struct interface
*ifp
;
3941 /* Walk VxLAN interfaces and create VNI hash. */
3942 zns
= zebra_ns_lookup(NS_DEFAULT
);
3943 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3945 zebra_vni_t
*zvni
= NULL
;
3946 zebra_l3vni_t
*zl3vni
= NULL
;
3947 struct zebra_if
*zif
;
3948 struct zebra_l2info_vxlan
*vxl
;
3950 ifp
= (struct interface
*)rn
->info
;
3954 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3957 vxl
= &zif
->l2info
.vxl
;
3960 /* L3-VNI and L2-VNI are handled seperately */
3961 zl3vni
= zl3vni_lookup(vni
);
3964 if (IS_ZEBRA_DEBUG_VXLAN
)
3966 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3967 ifp
->name
, ifp
->ifindex
, vni
);
3969 /* associate with vxlan_if */
3970 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
3971 zl3vni
->vxlan_if
= ifp
;
3974 * we need to associate with SVI.
3975 * we can associate with svi-if only after association
3976 * with vxlan-intf is complete
3978 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
3980 if (is_l3vni_oper_up(zl3vni
))
3981 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
3984 struct interface
*vlan_if
= NULL
;
3986 if (IS_ZEBRA_DEBUG_VXLAN
)
3988 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3989 ifp
->name
, ifp
->ifindex
, vni
,
3990 inet_ntoa(vxl
->vtep_ip
));
3992 /* VNI hash entry is not expected to exist. */
3993 zvni
= zvni_lookup(vni
);
3996 "VNI hash already present for IF %s(%u) L2-VNI %u",
3997 ifp
->name
, ifp
->ifindex
, vni
);
4001 zvni
= zvni_add(vni
);
4004 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4005 ifp
->name
, ifp
->ifindex
, vni
);
4009 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4010 zvni
->vxlan_if
= ifp
;
4011 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4012 zif
->brslave_info
.br_if
);
4014 zvni
->vrf_id
= vlan_if
->vrf_id
;
4015 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4017 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4021 /* Inform BGP if intf is up and mapped to bridge. */
4022 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4023 zvni_send_add_to_client(zvni
);
4029 * See if remote VTEP matches with prefix.
4031 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4033 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4037 * Locate remote VTEP in VNI hash table.
4039 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4041 zebra_vtep_t
*zvtep
;
4046 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4047 if (zvni_vtep_match(vtep_ip
, zvtep
))
4055 * Add remote VTEP to VNI hash table.
4057 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4059 zebra_vtep_t
*zvtep
;
4061 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4063 zvtep
->vtep_ip
= *vtep_ip
;
4066 zvni
->vteps
->prev
= zvtep
;
4067 zvtep
->next
= zvni
->vteps
;
4068 zvni
->vteps
= zvtep
;
4074 * Remove remote VTEP from VNI hash table.
4076 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4079 zvtep
->next
->prev
= zvtep
->prev
;
4081 zvtep
->prev
->next
= zvtep
->next
;
4083 zvni
->vteps
= zvtep
->next
;
4085 zvtep
->prev
= zvtep
->next
= NULL
;
4086 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4092 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4093 * uninstall from kernel if asked to.
4095 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4097 zebra_vtep_t
*zvtep
, *zvtep_next
;
4102 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4103 zvtep_next
= zvtep
->next
;
4105 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4106 zvni_vtep_del(zvni
, zvtep
);
4113 * Install remote VTEP into the kernel.
4115 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4117 if (is_vxlan_flooding_head_end())
4118 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4123 * Uninstall remote VTEP from the kernel.
4125 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4127 if (!zvni
->vxlan_if
) {
4128 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4133 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4137 * Install or uninstall flood entries in the kernel corresponding to
4138 * remote VTEPs. This is invoked upon change to BUM handling.
4140 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4144 zebra_vtep_t
*zvtep
;
4146 zvni
= (zebra_vni_t
*)bucket
->data
;
4150 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4151 if (is_vxlan_flooding_head_end())
4152 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4154 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4159 * Cleanup VNI/VTEP and update kernel
4161 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4163 zebra_vni_t
*zvni
= NULL
;
4164 zebra_l3vni_t
*zl3vni
= NULL
;
4165 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4167 zvni
= (zebra_vni_t
*)bucket
->data
;
4169 /* remove from l3-vni list */
4171 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4173 listnode_delete(zl3vni
->l2vnis
, zvni
);
4175 /* Free up all neighbors and MACs, if any. */
4176 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4177 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4179 /* Free up all remote VTEPs, if any. */
4180 zvni_vtep_del_all(zvni
, 1);
4182 /* Delete the hash entry. */
4187 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4189 zebra_l3vni_t
*zl3vni
= NULL
;
4191 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4193 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4196 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4197 struct prefix
*host
)
4199 struct host_rb_entry lookup
;
4200 struct host_rb_entry
*hle
;
4202 memset(&lookup
, 0, sizeof(lookup
));
4203 memcpy(&lookup
.p
, host
, sizeof(*host
));
4205 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4209 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4210 memcpy(hle
, &lookup
, sizeof(lookup
));
4212 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4215 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4217 struct host_rb_entry lookup
;
4218 struct host_rb_entry
*hle
;
4220 memset(&lookup
, 0, sizeof(lookup
));
4221 memcpy(&lookup
.p
, host
, sizeof(*host
));
4223 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4225 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4226 XFREE(MTYPE_HOST_PREFIX
, hle
);
4233 * Look up MAC hash entry.
4235 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4236 struct ethaddr
*rmac
)
4241 memset(&tmp
, 0, sizeof(tmp
));
4242 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4243 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4249 * Callback to allocate RMAC hash entry.
4251 static void *zl3vni_rmac_alloc(void *p
)
4253 const zebra_mac_t
*tmp_rmac
= p
;
4256 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4259 return ((void *)zrmac
);
4263 * Add RMAC entry to l3-vni
4265 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4267 zebra_mac_t tmp_rmac
;
4268 zebra_mac_t
*zrmac
= NULL
;
4270 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4271 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4272 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4275 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4277 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4278 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4286 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4288 zebra_mac_t
*tmp_rmac
;
4289 struct host_rb_entry
*hle
;
4291 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4292 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4294 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4295 XFREE(MTYPE_HOST_PREFIX
, hle
);
4298 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4299 XFREE(MTYPE_MAC
, tmp_rmac
);
4305 * Install remote RMAC into the kernel.
4307 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4309 struct zebra_if
*zif
= NULL
;
4310 struct zebra_l2info_vxlan
*vxl
= NULL
;
4312 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4313 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4316 zif
= zl3vni
->vxlan_if
->info
;
4320 vxl
= &zif
->l2info
.vxl
;
4322 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4323 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4327 * Uninstall remote RMAC from the kernel.
4329 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4331 char buf
[ETHER_ADDR_STRLEN
];
4332 struct zebra_if
*zif
= NULL
;
4333 struct zebra_l2info_vxlan
*vxl
= NULL
;
4335 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4336 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4339 if (!zl3vni
->vxlan_if
) {
4341 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4342 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4343 zl3vni
->vni
, zl3vni
);
4347 zif
= zl3vni
->vxlan_if
->info
;
4351 vxl
= &zif
->l2info
.vxl
;
4353 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4354 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4357 /* handle rmac add */
4358 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4359 struct ipaddr
*vtep_ip
,
4360 struct prefix
*host_prefix
)
4362 char buf
[ETHER_ADDR_STRLEN
];
4363 char buf1
[INET6_ADDRSTRLEN
];
4364 zebra_mac_t
*zrmac
= NULL
;
4366 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4369 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4372 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4373 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4375 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4378 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4379 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4381 /* install rmac in kernel */
4382 zl3vni_rmac_install(zl3vni
, zrmac
);
4385 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4391 /* handle rmac delete */
4392 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4393 struct prefix
*host_prefix
)
4395 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4397 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4398 /* uninstall from kernel */
4399 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4401 /* del the rmac entry */
4402 zl3vni_rmac_del(zl3vni
, zrmac
);
4407 * Look up nh hash entry on a l3-vni.
4409 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4414 memset(&tmp
, 0, sizeof(tmp
));
4415 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4416 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4423 * Callback to allocate NH hash entry on L3-VNI.
4425 static void *zl3vni_nh_alloc(void *p
)
4427 const zebra_neigh_t
*tmp_n
= p
;
4430 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4437 * Add neighbor entry.
4439 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4440 struct ethaddr
*mac
)
4442 zebra_neigh_t tmp_n
;
4443 zebra_neigh_t
*n
= NULL
;
4445 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4446 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4447 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4450 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4452 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4453 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4454 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4460 * Delete neighbor entry.
4462 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4464 zebra_neigh_t
*tmp_n
;
4465 struct host_rb_entry
*hle
;
4467 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4468 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4470 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4471 XFREE(MTYPE_HOST_PREFIX
, hle
);
4474 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4475 XFREE(MTYPE_NEIGH
, tmp_n
);
4481 * Install remote nh as neigh into the kernel.
4483 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4490 if (!is_l3vni_oper_up(zl3vni
))
4493 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4494 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4497 flags
= NTF_EXT_LEARNED
;
4498 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4499 flags
|= NTF_ROUTER
;
4500 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4506 * Uninstall remote nh from the kernel.
4508 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4510 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4511 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4514 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4517 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4520 /* add remote vtep as a neigh entry */
4521 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4522 struct ethaddr
*rmac
,
4523 struct prefix
*host_prefix
)
4525 char buf
[ETHER_ADDR_STRLEN
];
4526 char buf1
[INET6_ADDRSTRLEN
];
4527 zebra_neigh_t
*nh
= NULL
;
4529 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4531 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4535 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4536 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4537 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4542 /* install the nh neigh in kernel */
4543 zl3vni_nh_install(zl3vni
, nh
);
4546 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4551 /* handle nh neigh delete */
4552 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4553 struct prefix
*host_prefix
)
4555 rb_delete_host(&nh
->host_rb
, host_prefix
);
4557 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4558 /* uninstall from kernel */
4559 zl3vni_nh_uninstall(zl3vni
, nh
);
4561 /* delete the nh entry */
4562 zl3vni_nh_del(zl3vni
, nh
);
4566 /* handle neigh update from kernel - the only thing of interest is to
4567 * readd stale entries.
4569 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4573 zebra_neigh_t
*n
= NULL
;
4575 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4579 /* all next hop neigh are remote and installed by frr.
4580 * If the kernel has aged this entry, re-install.
4582 if (state
& NUD_STALE
)
4583 zl3vni_nh_install(zl3vni
, n
);
4588 /* handle neigh delete from kernel */
4589 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4591 zebra_neigh_t
*n
= NULL
;
4593 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4597 /* all next hop neigh are remote and installed by frr.
4598 * If we get an age out notification for these neigh entries, we have to
4601 zl3vni_nh_install(zl3vni
, n
);
4607 * Hash function for L3 VNI.
4609 static unsigned int l3vni_hash_keymake(void *p
)
4611 const zebra_l3vni_t
*zl3vni
= p
;
4613 return jhash_1word(zl3vni
->vni
, 0);
4617 * Compare 2 L3 VNI hash entries.
4619 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4621 const zebra_l3vni_t
*zl3vni1
= p1
;
4622 const zebra_l3vni_t
*zl3vni2
= p2
;
4624 return (zl3vni1
->vni
== zl3vni2
->vni
);
4628 * Callback to allocate L3 VNI hash entry.
4630 static void *zl3vni_alloc(void *p
)
4632 zebra_l3vni_t
*zl3vni
= NULL
;
4633 const zebra_l3vni_t
*tmp_l3vni
= p
;
4635 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4636 zl3vni
->vni
= tmp_l3vni
->vni
;
4637 return ((void *)zl3vni
);
4641 * Look up L3 VNI hash entry.
4643 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4645 zebra_l3vni_t tmp_l3vni
;
4646 zebra_l3vni_t
*zl3vni
= NULL
;
4648 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4649 tmp_l3vni
.vni
= vni
;
4650 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4656 * Add L3 VNI hash entry.
4658 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4660 zebra_l3vni_t tmp_zl3vni
;
4661 zebra_l3vni_t
*zl3vni
= NULL
;
4663 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4664 tmp_zl3vni
.vni
= vni
;
4666 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4669 zl3vni
->vrf_id
= vrf_id
;
4670 zl3vni
->svi_if
= NULL
;
4671 zl3vni
->vxlan_if
= NULL
;
4672 zl3vni
->l2vnis
= list_new();
4673 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4675 /* Create hash table for remote RMAC */
4676 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4677 "Zebra L3-VNI RMAC-Table");
4679 /* Create hash table for neighbors */
4680 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4681 "Zebra L3-VNI next-hop table");
4687 * Delete L3 VNI hash entry.
4689 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4691 zebra_l3vni_t
*tmp_zl3vni
;
4693 /* free the list of l2vnis */
4694 list_delete(&zl3vni
->l2vnis
);
4695 zl3vni
->l2vnis
= NULL
;
4697 /* Free the rmac table */
4698 hash_free(zl3vni
->rmac_table
);
4699 zl3vni
->rmac_table
= NULL
;
4701 /* Free the nh table */
4702 hash_free(zl3vni
->nh_table
);
4703 zl3vni
->nh_table
= NULL
;
4705 /* Free the VNI hash entry and allocated memory. */
4706 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4707 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4712 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4714 struct zebra_ns
*zns
= NULL
;
4715 struct route_node
*rn
= NULL
;
4716 struct interface
*ifp
= NULL
;
4718 /* loop through all vxlan-interface */
4719 zns
= zebra_ns_lookup(NS_DEFAULT
);
4720 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4722 struct zebra_if
*zif
= NULL
;
4723 struct zebra_l2info_vxlan
*vxl
= NULL
;
4725 ifp
= (struct interface
*)rn
->info
;
4730 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4733 vxl
= &zif
->l2info
.vxl
;
4734 if (vxl
->vni
== zl3vni
->vni
) {
4735 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4743 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4745 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4746 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4751 if (!zl3vni
->vxlan_if
)
4754 zif
= zl3vni
->vxlan_if
->info
;
4758 vxl
= &zif
->l2info
.vxl
;
4760 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4763 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4765 struct zebra_vrf
*zvrf
= NULL
;
4767 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4771 return zl3vni_lookup(zvrf
->l3vni
);
4775 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4776 * neighbor notifications, to see if they are of interest.
4778 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4779 struct interface
*br_if
)
4783 uint8_t bridge_vlan_aware
= 0;
4784 zebra_l3vni_t
*zl3vni
= NULL
;
4785 struct zebra_ns
*zns
= NULL
;
4786 struct route_node
*rn
= NULL
;
4787 struct zebra_if
*zif
= NULL
;
4788 struct interface
*tmp_if
= NULL
;
4789 struct zebra_l2info_bridge
*br
= NULL
;
4790 struct zebra_l2info_vxlan
*vxl
= NULL
;
4795 /* Make sure the linked interface is a bridge. */
4796 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4799 /* Determine if bridge is VLAN-aware or not */
4802 br
= &zif
->l2info
.br
;
4803 bridge_vlan_aware
= br
->vlan_aware
;
4804 if (bridge_vlan_aware
) {
4805 struct zebra_l2info_vlan
*vl
;
4807 if (!IS_ZEBRA_IF_VLAN(ifp
))
4812 vl
= &zif
->l2info
.vl
;
4816 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4817 /* TODO: Optimize with a hash. */
4818 zns
= zebra_ns_lookup(NS_DEFAULT
);
4819 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4820 tmp_if
= (struct interface
*)rn
->info
;
4824 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4826 if (!if_is_operative(tmp_if
))
4828 vxl
= &zif
->l2info
.vxl
;
4830 if (zif
->brslave_info
.br_if
!= br_if
)
4833 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4842 zl3vni
= zl3vni_lookup(vxl
->vni
);
4847 * Inform BGP about l3-vni.
4849 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4851 struct stream
*s
= NULL
;
4852 struct zserv
*client
= NULL
;
4853 struct ethaddr rmac
;
4854 char buf
[ETHER_ADDR_STRLEN
];
4856 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4857 /* BGP may not be running. */
4862 memset(&rmac
, 0, sizeof(struct ethaddr
));
4863 zl3vni_get_rmac(zl3vni
, &rmac
);
4865 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4867 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4868 stream_putl(s
, zl3vni
->vni
);
4869 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4870 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4871 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4872 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4874 /* Write packet size. */
4875 stream_putw_at(s
, 0, stream_get_endp(s
));
4877 if (IS_ZEBRA_DEBUG_VXLAN
)
4879 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4880 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4881 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4882 inet_ntoa(zl3vni
->local_vtep_ip
),
4883 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4884 ? "prefix-routes-only"
4886 zebra_route_string(client
->proto
));
4888 client
->l3vniadd_cnt
++;
4889 return zserv_send_message(client
, s
);
4893 * Inform BGP about local l3-VNI deletion.
4895 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4897 struct stream
*s
= NULL
;
4898 struct zserv
*client
= NULL
;
4900 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4901 /* BGP may not be running. */
4905 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4907 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4908 stream_putl(s
, zl3vni
->vni
);
4910 /* Write packet size. */
4911 stream_putw_at(s
, 0, stream_get_endp(s
));
4913 if (IS_ZEBRA_DEBUG_VXLAN
)
4914 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4915 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4916 zebra_route_string(client
->proto
));
4918 client
->l3vnidel_cnt
++;
4919 return zserv_send_message(client
, s
);
4922 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4927 /* send l3vni add to BGP */
4928 zl3vni_send_add_to_client(zl3vni
);
4931 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4936 /* send l3-vni del to BGP*/
4937 zl3vni_send_del_to_client(zl3vni
);
4940 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
4942 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
4943 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4945 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4946 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4950 * handle transition of vni from l2 to l3 and vice versa
4952 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4955 zebra_vni_t
*zvni
= NULL
;
4957 /* There is a possibility that VNI notification was already received
4958 * from kernel and we programmed it as L2-VNI
4959 * In such a case we need to delete this L2-VNI first, so
4960 * that it can be reprogrammed as L3-VNI in the system. It is also
4961 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4962 * interface is still present in kernel. In this case to keep it
4963 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4966 /* Locate hash entry */
4967 zvni
= zvni_lookup(vni
);
4971 if (IS_ZEBRA_DEBUG_VXLAN
)
4972 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
4974 /* Delete VNI from BGP. */
4975 zvni_send_del_to_client(zvni
->vni
);
4977 /* Free up all neighbors and MAC, if any. */
4978 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
4979 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
4981 /* Free up all remote VTEPs, if any. */
4982 zvni_vtep_del_all(zvni
, 0);
4984 /* Delete the hash entry. */
4985 if (zvni_del(zvni
)) {
4986 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
4987 "Failed to del VNI hash %p, VNI %u", zvni
,
4992 /* TODO_MITESH: This needs to be thought through. We don't have
4993 * enough information at this point to reprogram the vni as
4994 * l2-vni. One way is to store the required info in l3-vni and
4995 * used it solely for this purpose
5002 /* delete and uninstall rmac hash entry */
5003 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5005 zebra_mac_t
*zrmac
= NULL
;
5006 zebra_l3vni_t
*zl3vni
= NULL
;
5008 zrmac
= (zebra_mac_t
*)bucket
->data
;
5009 zl3vni
= (zebra_l3vni_t
*)ctx
;
5010 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5011 zl3vni_rmac_del(zl3vni
, zrmac
);
5014 /* delete and uninstall nh hash entry */
5015 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5017 zebra_neigh_t
*n
= NULL
;
5018 zebra_l3vni_t
*zl3vni
= NULL
;
5020 n
= (zebra_neigh_t
*)bucket
->data
;
5021 zl3vni
= (zebra_l3vni_t
*)ctx
;
5022 zl3vni_nh_uninstall(zl3vni
, n
);
5023 zl3vni_nh_del(zl3vni
, n
);
5026 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5029 struct zserv
*client
= NULL
;
5030 struct stream
*s
= NULL
;
5031 char buf
[PREFIX_STRLEN
];
5033 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5034 /* BGP may not be running. */
5038 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5040 zclient_create_header(s
, cmd
, vrf_id
);
5041 stream_put(s
, p
, sizeof(struct prefix
));
5043 /* Write packet size. */
5044 stream_putw_at(s
, 0, stream_get_endp(s
));
5046 if (IS_ZEBRA_DEBUG_VXLAN
)
5047 zlog_debug("Send ip prefix %s %s on vrf %s",
5048 prefix2str(p
, buf
, sizeof(buf
)),
5049 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5050 vrf_id_to_name(vrf_id
));
5052 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5053 client
->prefixadd_cnt
++;
5055 client
->prefixdel_cnt
++;
5057 return zserv_send_message(client
, s
);
5060 /* re-add remote rmac if needed */
5061 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5062 struct ethaddr
*rmac
)
5064 char buf
[ETHER_ADDR_STRLEN
];
5065 zebra_mac_t
*zrmac
= NULL
;
5067 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5071 if (IS_ZEBRA_DEBUG_VXLAN
)
5072 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5073 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5075 zl3vni_rmac_install(zl3vni
, zrmac
);
5079 /* Process a remote MACIP add from BGP. */
5080 static void process_remote_macip_add(vni_t vni
,
5081 struct ethaddr
*macaddr
,
5083 struct ipaddr
*ipaddr
,
5086 struct in_addr vtep_ip
)
5089 zebra_vtep_t
*zvtep
;
5090 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5091 zebra_neigh_t
*n
= NULL
;
5092 int update_mac
= 0, update_neigh
= 0;
5093 char buf
[ETHER_ADDR_STRLEN
];
5094 char buf1
[INET6_ADDRSTRLEN
];
5095 struct interface
*ifp
= NULL
;
5096 struct zebra_if
*zif
= NULL
;
5097 struct zebra_vrf
*zvrf
;
5102 bool do_dad
= false;
5103 bool is_dup_detect
= false;
5105 /* Locate VNI hash entry - expected to exist. */
5106 zvni
= zvni_lookup(vni
);
5108 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5112 ifp
= zvni
->vxlan_if
;
5116 !if_is_operative(ifp
) ||
5118 !zif
->brslave_info
.br_if
) {
5119 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5124 /* The remote VTEP specified should normally exist, but it is
5125 * possible that when peering comes up, peer may advertise MACIP
5126 * routes before advertising type-3 routes.
5128 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5130 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5132 EC_ZEBRA_VTEP_ADD_FAILED
,
5133 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5138 zvni_vtep_install(zvni
, &vtep_ip
);
5141 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5142 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5143 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5145 mac
= zvni_mac_lookup(zvni
, macaddr
);
5147 /* Ignore if the mac is already present as a gateway mac */
5149 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5150 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5151 if (IS_ZEBRA_DEBUG_VXLAN
)
5152 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5154 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5155 ipa_len
? " IP " : "",
5157 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5161 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5165 /* check if the remote MAC is unknown or has a change.
5166 * If so, that needs to be updated first. Note that client could
5167 * install MAC and MACIP separately or just install the latter.
5170 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5171 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5172 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5173 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5174 || seq
!= mac
->rem_seq
)
5179 mac
= zvni_mac_add(zvni
, macaddr
);
5182 "Failed to add MAC %s VNI %u Remote VTEP %s",
5183 prefix_mac2str(macaddr
, buf
,
5185 vni
, inet_ntoa(vtep_ip
));
5189 /* Is this MAC created for a MACIP? */
5191 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5193 const char *mac_type
;
5195 /* When host moves but changes its (MAC,IP)
5196 * binding, BGP may install a MACIP entry that
5197 * corresponds to "older" location of the host
5198 * in transient situations (because {IP1,M1}
5199 * is a different route from {IP1,M2}). Check
5200 * the sequence number and ignore this update
5203 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5204 tmp_seq
= mac
->loc_seq
;
5207 tmp_seq
= mac
->rem_seq
;
5208 mac_type
= "remote";
5210 if (seq
< tmp_seq
) {
5211 if (IS_ZEBRA_DEBUG_VXLAN
)
5212 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5214 prefix_mac2str(macaddr
,
5216 ipa_len
? " IP " : "",
5219 buf1
, sizeof(buf1
)) : "",
5226 /* Check MAC's curent state is local (this is the case
5227 * where MAC has moved from L->R) and check previous
5228 * detection started via local learning.
5229 * RFC-7432: A PE/VTEP that detects a MAC mobility
5230 * event via local learning starts an M-second timer.
5232 * VTEP-IP or seq. change alone is not considered
5233 * for dup. detection.
5235 * MAC is already marked duplicate set dad, then
5236 * is_dup_detect will be set to not install the entry.
5238 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5240 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5243 /* Remove local MAC from BGP. */
5244 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5245 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5247 /* Set "auto" and "remote" forwarding info. */
5248 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5249 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5250 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5251 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5254 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5256 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5259 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5261 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5263 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5264 mac
->fwd_info
.r_vtep_ip
,
5265 do_dad
, &is_dup_detect
,
5268 if (!is_dup_detect
) {
5269 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5270 /* Install the entry. */
5271 zvni_mac_install(zvni
, mac
);
5275 /* Update seq number. */
5278 /* If there is no IP, return after clearing AUTO flag of MAC. */
5280 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5287 /* Check if the remote neighbor itself is unknown or has a
5288 * change. If so, create or update and then install the entry.
5290 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5292 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5293 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5294 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5295 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5296 || seq
!= n
->rem_seq
)
5301 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5304 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5305 ipaddr2str(ipaddr
, buf1
,
5307 prefix_mac2str(macaddr
, buf
,
5309 vni
, inet_ntoa(vtep_ip
));
5316 /* When host moves but changes its (MAC,IP)
5317 * binding, BGP may install a MACIP entry that
5318 * corresponds to "older" location of the host
5319 * in transient situations (because {IP1,M1}
5320 * is a different route from {IP1,M2}). Check
5321 * the sequence number and ignore this update
5324 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5325 tmp_seq
= n
->loc_seq
;
5328 tmp_seq
= n
->rem_seq
;
5331 if (seq
< tmp_seq
) {
5332 if (IS_ZEBRA_DEBUG_VXLAN
)
5333 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5335 prefix_mac2str(macaddr
,
5338 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5343 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5344 /* MAC change, send a delete for old
5345 * neigh if learnt locally.
5347 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5348 IS_ZEBRA_NEIGH_ACTIVE(n
))
5349 zvni_neigh_send_del_to_client(
5351 &n
->emac
, 0, n
->state
);
5353 /* update neigh list for macs */
5354 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5356 listnode_delete(old_mac
->neigh_list
, n
);
5357 zvni_deref_ip2mac(zvni
, old_mac
);
5359 listnode_add_sort(mac
->neigh_list
, n
);
5360 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5362 /* Check Neigh's curent state is local
5363 * (this is the case where neigh/host has moved
5364 * from L->R) and check previous detction
5365 * started via local learning.
5367 * RFC-7432: A PE/VTEP that detects a MAC
5368 * mobilit event via local learning starts
5369 * an M-second timer.
5370 * VTEP-IP or seq. change along is not
5371 * considered for dup. detection.
5373 * Mobilty event scenario-B IP-MAC binding
5376 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5383 /* Set "remote" forwarding info. */
5384 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5385 n
->r_vtep_ip
= vtep_ip
;
5386 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5388 /* Set router flag (R-bit) to this Neighbor entry */
5389 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5390 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5392 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5394 /* Check old or new MAC detected as duplicate,
5395 * inherit duplicate flag to this neigh.
5397 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5399 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5400 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5402 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5403 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5406 /* Check duplicate address detection for IP */
5407 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5412 /* Install the entry. */
5414 zvni_neigh_install(zvni
, n
);
5417 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5419 /* Update seq number. */
5423 /* Process a remote MACIP delete from BGP. */
5424 static void process_remote_macip_del(vni_t vni
,
5425 struct ethaddr
*macaddr
,
5427 struct ipaddr
*ipaddr
,
5428 struct in_addr vtep_ip
)
5431 zebra_mac_t
*mac
= NULL
;
5432 zebra_neigh_t
*n
= NULL
;
5433 struct interface
*ifp
= NULL
;
5434 struct zebra_if
*zif
= NULL
;
5435 struct zebra_ns
*zns
;
5436 struct zebra_l2info_vxlan
*vxl
;
5437 struct zebra_vrf
*zvrf
;
5438 char buf
[ETHER_ADDR_STRLEN
];
5439 char buf1
[INET6_ADDRSTRLEN
];
5441 /* Locate VNI hash entry - expected to exist. */
5442 zvni
= zvni_lookup(vni
);
5444 if (IS_ZEBRA_DEBUG_VXLAN
)
5445 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5449 ifp
= zvni
->vxlan_if
;
5453 !if_is_operative(ifp
) ||
5455 !zif
->brslave_info
.br_if
) {
5456 if (IS_ZEBRA_DEBUG_VXLAN
)
5457 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5461 zns
= zebra_ns_lookup(NS_DEFAULT
);
5462 vxl
= &zif
->l2info
.vxl
;
5464 /* The remote VTEP specified is normally expected to exist, but
5465 * it is possible that the peer may delete the VTEP before deleting
5466 * any MACs referring to the VTEP, in which case the handler (see
5467 * remote_vtep_del) would have already deleted the MACs.
5469 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5472 mac
= zvni_mac_lookup(zvni
, macaddr
);
5474 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5477 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5478 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5479 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5483 /* If the remote mac or neighbor doesn't exist there is nothing
5484 * more to do. Otherwise, uninstall the entry and then remove it.
5489 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5491 /* Ignore the delete if this mac is a gateway mac-ip */
5492 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5493 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5495 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5497 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5498 ipa_len
? " IP " : "",
5500 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5504 /* Uninstall remote neighbor or MAC. */
5506 if (zvrf
->dad_freeze
&&
5507 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5508 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5509 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5510 struct interface
*vlan_if
;
5512 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5513 zif
->brslave_info
.br_if
);
5514 if (IS_ZEBRA_DEBUG_VXLAN
)
5515 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5516 __PRETTY_FUNCTION__
,
5517 ipaddr2str(ipaddr
, buf1
,
5518 sizeof(buf1
)), n
->flags
,
5520 neigh_read_specific_ip(ipaddr
, vlan_if
);
5523 /* When the MAC changes for an IP, it is possible the
5524 * client may update the new MAC before trying to delete the
5525 * "old" neighbor (as these are two different MACIP routes).
5526 * Do the delete only if the MAC matches.
5528 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5529 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5530 zvni_neigh_uninstall(zvni
, n
);
5531 zvni_neigh_del(zvni
, n
);
5532 zvni_deref_ip2mac(zvni
, mac
);
5535 /* DAD: when MAC is freeze state as remote learn event,
5536 * remote mac-ip delete event is received will result in freeze
5537 * entry removal, first fetch kernel for the same entry present
5538 * as LOCAL and reachable, avoid deleting this entry instead
5539 * use kerenel local entry to update during unfreeze time.
5541 if (zvrf
->dad_freeze
&&
5542 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5543 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5544 if (IS_ZEBRA_DEBUG_VXLAN
)
5545 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5546 __PRETTY_FUNCTION__
,
5547 prefix_mac2str(macaddr
, buf
,
5550 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5551 macaddr
, vxl
->access_vlan
);
5554 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5555 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5557 * the remote sequence number in the auto mac entry
5558 * needs to be reset to 0 as the mac entry may have
5559 * been removed on all VTEPs (including
5560 * the originating one)
5564 /* If all remote neighbors referencing a remote MAC
5565 * go away, we need to uninstall the MAC.
5567 if (remote_neigh_count(mac
) == 0) {
5568 zvni_mac_uninstall(zvni
, mac
);
5569 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5571 if (list_isempty(mac
->neigh_list
))
5572 zvni_mac_del(zvni
, mac
);
5574 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5580 /* Public functions */
5582 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5584 zebra_l3vni_t
*zl3vni
= NULL
;
5586 zl3vni
= zl3vni_lookup(vni
);
5590 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5593 /* handle evpn route in vrf table */
5594 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5595 struct ipaddr
*vtep_ip
,
5596 struct prefix
*host_prefix
)
5598 zebra_l3vni_t
*zl3vni
= NULL
;
5599 struct ipaddr ipv4_vtep
;
5601 zl3vni
= zl3vni_from_vrf(vrf_id
);
5602 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5606 * add the next hop neighbor -
5607 * neigh to be installed is the ipv6 nexthop neigh
5609 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5612 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5613 * address. Rmac is programmed against the ipv4 vtep because we only
5614 * support ipv4 tunnels in the h/w right now
5616 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5617 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5618 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5619 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5620 &(ipv4_vtep
.ipaddr_v4
));
5622 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5623 sizeof(struct in_addr
));
5626 * add the rmac - remote rmac to be installed is against the ipv4
5629 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5632 /* handle evpn vrf route delete */
5633 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5634 struct ipaddr
*vtep_ip
,
5635 struct prefix
*host_prefix
)
5637 zebra_l3vni_t
*zl3vni
= NULL
;
5638 zebra_neigh_t
*nh
= NULL
;
5639 zebra_mac_t
*zrmac
= NULL
;
5641 zl3vni
= zl3vni_from_vrf(vrf_id
);
5645 /* find the next hop entry and rmac entry */
5646 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5649 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5651 /* delete the next hop entry */
5652 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5654 /* delete the rmac entry */
5656 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5660 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5661 struct ethaddr
*rmac
, bool use_json
)
5663 zebra_l3vni_t
*zl3vni
= NULL
;
5664 zebra_mac_t
*zrmac
= NULL
;
5665 json_object
*json
= NULL
;
5667 if (!is_evpn_enabled()) {
5669 vty_out(vty
, "{}\n");
5674 json
= json_object_new_object();
5676 zl3vni
= zl3vni_lookup(l3vni
);
5679 vty_out(vty
, "{}\n");
5681 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5685 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5688 vty_out(vty
, "{}\n");
5691 "%% Requested RMAC doesn't exist in L3-VNI %u",
5696 zl3vni_print_rmac(zrmac
, vty
, json
);
5699 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5700 json
, JSON_C_TO_STRING_PRETTY
));
5701 json_object_free(json
);
5705 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5707 zebra_l3vni_t
*zl3vni
;
5709 struct rmac_walk_ctx wctx
;
5710 json_object
*json
= NULL
;
5712 if (!is_evpn_enabled())
5715 zl3vni
= zl3vni_lookup(l3vni
);
5718 vty_out(vty
, "{}\n");
5720 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5723 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5728 json
= json_object_new_object();
5730 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5734 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5736 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5738 json_object_int_add(json
, "numRmacs", num_rmacs
);
5740 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5743 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5744 json
, JSON_C_TO_STRING_PRETTY
));
5745 json_object_free(json
);
5749 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5751 json_object
*json
= NULL
;
5754 if (!is_evpn_enabled()) {
5756 vty_out(vty
, "{}\n");
5761 json
= json_object_new_object();
5765 hash_iterate(zrouter
.l3vni_table
,
5766 (void (*)(struct hash_bucket
*,
5767 void *))zl3vni_print_rmac_hash_all_vni
,
5771 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5772 json
, JSON_C_TO_STRING_PRETTY
));
5773 json_object_free(json
);
5777 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5778 struct ipaddr
*ip
, bool use_json
)
5780 zebra_l3vni_t
*zl3vni
= NULL
;
5781 zebra_neigh_t
*n
= NULL
;
5782 json_object
*json
= NULL
;
5784 if (!is_evpn_enabled()) {
5786 vty_out(vty
, "{}\n");
5791 json
= json_object_new_object();
5793 zl3vni
= zl3vni_lookup(l3vni
);
5796 vty_out(vty
, "{}\n");
5798 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5802 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5805 vty_out(vty
, "{}\n");
5808 "%% Requested next-hop not present for L3-VNI %u",
5813 zl3vni_print_nh(n
, vty
, json
);
5816 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5817 json
, JSON_C_TO_STRING_PRETTY
));
5818 json_object_free(json
);
5822 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5825 struct nh_walk_ctx wctx
;
5826 json_object
*json
= NULL
;
5827 zebra_l3vni_t
*zl3vni
= NULL
;
5829 if (!is_evpn_enabled())
5832 zl3vni
= zl3vni_lookup(l3vni
);
5835 vty_out(vty
, "{}\n");
5837 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5841 num_nh
= hashcount(zl3vni
->nh_table
);
5846 json
= json_object_new_object();
5851 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5853 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5855 json_object_int_add(json
, "numNextHops", num_nh
);
5857 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5860 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5861 json
, JSON_C_TO_STRING_PRETTY
));
5862 json_object_free(json
);
5866 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5868 json_object
*json
= NULL
;
5871 if (!is_evpn_enabled()) {
5873 vty_out(vty
, "{}\n");
5878 json
= json_object_new_object();
5882 hash_iterate(zrouter
.l3vni_table
,
5883 (void (*)(struct hash_bucket
*,
5884 void *))zl3vni_print_nh_hash_all_vni
,
5888 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5889 json
, JSON_C_TO_STRING_PRETTY
));
5890 json_object_free(json
);
5895 * Display L3 VNI information (VTY command handler).
5897 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5900 json_object
*json
= NULL
;
5901 zebra_l3vni_t
*zl3vni
= NULL
;
5903 if (!is_evpn_enabled()) {
5905 vty_out(vty
, "{}\n");
5909 zl3vni
= zl3vni_lookup(vni
);
5912 vty_out(vty
, "{}\n");
5914 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5919 json
= json_object_new_object();
5923 zl3vni_print(zl3vni
, (void *)args
);
5926 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5927 json
, JSON_C_TO_STRING_PRETTY
));
5928 json_object_free(json
);
5932 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5933 json_object
*json_vrfs
)
5935 char buf
[ETHER_ADDR_STRLEN
];
5936 zebra_l3vni_t
*zl3vni
= NULL
;
5938 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5943 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5944 zvrf_name(zvrf
), zl3vni
->vni
,
5945 zl3vni_vxlan_if_name(zl3vni
),
5946 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5947 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5949 json_object
*json_vrf
= NULL
;
5951 json_vrf
= json_object_new_object();
5952 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5953 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5954 json_object_string_add(json_vrf
, "vxlanIntf",
5955 zl3vni_vxlan_if_name(zl3vni
));
5956 json_object_string_add(json_vrf
, "sviIntf",
5957 zl3vni_svi_if_name(zl3vni
));
5958 json_object_string_add(json_vrf
, "state",
5959 zl3vni_state2str(zl3vni
));
5960 json_object_string_add(
5961 json_vrf
, "routerMac",
5962 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5963 json_object_array_add(json_vrfs
, json_vrf
);
5968 * Display Neighbors for a VNI (VTY command handler).
5970 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5971 vni_t vni
, bool use_json
)
5975 struct neigh_walk_ctx wctx
;
5976 json_object
*json
= NULL
;
5978 if (!is_evpn_enabled())
5980 zvni
= zvni_lookup(vni
);
5983 vty_out(vty
, "{}\n");
5985 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5988 num_neigh
= hashcount(zvni
->neigh_table
);
5993 json
= json_object_new_object();
5995 /* Since we have IPv6 addresses to deal with which can vary widely in
5996 * size, we try to be a bit more elegant in display by first computing
5997 * the maximum width.
5999 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6002 wctx
.addr_width
= 15;
6004 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6008 "Number of ARPs (local and remote) known for this VNI: %u\n",
6010 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6011 -wctx
.addr_width
, "IP", "Type",
6012 "State", "MAC", "Remote VTEP");
6014 json_object_int_add(json
, "numArpNd", num_neigh
);
6016 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6018 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6019 json
, JSON_C_TO_STRING_PRETTY
));
6020 json_object_free(json
);
6025 * Display neighbors across all VNIs (VTY command handler).
6027 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6028 bool print_dup
, bool use_json
)
6030 json_object
*json
= NULL
;
6033 if (!is_evpn_enabled())
6037 json
= json_object_new_object();
6041 args
[2] = (void *)(ptrdiff_t)print_dup
;
6043 hash_iterate(zvrf
->vni_table
,
6044 (void (*)(struct hash_bucket
*,
6045 void *))zvni_print_neigh_hash_all_vni
,
6048 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6049 json
, JSON_C_TO_STRING_PRETTY
));
6050 json_object_free(json
);
6055 * Display neighbors across all VNIs in detail(VTY command handler).
6057 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6058 struct zebra_vrf
*zvrf
,
6059 bool print_dup
, bool use_json
)
6061 json_object
*json
= NULL
;
6064 if (!is_evpn_enabled())
6068 json
= json_object_new_object();
6072 args
[2] = (void *)(ptrdiff_t)print_dup
;
6074 hash_iterate(zvrf
->vni_table
,
6075 (void (*)(struct hash_bucket
*,
6076 void *))zvni_print_neigh_hash_all_vni_detail
,
6079 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6080 json
, JSON_C_TO_STRING_PRETTY
));
6081 json_object_free(json
);
6086 * Display specific neighbor for a VNI, if present (VTY command handler).
6088 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6089 struct zebra_vrf
*zvrf
, vni_t vni
,
6090 struct ipaddr
*ip
, bool use_json
)
6094 json_object
*json
= NULL
;
6096 if (!is_evpn_enabled())
6098 zvni
= zvni_lookup(vni
);
6101 vty_out(vty
, "{}\n");
6103 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6106 n
= zvni_neigh_lookup(zvni
, ip
);
6110 "%% Requested neighbor does not exist in VNI %u\n",
6115 json
= json_object_new_object();
6117 zvni_print_neigh(n
, vty
, json
);
6120 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6121 json
, JSON_C_TO_STRING_PRETTY
));
6122 json_object_free(json
);
6127 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6128 * By definition, these are remote neighbors.
6130 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6131 vni_t vni
, struct in_addr vtep_ip
,
6136 struct neigh_walk_ctx wctx
;
6137 json_object
*json
= NULL
;
6139 if (!is_evpn_enabled())
6141 zvni
= zvni_lookup(vni
);
6144 vty_out(vty
, "{}\n");
6146 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6149 num_neigh
= hashcount(zvni
->neigh_table
);
6153 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6156 wctx
.addr_width
= 15;
6157 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6158 wctx
.r_vtep_ip
= vtep_ip
;
6160 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6161 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6164 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6165 json
, JSON_C_TO_STRING_PRETTY
));
6166 json_object_free(json
);
6171 * Display Duplicate detected Neighbors for a VNI
6172 * (VTY command handler).
6174 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6175 struct zebra_vrf
*zvrf
,
6181 struct neigh_walk_ctx wctx
;
6182 json_object
*json
= NULL
;
6184 if (!is_evpn_enabled())
6187 zvni
= zvni_lookup(vni
);
6189 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6193 num_neigh
= hashcount(zvni
->neigh_table
);
6197 num_neigh
= num_dup_detected_neighs(zvni
);
6202 json
= json_object_new_object();
6204 /* Since we have IPv6 addresses to deal with which can vary widely in
6205 * size, we try to be a bit more elegant in display by first computing
6206 * the maximum width.
6208 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6211 wctx
.addr_width
= 15;
6213 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6217 "Number of ARPs (local and remote) known for this VNI: %u\n",
6219 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6220 -wctx
.addr_width
, "IP", "Type",
6221 "State", "MAC", "Remote VTEP");
6223 json_object_int_add(json
, "numArpNd", num_neigh
);
6225 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6228 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6229 json
, JSON_C_TO_STRING_PRETTY
));
6230 json_object_free(json
);
6235 * Display MACs for a VNI (VTY command handler).
6237 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6238 vni_t vni
, bool use_json
)
6242 struct mac_walk_ctx wctx
;
6243 json_object
*json
= NULL
;
6244 json_object
*json_mac
= NULL
;
6246 if (!is_evpn_enabled())
6248 zvni
= zvni_lookup(vni
);
6251 vty_out(vty
, "{}\n");
6253 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6256 num_macs
= num_valid_macs(zvni
);
6261 json
= json_object_new_object();
6262 json_mac
= json_object_new_object();
6265 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6268 wctx
.json
= json_mac
;
6272 "Number of MACs (local and remote) known for this VNI: %u\n",
6274 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6275 "Intf/Remote VTEP", "VLAN");
6277 json_object_int_add(json
, "numMacs", num_macs
);
6279 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6282 json_object_object_add(json
, "macs", json_mac
);
6283 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6284 json
, JSON_C_TO_STRING_PRETTY
));
6285 json_object_free(json
);
6290 * Display MACs for all VNIs (VTY command handler).
6292 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6293 bool print_dup
, bool use_json
)
6295 struct mac_walk_ctx wctx
;
6296 json_object
*json
= NULL
;
6298 if (!is_evpn_enabled()) {
6300 vty_out(vty
, "{}\n");
6304 json
= json_object_new_object();
6306 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6309 wctx
.print_dup
= print_dup
;
6310 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6313 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6314 json
, JSON_C_TO_STRING_PRETTY
));
6315 json_object_free(json
);
6320 * Display MACs in detail for all VNIs (VTY command handler).
6322 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6323 struct zebra_vrf
*zvrf
,
6324 bool print_dup
, bool use_json
)
6326 struct mac_walk_ctx wctx
;
6327 json_object
*json
= NULL
;
6329 if (!is_evpn_enabled()) {
6331 vty_out(vty
, "{}\n");
6335 json
= json_object_new_object();
6337 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6340 wctx
.print_dup
= print_dup
;
6341 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6345 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6346 json
, JSON_C_TO_STRING_PRETTY
));
6347 json_object_free(json
);
6352 * Display MACs for all VNIs (VTY command handler).
6354 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6355 struct zebra_vrf
*zvrf
,
6356 struct in_addr vtep_ip
, bool use_json
)
6358 struct mac_walk_ctx wctx
;
6359 json_object
*json
= NULL
;
6361 if (!is_evpn_enabled())
6365 json
= json_object_new_object();
6367 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6369 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6370 wctx
.r_vtep_ip
= vtep_ip
;
6372 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6375 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6376 json
, JSON_C_TO_STRING_PRETTY
));
6377 json_object_free(json
);
6382 * Display specific MAC for a VNI, if present (VTY command handler).
6384 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6385 vni_t vni
, struct ethaddr
*macaddr
,
6390 json_object
*json
= NULL
;
6392 if (!is_evpn_enabled())
6395 zvni
= zvni_lookup(vni
);
6398 vty_out(vty
, "{}\n");
6400 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6403 mac
= zvni_mac_lookup(zvni
, macaddr
);
6406 vty_out(vty
, "{}\n");
6409 "%% Requested MAC does not exist in VNI %u\n",
6415 json
= json_object_new_object();
6417 zvni_print_mac(mac
, vty
, json
);
6419 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6420 json
, JSON_C_TO_STRING_PRETTY
));
6421 json_object_free(json
);
6425 /* Print Duplicate MACs per VNI */
6426 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6427 struct zebra_vrf
*zvrf
,
6428 vni_t vni
, bool use_json
)
6431 struct mac_walk_ctx wctx
;
6433 json_object
*json
= NULL
;
6434 json_object
*json_mac
= NULL
;
6436 if (!is_evpn_enabled())
6439 zvni
= zvni_lookup(vni
);
6441 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6445 num_macs
= num_valid_macs(zvni
);
6449 num_macs
= num_dup_detected_macs(zvni
);
6454 json
= json_object_new_object();
6455 json_mac
= json_object_new_object();
6458 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6461 wctx
.json
= json_mac
;
6465 "Number of MACs (local and remote) known for this VNI: %u\n",
6467 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6468 "Intf/Remote VTEP", "VLAN");
6470 json_object_int_add(json
, "numMacs", num_macs
);
6472 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6475 json_object_object_add(json
, "macs", json_mac
);
6476 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6477 json
, JSON_C_TO_STRING_PRETTY
));
6478 json_object_free(json
);
6483 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6484 struct zebra_vrf
*zvrf
,
6485 vni_t vni
, struct ethaddr
*macaddr
)
6489 struct listnode
*node
= NULL
;
6490 zebra_neigh_t
*nbr
= NULL
;
6492 if (!is_evpn_enabled())
6495 zvni
= zvni_lookup(vni
);
6497 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6501 mac
= zvni_mac_lookup(zvni
, macaddr
);
6503 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6508 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6509 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6513 /* Remove all IPs as duplicate associcated with this MAC */
6514 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6515 /* For local neigh mark inactive so MACIP update is generated
6516 * to BGP. This is a scenario where MAC update received
6517 * and detected as duplicate which marked neigh as duplicate.
6518 * Later local neigh update did not get a chance to relay
6519 * to BGP. Similarly remote macip update, neigh needs to be
6520 * installed locally.
6522 if (zvrf
->dad_freeze
&&
6523 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6524 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6525 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6526 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6527 zvni_neigh_install(zvni
, nbr
);
6530 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6532 nbr
->detect_start_time
.tv_sec
= 0;
6533 nbr
->dad_dup_detect_time
= 0;
6536 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6538 mac
->detect_start_time
.tv_sec
= 0;
6539 mac
->detect_start_time
.tv_usec
= 0;
6540 mac
->dad_dup_detect_time
= 0;
6541 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6543 /* warn-only action return */
6544 if (!zvrf
->dad_freeze
)
6547 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6548 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6550 if (zvni_mac_send_add_to_client(zvni
->vni
,
6556 /* Process all neighbors associated with this MAC. */
6557 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6559 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6560 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6562 /* Install the entry. */
6563 zvni_mac_install(zvni
, mac
);
6569 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6570 struct zebra_vrf
*zvrf
,
6571 vni_t vni
, struct ipaddr
*ip
)
6576 char buf
[INET6_ADDRSTRLEN
];
6577 char buf2
[ETHER_ADDR_STRLEN
];
6579 if (!is_evpn_enabled())
6582 zvni
= zvni_lookup(vni
);
6584 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6588 nbr
= zvni_neigh_lookup(zvni
, ip
);
6591 "%% Requested host IP does not exist in VNI %u\n",
6596 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6598 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6600 "%% Requsted host IP %s is not duplicate detected\n",
6605 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6607 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6609 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6610 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6611 return CMD_WARNING_CONFIG_FAILED
;
6614 if (IS_ZEBRA_DEBUG_VXLAN
)
6615 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6616 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6619 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6621 nbr
->detect_start_time
.tv_sec
= 0;
6622 nbr
->detect_start_time
.tv_usec
= 0;
6623 nbr
->dad_dup_detect_time
= 0;
6624 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6626 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6627 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6629 nbr
->flags
, nbr
->loc_seq
);
6630 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6631 zvni_neigh_install(zvni
, nbr
);
6637 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6639 struct mac_walk_ctx
*wctx
= ctxt
;
6642 struct listnode
*node
= NULL
;
6643 zebra_neigh_t
*nbr
= NULL
;
6645 mac
= (zebra_mac_t
*)bucket
->data
;
6651 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6654 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6656 mac
->detect_start_time
.tv_sec
= 0;
6657 mac
->detect_start_time
.tv_usec
= 0;
6658 mac
->dad_dup_detect_time
= 0;
6659 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6661 /* Remove all IPs as duplicate associcated with this MAC */
6662 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6663 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6665 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6667 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6669 nbr
->detect_start_time
.tv_sec
= 0;
6670 nbr
->dad_dup_detect_time
= 0;
6673 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6674 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6676 if (zvni_mac_send_add_to_client(zvni
->vni
,
6678 mac
->flags
, mac
->loc_seq
))
6681 /* Process all neighbors associated with this MAC. */
6682 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6684 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6685 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6687 /* Install the entry. */
6688 zvni_mac_install(zvni
, mac
);
6692 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6694 struct neigh_walk_ctx
*wctx
= ctxt
;
6697 char buf
[INET6_ADDRSTRLEN
];
6699 nbr
= (zebra_neigh_t
*)bucket
->data
;
6705 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6708 if (IS_ZEBRA_DEBUG_VXLAN
) {
6709 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6711 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6712 __PRETTY_FUNCTION__
, buf
,
6713 nbr
->flags
, nbr
->loc_seq
);
6716 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6718 nbr
->detect_start_time
.tv_sec
= 0;
6719 nbr
->detect_start_time
.tv_usec
= 0;
6720 nbr
->dad_dup_detect_time
= 0;
6721 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6723 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6724 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6726 nbr
->flags
, nbr
->loc_seq
);
6727 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6728 zvni_neigh_install(zvni
, nbr
);
6732 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6737 struct zebra_vrf
*zvrf
;
6738 struct mac_walk_ctx m_wctx
;
6739 struct neigh_walk_ctx n_wctx
;
6741 zvni
= (zebra_vni_t
*)bucket
->data
;
6745 vty
= (struct vty
*)args
[0];
6746 zvrf
= (struct zebra_vrf
*)args
[1];
6748 if (hashcount(zvni
->neigh_table
)) {
6749 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6753 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6757 if (num_valid_macs(zvni
)) {
6758 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6762 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6767 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6768 struct zebra_vrf
*zvrf
)
6772 if (!is_evpn_enabled())
6778 hash_iterate(zvrf
->vni_table
,
6779 (void (*)(struct hash_bucket
*, void *))
6780 zvni_clear_dup_detect_hash_vni_all
, args
);
6785 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6786 struct zebra_vrf
*zvrf
,
6790 struct mac_walk_ctx m_wctx
;
6791 struct neigh_walk_ctx n_wctx
;
6793 if (!is_evpn_enabled())
6796 zvni
= zvni_lookup(vni
);
6798 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6802 if (hashcount(zvni
->neigh_table
)) {
6803 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6807 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6811 if (num_valid_macs(zvni
)) {
6812 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6816 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6823 * Display MACs for a VNI from specific VTEP (VTY command handler).
6825 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6826 vni_t vni
, struct in_addr vtep_ip
,
6831 struct mac_walk_ctx wctx
;
6832 json_object
*json
= NULL
;
6833 json_object
*json_mac
= NULL
;
6835 if (!is_evpn_enabled())
6837 zvni
= zvni_lookup(vni
);
6840 vty_out(vty
, "{}\n");
6842 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6845 num_macs
= num_valid_macs(zvni
);
6850 json
= json_object_new_object();
6851 json_mac
= json_object_new_object();
6854 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6857 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6858 wctx
.r_vtep_ip
= vtep_ip
;
6859 wctx
.json
= json_mac
;
6860 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6863 json_object_int_add(json
, "numMacs", wctx
.count
);
6865 json_object_object_add(json
, "macs", json_mac
);
6866 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6867 json
, JSON_C_TO_STRING_PRETTY
));
6868 json_object_free(json
);
6874 * Display VNI information (VTY command handler).
6876 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6879 json_object
*json
= NULL
;
6881 zebra_l3vni_t
*zl3vni
= NULL
;
6882 zebra_vni_t
*zvni
= NULL
;
6884 if (!is_evpn_enabled())
6888 json
= json_object_new_object();
6892 zl3vni
= zl3vni_lookup(vni
);
6894 zl3vni_print(zl3vni
, (void *)args
);
6896 zvni
= zvni_lookup(vni
);
6899 vty_out(vty
, "{}\n");
6901 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6905 zvni_print(zvni
, (void *)args
);
6909 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6910 json
, JSON_C_TO_STRING_PRETTY
));
6911 json_object_free(json
);
6915 /* Display all global details for EVPN */
6916 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6921 json_object
*json
= NULL
;
6922 struct zebra_vrf
*zvrf
= NULL
;
6924 if (!is_evpn_enabled())
6927 zvrf
= zebra_vrf_get_evpn();
6931 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6932 num_l2vnis
= hashcount(zvrf
->vni_table
);
6933 num_vnis
= num_l2vnis
+ num_l3vnis
;
6936 json
= json_object_new_object();
6937 json_object_string_add(json
, "advertiseGatewayMacip",
6938 zvrf
->advertise_gw_macip
? "Yes" : "No");
6939 json_object_int_add(json
, "numVnis", num_vnis
);
6940 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6941 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6942 if (zvrf
->dup_addr_detect
)
6943 json_object_boolean_true_add(json
,
6944 "isDuplicateAddrDetection");
6946 json_object_boolean_false_add(json
,
6947 "isDuplicateAddrDetection");
6948 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6949 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6950 json_object_int_add(json
, "detectionFreezeTime",
6951 zvrf
->dad_freeze_time
);
6954 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6955 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6956 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6957 zvrf
->advertise_gw_macip
? "Yes" : "No");
6958 vty_out(vty
, "Advertise svi mac-ip: %s\n",
6959 zvrf
->advertise_svi_macip
? "Yes" : "No");
6960 vty_out(vty
, "Duplicate address detection: %s\n",
6961 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6962 vty_out(vty
, " Detection max-moves %u, time %d\n",
6963 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6964 if (zvrf
->dad_freeze
) {
6965 if (zvrf
->dad_freeze_time
)
6966 vty_out(vty
, " Detection freeze %u\n",
6967 zvrf
->dad_freeze_time
);
6969 vty_out(vty
, " Detection freeze %s\n",
6975 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6976 json
, JSON_C_TO_STRING_PRETTY
));
6977 json_object_free(json
);
6982 * Display VNI hash table (VTY command handler).
6984 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6987 json_object
*json
= NULL
;
6990 if (!is_evpn_enabled())
6994 json
= json_object_new_object();
6996 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
6997 "Type", "VxLAN IF", "# MACs", "# ARPs",
6998 "# Remote VTEPs", "Tenant VRF");
7003 /* Display all L2-VNIs */
7004 hash_iterate(zvrf
->vni_table
,
7005 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7008 /* Display all L3-VNIs */
7009 hash_iterate(zrouter
.l3vni_table
,
7010 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7014 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7015 json
, JSON_C_TO_STRING_PRETTY
));
7016 json_object_free(json
);
7020 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7024 uint32_t max_moves
= 0;
7025 uint32_t freeze_time
= 0;
7026 bool dup_addr_detect
= false;
7027 bool freeze
= false;
7030 STREAM_GETL(s
, dup_addr_detect
);
7031 STREAM_GETL(s
, time
);
7032 STREAM_GETL(s
, max_moves
);
7033 STREAM_GETL(s
, freeze
);
7034 STREAM_GETL(s
, freeze_time
);
7036 /* DAD previous state was enabled, and new state is disable,
7037 * clear all duplicate detected addresses.
7039 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7040 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7042 zvrf
->dup_addr_detect
= dup_addr_detect
;
7043 zvrf
->dad_time
= time
;
7044 zvrf
->dad_max_moves
= max_moves
;
7045 zvrf
->dad_freeze
= freeze
;
7046 zvrf
->dad_freeze_time
= freeze_time
;
7048 if (IS_ZEBRA_DEBUG_VXLAN
)
7050 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7051 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7052 zvrf
->dup_addr_detect
? "enable" : "disable",
7053 zvrf
->dad_max_moves
,
7055 zvrf
->dad_freeze
? "enable" : "disable",
7056 zvrf
->dad_freeze_time
);
7063 * Display VNI hash table in detail(VTY command handler).
7065 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7068 json_object
*json
= NULL
;
7069 struct zebra_ns
*zns
= NULL
;
7070 struct zvni_evpn_show zes
;
7072 if (!is_evpn_enabled())
7075 zns
= zebra_ns_lookup(NS_DEFAULT
);
7081 json
= json_object_new_object();
7087 /* Display all L2-VNIs */
7090 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7093 /* Display all L3-VNIs */
7094 hash_iterate(zrouter
.l3vni_table
,
7095 (void (*)(struct hash_bucket
*,
7096 void *))zl3vni_print_hash_detail
,
7100 vty_out(vty
, "%s\n",
7101 json_object_to_json_string_ext(
7102 json
, JSON_C_TO_STRING_PRETTY
));
7103 json_object_free(json
);
7108 * Handle neighbor delete notification from the kernel (on a VLAN device
7109 * / L3 interface). This may result in either the neighbor getting deleted
7110 * from our database or being re-added to the kernel (if it is a valid
7113 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7114 struct interface
*link_if
,
7117 char buf
[INET6_ADDRSTRLEN
];
7118 char buf2
[ETHER_ADDR_STRLEN
];
7119 zebra_neigh_t
*n
= NULL
;
7120 zebra_vni_t
*zvni
= NULL
;
7121 zebra_mac_t
*zmac
= NULL
;
7122 zebra_l3vni_t
*zl3vni
= NULL
;
7123 struct zebra_vrf
*zvrf
;
7125 /* check if this is a remote neigh entry corresponding to remote
7128 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7130 return zl3vni_local_nh_del(zl3vni
, ip
);
7132 /* We are only interested in neighbors on an SVI that resides on top
7133 * of a VxLAN bridge.
7135 zvni
= zvni_from_svi(ifp
, link_if
);
7139 if (!zvni
->vxlan_if
) {
7141 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7146 if (IS_ZEBRA_DEBUG_VXLAN
)
7147 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7148 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7149 ifp
->ifindex
, zvni
->vni
);
7151 /* If entry doesn't exist, nothing to do. */
7152 n
= zvni_neigh_lookup(zvni
, ip
);
7156 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7158 if (IS_ZEBRA_DEBUG_VXLAN
)
7160 "Trying to del a neigh %s without a mac %s on VNI %u",
7161 ipaddr2str(ip
, buf
, sizeof(buf
)),
7162 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7168 /* If it is a remote entry, the kernel has aged this out or someone has
7169 * deleted it, it needs to be re-installed as Quagga is the owner.
7171 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7172 zvni_neigh_install(zvni
, n
);
7176 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7178 zlog_debug("%s: VNI %u vrf lookup failed.",
7179 __PRETTY_FUNCTION__
, zvni
->vni
);
7183 /* In case of feeze action, if local neigh is in duplicate state,
7184 * Mark the Neigh as inactive before sending delete request to BGPd,
7185 * If BGPd has remote entry, it will re-install
7187 if (zvrf
->dad_freeze
&&
7188 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7189 ZEBRA_NEIGH_SET_INACTIVE(n
);
7191 /* Remove neighbor from BGP. */
7192 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7194 /* Delete this neighbor entry. */
7195 zvni_neigh_del(zvni
, n
);
7197 /* see if the AUTO mac needs to be deleted */
7198 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7199 && !listcount(zmac
->neigh_list
))
7200 zvni_mac_del(zvni
, zmac
);
7206 * Handle neighbor add or update notification from the kernel (on a VLAN
7207 * device / L3 interface). This is typically for a local neighbor but can
7208 * also be for a remote neighbor (e.g., ageout notification). It could
7209 * also be a "move" scenario.
7211 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7212 struct interface
*link_if
,
7214 struct ethaddr
*macaddr
,
7219 char buf
[ETHER_ADDR_STRLEN
];
7220 char buf2
[INET6_ADDRSTRLEN
];
7221 zebra_vni_t
*zvni
= NULL
;
7222 zebra_l3vni_t
*zl3vni
= NULL
;
7224 /* check if this is a remote neigh entry corresponding to remote
7227 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7229 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7231 /* We are only interested in neighbors on an SVI that resides on top
7232 * of a VxLAN bridge.
7234 zvni
= zvni_from_svi(ifp
, link_if
);
7238 if (IS_ZEBRA_DEBUG_VXLAN
)
7240 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7241 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7242 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7243 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7244 is_router
? "router " : "",
7247 /* Is this about a local neighbor or a remote one? */
7249 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7252 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7257 * Handle message from client to delete a remote MACIP for a VNI.
7259 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7263 struct ethaddr macaddr
;
7265 struct in_addr vtep_ip
;
7266 uint16_t l
= 0, ipa_len
;
7267 char buf
[ETHER_ADDR_STRLEN
];
7268 char buf1
[INET6_ADDRSTRLEN
];
7270 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7271 memset(&ip
, 0, sizeof(struct ipaddr
));
7272 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7276 while (l
< hdr
->length
) {
7277 /* Obtain each remote MACIP and process. */
7278 /* Message contains VNI, followed by MAC followed by IP (if any)
7279 * followed by remote VTEP IP.
7281 memset(&ip
, 0, sizeof(ip
));
7282 STREAM_GETL(s
, vni
);
7283 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7284 STREAM_GETL(s
, ipa_len
);
7286 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7288 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7290 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7291 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7292 l
+= IPV4_MAX_BYTELEN
;
7294 if (IS_ZEBRA_DEBUG_VXLAN
)
7296 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7298 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7299 ipa_len
? " IP " : "",
7301 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7303 zebra_route_string(client
->proto
));
7305 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7313 * Handle message from client to add a remote MACIP for a VNI. This
7314 * could be just the add of a MAC address or the add of a neighbor
7317 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7321 struct ethaddr macaddr
;
7323 struct in_addr vtep_ip
;
7324 uint16_t l
= 0, ipa_len
;
7327 char buf
[ETHER_ADDR_STRLEN
];
7328 char buf1
[INET6_ADDRSTRLEN
];
7330 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7331 memset(&ip
, 0, sizeof(struct ipaddr
));
7332 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7334 if (!EVPN_ENABLED(zvrf
)) {
7335 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7341 while (l
< hdr
->length
) {
7342 /* Obtain each remote MACIP and process. */
7343 /* Message contains VNI, followed by MAC followed by IP (if any)
7344 * followed by remote VTEP IP.
7346 memset(&ip
, 0, sizeof(ip
));
7347 STREAM_GETL(s
, vni
);
7348 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7349 STREAM_GETL(s
, ipa_len
);
7351 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7353 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7355 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7356 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7357 l
+= IPV4_MAX_BYTELEN
;
7359 /* Get flags - sticky mac and/or gateway mac */
7360 STREAM_GETC(s
, flags
);
7362 STREAM_GETL(s
, seq
);
7365 if (IS_ZEBRA_DEBUG_VXLAN
)
7367 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7369 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7370 ipa_len
? " IP " : "",
7372 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7373 flags
, seq
, inet_ntoa(vtep_ip
),
7374 zebra_route_string(client
->proto
));
7376 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7377 flags
, seq
, vtep_ip
);
7385 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7386 * us, this must involve a multihoming scenario. Treat this as implicit delete
7387 * of any prior local MAC.
7389 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7390 struct interface
*br_if
,
7391 struct ethaddr
*macaddr
, vlanid_t vid
)
7393 struct zebra_if
*zif
;
7394 struct zebra_l2info_vxlan
*vxl
;
7398 char buf
[ETHER_ADDR_STRLEN
];
7402 vxl
= &zif
->l2info
.vxl
;
7405 /* Check if EVPN is enabled. */
7406 if (!is_evpn_enabled())
7409 /* Locate hash entry; it is expected to exist. */
7410 zvni
= zvni_lookup(vni
);
7414 /* If entry doesn't exist, nothing to do. */
7415 mac
= zvni_mac_lookup(zvni
, macaddr
);
7419 /* Is it a local entry? */
7420 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7423 if (IS_ZEBRA_DEBUG_VXLAN
)
7425 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7426 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7429 /* Remove MAC from BGP. */
7430 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7433 * If there are no neigh associated with the mac delete the mac
7434 * else mark it as AUTO for forward reference
7436 if (!listcount(mac
->neigh_list
)) {
7437 zvni_mac_del(zvni
, mac
);
7439 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7440 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7447 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7448 * This can happen because the remote MAC entries are also added as "dynamic",
7449 * so the kernel can ageout the entry.
7451 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7452 struct interface
*br_if
,
7453 struct ethaddr
*macaddr
, vlanid_t vid
)
7455 struct zebra_if
*zif
= NULL
;
7456 struct zebra_l2info_vxlan
*vxl
= NULL
;
7458 zebra_vni_t
*zvni
= NULL
;
7459 zebra_l3vni_t
*zl3vni
= NULL
;
7460 zebra_mac_t
*mac
= NULL
;
7461 char buf
[ETHER_ADDR_STRLEN
];
7465 vxl
= &zif
->l2info
.vxl
;
7468 /* Check if EVPN is enabled. */
7469 if (!is_evpn_enabled())
7472 /* check if this is a remote RMAC and readd simillar to remote macs */
7473 zl3vni
= zl3vni_lookup(vni
);
7475 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7477 /* Locate hash entry; it is expected to exist. */
7478 zvni
= zvni_lookup(vni
);
7482 /* If entry doesn't exist, nothing to do. */
7483 mac
= zvni_mac_lookup(zvni
, macaddr
);
7487 /* Is it a remote entry? */
7488 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7491 if (IS_ZEBRA_DEBUG_VXLAN
)
7492 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7493 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7496 zvni_mac_install(zvni
, mac
);
7501 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7503 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7504 struct ethaddr
*macaddr
, vlanid_t vid
)
7508 char buf
[ETHER_ADDR_STRLEN
];
7510 /* We are interested in MACs only on ports or (port, VLAN) that
7513 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7516 if (!zvni
->vxlan_if
) {
7518 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7523 if (IS_ZEBRA_DEBUG_VXLAN
)
7524 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7525 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7526 ifp
->ifindex
, vid
, zvni
->vni
);
7528 /* If entry doesn't exist, nothing to do. */
7529 mac
= zvni_mac_lookup(zvni
, macaddr
);
7533 /* Is it a local entry? */
7534 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7537 /* Update all the neigh entries associated with this mac */
7538 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7540 /* Remove MAC from BGP. */
7541 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7544 * If there are no neigh associated with the mac delete the mac
7545 * else mark it as AUTO for forward reference
7547 if (!listcount(mac
->neigh_list
)) {
7548 zvni_mac_del(zvni
, mac
);
7550 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7551 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7558 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7560 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7561 struct interface
*br_if
,
7562 struct ethaddr
*macaddr
, vlanid_t vid
,
7567 struct zebra_vrf
*zvrf
;
7568 char buf
[ETHER_ADDR_STRLEN
];
7569 bool mac_sticky
= false;
7570 bool inform_client
= false;
7571 bool upd_neigh
= false;
7572 bool is_dup_detect
= false;
7573 struct in_addr vtep_ip
= {.s_addr
= 0};
7575 /* We are interested in MACs only on ports or (port, VLAN) that
7578 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7580 if (IS_ZEBRA_DEBUG_VXLAN
)
7582 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7583 sticky
? "sticky " : "",
7584 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7585 ifp
->name
, ifp
->ifindex
, vid
);
7589 if (!zvni
->vxlan_if
) {
7591 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7596 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7600 /* Check if we need to create or update or it is a NO-OP. */
7601 mac
= zvni_mac_lookup(zvni
, macaddr
);
7603 if (IS_ZEBRA_DEBUG_VXLAN
)
7605 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7606 sticky
? "sticky " : "",
7607 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7608 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7610 mac
= zvni_mac_add(zvni
, macaddr
);
7613 EC_ZEBRA_MAC_ADD_FAILED
,
7614 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7615 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7616 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7619 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7620 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7621 mac
->fwd_info
.local
.vid
= vid
;
7623 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7624 inform_client
= true;
7627 if (IS_ZEBRA_DEBUG_VXLAN
)
7629 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7630 sticky
? "sticky " : "",
7631 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7632 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7635 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7636 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7640 * Update any changes and if changes are relevant to
7643 if (mac_sticky
== sticky
7644 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7645 && mac
->fwd_info
.local
.vid
== vid
) {
7646 if (IS_ZEBRA_DEBUG_VXLAN
)
7648 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7649 "entry exists and has not changed ",
7650 sticky
? "sticky " : "",
7651 prefix_mac2str(macaddr
, buf
,
7653 ifp
->name
, ifp
->ifindex
, vid
,
7657 if (mac_sticky
!= sticky
) {
7659 SET_FLAG(mac
->flags
,
7662 UNSET_FLAG(mac
->flags
,
7664 inform_client
= true;
7667 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7668 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7669 mac
->fwd_info
.local
.vid
= vid
;
7671 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7672 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7673 bool do_dad
= false;
7676 * MAC has either moved or was "internally" created due
7677 * to a neighbor learn and is now actually learnt. If
7678 * it was learnt as a remote sticky MAC, this is an
7681 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7683 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7684 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7685 prefix_mac2str(macaddr
, buf
,
7687 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7692 /* If an actual move, compute MAC's seq number */
7693 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7694 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7696 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7697 /* Trigger DAD for remote MAC */
7701 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7702 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7703 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7704 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7705 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7706 mac
->fwd_info
.local
.vid
= vid
;
7708 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7710 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7712 * We have to inform BGP of this MAC as well as process
7715 inform_client
= true;
7718 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7722 if (is_dup_detect
) {
7723 inform_client
= false;
7729 /* Inform BGP if required. */
7730 if (inform_client
) {
7731 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7732 mac
->flags
, mac
->loc_seq
))
7736 /* Process all neighbors associated with this MAC, if required. */
7738 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7744 * Handle message from client to delete a remote VTEP for a VNI.
7746 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7749 unsigned short l
= 0;
7751 struct in_addr vtep_ip
;
7753 zebra_vtep_t
*zvtep
;
7754 struct interface
*ifp
;
7755 struct zebra_if
*zif
;
7757 if (!is_evpn_enabled()) {
7759 "%s: EVPN is not enabled yet we have received a vtep del command",
7760 __PRETTY_FUNCTION__
);
7764 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
7765 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7772 while (l
< hdr
->length
) {
7773 /* Obtain each remote VTEP and process. */
7774 STREAM_GETL(s
, vni
);
7776 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7777 l
+= IPV4_MAX_BYTELEN
;
7779 if (IS_ZEBRA_DEBUG_VXLAN
)
7780 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7781 inet_ntoa(vtep_ip
), vni
,
7782 zebra_route_string(client
->proto
));
7784 /* Locate VNI hash entry - expected to exist. */
7785 zvni
= zvni_lookup(vni
);
7787 if (IS_ZEBRA_DEBUG_VXLAN
)
7789 "Failed to locate VNI hash upon remote VTEP DEL, "
7795 ifp
= zvni
->vxlan_if
;
7798 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7804 /* If down or not mapped to a bridge, we're done. */
7805 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7808 /* If the remote VTEP does not exist, there's nothing more to
7810 * Otherwise, uninstall any remote MACs pointing to this VTEP
7812 * then, the VTEP entry itself and remove it.
7814 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7818 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7819 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7820 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7821 zvni_vtep_del(zvni
, zvtep
);
7829 * Handle message from client to add a remote VTEP for a VNI.
7831 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7834 unsigned short l
= 0;
7836 struct in_addr vtep_ip
;
7838 struct interface
*ifp
;
7839 struct zebra_if
*zif
;
7841 if (!is_evpn_enabled()) {
7843 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7844 __PRETTY_FUNCTION__
);
7848 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
7849 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7856 while (l
< hdr
->length
) {
7857 /* Obtain each remote VTEP and process. */
7858 STREAM_GETL(s
, vni
);
7860 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7861 l
+= IPV4_MAX_BYTELEN
;
7863 if (IS_ZEBRA_DEBUG_VXLAN
)
7864 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7865 inet_ntoa(vtep_ip
), vni
,
7866 zebra_route_string(client
->proto
));
7868 /* Locate VNI hash entry - expected to exist. */
7869 zvni
= zvni_lookup(vni
);
7872 EC_ZEBRA_VTEP_ADD_FAILED
,
7873 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7878 ifp
= zvni
->vxlan_if
;
7881 EC_ZEBRA_VTEP_ADD_FAILED
,
7882 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7889 /* If down or not mapped to a bridge, we're done. */
7890 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7893 /* If the remote VTEP already exists,
7894 there's nothing more to do. */
7895 if (zvni_vtep_find(zvni
, &vtep_ip
))
7898 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7899 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7900 "Failed to add remote VTEP, VNI %u zvni %p",
7905 zvni_vtep_install(zvni
, &vtep_ip
);
7913 * Add/Del gateway macip to evpn
7915 * 1. SVI interface on a vlan aware bridge
7916 * 2. SVI interface on a vlan unaware bridge
7917 * 3. vrr interface (MACVLAN) associated to a SVI
7918 * We advertise macip routes for an interface if it is associated to VxLan vlan
7920 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7924 struct ethaddr macaddr
;
7925 zebra_vni_t
*zvni
= NULL
;
7927 memset(&ip
, 0, sizeof(struct ipaddr
));
7928 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7930 /* Check if EVPN is enabled. */
7931 if (!is_evpn_enabled())
7934 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7935 struct interface
*svi_if
=
7936 NULL
; /* SVI corresponding to the MACVLAN */
7937 struct zebra_if
*ifp_zif
=
7938 NULL
; /* Zebra daemon specific info for MACVLAN */
7939 struct zebra_if
*svi_if_zif
=
7940 NULL
; /* Zebra daemon specific info for SVI*/
7942 ifp_zif
= ifp
->info
;
7947 * for a MACVLAN interface the link represents the svi_if
7949 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7950 ifp_zif
->link_ifindex
);
7952 zlog_debug("MACVLAN %s(%u) without link information",
7953 ifp
->name
, ifp
->ifindex
);
7957 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7959 * If it is a vlan aware bridge then the link gives the
7960 * bridge information
7962 struct interface
*svi_if_link
= NULL
;
7964 svi_if_zif
= svi_if
->info
;
7966 svi_if_link
= if_lookup_by_index_per_ns(
7967 zebra_ns_lookup(NS_DEFAULT
),
7968 svi_if_zif
->link_ifindex
);
7969 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
7971 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
7973 * If it is a vlan unaware bridge then svi is the bridge
7976 zvni
= zvni_from_svi(svi_if
, svi_if
);
7978 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
7979 struct zebra_if
*svi_if_zif
=
7980 NULL
; /* Zebra daemon specific info for SVI */
7981 struct interface
*svi_if_link
=
7982 NULL
; /* link info for the SVI = bridge info */
7984 svi_if_zif
= ifp
->info
;
7986 svi_if_link
= if_lookup_by_index_per_ns(
7987 zebra_ns_lookup(NS_DEFAULT
),
7988 svi_if_zif
->link_ifindex
);
7990 zvni
= zvni_from_svi(ifp
, svi_if_link
);
7992 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
7993 zvni
= zvni_from_svi(ifp
, ifp
);
7999 if (!zvni
->vxlan_if
) {
8000 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8006 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8008 if (p
->family
== AF_INET
) {
8009 ip
.ipa_type
= IPADDR_V4
;
8010 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8011 sizeof(struct in_addr
));
8012 } else if (p
->family
== AF_INET6
) {
8013 ip
.ipa_type
= IPADDR_V6
;
8014 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8015 sizeof(struct in6_addr
));
8020 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8022 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8028 * Handle SVI interface going down.
8029 * SVI can be associated to either L3-VNI or L2-VNI.
8030 * For L2-VNI: At this point, this is a NOP since
8031 * the kernel deletes the neighbor entries on this SVI (if any).
8032 * We only need to update the vrf corresponding to zvni.
8033 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8036 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8038 zebra_l3vni_t
*zl3vni
= NULL
;
8040 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8043 /* process l3-vni down */
8044 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8046 /* remove association with svi-if */
8047 zl3vni
->svi_if
= NULL
;
8049 zebra_vni_t
*zvni
= NULL
;
8051 /* since we dont have svi corresponding to zvni, we associate it
8052 * to default vrf. Note: the corresponding neigh entries on the
8053 * SVI would have already been deleted */
8054 zvni
= zvni_from_svi(ifp
, link_if
);
8056 zvni
->vrf_id
= VRF_DEFAULT
;
8058 /* update the tenant vrf in BGP */
8059 zvni_send_add_to_client(zvni
);
8066 * Handle SVI interface coming up.
8067 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8069 * For L2-VNI: we need to install any remote neighbors entried (used for
8071 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8073 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8075 zebra_vni_t
*zvni
= NULL
;
8076 zebra_l3vni_t
*zl3vni
= NULL
;
8078 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8081 /* associate with svi */
8082 zl3vni
->svi_if
= ifp
;
8084 /* process oper-up */
8085 if (is_l3vni_oper_up(zl3vni
))
8086 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8089 /* process SVI up for l2-vni */
8090 struct neigh_walk_ctx n_wctx
;
8092 zvni
= zvni_from_svi(ifp
, link_if
);
8096 if (!zvni
->vxlan_if
) {
8098 "VNI %u hash %p doesn't have intf upon SVI up",
8103 if (IS_ZEBRA_DEBUG_VXLAN
)
8105 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8106 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8107 vrf_id_to_name(ifp
->vrf_id
));
8109 /* update the vrf information for l2-vni and inform bgp */
8110 zvni
->vrf_id
= ifp
->vrf_id
;
8111 zvni_send_add_to_client(zvni
);
8113 /* Install any remote neighbors for this VNI. */
8114 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8116 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8124 * Handle VxLAN interface down
8126 int zebra_vxlan_if_down(struct interface
*ifp
)
8129 struct zebra_if
*zif
= NULL
;
8130 struct zebra_l2info_vxlan
*vxl
= NULL
;
8131 zebra_l3vni_t
*zl3vni
= NULL
;
8134 /* Check if EVPN is enabled. */
8135 if (!is_evpn_enabled())
8140 vxl
= &zif
->l2info
.vxl
;
8143 zl3vni
= zl3vni_lookup(vni
);
8145 /* process-if-down for l3-vni */
8146 if (IS_ZEBRA_DEBUG_VXLAN
)
8147 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8150 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8152 /* process if-down for l2-vni */
8153 if (IS_ZEBRA_DEBUG_VXLAN
)
8154 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8157 /* Locate hash entry; it is expected to exist. */
8158 zvni
= zvni_lookup(vni
);
8161 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8162 ifp
->name
, ifp
->ifindex
, vni
);
8166 assert(zvni
->vxlan_if
== ifp
);
8168 /* Delete this VNI from BGP. */
8169 zvni_send_del_to_client(zvni
->vni
);
8171 /* Free up all neighbors and MACs, if any. */
8172 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8173 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8175 /* Free up all remote VTEPs, if any. */
8176 zvni_vtep_del_all(zvni
, 1);
8182 * Handle VxLAN interface up - update BGP if required.
8184 int zebra_vxlan_if_up(struct interface
*ifp
)
8187 struct zebra_if
*zif
= NULL
;
8188 struct zebra_l2info_vxlan
*vxl
= NULL
;
8189 zebra_vni_t
*zvni
= NULL
;
8190 zebra_l3vni_t
*zl3vni
= NULL
;
8192 /* Check if EVPN is enabled. */
8193 if (!is_evpn_enabled())
8198 vxl
= &zif
->l2info
.vxl
;
8201 zl3vni
= zl3vni_lookup(vni
);
8204 if (IS_ZEBRA_DEBUG_VXLAN
)
8205 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8208 /* we need to associate with SVI, if any, we can associate with
8209 * svi-if only after association with vxlan-intf is complete
8211 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8213 if (is_l3vni_oper_up(zl3vni
))
8214 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8216 /* Handle L2-VNI add */
8217 struct interface
*vlan_if
= NULL
;
8219 if (IS_ZEBRA_DEBUG_VXLAN
)
8220 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8223 /* Locate hash entry; it is expected to exist. */
8224 zvni
= zvni_lookup(vni
);
8227 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8228 ifp
->name
, ifp
->ifindex
, vni
);
8232 assert(zvni
->vxlan_if
== ifp
);
8233 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8234 zif
->brslave_info
.br_if
);
8236 zvni
->vrf_id
= vlan_if
->vrf_id
;
8237 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8239 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8242 /* If part of a bridge, inform BGP about this VNI. */
8243 /* Also, read and populate local MACs and neighbors. */
8244 if (zif
->brslave_info
.br_if
) {
8245 zvni_send_add_to_client(zvni
);
8246 zvni_read_mac_neigh(zvni
, ifp
);
8254 * Handle VxLAN interface delete. Locate and remove entry in hash table
8255 * and update BGP, if required.
8257 int zebra_vxlan_if_del(struct interface
*ifp
)
8260 struct zebra_if
*zif
= NULL
;
8261 struct zebra_l2info_vxlan
*vxl
= NULL
;
8262 zebra_vni_t
*zvni
= NULL
;
8263 zebra_l3vni_t
*zl3vni
= NULL
;
8265 /* Check if EVPN is enabled. */
8266 if (!is_evpn_enabled())
8271 vxl
= &zif
->l2info
.vxl
;
8274 zl3vni
= zl3vni_lookup(vni
);
8277 if (IS_ZEBRA_DEBUG_VXLAN
)
8278 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8281 /* process oper-down for l3-vni */
8282 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8284 /* remove the association with vxlan_if */
8285 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8286 zl3vni
->vxlan_if
= NULL
;
8289 /* process if-del for l2-vni*/
8290 if (IS_ZEBRA_DEBUG_VXLAN
)
8291 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8294 /* Locate hash entry; it is expected to exist. */
8295 zvni
= zvni_lookup(vni
);
8298 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8299 ifp
->name
, ifp
->ifindex
, vni
);
8303 /* remove from l3-vni list */
8304 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8306 listnode_delete(zl3vni
->l2vnis
, zvni
);
8308 /* Delete VNI from BGP. */
8309 zvni_send_del_to_client(zvni
->vni
);
8311 /* Free up all neighbors and MAC, if any. */
8312 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8313 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8315 /* Free up all remote VTEPs, if any. */
8316 zvni_vtep_del_all(zvni
, 0);
8318 /* Delete the hash entry. */
8319 if (zvni_del(zvni
)) {
8320 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8321 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8322 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8330 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8332 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8335 struct zebra_if
*zif
= NULL
;
8336 struct zebra_l2info_vxlan
*vxl
= NULL
;
8337 zebra_vni_t
*zvni
= NULL
;
8338 zebra_l3vni_t
*zl3vni
= NULL
;
8340 /* Check if EVPN is enabled. */
8341 if (!is_evpn_enabled())
8346 vxl
= &zif
->l2info
.vxl
;
8349 zl3vni
= zl3vni_lookup(vni
);
8352 if (IS_ZEBRA_DEBUG_VXLAN
)
8354 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8355 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8356 inet_ntoa(vxl
->vtep_ip
),
8357 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8359 /* Removed from bridge? Cleanup and return */
8360 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8361 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8362 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8366 /* access-vlan change - process oper down, associate with new
8367 * svi_if and then process oper up again
8369 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8370 if (if_is_operative(ifp
)) {
8371 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8372 zl3vni
->svi_if
= NULL
;
8373 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8374 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8375 if (is_l3vni_oper_up(zl3vni
))
8376 zebra_vxlan_process_l3vni_oper_up(
8382 * local-ip change - process oper down, associate with new
8383 * local-ip and then process oper up again
8385 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8386 if (if_is_operative(ifp
)) {
8387 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8388 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8389 if (is_l3vni_oper_up(zl3vni
))
8390 zebra_vxlan_process_l3vni_oper_up(
8395 /* Update local tunnel IP. */
8396 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8398 /* if we have a valid new master, process l3-vni oper up */
8399 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8400 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8401 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8405 /* Update VNI hash. */
8406 zvni
= zvni_lookup(vni
);
8409 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8410 ifp
->name
, ifp
->ifindex
, vni
);
8414 if (IS_ZEBRA_DEBUG_VXLAN
)
8416 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8417 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8418 inet_ntoa(vxl
->vtep_ip
),
8419 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8421 /* Removed from bridge? Cleanup and return */
8422 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8423 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8424 /* Delete from client, remove all remote VTEPs */
8425 /* Also, free up all MACs and neighbors. */
8426 zvni_send_del_to_client(zvni
->vni
);
8427 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8428 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8429 zvni_vtep_del_all(zvni
, 1);
8433 /* Handle other changes. */
8434 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8435 /* Remove all existing local neigh and MACs for this VNI
8436 * (including from BGP)
8438 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8439 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8442 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8443 zvni
->vxlan_if
= ifp
;
8445 /* Take further actions needed.
8446 * Note that if we are here, there is a change of interest.
8448 /* If down or not mapped to a bridge, we're done. */
8449 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8452 /* Inform BGP, if there is a change of interest. */
8454 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8455 zvni_send_add_to_client(zvni
);
8457 /* If there is a valid new master or a VLAN mapping change,
8458 * read and populate local MACs and neighbors.
8459 * Also, reinstall any remote MACs and neighbors
8460 * for this VNI (based on new VLAN).
8462 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8463 zvni_read_mac_neigh(zvni
, ifp
);
8464 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8465 struct mac_walk_ctx m_wctx
;
8466 struct neigh_walk_ctx n_wctx
;
8468 zvni_read_mac_neigh(zvni
, ifp
);
8470 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8472 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8475 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8477 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8486 * Handle VxLAN interface add.
8488 int zebra_vxlan_if_add(struct interface
*ifp
)
8491 struct zebra_if
*zif
= NULL
;
8492 struct zebra_l2info_vxlan
*vxl
= NULL
;
8493 zebra_vni_t
*zvni
= NULL
;
8494 zebra_l3vni_t
*zl3vni
= NULL
;
8496 /* Check if EVPN is enabled. */
8497 if (!is_evpn_enabled())
8502 vxl
= &zif
->l2info
.vxl
;
8505 zl3vni
= zl3vni_lookup(vni
);
8508 /* process if-add for l3-vni*/
8509 if (IS_ZEBRA_DEBUG_VXLAN
)
8511 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8512 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8513 inet_ntoa(vxl
->vtep_ip
),
8514 zif
->brslave_info
.bridge_ifindex
);
8516 /* associate with vxlan_if */
8517 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8518 zl3vni
->vxlan_if
= ifp
;
8520 /* Associate with SVI, if any. We can associate with svi-if only
8521 * after association with vxlan_if is complete */
8522 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8524 if (is_l3vni_oper_up(zl3vni
))
8525 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8528 /* process if-add for l2-vni */
8529 struct interface
*vlan_if
= NULL
;
8531 /* Create or update VNI hash. */
8532 zvni
= zvni_lookup(vni
);
8534 zvni
= zvni_add(vni
);
8537 EC_ZEBRA_VNI_ADD_FAILED
,
8538 "Failed to add VNI hash, IF %s(%u) VNI %u",
8539 ifp
->name
, ifp
->ifindex
, vni
);
8544 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8545 zvni
->vxlan_if
= ifp
;
8546 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8547 zif
->brslave_info
.br_if
);
8549 zvni
->vrf_id
= vlan_if
->vrf_id
;
8550 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8552 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8555 if (IS_ZEBRA_DEBUG_VXLAN
)
8557 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8559 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8561 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8562 inet_ntoa(vxl
->vtep_ip
),
8563 zif
->brslave_info
.bridge_ifindex
);
8565 /* If down or not mapped to a bridge, we're done. */
8566 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8570 zvni_send_add_to_client(zvni
);
8572 /* Read and populate local MACs and neighbors */
8573 zvni_read_mac_neigh(zvni
, ifp
);
8579 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8580 char *err
, int err_str_sz
, int filter
,
8583 zebra_l3vni_t
*zl3vni
= NULL
;
8584 struct zebra_vrf
*zvrf_evpn
= NULL
;
8586 zvrf_evpn
= zebra_vrf_get_evpn();
8590 if (IS_ZEBRA_DEBUG_VXLAN
)
8591 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8592 add
? "ADD" : "DEL");
8596 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8598 /* check if the vni is already present under zvrf */
8600 snprintf(err
, err_str_sz
,
8601 "VNI is already configured under the vrf");
8605 /* check if this VNI is already present in the system */
8606 zl3vni
= zl3vni_lookup(vni
);
8608 snprintf(err
, err_str_sz
,
8609 "VNI is already configured as L3-VNI");
8613 /* add the L3-VNI to the global table */
8614 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8616 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8620 /* associate the vrf with vni */
8623 /* set the filter in l3vni to denote if we are using l3vni only
8627 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8629 /* associate with vxlan-intf;
8630 * we need to associate with the vxlan-intf first
8632 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8634 /* associate with corresponding SVI interface, we can associate
8635 * with svi-if only after vxlan interface association is
8638 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8640 /* formulate l2vni list */
8641 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8644 if (is_l3vni_oper_up(zl3vni
))
8645 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8648 zl3vni
= zl3vni_lookup(vni
);
8650 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8654 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8655 snprintf(err
, ERR_STR_SZ
,
8656 "prefix-routes-only is not set for the vni");
8660 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8662 /* delete and uninstall all rmacs */
8663 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8666 /* delete and uninstall all next-hops */
8667 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8673 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8678 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8680 zebra_l3vni_t
*zl3vni
= NULL
;
8683 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8687 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8688 if (is_l3vni_oper_up(zl3vni
))
8689 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8693 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8695 zebra_l3vni_t
*zl3vni
= NULL
;
8698 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8702 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8703 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8707 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8709 zebra_l3vni_t
*zl3vni
= NULL
;
8713 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8719 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8725 * Handle message from client to specify the flooding mechanism for
8726 * BUM packets. The default is to do head-end (ingress) replication
8727 * and the other supported option is to disable it. This applies to
8728 * all BUM traffic and disabling it applies to both the transmit and
8729 * receive direction.
8731 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8734 enum vxlan_flood_control flood_ctrl
;
8736 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
8737 zlog_err("EVPN flood control for non-EVPN VRF %u",
8743 STREAM_GETC(s
, flood_ctrl
);
8745 if (IS_ZEBRA_DEBUG_VXLAN
)
8746 zlog_debug("EVPN flood control %u, currently %u",
8747 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8749 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8752 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8754 /* Install or uninstall flood entries corresponding to
8757 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8765 * Handle message from client to enable/disable advertisement of svi macip
8768 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8773 zebra_vni_t
*zvni
= NULL
;
8774 struct interface
*ifp
= NULL
;
8776 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
8777 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8783 STREAM_GETC(s
, advertise
);
8784 STREAM_GETL(s
, vni
);
8787 if (IS_ZEBRA_DEBUG_VXLAN
)
8788 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8789 advertise
? "enabled" : "disabled",
8790 advertise_gw_macip_enabled(NULL
)
8794 if (zvrf
->advertise_svi_macip
== advertise
)
8799 zvrf
->advertise_svi_macip
= advertise
;
8800 hash_iterate(zvrf
->vni_table
,
8801 zvni_gw_macip_add_for_vni_hash
, NULL
);
8803 hash_iterate(zvrf
->vni_table
,
8804 zvni_svi_macip_del_for_vni_hash
, NULL
);
8805 zvrf
->advertise_svi_macip
= advertise
;
8809 struct zebra_if
*zif
= NULL
;
8810 struct zebra_l2info_vxlan zl2_info
;
8811 struct interface
*vlan_if
= NULL
;
8813 zvni
= zvni_lookup(vni
);
8817 if (IS_ZEBRA_DEBUG_VXLAN
)
8819 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8820 advertise
? "enabled" : "disabled", vni
,
8821 advertise_svi_macip_enabled(zvni
)
8825 if (zvni
->advertise_svi_macip
== advertise
)
8828 ifp
= zvni
->vxlan_if
;
8834 /* If down or not mapped to a bridge, we're done. */
8835 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8838 zl2_info
= zif
->l2info
.vxl
;
8840 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8841 zif
->brslave_info
.br_if
);
8846 zvni
->advertise_svi_macip
= advertise
;
8847 /* Add primary SVI MAC-IP */
8848 zvni_add_macip_for_intf(vlan_if
, zvni
);
8850 /* Del primary MAC-IP */
8851 zvni_del_macip_for_intf(vlan_if
, zvni
);
8852 zvni
->advertise_svi_macip
= advertise
;
8861 * Handle message from client to enable/disable advertisement of g/w macip
8864 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8869 zebra_vni_t
*zvni
= NULL
;
8870 struct interface
*ifp
= NULL
;
8871 struct zebra_if
*zif
= NULL
;
8872 struct zebra_l2info_vxlan zl2_info
;
8873 struct interface
*vlan_if
= NULL
;
8875 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
8876 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8882 STREAM_GETC(s
, advertise
);
8883 vni
= stream_get3(s
);
8885 zvni
= zvni_lookup(vni
);
8889 if (zvni
->advertise_subnet
== advertise
)
8892 if (IS_ZEBRA_DEBUG_VXLAN
)
8893 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8894 advertise
? "enabled" : "disabled", vni
,
8895 zvni
->advertise_subnet
? "enabled" : "disabled");
8898 zvni
->advertise_subnet
= advertise
;
8900 ifp
= zvni
->vxlan_if
;
8906 /* If down or not mapped to a bridge, we're done. */
8907 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8910 zl2_info
= zif
->l2info
.vxl
;
8913 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8917 if (zvni
->advertise_subnet
)
8918 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8920 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8927 * Handle message from client to enable/disable advertisement of g/w macip
8930 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8935 zebra_vni_t
*zvni
= NULL
;
8936 struct interface
*ifp
= NULL
;
8938 if (zvrf_id(zvrf
) != zebra_vrf_get_evpn_id()) {
8939 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8945 STREAM_GETC(s
, advertise
);
8946 STREAM_GETL(s
, vni
);
8949 if (IS_ZEBRA_DEBUG_VXLAN
)
8950 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8951 advertise
? "enabled" : "disabled",
8952 advertise_gw_macip_enabled(NULL
)
8956 if (zvrf
->advertise_gw_macip
== advertise
)
8959 zvrf
->advertise_gw_macip
= advertise
;
8961 if (advertise_gw_macip_enabled(zvni
))
8962 hash_iterate(zvrf
->vni_table
,
8963 zvni_gw_macip_add_for_vni_hash
, NULL
);
8965 hash_iterate(zvrf
->vni_table
,
8966 zvni_gw_macip_del_for_vni_hash
, NULL
);
8969 struct zebra_if
*zif
= NULL
;
8970 struct zebra_l2info_vxlan zl2_info
;
8971 struct interface
*vlan_if
= NULL
;
8972 struct interface
*vrr_if
= NULL
;
8974 zvni
= zvni_lookup(vni
);
8978 if (IS_ZEBRA_DEBUG_VXLAN
)
8980 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8981 advertise
? "enabled" : "disabled", vni
,
8982 advertise_gw_macip_enabled(zvni
) ? "enabled"
8985 if (zvni
->advertise_gw_macip
== advertise
)
8988 zvni
->advertise_gw_macip
= advertise
;
8990 ifp
= zvni
->vxlan_if
;
8996 /* If down or not mapped to a bridge, we're done. */
8997 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9000 zl2_info
= zif
->l2info
.vxl
;
9002 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9003 zif
->brslave_info
.br_if
);
9007 if (advertise_gw_macip_enabled(zvni
)) {
9008 /* Add primary SVI MAC-IP */
9009 zvni_add_macip_for_intf(vlan_if
, zvni
);
9011 /* Add VRR MAC-IP - if any*/
9012 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9014 zvni_add_macip_for_intf(vrr_if
, zvni
);
9016 /* Del primary MAC-IP */
9017 zvni_del_macip_for_intf(vlan_if
, zvni
);
9019 /* Del VRR MAC-IP - if any*/
9020 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9022 zvni_del_macip_for_intf(vrr_if
, zvni
);
9032 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9033 * When enabled, the VNI hash table will be built and MAC FDB table read;
9034 * when disabled, the entries should be deleted and remote VTEPs and MACs
9035 * uninstalled from the kernel.
9036 * This also informs the setting for BUM handling at the time this change
9037 * occurs; it is relevant only when specifying "learn".
9039 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9041 struct stream
*s
= NULL
;
9043 enum vxlan_flood_control flood_ctrl
;
9044 struct zebra_vrf
*zvrf_default
= NULL
;
9046 zvrf_default
= zebra_vrf_lookup_by_id(VRF_DEFAULT
);
9051 STREAM_GETC(s
, advertise
);
9052 STREAM_GETC(s
, flood_ctrl
);
9054 if (IS_ZEBRA_DEBUG_VXLAN
)
9055 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9056 zvrf_name(zvrf
), zvrf_id(zvrf
),
9057 advertise
? "enabled" : "disabled",
9058 is_evpn_enabled() ? "enabled" : "disabled",
9061 if (zvrf
->advertise_all_vni
== advertise
)
9064 zvrf
->advertise_all_vni
= advertise
;
9065 if (zvrf
->advertise_all_vni
) {
9066 zvrf_default
->evpn_vrf_id
= zvrf_id(zvrf
);
9068 /* Note BUM handling */
9069 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9071 /* Build VNI hash table and inform BGP. */
9072 zvni_build_hash_table();
9074 /* Add all SVI (L3 GW) MACs to BGP*/
9075 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9078 /* Read the MAC FDB */
9079 macfdb_read(zvrf
->zns
);
9081 /* Read neighbors */
9082 neigh_read(zvrf
->zns
);
9084 /* Cleanup VTEPs for all VNIs - uninstall from
9085 * kernel and free entries.
9087 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9089 /* cleanup all l3vnis */
9090 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9092 /* Fallback to the default VRF. */
9093 zvrf_default
->evpn_vrf_id
= VRF_DEFAULT
;
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 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9169 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9173 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
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 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9219 zvni
= zvni_lookup(mac
->zvni
->vni
);
9223 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
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
);