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
);
385 /* Mark neigh inactive */
386 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
389 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
390 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
392 nbr
->detect_start_time
.tv_sec
= 0;
393 nbr
->detect_start_time
.tv_usec
= 0;
398 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
400 struct in_addr vtep_ip
,
406 struct listnode
*node
= NULL
;
407 struct timeval elapsed
= {0, 0};
408 char buf
[ETHER_ADDR_STRLEN
];
409 char buf1
[INET6_ADDRSTRLEN
];
410 bool reset_params
= false;
412 if (!(zvrf
->dup_addr_detect
&& do_dad
))
415 /* MAC is detected as duplicate,
416 * Local MAC event -> hold on advertising to BGP.
417 * Remote MAC event -> hold on installing it.
419 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
420 if (IS_ZEBRA_DEBUG_VXLAN
)
422 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
424 prefix_mac2str(&mac
->macaddr
, buf
,
426 mac
->flags
, mac
->dad_count
,
427 zvrf
->dad_freeze_time
);
429 /* For duplicate MAC do not update
430 * client but update neigh due to
433 if (zvrf
->dad_freeze
)
434 *is_dup_detect
= true;
439 /* Check if detection time (M-secs) expired.
440 * Reset learn count and detection start time.
442 monotime_since(&mac
->detect_start_time
, &elapsed
);
443 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
444 if (is_local
&& !reset_params
) {
445 /* RFC-7432: A PE/VTEP that detects a MAC mobility
446 * event via LOCAL learning starts an M-second timer.
448 * NOTE: This is the START of the probe with count is
449 * 0 during LOCAL learn event.
450 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
452 reset_params
= !mac
->dad_count
;
456 if (IS_ZEBRA_DEBUG_VXLAN
)
458 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
459 , __PRETTY_FUNCTION__
,
460 prefix_mac2str(&mac
->macaddr
, buf
,
462 mac
->flags
, mac
->dad_count
);
465 /* Start dup. addr detection (DAD) start time,
466 * ONLY during LOCAL learn.
469 monotime(&mac
->detect_start_time
);
471 } else if (!is_local
) {
472 /* For REMOTE MAC, increment detection count
473 * ONLY while in probe window, once window passed,
474 * next local learn event should trigger DAD.
479 /* For LOCAL MAC learn event, once count is reset above via either
480 * initial/start detection time or passed the probe time, the count
481 * needs to be incremented.
486 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
487 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
488 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
490 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
491 is_local
? "local update, last" :
492 "remote update, from", inet_ntoa(vtep_ip
));
494 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
496 /* Capture Duplicate detection time */
497 mac
->dad_dup_detect_time
= monotime(NULL
);
499 /* Mark all IPs/Neighs as duplicate
500 * associcated with this MAC
502 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
504 /* Ony Mark IPs which are Local */
505 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
508 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
510 nbr
->dad_dup_detect_time
= monotime(NULL
);
512 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
513 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
515 prefix_mac2str(&mac
->macaddr
,
517 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
518 is_local
? "local" : "remote");
521 /* Start auto recovery timer for this MAC */
522 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
523 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
524 if (IS_ZEBRA_DEBUG_VXLAN
)
526 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
527 , __PRETTY_FUNCTION__
,
528 prefix_mac2str(&mac
->macaddr
, buf
,
530 mac
->flags
, zvrf
->dad_freeze_time
);
532 thread_add_timer(zrouter
.master
,
533 zebra_vxlan_dad_mac_auto_recovery_exp
,
534 mac
, zvrf
->dad_freeze_time
,
535 &mac
->dad_mac_auto_recovery_timer
);
538 /* In case of local update, do not inform to client (BGPd),
539 * upd_neigh for neigh sequence change.
541 if (zvrf
->dad_freeze
)
542 *is_dup_detect
= true;
546 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
548 struct in_addr vtep_ip
,
554 struct timeval elapsed
= {0, 0};
555 char buf
[ETHER_ADDR_STRLEN
];
556 char buf1
[INET6_ADDRSTRLEN
];
557 bool reset_params
= false;
559 if (!zvrf
->dup_addr_detect
)
562 /* IP is detected as duplicate or inherit dup
563 * state, hold on to install as remote entry
564 * only if freeze is enabled.
566 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
567 if (IS_ZEBRA_DEBUG_VXLAN
)
569 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
571 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
572 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
573 nbr
->flags
, nbr
->dad_count
,
574 zvrf
->dad_freeze_time
);
576 if (zvrf
->dad_freeze
)
577 *is_dup_detect
= true;
579 /* warn-only action, neigh will be installed.
580 * freeze action, it wil not be installed.
588 /* Check if detection time (M-secs) expired.
589 * Reset learn count and detection start time.
590 * During remote mac add, count should already be 1
591 * via local learning.
593 monotime_since(&nbr
->detect_start_time
, &elapsed
);
594 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
596 if (is_local
&& !reset_params
) {
597 /* RFC-7432: A PE/VTEP that detects a MAC mobility
598 * event via LOCAL learning starts an M-second timer.
600 * NOTE: This is the START of the probe with count is
601 * 0 during LOCAL learn event.
603 reset_params
= !nbr
->dad_count
;
607 if (IS_ZEBRA_DEBUG_VXLAN
)
609 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
611 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
612 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
613 nbr
->flags
, nbr
->dad_count
);
614 /* Reset learn count but do not start detection
615 * during REMOTE learn event.
618 /* Start dup. addr detection (DAD) start time,
619 * ONLY during LOCAL learn.
622 monotime(&nbr
->detect_start_time
);
624 } else if (!is_local
) {
625 /* For REMOTE IP/Neigh, increment detection count
626 * ONLY while in probe window, once window passed,
627 * next local learn event should trigger DAD.
632 /* For LOCAL IP/Neigh learn event, once count is reset above via either
633 * initial/start detection time or passed the probe time, the count
634 * needs to be incremented.
639 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
640 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
641 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
643 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
644 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
645 is_local
? "local update, last" :
646 "remote update, from",
649 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
651 /* Capture Duplicate detection time */
652 nbr
->dad_dup_detect_time
= monotime(NULL
);
654 /* Start auto recovery timer for this IP */
655 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
656 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
657 if (IS_ZEBRA_DEBUG_VXLAN
)
659 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
661 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
662 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
663 nbr
->flags
, zvrf
->dad_freeze_time
);
665 thread_add_timer(zrouter
.master
,
666 zebra_vxlan_dad_ip_auto_recovery_exp
,
667 nbr
, zvrf
->dad_freeze_time
,
668 &nbr
->dad_ip_auto_recovery_timer
);
670 if (zvrf
->dad_freeze
)
671 *is_dup_detect
= true;
676 * Helper function to determine maximum width of neighbor IP address for
677 * display - just because we're dealing with IPv6 addresses that can
680 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
683 char buf
[INET6_ADDRSTRLEN
];
684 struct neigh_walk_ctx
*wctx
= ctxt
;
687 n
= (zebra_neigh_t
*)bucket
->data
;
689 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
691 if (width
> wctx
->addr_width
)
692 wctx
->addr_width
= width
;
697 * Print a specific neighbor entry.
699 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
702 char buf1
[ETHER_ADDR_STRLEN
];
703 char buf2
[INET6_ADDRSTRLEN
];
704 const char *type_str
;
705 const char *state_str
;
706 bool flags_present
= false;
707 struct zebra_vrf
*zvrf
= NULL
;
708 struct timeval detect_start_time
= {0, 0};
710 zvrf
= zebra_vrf_get_evpn();
714 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
715 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
716 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
718 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
719 vty
= (struct vty
*)ctxt
;
721 vty_out(vty
, "IP: %s\n",
722 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
723 vty_out(vty
, " Type: %s\n", type_str
);
724 vty_out(vty
, " State: %s\n", state_str
);
725 vty_out(vty
, " MAC: %s\n",
726 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
728 json_object_string_add(json
, "ip", buf2
);
729 json_object_string_add(json
, "type", type_str
);
730 json_object_string_add(json
, "state", state_str
);
731 json_object_string_add(json
, "mac", buf1
);
733 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
735 vty_out(vty
, " Remote VTEP: %s\n",
736 inet_ntoa(n
->r_vtep_ip
));
738 json_object_string_add(json
, "remoteVtep",
739 inet_ntoa(n
->r_vtep_ip
));
741 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
743 vty_out(vty
, " Flags: Default-gateway");
744 flags_present
= true;
746 json_object_boolean_true_add(json
, "defaultGateway");
748 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
751 flags_present
? " ,Router" : " Flags: Router");
752 flags_present
= true;
758 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
759 n
->loc_seq
, n
->rem_seq
);
761 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
762 vty_out(vty
, " Duplicate, detected at %s",
763 time_to_string(n
->dad_dup_detect_time
));
764 } else if (n
->dad_count
) {
765 monotime_since(&n
->detect_start_time
,
767 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
768 char *buf
= time_to_string(
769 n
->detect_start_time
.tv_sec
);
772 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
774 " Duplicate detection started at %s, detection count %u\n",
775 tmp_buf
, n
->dad_count
);
779 json_object_int_add(json
, "localSequence", n
->loc_seq
);
780 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
781 json_object_int_add(json
, "detectionCount",
783 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
784 json_object_boolean_true_add(json
, "isDuplicate");
786 json_object_boolean_false_add(json
, "isDuplicate");
793 * Print neighbor hash entry - called for display of all neighbors.
795 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
798 json_object
*json_vni
= NULL
, *json_row
= NULL
;
800 char buf1
[ETHER_ADDR_STRLEN
];
801 char buf2
[INET6_ADDRSTRLEN
];
802 struct neigh_walk_ctx
*wctx
= ctxt
;
803 const char *state_str
;
806 json_vni
= wctx
->json
;
807 n
= (zebra_neigh_t
*)bucket
->data
;
810 json_row
= json_object_new_object();
812 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
813 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
814 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
815 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
816 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
819 if (json_vni
== NULL
) {
820 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
821 -wctx
->addr_width
, buf2
, "local",
824 json_object_string_add(json_row
, "type", "local");
825 json_object_string_add(json_row
, "state", state_str
);
826 json_object_string_add(json_row
, "mac", buf1
);
827 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
828 json_object_boolean_true_add(
829 json_row
, "defaultGateway");
830 json_object_int_add(json_row
, "localSequence",
832 json_object_int_add(json_row
, "remoteSequence",
834 json_object_int_add(json_row
, "detectionCount",
836 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
837 json_object_boolean_true_add(json_row
,
840 json_object_boolean_false_add(json_row
,
844 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
845 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
846 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
849 if (json_vni
== NULL
) {
850 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
853 "%*s %-6s %-8s %-17s %-21s\n",
854 -wctx
->addr_width
, "Neighbor", "Type",
855 "State", "MAC", "Remote VTEP");
856 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
857 -wctx
->addr_width
, buf2
, "remote", state_str
,
858 buf1
, inet_ntoa(n
->r_vtep_ip
));
860 json_object_string_add(json_row
, "type", "remote");
861 json_object_string_add(json_row
, "state", state_str
);
862 json_object_string_add(json_row
, "mac", buf1
);
863 json_object_string_add(json_row
, "remoteVtep",
864 inet_ntoa(n
->r_vtep_ip
));
865 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
866 json_object_boolean_true_add(json_row
,
868 json_object_int_add(json_row
, "localSequence",
870 json_object_int_add(json_row
, "remoteSequence",
872 json_object_int_add(json_row
, "detectionCount",
874 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
875 json_object_boolean_true_add(json_row
,
878 json_object_boolean_false_add(json_row
,
885 json_object_object_add(json_vni
, buf2
, json_row
);
889 * Print neighbor hash entry in detail - called for display of all neighbors.
891 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
894 json_object
*json_vni
= NULL
, *json_row
= NULL
;
896 char buf
[INET6_ADDRSTRLEN
];
897 struct neigh_walk_ctx
*wctx
= ctxt
;
900 json_vni
= wctx
->json
;
901 n
= (zebra_neigh_t
*)bucket
->data
;
905 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
907 json_row
= json_object_new_object();
909 zvni_print_neigh(n
, vty
, json_row
);
912 json_object_object_add(json_vni
, buf
, json_row
);
916 * Print neighbors for all VNI.
918 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
922 json_object
*json
= NULL
, *json_vni
= NULL
;
925 struct neigh_walk_ctx wctx
;
926 char vni_str
[VNI_STR_LEN
];
929 vty
= (struct vty
*)args
[0];
930 json
= (json_object
*)args
[1];
931 print_dup
= (uint32_t)(uintptr_t)args
[2];
933 zvni
= (zebra_vni_t
*)bucket
->data
;
935 num_neigh
= hashcount(zvni
->neigh_table
);
938 num_neigh
= num_dup_detected_neighs(zvni
);
942 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
943 zvni
->vni
, num_neigh
);
945 json_vni
= json_object_new_object();
946 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
947 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
952 json_object_object_add(json
, vni_str
, json_vni
);
956 /* Since we have IPv6 addresses to deal with which can vary widely in
957 * size, we try to be a bit more elegant in display by first computing
960 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
963 wctx
.addr_width
= 15;
964 wctx
.json
= json_vni
;
965 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
968 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
969 -wctx
.addr_width
, "IP", "Type",
970 "State", "MAC", "Remote VTEP");
973 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
976 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
979 json_object_object_add(json
, vni_str
, json_vni
);
982 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
986 nbr
= (zebra_neigh_t
*)bucket
->data
;
990 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
991 zvni_print_neigh_hash(bucket
, ctxt
);
994 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
999 nbr
= (zebra_neigh_t
*)bucket
->data
;
1003 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1004 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1008 * Print neighbors for all VNIs in detail.
1010 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1014 json_object
*json
= NULL
, *json_vni
= NULL
;
1017 struct neigh_walk_ctx wctx
;
1018 char vni_str
[VNI_STR_LEN
];
1021 vty
= (struct vty
*)args
[0];
1022 json
= (json_object
*)args
[1];
1023 print_dup
= (uint32_t)(uintptr_t)args
[2];
1025 zvni
= (zebra_vni_t
*)bucket
->data
;
1028 vty_out(vty
, "{}\n");
1031 num_neigh
= hashcount(zvni
->neigh_table
);
1033 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1038 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1039 zvni
->vni
, num_neigh
);
1041 json_vni
= json_object_new_object();
1042 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1043 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1047 json_object_object_add(json
, vni_str
, json_vni
);
1051 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1054 wctx
.addr_width
= 15;
1055 wctx
.json
= json_vni
;
1058 hash_iterate(zvni
->neigh_table
,
1059 zvni_print_dad_neigh_hash_detail
, &wctx
);
1061 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1065 json_object_object_add(json
, vni_str
, json_vni
);
1068 /* print a specific next hop for an l3vni */
1069 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1072 char buf1
[ETHER_ADDR_STRLEN
];
1073 char buf2
[INET6_ADDRSTRLEN
];
1074 json_object
*json_hosts
= NULL
;
1075 struct host_rb_entry
*hle
;
1078 vty_out(vty
, "Ip: %s\n",
1079 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1080 vty_out(vty
, " RMAC: %s\n",
1081 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1082 vty_out(vty
, " Refcount: %d\n",
1083 rb_host_count(&n
->host_rb
));
1084 vty_out(vty
, " Prefixes:\n");
1085 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1086 vty_out(vty
, " %s\n",
1087 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1089 json_hosts
= json_object_new_array();
1090 json_object_string_add(
1091 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1092 json_object_string_add(
1094 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1095 json_object_int_add(json
, "refCount",
1096 rb_host_count(&n
->host_rb
));
1097 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1098 json_object_array_add(json_hosts
,
1099 json_object_new_string(prefix2str(
1100 &hle
->p
, buf2
, sizeof(buf2
))));
1101 json_object_object_add(json
, "prefixList", json_hosts
);
1105 /* Print a specific RMAC entry */
1106 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1109 char buf1
[ETHER_ADDR_STRLEN
];
1110 char buf2
[PREFIX_STRLEN
];
1111 json_object
*json_hosts
= NULL
;
1112 struct host_rb_entry
*hle
;
1115 vty_out(vty
, "MAC: %s\n",
1116 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1117 vty_out(vty
, " Remote VTEP: %s\n",
1118 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1119 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1120 vty_out(vty
, " Prefixes:\n");
1121 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1122 vty_out(vty
, " %s\n",
1123 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1125 json_hosts
= json_object_new_array();
1126 json_object_string_add(
1128 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1129 json_object_string_add(json
, "vtepIp",
1130 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1131 json_object_int_add(json
, "refCount",
1132 rb_host_count(&zrmac
->host_rb
));
1133 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1134 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1135 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1136 json_object_array_add(
1138 json_object_new_string(prefix2str(
1139 &hle
->p
, buf2
, sizeof(buf2
))));
1140 json_object_object_add(json
, "prefixList", json_hosts
);
1145 * Print a specific MAC entry.
1147 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1150 zebra_neigh_t
*n
= NULL
;
1151 struct listnode
*node
= NULL
;
1152 char buf1
[ETHER_ADDR_STRLEN
];
1153 char buf2
[INET6_ADDRSTRLEN
];
1154 struct zebra_vrf
*zvrf
;
1155 struct timeval detect_start_time
= {0, 0};
1157 zvrf
= zebra_vrf_get_evpn();
1161 vty
= (struct vty
*)ctxt
;
1162 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1165 json_object
*json_mac
= json_object_new_object();
1167 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1168 struct zebra_ns
*zns
;
1169 struct interface
*ifp
;
1172 ifindex
= mac
->fwd_info
.local
.ifindex
;
1173 zns
= zebra_ns_lookup(NS_DEFAULT
);
1174 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1177 json_object_string_add(json_mac
, "type", "local");
1178 json_object_string_add(json_mac
, "intf", ifp
->name
);
1179 json_object_int_add(json_mac
, "ifindex", ifindex
);
1180 if (mac
->fwd_info
.local
.vid
)
1181 json_object_int_add(json_mac
, "vlan",
1182 mac
->fwd_info
.local
.vid
);
1183 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1184 json_object_string_add(json_mac
, "type", "remote");
1185 json_object_string_add(
1186 json_mac
, "remoteVtep",
1187 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1188 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1189 json_object_string_add(json_mac
, "type", "auto");
1191 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1192 json_object_boolean_true_add(json_mac
, "stickyMac");
1194 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1195 json_object_boolean_true_add(json_mac
,
1198 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1199 json_object_boolean_true_add(json_mac
,
1200 "remoteGatewayMac");
1202 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1203 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1205 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1206 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1207 json_object_boolean_true_add(json_mac
, "isDuplicate");
1209 json_object_boolean_false_add(json_mac
, "isDuplicate");
1211 /* print all the associated neigh */
1212 if (!listcount(mac
->neigh_list
))
1213 json_object_string_add(json_mac
, "neighbors", "none");
1215 json_object
*json_active_nbrs
= json_object_new_array();
1216 json_object
*json_inactive_nbrs
=
1217 json_object_new_array();
1218 json_object
*json_nbrs
= json_object_new_object();
1220 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1221 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1222 json_object_array_add(
1224 json_object_new_string(
1229 json_object_array_add(
1231 json_object_new_string(
1237 json_object_object_add(json_nbrs
, "active",
1239 json_object_object_add(json_nbrs
, "inactive",
1240 json_inactive_nbrs
);
1241 json_object_object_add(json_mac
, "neighbors",
1245 json_object_object_add(json
, buf1
, json_mac
);
1247 vty_out(vty
, "MAC: %s\n", buf1
);
1249 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1250 struct zebra_ns
*zns
;
1251 struct interface
*ifp
;
1254 ifindex
= mac
->fwd_info
.local
.ifindex
;
1255 zns
= zebra_ns_lookup(NS_DEFAULT
);
1256 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1259 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1260 if (mac
->fwd_info
.local
.vid
)
1261 vty_out(vty
, " VLAN: %u",
1262 mac
->fwd_info
.local
.vid
);
1263 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1264 vty_out(vty
, " Remote VTEP: %s",
1265 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1266 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1267 vty_out(vty
, " Auto Mac ");
1270 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1271 vty_out(vty
, " Sticky Mac ");
1273 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1274 vty_out(vty
, " Default-gateway Mac ");
1276 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1277 vty_out(vty
, " Remote-gateway Mac ");
1280 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1284 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1285 vty_out(vty
, " Duplicate, detected at %s",
1286 time_to_string(mac
->dad_dup_detect_time
));
1287 } else if (mac
->dad_count
) {
1288 monotime_since(&mac
->detect_start_time
,
1289 &detect_start_time
);
1290 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1291 char *buf
= time_to_string(
1292 mac
->detect_start_time
.tv_sec
);
1295 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1297 " Duplicate detection started at %s, detection count %u\n",
1298 tmp_buf
, mac
->dad_count
);
1302 /* print all the associated neigh */
1303 vty_out(vty
, " Neighbors:\n");
1304 if (!listcount(mac
->neigh_list
))
1305 vty_out(vty
, " No Neighbors\n");
1307 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1308 vty_out(vty
, " %s %s\n",
1309 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1310 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1321 * Print MAC hash entry - called for display of all MACs.
1323 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1326 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1328 char buf1
[ETHER_ADDR_STRLEN
];
1329 struct mac_walk_ctx
*wctx
= ctxt
;
1332 json_mac_hdr
= wctx
->json
;
1333 mac
= (zebra_mac_t
*)bucket
->data
;
1335 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1338 json_mac
= json_object_new_object();
1340 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1341 struct zebra_ns
*zns
;
1343 struct interface
*ifp
;
1346 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1349 zns
= zebra_ns_lookup(NS_DEFAULT
);
1350 ifindex
= mac
->fwd_info
.local
.ifindex
;
1351 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1352 if (!ifp
) // unexpected
1354 vid
= mac
->fwd_info
.local
.vid
;
1355 if (json_mac_hdr
== NULL
)
1356 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1359 json_object_string_add(json_mac
, "type", "local");
1360 json_object_string_add(json_mac
, "intf", ifp
->name
);
1363 if (json_mac_hdr
== NULL
)
1364 vty_out(vty
, " %-5u", vid
);
1366 json_object_int_add(json_mac
, "vlan", vid
);
1368 if (json_mac_hdr
== NULL
) {
1371 json_object_int_add(json_mac
, "localSequence",
1373 json_object_int_add(json_mac
, "remoteSequence",
1375 json_object_int_add(json_mac
, "detectionCount",
1377 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1378 json_object_boolean_true_add(json_mac
,
1381 json_object_boolean_false_add(json_mac
,
1383 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1388 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1390 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1391 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1395 if (json_mac_hdr
== NULL
) {
1396 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1397 (wctx
->count
== 0)) {
1398 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1399 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1400 "Type", "Intf/Remote VTEP", "VLAN");
1402 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1403 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1405 json_object_string_add(json_mac
, "type", "remote");
1406 json_object_string_add(json_mac
, "remoteVtep",
1407 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1408 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1409 json_object_int_add(json_mac
, "localSequence",
1411 json_object_int_add(json_mac
, "remoteSequence",
1413 json_object_int_add(json_mac
, "detectionCount",
1415 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1416 json_object_boolean_true_add(json_mac
,
1419 json_object_boolean_false_add(json_mac
,
1428 /* Print Duplicate MAC */
1429 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1433 mac
= (zebra_mac_t
*)bucket
->data
;
1437 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1438 zvni_print_mac_hash(bucket
, ctxt
);
1442 * Print MAC hash entry in detail - called for display of all MACs.
1444 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1447 json_object
*json_mac_hdr
= NULL
;
1449 struct mac_walk_ctx
*wctx
= ctxt
;
1450 char buf1
[ETHER_ADDR_STRLEN
];
1453 json_mac_hdr
= wctx
->json
;
1454 mac
= (zebra_mac_t
*)bucket
->data
;
1459 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1461 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1464 /* Print Duplicate MAC in detail */
1465 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1470 mac
= (zebra_mac_t
*)bucket
->data
;
1474 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1475 zvni_print_mac_hash_detail(bucket
, ctxt
);
1479 * Print MACs for all VNI.
1481 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1484 json_object
*json
= NULL
, *json_vni
= NULL
;
1485 json_object
*json_mac
= NULL
;
1488 struct mac_walk_ctx
*wctx
= ctxt
;
1489 char vni_str
[VNI_STR_LEN
];
1491 vty
= (struct vty
*)wctx
->vty
;
1492 json
= (struct json_object
*)wctx
->json
;
1494 zvni
= (zebra_vni_t
*)bucket
->data
;
1497 /*We are iterating over a new VNI, set the count to 0*/
1500 num_macs
= num_valid_macs(zvni
);
1504 if (wctx
->print_dup
)
1505 num_macs
= num_dup_detected_macs(zvni
);
1508 json_vni
= json_object_new_object();
1509 json_mac
= json_object_new_object();
1510 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1513 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1515 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1516 zvni
->vni
, num_macs
);
1517 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1518 "Intf/Remote VTEP", "VLAN");
1520 json_object_int_add(json_vni
, "numMacs", num_macs
);
1525 json_object_int_add(json_vni
, "numMacs", num_macs
);
1526 json_object_object_add(json
, vni_str
, json_vni
);
1531 /* assign per-vni to wctx->json object to fill macs
1532 * under the vni. Re-assign primary json object to fill
1533 * next vni information.
1535 wctx
->json
= json_mac
;
1536 if (wctx
->print_dup
)
1537 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1539 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1543 json_object_object_add(json_vni
, "macs", json_mac
);
1544 json_object_object_add(json
, vni_str
, json_vni
);
1549 * Print MACs in detail for all VNI.
1551 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1555 json_object
*json
= NULL
, *json_vni
= NULL
;
1556 json_object
*json_mac
= NULL
;
1559 struct mac_walk_ctx
*wctx
= ctxt
;
1560 char vni_str
[VNI_STR_LEN
];
1562 vty
= (struct vty
*)wctx
->vty
;
1563 json
= (struct json_object
*)wctx
->json
;
1565 zvni
= (zebra_vni_t
*)bucket
->data
;
1568 vty_out(vty
, "{}\n");
1573 /*We are iterating over a new VNI, set the count to 0*/
1576 num_macs
= num_valid_macs(zvni
);
1580 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1584 json_vni
= json_object_new_object();
1585 json_mac
= json_object_new_object();
1586 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1589 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1591 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1592 zvni
->vni
, num_macs
);
1594 json_object_int_add(json_vni
, "numMacs", num_macs
);
1596 /* assign per-vni to wctx->json object to fill macs
1597 * under the vni. Re-assign primary json object to fill
1598 * next vni information.
1600 wctx
->json
= json_mac
;
1601 if (wctx
->print_dup
)
1602 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1605 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1609 json_object_object_add(json_vni
, "macs", json_mac
);
1610 json_object_object_add(json
, vni_str
, json_vni
);
1614 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1616 struct nh_walk_ctx
*wctx
= NULL
;
1617 struct vty
*vty
= NULL
;
1618 struct json_object
*json_vni
= NULL
;
1619 struct json_object
*json_nh
= NULL
;
1620 zebra_neigh_t
*n
= NULL
;
1621 char buf1
[ETHER_ADDR_STRLEN
];
1622 char buf2
[INET6_ADDRSTRLEN
];
1624 wctx
= (struct nh_walk_ctx
*)ctx
;
1626 json_vni
= wctx
->json
;
1628 json_nh
= json_object_new_object();
1629 n
= (zebra_neigh_t
*)bucket
->data
;
1632 vty_out(vty
, "%-15s %-17s\n",
1633 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1634 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1636 json_object_string_add(json_nh
, "nexthopIp",
1637 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1638 json_object_string_add(
1639 json_nh
, "routerMac",
1640 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1641 json_object_object_add(json_vni
,
1642 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1647 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1650 struct vty
*vty
= NULL
;
1651 json_object
*json
= NULL
;
1652 json_object
*json_vni
= NULL
;
1653 zebra_l3vni_t
*zl3vni
= NULL
;
1654 uint32_t num_nh
= 0;
1655 struct nh_walk_ctx wctx
;
1656 char vni_str
[VNI_STR_LEN
];
1658 vty
= (struct vty
*)args
[0];
1659 json
= (struct json_object
*)args
[1];
1661 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1663 num_nh
= hashcount(zl3vni
->nh_table
);
1668 json_vni
= json_object_new_object();
1669 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1673 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1674 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1676 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1678 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1680 wctx
.json
= json_vni
;
1681 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1683 json_object_object_add(json
, vni_str
, json_vni
);
1686 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1689 struct vty
*vty
= NULL
;
1690 json_object
*json
= NULL
;
1691 json_object
*json_vni
= NULL
;
1692 zebra_l3vni_t
*zl3vni
= NULL
;
1694 struct rmac_walk_ctx wctx
;
1695 char vni_str
[VNI_STR_LEN
];
1697 vty
= (struct vty
*)args
[0];
1698 json
= (struct json_object
*)args
[1];
1700 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1702 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1707 json_vni
= json_object_new_object();
1708 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1712 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1713 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1715 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1717 /* assign per-vni to wctx->json object to fill macs
1718 * under the vni. Re-assign primary json object to fill
1719 * next vni information.
1721 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1723 wctx
.json
= json_vni
;
1724 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1726 json_object_object_add(json
, vni_str
, json_vni
);
1729 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1731 zebra_mac_t
*zrmac
= NULL
;
1732 struct rmac_walk_ctx
*wctx
= NULL
;
1733 struct vty
*vty
= NULL
;
1734 struct json_object
*json
= NULL
;
1735 struct json_object
*json_rmac
= NULL
;
1736 char buf
[ETHER_ADDR_STRLEN
];
1738 wctx
= (struct rmac_walk_ctx
*)ctx
;
1742 json_rmac
= json_object_new_object();
1743 zrmac
= (zebra_mac_t
*)bucket
->data
;
1746 vty_out(vty
, "%-17s %-21s\n",
1747 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1748 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1750 json_object_string_add(
1751 json_rmac
, "routerMac",
1752 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1753 json_object_string_add(json_rmac
, "vtepIp",
1754 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1755 json_object_object_add(
1756 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1761 /* print a specific L3 VNI entry */
1762 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1764 char buf
[ETHER_ADDR_STRLEN
];
1765 struct vty
*vty
= NULL
;
1766 json_object
*json
= NULL
;
1767 zebra_vni_t
*zvni
= NULL
;
1768 json_object
*json_vni_list
= NULL
;
1769 struct listnode
*node
= NULL
, *nnode
= NULL
;
1775 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1776 vty_out(vty
, " Type: %s\n", "L3");
1777 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1778 vty_out(vty
, " Local Vtep Ip: %s\n",
1779 inet_ntoa(zl3vni
->local_vtep_ip
));
1780 vty_out(vty
, " Vxlan-Intf: %s\n",
1781 zl3vni_vxlan_if_name(zl3vni
));
1782 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1783 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1784 vty_out(vty
, " VNI Filter: %s\n",
1785 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1786 ? "prefix-routes-only"
1788 vty_out(vty
, " Router MAC: %s\n",
1789 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1790 vty_out(vty
, " L2 VNIs: ");
1791 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1792 vty_out(vty
, "%u ", zvni
->vni
);
1795 json_vni_list
= json_object_new_array();
1796 json_object_int_add(json
, "vni", zl3vni
->vni
);
1797 json_object_string_add(json
, "type", "L3");
1798 json_object_string_add(json
, "localVtepIp",
1799 inet_ntoa(zl3vni
->local_vtep_ip
));
1800 json_object_string_add(json
, "vxlanIntf",
1801 zl3vni_vxlan_if_name(zl3vni
));
1802 json_object_string_add(json
, "sviIntf",
1803 zl3vni_svi_if_name(zl3vni
));
1804 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1805 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1806 json_object_string_add(
1808 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1809 json_object_string_add(
1811 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1812 ? "prefix-routes-only"
1814 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1815 json_object_array_add(json_vni_list
,
1816 json_object_new_int(zvni
->vni
));
1818 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1823 * Print a specific VNI entry.
1825 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1828 zebra_vtep_t
*zvtep
;
1831 json_object
*json
= NULL
;
1832 json_object
*json_vtep_list
= NULL
;
1833 json_object
*json_ip_str
= NULL
;
1839 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1840 vty_out(vty
, " Type: %s\n", "L2");
1841 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1843 json_object_int_add(json
, "vni", zvni
->vni
);
1844 json_object_string_add(json
, "type", "L2");
1845 json_object_string_add(json
, "vrf",
1846 vrf_id_to_name(zvni
->vrf_id
));
1849 if (!zvni
->vxlan_if
) { // unexpected
1851 vty_out(vty
, " VxLAN interface: unknown\n");
1854 num_macs
= num_valid_macs(zvni
);
1855 num_neigh
= hashcount(zvni
->neigh_table
);
1857 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1858 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1859 vty_out(vty
, " Local VTEP IP: %s\n",
1860 inet_ntoa(zvni
->local_vtep_ip
));
1862 json_object_string_add(json
, "vxlanInterface",
1863 zvni
->vxlan_if
->name
);
1864 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1865 json_object_string_add(json
, "vtepIp",
1866 inet_ntoa(zvni
->local_vtep_ip
));
1867 json_object_string_add(json
, "advertiseGatewayMacip",
1868 zvni
->advertise_gw_macip
? "Yes" : "No");
1869 json_object_int_add(json
, "numMacs", num_macs
);
1870 json_object_int_add(json
, "numArpNd", num_neigh
);
1874 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1877 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1879 json_vtep_list
= json_object_new_array();
1880 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1882 vty_out(vty
, " %s\n",
1883 inet_ntoa(zvtep
->vtep_ip
));
1885 json_ip_str
= json_object_new_string(
1886 inet_ntoa(zvtep
->vtep_ip
));
1887 json_object_array_add(json_vtep_list
,
1892 json_object_object_add(json
, "numRemoteVteps",
1897 " Number of MACs (local and remote) known for this VNI: %u\n",
1900 " Number of ARPs (IPv4 and IPv6, local and remote) "
1901 "known for this VNI: %u\n",
1903 vty_out(vty
, " Advertise-gw-macip: %s\n",
1904 zvni
->advertise_gw_macip
? "Yes" : "No");
1908 /* print a L3 VNI hash entry */
1909 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1911 struct vty
*vty
= NULL
;
1912 json_object
*json
= NULL
;
1913 json_object
*json_vni
= NULL
;
1914 zebra_l3vni_t
*zl3vni
= NULL
;
1916 vty
= (struct vty
*)ctx
[0];
1917 json
= (json_object
*)ctx
[1];
1919 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1922 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1923 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1924 hashcount(zl3vni
->rmac_table
),
1925 hashcount(zl3vni
->nh_table
), "n/a",
1926 zl3vni_vrf_name(zl3vni
));
1928 char vni_str
[VNI_STR_LEN
];
1930 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1931 json_vni
= json_object_new_object();
1932 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1933 json_object_string_add(json_vni
, "vxlanIf",
1934 zl3vni_vxlan_if_name(zl3vni
));
1935 json_object_int_add(json_vni
, "numMacs",
1936 hashcount(zl3vni
->rmac_table
));
1937 json_object_int_add(json_vni
, "numArpNd",
1938 hashcount(zl3vni
->nh_table
));
1939 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1940 json_object_string_add(json_vni
, "type", "L3");
1941 json_object_string_add(json_vni
, "tenantVrf",
1942 zl3vni_vrf_name(zl3vni
));
1943 json_object_object_add(json
, vni_str
, json_vni
);
1947 /* Private Structure to pass callback data for hash iterator */
1948 struct zvni_evpn_show
{
1951 struct zebra_vrf
*zvrf
;
1954 /* print a L3 VNI hash entry in detail*/
1955 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1957 struct vty
*vty
= NULL
;
1958 zebra_l3vni_t
*zl3vni
= NULL
;
1959 json_object
*json
= NULL
;
1960 bool use_json
= false;
1961 struct zvni_evpn_show
*zes
= data
;
1969 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1971 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
1977 * Print a VNI hash entry - called for display of all VNIs.
1979 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
1983 zebra_vtep_t
*zvtep
;
1984 uint32_t num_vteps
= 0;
1985 uint32_t num_macs
= 0;
1986 uint32_t num_neigh
= 0;
1987 json_object
*json
= NULL
;
1988 json_object
*json_vni
= NULL
;
1989 json_object
*json_ip_str
= NULL
;
1990 json_object
*json_vtep_list
= NULL
;
1995 zvni
= (zebra_vni_t
*)bucket
->data
;
1997 zvtep
= zvni
->vteps
;
2000 zvtep
= zvtep
->next
;
2003 num_macs
= num_valid_macs(zvni
);
2004 num_neigh
= hashcount(zvni
->neigh_table
);
2006 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2008 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2009 num_macs
, num_neigh
, num_vteps
,
2010 vrf_id_to_name(zvni
->vrf_id
));
2012 char vni_str
[VNI_STR_LEN
];
2013 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2014 json_vni
= json_object_new_object();
2015 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2016 json_object_string_add(json_vni
, "type", "L2");
2017 json_object_string_add(json_vni
, "vxlanIf",
2018 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2020 json_object_int_add(json_vni
, "numMacs", num_macs
);
2021 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2022 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2023 json_object_string_add(json_vni
, "tenantVrf",
2024 vrf_id_to_name(zvni
->vrf_id
));
2026 json_vtep_list
= json_object_new_array();
2027 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2028 json_ip_str
= json_object_new_string(
2029 inet_ntoa(zvtep
->vtep_ip
));
2030 json_object_array_add(json_vtep_list
,
2033 json_object_object_add(json_vni
, "remoteVteps",
2036 json_object_object_add(json
, vni_str
, json_vni
);
2041 * Print a VNI hash entry in detail - called for display of all VNIs.
2043 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2047 json_object
*json
= NULL
;
2048 bool use_json
= false;
2049 struct zvni_evpn_show
*zes
= data
;
2057 zvni
= (zebra_vni_t
*)bucket
->data
;
2059 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2064 * Inform BGP about local MACIP.
2066 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2067 struct ipaddr
*ip
, uint8_t flags
,
2068 uint32_t seq
, int state
, uint16_t cmd
)
2070 char buf
[ETHER_ADDR_STRLEN
];
2071 char buf2
[INET6_ADDRSTRLEN
];
2073 struct zserv
*client
= NULL
;
2074 struct stream
*s
= NULL
;
2076 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2077 /* BGP may not be running. */
2081 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2083 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2084 stream_putl(s
, vni
);
2085 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2088 if (IS_IPADDR_V4(ip
))
2089 ipa_len
= IPV4_MAX_BYTELEN
;
2090 else if (IS_IPADDR_V6(ip
))
2091 ipa_len
= IPV6_MAX_BYTELEN
;
2093 stream_putl(s
, ipa_len
); /* IP address length */
2095 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2097 stream_putl(s
, 0); /* Just MAC. */
2099 if (cmd
== ZEBRA_MACIP_ADD
) {
2100 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2101 stream_putl(s
, seq
); /* sequence number */
2103 stream_putl(s
, state
); /* state - active/inactive */
2107 /* Write packet size. */
2108 stream_putw_at(s
, 0, stream_get_endp(s
));
2110 if (IS_ZEBRA_DEBUG_VXLAN
)
2112 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2113 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2114 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2115 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2116 zebra_route_string(client
->proto
));
2118 if (cmd
== ZEBRA_MACIP_ADD
)
2119 client
->macipadd_cnt
++;
2121 client
->macipdel_cnt
++;
2123 return zserv_send_message(client
, s
);
2127 * Make hash key for neighbors.
2129 static unsigned int neigh_hash_keymake(void *p
)
2131 zebra_neigh_t
*n
= p
;
2132 struct ipaddr
*ip
= &n
->ip
;
2134 if (IS_IPADDR_V4(ip
))
2135 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2137 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2138 ZEBRA_NUM_OF(ip
->ipaddr_v6
.s6_addr32
), 0);
2142 * Compare two neighbor hash structures.
2144 static bool neigh_cmp(const void *p1
, const void *p2
)
2146 const zebra_neigh_t
*n1
= p1
;
2147 const zebra_neigh_t
*n2
= p2
;
2149 if (n1
== NULL
&& n2
== NULL
)
2152 if (n1
== NULL
|| n2
== NULL
)
2155 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2158 static int neigh_list_cmp(void *p1
, void *p2
)
2160 const zebra_neigh_t
*n1
= p1
;
2161 const zebra_neigh_t
*n2
= p2
;
2163 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2167 * Callback to allocate neighbor hash entry.
2169 static void *zvni_neigh_alloc(void *p
)
2171 const zebra_neigh_t
*tmp_n
= p
;
2174 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2181 * Add neighbor entry.
2183 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2184 struct ethaddr
*mac
)
2186 zebra_neigh_t tmp_n
;
2187 zebra_neigh_t
*n
= NULL
;
2188 zebra_mac_t
*zmac
= NULL
;
2190 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2191 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2192 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2195 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2196 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2198 n
->dad_ip_auto_recovery_timer
= NULL
;
2200 /* Associate the neigh to mac */
2201 zmac
= zvni_mac_lookup(zvni
, mac
);
2203 listnode_add_sort(zmac
->neigh_list
, n
);
2209 * Delete neighbor entry.
2211 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2213 zebra_neigh_t
*tmp_n
;
2214 zebra_mac_t
*zmac
= NULL
;
2216 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2218 listnode_delete(zmac
->neigh_list
, n
);
2220 /* Cancel auto recovery */
2221 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2223 /* Free the VNI hash entry and allocated memory. */
2224 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2225 XFREE(MTYPE_NEIGH
, tmp_n
);
2231 * Free neighbor hash entry (callback)
2233 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2235 struct neigh_walk_ctx
*wctx
= arg
;
2236 zebra_neigh_t
*n
= bucket
->data
;
2238 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2239 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2240 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2241 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2242 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2243 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2244 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2245 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2246 &n
->emac
, 0, n
->state
);
2248 if (wctx
->uninstall
)
2249 zvni_neigh_uninstall(wctx
->zvni
, n
);
2251 zvni_neigh_del(wctx
->zvni
, n
);
2258 * Delete all neighbor entries from specific VTEP for a particular VNI.
2260 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2261 struct in_addr
*r_vtep_ip
)
2263 struct neigh_walk_ctx wctx
;
2265 if (!zvni
->neigh_table
)
2268 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2270 wctx
.uninstall
= uninstall
;
2271 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2272 wctx
.r_vtep_ip
= *r_vtep_ip
;
2274 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2278 * Delete all neighbor entries for this VNI.
2280 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2283 struct neigh_walk_ctx wctx
;
2285 if (!zvni
->neigh_table
)
2288 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2290 wctx
.uninstall
= uninstall
;
2291 wctx
.upd_client
= upd_client
;
2294 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2298 * Look up neighbor hash entry.
2300 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2305 memset(&tmp
, 0, sizeof(tmp
));
2306 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2307 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2313 * Process all neighbors associated with a MAC upon the MAC being learnt
2314 * locally or undergoing any other change (such as sequence number).
2316 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2320 zebra_neigh_t
*n
= NULL
;
2321 struct listnode
*node
= NULL
;
2322 struct zebra_vrf
*zvrf
= NULL
;
2323 char buf
[ETHER_ADDR_STRLEN
];
2325 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2327 if (IS_ZEBRA_DEBUG_VXLAN
)
2328 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2329 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2330 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2332 /* Walk all neighbors and mark any inactive local neighbors as
2333 * active and/or update sequence number upon a move, and inform BGP.
2334 * The action for remote neighbors is TBD.
2335 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2336 * accidentally end up deleting a just-learnt local neighbor.
2338 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2339 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2340 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2341 ZEBRA_NEIGH_SET_ACTIVE(n
);
2342 n
->loc_seq
= zmac
->loc_seq
;
2343 if (!(zvrf
->dup_addr_detect
&&
2344 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2345 ZEBRA_NEIGH_DUPLICATE
)))
2346 zvni_neigh_send_add_to_client(
2347 zvni
->vni
, &n
->ip
, &n
->emac
,
2348 n
->flags
, n
->loc_seq
);
2355 * Process all neighbors associated with a local MAC upon the MAC being
2358 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2361 zebra_neigh_t
*n
= NULL
;
2362 struct listnode
*node
= NULL
;
2363 char buf
[ETHER_ADDR_STRLEN
];
2365 if (IS_ZEBRA_DEBUG_VXLAN
)
2366 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2367 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2370 /* Walk all local neighbors and mark as inactive and inform
2372 * TBD: There is currently no handling for remote neighbors. We
2373 * don't expect them to exist, if they do, do we install the MAC
2374 * as a remote MAC and the neighbor as remote?
2376 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2377 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2378 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2379 ZEBRA_NEIGH_SET_INACTIVE(n
);
2381 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2382 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2389 * Process all neighbors associated with a MAC upon the MAC being remotely
2392 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2395 zebra_neigh_t
*n
= NULL
;
2396 struct listnode
*node
= NULL
;
2397 char buf
[ETHER_ADDR_STRLEN
];
2399 if (IS_ZEBRA_DEBUG_VXLAN
)
2400 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2401 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2404 /* Walk all local neighbors and mark as inactive and inform
2407 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2408 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2409 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2410 ZEBRA_NEIGH_SET_INACTIVE(n
);
2412 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2413 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2420 * Process all neighbors associated with a remote MAC upon the MAC being
2423 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2426 /* NOTE: Currently a NO-OP. */
2429 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2431 zebra_neigh_t
*nbr
= NULL
;
2432 struct listnode
*node
= NULL
;
2434 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2435 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2436 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2437 zvni_neigh_probe(zvni
, nbr
);
2442 * Inform BGP about local neighbor addition.
2444 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2445 struct ethaddr
*macaddr
,
2446 uint8_t neigh_flags
,
2451 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2452 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2453 /* Set router flag (R-bit) based on local neigh entry add */
2454 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2455 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2457 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2458 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2462 * Inform BGP about local neighbor deletion.
2464 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2465 struct ethaddr
*macaddr
, uint8_t flags
,
2468 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2469 0, state
, ZEBRA_MACIP_DEL
);
2473 * Install remote neighbor into the kernel.
2475 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2477 struct zebra_if
*zif
;
2478 struct zebra_l2info_vxlan
*vxl
;
2479 struct interface
*vlan_if
;
2485 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2488 zif
= zvni
->vxlan_if
->info
;
2491 vxl
= &zif
->l2info
.vxl
;
2493 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2497 flags
= NTF_EXT_LEARNED
;
2498 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2499 flags
|= NTF_ROUTER
;
2500 ZEBRA_NEIGH_SET_ACTIVE(n
);
2501 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2507 * Uninstall remote neighbor from the kernel.
2509 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2511 struct zebra_if
*zif
;
2512 struct zebra_l2info_vxlan
*vxl
;
2513 struct interface
*vlan_if
;
2515 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2518 if (!zvni
->vxlan_if
) {
2519 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2524 zif
= zvni
->vxlan_if
->info
;
2527 vxl
= &zif
->l2info
.vxl
;
2528 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2532 ZEBRA_NEIGH_SET_INACTIVE(n
);
2534 return kernel_del_neigh(vlan_if
, &n
->ip
);
2538 * Probe neighbor from the kernel.
2540 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2542 struct zebra_if
*zif
;
2543 struct zebra_l2info_vxlan
*vxl
;
2544 struct interface
*vlan_if
;
2546 zif
= zvni
->vxlan_if
->info
;
2549 vxl
= &zif
->l2info
.vxl
;
2551 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2556 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2564 * Install neighbor hash entry - called upon access VLAN change.
2566 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2569 struct neigh_walk_ctx
*wctx
= ctxt
;
2571 n
= (zebra_neigh_t
*)bucket
->data
;
2573 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2574 zvni_neigh_install(wctx
->zvni
, n
);
2577 /* Get the VRR interface for SVI if any */
2578 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2580 struct zebra_vrf
*zvrf
= NULL
;
2581 struct interface
*tmp_if
= NULL
;
2582 struct zebra_if
*zif
= NULL
;
2584 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2587 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2592 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2595 if (zif
->link
== ifp
)
2602 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2604 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2605 struct connected
*c
= NULL
;
2606 struct ethaddr macaddr
;
2608 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2610 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2613 memset(&ip
, 0, sizeof(struct ipaddr
));
2614 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2617 if (c
->address
->family
== AF_INET
) {
2618 ip
.ipa_type
= IPADDR_V4
;
2619 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2620 sizeof(struct in_addr
));
2621 } else if (c
->address
->family
== AF_INET6
) {
2622 ip
.ipa_type
= IPADDR_V6
;
2623 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2624 sizeof(struct in6_addr
));
2629 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2635 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2637 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2638 struct connected
*c
= NULL
;
2639 struct ethaddr macaddr
;
2641 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2643 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2646 memset(&ip
, 0, sizeof(struct ipaddr
));
2647 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2650 if (c
->address
->family
== AF_INET
) {
2651 ip
.ipa_type
= IPADDR_V4
;
2652 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2653 sizeof(struct in_addr
));
2654 } else if (c
->address
->family
== AF_INET6
) {
2655 ip
.ipa_type
= IPADDR_V6
;
2656 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2657 sizeof(struct in6_addr
));
2662 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2668 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2671 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2672 struct connected
*c
= NULL
;
2673 struct ethaddr macaddr
;
2675 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2677 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2680 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2682 /* skip link local address */
2683 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2688 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2689 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2691 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2692 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2698 * zvni_gw_macip_add_to_client
2700 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2701 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2703 char buf
[ETHER_ADDR_STRLEN
];
2704 char buf2
[INET6_ADDRSTRLEN
];
2705 zebra_neigh_t
*n
= NULL
;
2706 zebra_mac_t
*mac
= NULL
;
2707 struct zebra_if
*zif
= NULL
;
2708 struct zebra_l2info_vxlan
*vxl
= NULL
;
2710 zif
= zvni
->vxlan_if
->info
;
2714 vxl
= &zif
->l2info
.vxl
;
2716 mac
= zvni_mac_lookup(zvni
, macaddr
);
2718 mac
= zvni_mac_add(zvni
, macaddr
);
2720 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2721 "Failed to add MAC %s intf %s(%u) VID %u",
2722 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2723 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2728 /* Set "local" forwarding info. */
2729 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2730 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2731 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2732 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2733 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2734 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2736 n
= zvni_neigh_lookup(zvni
, ip
);
2738 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2741 EC_ZEBRA_MAC_ADD_FAILED
,
2742 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2743 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2744 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2745 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2750 /* Set "local" forwarding info. */
2751 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2752 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2753 ZEBRA_NEIGH_SET_ACTIVE(n
);
2754 /* Set Router flag (R-bit) */
2755 if (ip
->ipa_type
== IPADDR_V6
)
2756 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2757 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2758 n
->ifindex
= ifp
->ifindex
;
2760 /* Only advertise in BGP if the knob is enabled */
2761 if (!advertise_gw_macip_enabled(zvni
))
2764 if (IS_ZEBRA_DEBUG_VXLAN
)
2766 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2767 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2768 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2769 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2771 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2772 n
->flags
, n
->loc_seq
);
2778 * zvni_gw_macip_del_from_client
2780 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2783 char buf1
[ETHER_ADDR_STRLEN
];
2784 char buf2
[INET6_ADDRSTRLEN
];
2785 zebra_neigh_t
*n
= NULL
;
2786 zebra_mac_t
*mac
= NULL
;
2788 /* If the neigh entry is not present nothing to do*/
2789 n
= zvni_neigh_lookup(zvni
, ip
);
2793 /* mac entry should be present */
2794 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2796 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2797 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2798 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2802 /* If the entry is not local nothing to do*/
2803 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2806 /* only need to delete the entry from bgp if we sent it before */
2807 if (IS_ZEBRA_DEBUG_VXLAN
)
2809 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2810 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2811 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2812 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2814 /* Remove neighbor from BGP. */
2815 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2816 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2818 /* Delete this neighbor entry. */
2819 zvni_neigh_del(zvni
, n
);
2821 /* see if the mac needs to be deleted as well*/
2823 zvni_deref_ip2mac(zvni
, mac
);
2828 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2831 zebra_vni_t
*zvni
= NULL
;
2832 struct zebra_if
*zif
= NULL
;
2833 struct zebra_l2info_vxlan zl2_info
;
2834 struct interface
*vlan_if
= NULL
;
2835 struct interface
*vrr_if
= NULL
;
2836 struct interface
*ifp
;
2838 /* Add primary SVI MAC*/
2839 zvni
= (zebra_vni_t
*)bucket
->data
;
2841 ifp
= zvni
->vxlan_if
;
2846 /* If down or not mapped to a bridge, we're done. */
2847 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2850 zl2_info
= zif
->l2info
.vxl
;
2853 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2857 /* Del primary MAC-IP */
2858 zvni_del_macip_for_intf(vlan_if
, zvni
);
2860 /* Del VRR MAC-IP - if any*/
2861 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2863 zvni_del_macip_for_intf(vrr_if
, zvni
);
2868 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2871 zebra_vni_t
*zvni
= NULL
;
2872 struct zebra_if
*zif
= NULL
;
2873 struct zebra_l2info_vxlan zl2_info
;
2874 struct interface
*vlan_if
= NULL
;
2875 struct interface
*vrr_if
= NULL
;
2876 struct interface
*ifp
= NULL
;
2878 zvni
= (zebra_vni_t
*)bucket
->data
;
2880 ifp
= zvni
->vxlan_if
;
2885 /* If down or not mapped to a bridge, we're done. */
2886 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2888 zl2_info
= zif
->l2info
.vxl
;
2891 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2895 /* Add primary SVI MAC-IP */
2896 zvni_add_macip_for_intf(vlan_if
, zvni
);
2898 if (advertise_gw_macip_enabled(zvni
)) {
2899 /* Add VRR MAC-IP - if any*/
2900 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2902 zvni_add_macip_for_intf(vrr_if
, zvni
);
2908 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2911 zebra_vni_t
*zvni
= NULL
;
2912 struct zebra_if
*zif
= NULL
;
2913 struct zebra_l2info_vxlan zl2_info
;
2914 struct interface
*vlan_if
= NULL
;
2915 struct interface
*ifp
;
2917 /* Add primary SVI MAC*/
2918 zvni
= (zebra_vni_t
*)bucket
->data
;
2922 ifp
= zvni
->vxlan_if
;
2927 /* If down or not mapped to a bridge, we're done. */
2928 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2931 zl2_info
= zif
->l2info
.vxl
;
2933 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2934 zif
->brslave_info
.br_if
);
2938 /* Del primary MAC-IP */
2939 zvni_del_macip_for_intf(vlan_if
, zvni
);
2944 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2945 struct interface
*ifp
,
2947 struct ethaddr
*macaddr
,
2950 char buf
[ETHER_ADDR_STRLEN
];
2951 char buf2
[INET6_ADDRSTRLEN
];
2952 struct zebra_vrf
*zvrf
;
2953 zebra_neigh_t
*n
= NULL
;
2954 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2955 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2956 bool upd_mac_seq
= false;
2957 bool neigh_mac_change
= false;
2958 bool neigh_on_hold
= false;
2959 bool neigh_was_remote
= false;
2960 bool do_dad
= false;
2961 struct in_addr vtep_ip
= {.s_addr
= 0};
2963 /* Check if the MAC exists. */
2964 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2966 /* create a dummy MAC if the MAC is not already present */
2967 if (IS_ZEBRA_DEBUG_VXLAN
)
2969 "AUTO MAC %s created for neigh %s on VNI %u",
2970 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2971 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2973 zmac
= zvni_mac_add(zvni
, macaddr
);
2975 zlog_debug("Failed to add MAC %s VNI %u",
2976 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2981 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
2982 memset(&zmac
->flags
, 0, sizeof(uint32_t));
2983 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
2985 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
2987 * We don't change the MAC to local upon a neighbor
2988 * learn event, we wait for the explicit local MAC
2989 * learn. However, we have to compute its sequence
2990 * number in preparation for when it actually turns
2997 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2999 if (IS_ZEBRA_DEBUG_VXLAN
)
3000 zlog_debug("\tUnable to find vrf for: %d",
3001 zvni
->vxlan_if
->vrf_id
);
3005 /* Check if the neighbor exists. */
3006 n
= zvni_neigh_lookup(zvni
, ip
);
3008 /* New neighbor - create */
3009 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3012 EC_ZEBRA_MAC_ADD_FAILED
,
3013 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3014 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3015 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3016 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3019 /* Set "local" forwarding info. */
3020 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3021 n
->ifindex
= ifp
->ifindex
;
3023 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3027 /* Note any changes and see if of interest to BGP. */
3028 mac_different
= (memcmp(n
->emac
.octet
,
3029 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3030 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3031 ZEBRA_NEIGH_ROUTER_FLAG
);
3032 if (!mac_different
&& is_router
== cur_is_router
) {
3033 if (IS_ZEBRA_DEBUG_VXLAN
)
3035 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3036 n
->ifindex
= ifp
->ifindex
;
3040 if (!mac_different
) {
3041 bool is_neigh_freezed
= false;
3043 /* Only the router flag has changed. */
3046 ZEBRA_NEIGH_ROUTER_FLAG
);
3048 UNSET_FLAG(n
->flags
,
3049 ZEBRA_NEIGH_ROUTER_FLAG
);
3051 /* Neigh is in freeze state and freeze action
3052 * is enabled, do not send update to client.
3054 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3056 CHECK_FLAG(n
->flags
,
3057 ZEBRA_NEIGH_DUPLICATE
));
3059 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3061 return zvni_neigh_send_add_to_client(
3062 zvni
->vni
, ip
, macaddr
,
3063 n
->flags
, n
->loc_seq
);
3065 if (IS_ZEBRA_DEBUG_VXLAN
)
3067 "\tNeighbor active and frozen");
3072 /* The MAC has changed, need to issue a delete
3073 * first as this means a different MACIP route.
3074 * Also, need to do some unlinking/relinking.
3075 * We also need to update the MAC's sequence number
3076 * in different situations.
3078 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3079 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3080 &n
->emac
, 0, n
->state
);
3081 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3083 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3085 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3086 neigh_mac_change
= upd_mac_seq
= true;
3087 listnode_delete(old_zmac
->neigh_list
, n
);
3088 zvni_deref_ip2mac(zvni
, old_zmac
);
3091 /* Update the forwarding info. */
3092 n
->ifindex
= ifp
->ifindex
;
3093 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3095 /* Link to new MAC */
3096 listnode_add_sort(zmac
->neigh_list
, n
);
3097 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3099 * Neighbor has moved from remote to local. Its
3100 * MAC could have also changed as part of the move.
3102 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3104 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3106 old_mac_seq
= CHECK_FLAG(
3111 neigh_mac_change
= upd_mac_seq
= true;
3112 listnode_delete(old_zmac
->neigh_list
,
3114 zvni_deref_ip2mac(zvni
, old_zmac
);
3117 /* Link to new MAC */
3118 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3119 listnode_add_sort(zmac
->neigh_list
, n
);
3121 /* Based on Mobility event Scenario-B from the
3122 * draft, neigh's previous state was remote treat this
3125 neigh_was_remote
= true;
3126 vtep_ip
= n
->r_vtep_ip
;
3127 /* Mark appropriately */
3128 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3129 n
->r_vtep_ip
.s_addr
= 0;
3130 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3131 n
->ifindex
= ifp
->ifindex
;
3135 /* If MAC was previously remote, or the neighbor had a different
3136 * MAC earlier, recompute the sequence number.
3139 uint32_t seq1
, seq2
;
3141 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3142 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3143 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3144 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3145 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3148 /* Mark Router flag (R-bit) */
3150 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3152 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3154 /* Check old and/or new MAC detected as duplicate mark
3155 * the neigh as duplicate
3157 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3158 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3159 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3161 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3162 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3165 /* For IP Duplicate Address Detection (DAD) is trigger,
3166 * when the event is extended mobility based on scenario-B
3167 * from the draft, IP/Neigh's MAC binding changed and
3168 * neigh's previous state was remote.
3170 if (neigh_mac_change
&& neigh_was_remote
)
3173 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3174 &neigh_on_hold
, true);
3176 /* Before we program this in BGP, we need to check if MAC is locally
3177 * learnt. If not, force neighbor to be inactive and reset its seq.
3179 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3180 ZEBRA_NEIGH_SET_INACTIVE(n
);
3182 zmac
->loc_seq
= mac_new_seq
;
3186 /* If the MAC's sequence number has changed, inform the MAC and all
3187 * neighbors associated with the MAC to BGP, else just inform this
3190 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3191 if (IS_ZEBRA_DEBUG_VXLAN
)
3192 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3193 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3194 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3195 zmac
->loc_seq
= mac_new_seq
;
3196 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3197 zmac
->flags
, zmac
->loc_seq
))
3199 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3203 n
->loc_seq
= zmac
->loc_seq
;
3205 if (!neigh_on_hold
) {
3206 ZEBRA_NEIGH_SET_ACTIVE(n
);
3208 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3209 n
->flags
, n
->loc_seq
);
3211 if (IS_ZEBRA_DEBUG_VXLAN
)
3212 zlog_debug("\tNeighbor on hold not sending");
3217 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3218 struct interface
*ifp
,
3220 struct ethaddr
*macaddr
,
3223 char buf
[ETHER_ADDR_STRLEN
];
3224 char buf2
[INET6_ADDRSTRLEN
];
3225 zebra_neigh_t
*n
= NULL
;
3226 zebra_mac_t
*zmac
= NULL
;
3228 /* If the neighbor is unknown, there is no further action. */
3229 n
= zvni_neigh_lookup(zvni
, ip
);
3233 /* If a remote entry, see if it needs to be refreshed */
3234 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3236 if (state
& NUD_STALE
)
3237 zvni_neigh_install(zvni
, n
);
3240 /* We got a "remote" neighbor notification for an entry
3241 * we think is local. This can happen in a multihoming
3242 * scenario - but only if the MAC is already "remote".
3243 * Just mark our entry as "remote".
3245 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3246 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3248 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3249 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3250 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3255 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3256 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3257 ZEBRA_NEIGH_SET_ACTIVE(n
);
3258 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3265 * Make hash key for MAC.
3267 static unsigned int mac_hash_keymake(void *p
)
3269 zebra_mac_t
*pmac
= p
;
3270 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3272 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3276 * Compare two MAC addresses.
3278 static bool mac_cmp(const void *p1
, const void *p2
)
3280 const zebra_mac_t
*pmac1
= p1
;
3281 const zebra_mac_t
*pmac2
= p2
;
3283 if (pmac1
== NULL
&& pmac2
== NULL
)
3286 if (pmac1
== NULL
|| pmac2
== NULL
)
3289 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3294 * Callback to allocate MAC hash entry.
3296 static void *zvni_mac_alloc(void *p
)
3298 const zebra_mac_t
*tmp_mac
= p
;
3301 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3304 return ((void *)mac
);
3310 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3312 zebra_mac_t tmp_mac
;
3313 zebra_mac_t
*mac
= NULL
;
3315 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3316 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3317 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3321 mac
->dad_mac_auto_recovery_timer
= NULL
;
3323 mac
->neigh_list
= list_new();
3324 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3332 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3334 zebra_mac_t
*tmp_mac
;
3336 /* Cancel auto recovery */
3337 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3339 list_delete(&mac
->neigh_list
);
3341 /* Free the VNI hash entry and allocated memory. */
3342 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3343 XFREE(MTYPE_MAC
, tmp_mac
);
3349 * Free MAC hash entry (callback)
3351 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3353 struct mac_walk_ctx
*wctx
= arg
;
3354 zebra_mac_t
*mac
= bucket
->data
;
3356 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3357 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3358 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3359 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3360 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3361 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3362 &wctx
->r_vtep_ip
))) {
3363 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3364 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3368 if (wctx
->uninstall
)
3369 zvni_mac_uninstall(wctx
->zvni
, mac
);
3371 zvni_mac_del(wctx
->zvni
, mac
);
3378 * Delete all MAC entries from specific VTEP for a particular VNI.
3380 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3381 struct in_addr
*r_vtep_ip
)
3383 struct mac_walk_ctx wctx
;
3385 if (!zvni
->mac_table
)
3388 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3390 wctx
.uninstall
= uninstall
;
3391 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3392 wctx
.r_vtep_ip
= *r_vtep_ip
;
3394 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3398 * Delete all MAC entries for this VNI.
3400 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3403 struct mac_walk_ctx wctx
;
3405 if (!zvni
->mac_table
)
3408 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3410 wctx
.uninstall
= uninstall
;
3411 wctx
.upd_client
= upd_client
;
3414 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3418 * Look up MAC hash entry.
3420 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3425 memset(&tmp
, 0, sizeof(tmp
));
3426 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3427 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3433 * Inform BGP about local MAC addition.
3435 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3436 uint8_t mac_flags
, uint32_t seq
)
3440 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3441 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3442 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3443 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3445 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3446 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3450 * Inform BGP about local MAC deletion.
3452 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3454 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3455 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3459 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3460 * notifications, to see if they are of interest.
3462 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3463 struct interface
*br_if
, vlanid_t vid
)
3465 struct zebra_ns
*zns
;
3466 struct route_node
*rn
;
3467 struct interface
*tmp_if
= NULL
;
3468 struct zebra_if
*zif
;
3469 struct zebra_l2info_bridge
*br
;
3470 struct zebra_l2info_vxlan
*vxl
= NULL
;
3471 uint8_t bridge_vlan_aware
;
3475 /* Determine if bridge is VLAN-aware or not */
3478 br
= &zif
->l2info
.br
;
3479 bridge_vlan_aware
= br
->vlan_aware
;
3481 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3482 /* TODO: Optimize with a hash. */
3483 zns
= zebra_ns_lookup(NS_DEFAULT
);
3484 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3485 tmp_if
= (struct interface
*)rn
->info
;
3489 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3491 if (!if_is_operative(tmp_if
))
3493 vxl
= &zif
->l2info
.vxl
;
3495 if (zif
->brslave_info
.br_if
!= br_if
)
3498 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3507 zvni
= zvni_lookup(vxl
->vni
);
3512 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3513 * neighbor notifications, to see if they are of interest.
3515 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3516 struct interface
*br_if
)
3518 struct zebra_ns
*zns
;
3519 struct route_node
*rn
;
3520 struct interface
*tmp_if
= NULL
;
3521 struct zebra_if
*zif
;
3522 struct zebra_l2info_bridge
*br
;
3523 struct zebra_l2info_vxlan
*vxl
= NULL
;
3524 uint8_t bridge_vlan_aware
;
3532 /* Make sure the linked interface is a bridge. */
3533 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3536 /* Determine if bridge is VLAN-aware or not */
3539 br
= &zif
->l2info
.br
;
3540 bridge_vlan_aware
= br
->vlan_aware
;
3541 if (bridge_vlan_aware
) {
3542 struct zebra_l2info_vlan
*vl
;
3544 if (!IS_ZEBRA_IF_VLAN(ifp
))
3549 vl
= &zif
->l2info
.vl
;
3553 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3554 /* TODO: Optimize with a hash. */
3555 zns
= zebra_ns_lookup(NS_DEFAULT
);
3556 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3557 tmp_if
= (struct interface
*)rn
->info
;
3561 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3563 if (!if_is_operative(tmp_if
))
3565 vxl
= &zif
->l2info
.vxl
;
3567 if (zif
->brslave_info
.br_if
!= br_if
)
3570 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3579 zvni
= zvni_lookup(vxl
->vni
);
3583 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3585 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3586 * linked to the bridge
3587 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3590 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3592 struct zebra_ns
*zns
;
3593 struct route_node
*rn
;
3594 struct interface
*tmp_if
= NULL
;
3595 struct zebra_if
*zif
;
3596 struct zebra_l2info_bridge
*br
;
3597 struct zebra_l2info_vlan
*vl
;
3598 uint8_t bridge_vlan_aware
;
3601 /* Defensive check, caller expected to invoke only with valid bridge. */
3605 /* Determine if bridge is VLAN-aware or not */
3608 br
= &zif
->l2info
.br
;
3609 bridge_vlan_aware
= br
->vlan_aware
;
3611 /* Check oper status of the SVI. */
3612 if (!bridge_vlan_aware
)
3613 return if_is_operative(br_if
) ? br_if
: NULL
;
3615 /* Identify corresponding VLAN interface. */
3616 /* TODO: Optimize with a hash. */
3617 zns
= zebra_ns_lookup(NS_DEFAULT
);
3618 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3619 tmp_if
= (struct interface
*)rn
->info
;
3620 /* Check oper status of the SVI. */
3621 if (!tmp_if
|| !if_is_operative(tmp_if
))
3624 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3625 || zif
->link
!= br_if
)
3627 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3629 if (vl
->vid
== vid
) {
3635 return found
? tmp_if
: NULL
;
3639 * Install remote MAC into the kernel.
3641 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3643 struct zebra_if
*zif
;
3644 struct zebra_l2info_vxlan
*vxl
;
3647 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3650 zif
= zvni
->vxlan_if
->info
;
3653 vxl
= &zif
->l2info
.vxl
;
3655 sticky
= !!CHECK_FLAG(mac
->flags
,
3656 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3658 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3659 mac
->fwd_info
.r_vtep_ip
, sticky
);
3663 * Uninstall remote MAC from the kernel.
3665 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3667 struct zebra_if
*zif
;
3668 struct zebra_l2info_vxlan
*vxl
;
3669 struct in_addr vtep_ip
;
3670 struct interface
*ifp
;
3672 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3675 if (!zvni
->vxlan_if
) {
3676 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3681 zif
= zvni
->vxlan_if
->info
;
3684 vxl
= &zif
->l2info
.vxl
;
3686 ifp
= zvni
->vxlan_if
;
3687 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3689 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3693 * Install MAC hash entry - called upon access VLAN change.
3695 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3698 struct mac_walk_ctx
*wctx
= ctxt
;
3700 mac
= (zebra_mac_t
*)bucket
->data
;
3702 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3703 zvni_mac_install(wctx
->zvni
, mac
);
3707 * Count of remote neighbors referencing this MAC.
3709 static int remote_neigh_count(zebra_mac_t
*zmac
)
3711 zebra_neigh_t
*n
= NULL
;
3712 struct listnode
*node
= NULL
;
3715 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3716 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3724 * Decrement neighbor refcount of MAC; uninstall and free it if
3727 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3729 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3732 /* If all remote neighbors referencing a remote MAC go away,
3733 * we need to uninstall the MAC.
3735 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3736 remote_neigh_count(mac
) == 0) {
3737 zvni_mac_uninstall(zvni
, mac
);
3738 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3741 /* If no neighbors, delete the MAC. */
3742 if (list_isempty(mac
->neigh_list
))
3743 zvni_mac_del(zvni
, mac
);
3747 * Read and populate local MACs and neighbors corresponding to this VNI.
3749 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3751 struct zebra_ns
*zns
;
3752 struct zebra_if
*zif
;
3753 struct interface
*vlan_if
;
3754 struct zebra_l2info_vxlan
*vxl
;
3755 struct interface
*vrr_if
;
3758 vxl
= &zif
->l2info
.vxl
;
3759 zns
= zebra_ns_lookup(NS_DEFAULT
);
3761 if (IS_ZEBRA_DEBUG_VXLAN
)
3763 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3764 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3765 zif
->brslave_info
.bridge_ifindex
);
3767 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3768 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3771 /* Add SVI MAC-IP */
3772 zvni_add_macip_for_intf(vlan_if
, zvni
);
3774 /* Add VRR MAC-IP - if any*/
3775 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3777 zvni_add_macip_for_intf(vrr_if
, zvni
);
3779 neigh_read_for_vlan(zns
, vlan_if
);
3784 * Hash function for VNI.
3786 static unsigned int vni_hash_keymake(void *p
)
3788 const zebra_vni_t
*zvni
= p
;
3790 return (jhash_1word(zvni
->vni
, 0));
3794 * Compare 2 VNI hash entries.
3796 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3798 const zebra_vni_t
*zvni1
= p1
;
3799 const zebra_vni_t
*zvni2
= p2
;
3801 return (zvni1
->vni
== zvni2
->vni
);
3804 static int vni_list_cmp(void *p1
, void *p2
)
3806 const zebra_vni_t
*zvni1
= p1
;
3807 const zebra_vni_t
*zvni2
= p2
;
3809 if (zvni1
->vni
== zvni2
->vni
)
3811 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3815 * Callback to allocate VNI hash entry.
3817 static void *zvni_alloc(void *p
)
3819 const zebra_vni_t
*tmp_vni
= p
;
3822 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3823 zvni
->vni
= tmp_vni
->vni
;
3824 return ((void *)zvni
);
3828 * Look up VNI hash entry.
3830 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3832 struct zebra_vrf
*zvrf
;
3833 zebra_vni_t tmp_vni
;
3834 zebra_vni_t
*zvni
= NULL
;
3836 zvrf
= zebra_vrf_get_evpn();
3838 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3840 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3846 * Add VNI hash entry.
3848 static zebra_vni_t
*zvni_add(vni_t vni
)
3850 struct zebra_vrf
*zvrf
;
3851 zebra_vni_t tmp_zvni
;
3852 zebra_vni_t
*zvni
= NULL
;
3854 zvrf
= zebra_vrf_get_evpn();
3856 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3858 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3861 /* Create hash table for MAC */
3863 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3865 /* Create hash table for neighbors */
3866 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3867 "Zebra VNI Neighbor Table");
3873 * Delete VNI hash entry.
3875 static int zvni_del(zebra_vni_t
*zvni
)
3877 struct zebra_vrf
*zvrf
;
3878 zebra_vni_t
*tmp_zvni
;
3880 zvrf
= zebra_vrf_get_evpn();
3883 zvni
->vxlan_if
= NULL
;
3885 /* Free the neighbor hash table. */
3886 hash_free(zvni
->neigh_table
);
3887 zvni
->neigh_table
= NULL
;
3889 /* Free the MAC hash table. */
3890 hash_free(zvni
->mac_table
);
3891 zvni
->mac_table
= NULL
;
3893 /* Free the VNI hash entry and allocated memory. */
3894 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3895 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3901 * Inform BGP about local VNI addition.
3903 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3905 struct zserv
*client
;
3908 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3909 /* BGP may not be running. */
3913 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3915 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3916 stream_putl(s
, zvni
->vni
);
3917 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3918 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
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_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3925 inet_ntoa(zvni
->local_vtep_ip
),
3926 vrf_id_to_name(zvni
->vrf_id
),
3927 zebra_route_string(client
->proto
));
3929 client
->vniadd_cnt
++;
3930 return zserv_send_message(client
, s
);
3934 * Inform BGP about local VNI deletion.
3936 static int zvni_send_del_to_client(vni_t vni
)
3938 struct zserv
*client
;
3941 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3942 /* BGP may not be running. */
3946 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3949 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3950 stream_putl(s
, vni
);
3952 /* Write packet size. */
3953 stream_putw_at(s
, 0, stream_get_endp(s
));
3955 if (IS_ZEBRA_DEBUG_VXLAN
)
3956 zlog_debug("Send VNI_DEL %u to %s", vni
,
3957 zebra_route_string(client
->proto
));
3959 client
->vnidel_cnt
++;
3960 return zserv_send_message(client
, s
);
3964 * Build the VNI hash table by going over the VxLAN interfaces. This
3965 * is called when EVPN (advertise-all-vni) is enabled.
3967 static void zvni_build_hash_table(void)
3969 struct zebra_ns
*zns
;
3970 struct route_node
*rn
;
3971 struct interface
*ifp
;
3973 /* Walk VxLAN interfaces and create VNI hash. */
3974 zns
= zebra_ns_lookup(NS_DEFAULT
);
3975 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3977 zebra_vni_t
*zvni
= NULL
;
3978 zebra_l3vni_t
*zl3vni
= NULL
;
3979 struct zebra_if
*zif
;
3980 struct zebra_l2info_vxlan
*vxl
;
3982 ifp
= (struct interface
*)rn
->info
;
3986 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3989 vxl
= &zif
->l2info
.vxl
;
3992 /* L3-VNI and L2-VNI are handled seperately */
3993 zl3vni
= zl3vni_lookup(vni
);
3996 if (IS_ZEBRA_DEBUG_VXLAN
)
3998 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3999 ifp
->name
, ifp
->ifindex
, vni
);
4001 /* associate with vxlan_if */
4002 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4003 zl3vni
->vxlan_if
= ifp
;
4006 * we need to associate with SVI.
4007 * we can associate with svi-if only after association
4008 * with vxlan-intf is complete
4010 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4012 if (is_l3vni_oper_up(zl3vni
))
4013 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4016 struct interface
*vlan_if
= NULL
;
4018 if (IS_ZEBRA_DEBUG_VXLAN
)
4020 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4021 ifp
->name
, ifp
->ifindex
, vni
,
4022 inet_ntoa(vxl
->vtep_ip
));
4024 /* VNI hash entry is not expected to exist. */
4025 zvni
= zvni_lookup(vni
);
4028 "VNI hash already present for IF %s(%u) L2-VNI %u",
4029 ifp
->name
, ifp
->ifindex
, vni
);
4033 zvni
= zvni_add(vni
);
4036 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4037 ifp
->name
, ifp
->ifindex
, vni
);
4041 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4042 zvni
->vxlan_if
= ifp
;
4043 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4044 zif
->brslave_info
.br_if
);
4046 zvni
->vrf_id
= vlan_if
->vrf_id
;
4047 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4049 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4053 /* Inform BGP if intf is up and mapped to bridge. */
4054 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4055 zvni_send_add_to_client(zvni
);
4061 * See if remote VTEP matches with prefix.
4063 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4065 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4069 * Locate remote VTEP in VNI hash table.
4071 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4073 zebra_vtep_t
*zvtep
;
4078 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4079 if (zvni_vtep_match(vtep_ip
, zvtep
))
4087 * Add remote VTEP to VNI hash table.
4089 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4091 zebra_vtep_t
*zvtep
;
4093 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4095 zvtep
->vtep_ip
= *vtep_ip
;
4098 zvni
->vteps
->prev
= zvtep
;
4099 zvtep
->next
= zvni
->vteps
;
4100 zvni
->vteps
= zvtep
;
4106 * Remove remote VTEP from VNI hash table.
4108 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4111 zvtep
->next
->prev
= zvtep
->prev
;
4113 zvtep
->prev
->next
= zvtep
->next
;
4115 zvni
->vteps
= zvtep
->next
;
4117 zvtep
->prev
= zvtep
->next
= NULL
;
4118 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4124 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4125 * uninstall from kernel if asked to.
4127 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4129 zebra_vtep_t
*zvtep
, *zvtep_next
;
4134 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4135 zvtep_next
= zvtep
->next
;
4137 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4138 zvni_vtep_del(zvni
, zvtep
);
4145 * Install remote VTEP into the kernel.
4147 static int zvni_vtep_install(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4149 if (is_vxlan_flooding_head_end())
4150 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4155 * Uninstall remote VTEP from the kernel.
4157 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4159 if (!zvni
->vxlan_if
) {
4160 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4165 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4169 * Install or uninstall flood entries in the kernel corresponding to
4170 * remote VTEPs. This is invoked upon change to BUM handling.
4172 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4176 zebra_vtep_t
*zvtep
;
4178 zvni
= (zebra_vni_t
*)bucket
->data
;
4182 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4183 if (is_vxlan_flooding_head_end())
4184 zvni_vtep_install(zvni
, &zvtep
->vtep_ip
);
4186 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4191 * Cleanup VNI/VTEP and update kernel
4193 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4195 zebra_vni_t
*zvni
= NULL
;
4196 zebra_l3vni_t
*zl3vni
= NULL
;
4197 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4199 zvni
= (zebra_vni_t
*)bucket
->data
;
4201 /* remove from l3-vni list */
4203 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4205 listnode_delete(zl3vni
->l2vnis
, zvni
);
4207 /* Free up all neighbors and MACs, if any. */
4208 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4209 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4211 /* Free up all remote VTEPs, if any. */
4212 zvni_vtep_del_all(zvni
, 1);
4214 /* Delete the hash entry. */
4219 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4221 zebra_l3vni_t
*zl3vni
= NULL
;
4223 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4225 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4228 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4229 struct prefix
*host
)
4231 struct host_rb_entry lookup
;
4232 struct host_rb_entry
*hle
;
4234 memset(&lookup
, 0, sizeof(lookup
));
4235 memcpy(&lookup
.p
, host
, sizeof(*host
));
4237 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4241 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4242 memcpy(hle
, &lookup
, sizeof(lookup
));
4244 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4247 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4249 struct host_rb_entry lookup
;
4250 struct host_rb_entry
*hle
;
4252 memset(&lookup
, 0, sizeof(lookup
));
4253 memcpy(&lookup
.p
, host
, sizeof(*host
));
4255 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4257 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4258 XFREE(MTYPE_HOST_PREFIX
, hle
);
4265 * Look up MAC hash entry.
4267 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4268 struct ethaddr
*rmac
)
4273 memset(&tmp
, 0, sizeof(tmp
));
4274 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4275 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4281 * Callback to allocate RMAC hash entry.
4283 static void *zl3vni_rmac_alloc(void *p
)
4285 const zebra_mac_t
*tmp_rmac
= p
;
4288 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4291 return ((void *)zrmac
);
4295 * Add RMAC entry to l3-vni
4297 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4299 zebra_mac_t tmp_rmac
;
4300 zebra_mac_t
*zrmac
= NULL
;
4302 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4303 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4304 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4307 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4309 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4310 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4318 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4320 zebra_mac_t
*tmp_rmac
;
4321 struct host_rb_entry
*hle
;
4323 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4324 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4326 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4327 XFREE(MTYPE_HOST_PREFIX
, hle
);
4330 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4331 XFREE(MTYPE_MAC
, tmp_rmac
);
4337 * Install remote RMAC into the kernel.
4339 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4341 struct zebra_if
*zif
= NULL
;
4342 struct zebra_l2info_vxlan
*vxl
= NULL
;
4344 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4345 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4348 zif
= zl3vni
->vxlan_if
->info
;
4352 vxl
= &zif
->l2info
.vxl
;
4354 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4355 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4359 * Uninstall remote RMAC from the kernel.
4361 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4363 char buf
[ETHER_ADDR_STRLEN
];
4364 struct zebra_if
*zif
= NULL
;
4365 struct zebra_l2info_vxlan
*vxl
= NULL
;
4367 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4368 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4371 if (!zl3vni
->vxlan_if
) {
4373 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4374 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4375 zl3vni
->vni
, zl3vni
);
4379 zif
= zl3vni
->vxlan_if
->info
;
4383 vxl
= &zif
->l2info
.vxl
;
4385 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4386 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4389 /* handle rmac add */
4390 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4391 struct ipaddr
*vtep_ip
,
4392 struct prefix
*host_prefix
)
4394 char buf
[ETHER_ADDR_STRLEN
];
4395 char buf1
[INET6_ADDRSTRLEN
];
4396 zebra_mac_t
*zrmac
= NULL
;
4398 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4401 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4404 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4405 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4407 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4410 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4411 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4413 /* install rmac in kernel */
4414 zl3vni_rmac_install(zl3vni
, zrmac
);
4417 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4423 /* handle rmac delete */
4424 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4425 struct prefix
*host_prefix
)
4427 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4429 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4430 /* uninstall from kernel */
4431 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4433 /* del the rmac entry */
4434 zl3vni_rmac_del(zl3vni
, zrmac
);
4439 * Look up nh hash entry on a l3-vni.
4441 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4446 memset(&tmp
, 0, sizeof(tmp
));
4447 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4448 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4455 * Callback to allocate NH hash entry on L3-VNI.
4457 static void *zl3vni_nh_alloc(void *p
)
4459 const zebra_neigh_t
*tmp_n
= p
;
4462 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4469 * Add neighbor entry.
4471 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4472 struct ethaddr
*mac
)
4474 zebra_neigh_t tmp_n
;
4475 zebra_neigh_t
*n
= NULL
;
4477 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4478 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4479 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4482 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4484 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4485 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4486 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4492 * Delete neighbor entry.
4494 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4496 zebra_neigh_t
*tmp_n
;
4497 struct host_rb_entry
*hle
;
4499 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4500 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4502 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4503 XFREE(MTYPE_HOST_PREFIX
, hle
);
4506 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4507 XFREE(MTYPE_NEIGH
, tmp_n
);
4513 * Install remote nh as neigh into the kernel.
4515 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4522 if (!is_l3vni_oper_up(zl3vni
))
4525 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4526 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4529 flags
= NTF_EXT_LEARNED
;
4530 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4531 flags
|= NTF_ROUTER
;
4532 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4538 * Uninstall remote nh from the kernel.
4540 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4542 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4543 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4546 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4549 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4552 /* add remote vtep as a neigh entry */
4553 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4554 struct ethaddr
*rmac
,
4555 struct prefix
*host_prefix
)
4557 char buf
[ETHER_ADDR_STRLEN
];
4558 char buf1
[INET6_ADDRSTRLEN
];
4559 zebra_neigh_t
*nh
= NULL
;
4561 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4563 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4567 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4568 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4569 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4574 /* install the nh neigh in kernel */
4575 zl3vni_nh_install(zl3vni
, nh
);
4578 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4583 /* handle nh neigh delete */
4584 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4585 struct prefix
*host_prefix
)
4587 rb_delete_host(&nh
->host_rb
, host_prefix
);
4589 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4590 /* uninstall from kernel */
4591 zl3vni_nh_uninstall(zl3vni
, nh
);
4593 /* delete the nh entry */
4594 zl3vni_nh_del(zl3vni
, nh
);
4598 /* handle neigh update from kernel - the only thing of interest is to
4599 * readd stale entries.
4601 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4605 zebra_neigh_t
*n
= NULL
;
4607 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4611 /* all next hop neigh are remote and installed by frr.
4612 * If the kernel has aged this entry, re-install.
4614 if (state
& NUD_STALE
)
4615 zl3vni_nh_install(zl3vni
, n
);
4620 /* handle neigh delete from kernel */
4621 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4623 zebra_neigh_t
*n
= NULL
;
4625 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4629 /* all next hop neigh are remote and installed by frr.
4630 * If we get an age out notification for these neigh entries, we have to
4633 zl3vni_nh_install(zl3vni
, n
);
4639 * Hash function for L3 VNI.
4641 static unsigned int l3vni_hash_keymake(void *p
)
4643 const zebra_l3vni_t
*zl3vni
= p
;
4645 return jhash_1word(zl3vni
->vni
, 0);
4649 * Compare 2 L3 VNI hash entries.
4651 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4653 const zebra_l3vni_t
*zl3vni1
= p1
;
4654 const zebra_l3vni_t
*zl3vni2
= p2
;
4656 return (zl3vni1
->vni
== zl3vni2
->vni
);
4660 * Callback to allocate L3 VNI hash entry.
4662 static void *zl3vni_alloc(void *p
)
4664 zebra_l3vni_t
*zl3vni
= NULL
;
4665 const zebra_l3vni_t
*tmp_l3vni
= p
;
4667 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4668 zl3vni
->vni
= tmp_l3vni
->vni
;
4669 return ((void *)zl3vni
);
4673 * Look up L3 VNI hash entry.
4675 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4677 zebra_l3vni_t tmp_l3vni
;
4678 zebra_l3vni_t
*zl3vni
= NULL
;
4680 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4681 tmp_l3vni
.vni
= vni
;
4682 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4688 * Add L3 VNI hash entry.
4690 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4692 zebra_l3vni_t tmp_zl3vni
;
4693 zebra_l3vni_t
*zl3vni
= NULL
;
4695 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4696 tmp_zl3vni
.vni
= vni
;
4698 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4701 zl3vni
->vrf_id
= vrf_id
;
4702 zl3vni
->svi_if
= NULL
;
4703 zl3vni
->vxlan_if
= NULL
;
4704 zl3vni
->l2vnis
= list_new();
4705 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4707 /* Create hash table for remote RMAC */
4708 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4709 "Zebra L3-VNI RMAC-Table");
4711 /* Create hash table for neighbors */
4712 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4713 "Zebra L3-VNI next-hop table");
4719 * Delete L3 VNI hash entry.
4721 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4723 zebra_l3vni_t
*tmp_zl3vni
;
4725 /* free the list of l2vnis */
4726 list_delete(&zl3vni
->l2vnis
);
4727 zl3vni
->l2vnis
= NULL
;
4729 /* Free the rmac table */
4730 hash_free(zl3vni
->rmac_table
);
4731 zl3vni
->rmac_table
= NULL
;
4733 /* Free the nh table */
4734 hash_free(zl3vni
->nh_table
);
4735 zl3vni
->nh_table
= NULL
;
4737 /* Free the VNI hash entry and allocated memory. */
4738 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4739 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4744 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4746 struct zebra_ns
*zns
= NULL
;
4747 struct route_node
*rn
= NULL
;
4748 struct interface
*ifp
= NULL
;
4750 /* loop through all vxlan-interface */
4751 zns
= zebra_ns_lookup(NS_DEFAULT
);
4752 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4754 struct zebra_if
*zif
= NULL
;
4755 struct zebra_l2info_vxlan
*vxl
= NULL
;
4757 ifp
= (struct interface
*)rn
->info
;
4762 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4765 vxl
= &zif
->l2info
.vxl
;
4766 if (vxl
->vni
== zl3vni
->vni
) {
4767 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4775 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4777 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4778 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4783 if (!zl3vni
->vxlan_if
)
4786 zif
= zl3vni
->vxlan_if
->info
;
4790 vxl
= &zif
->l2info
.vxl
;
4792 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4795 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4797 struct zebra_vrf
*zvrf
= NULL
;
4799 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4803 return zl3vni_lookup(zvrf
->l3vni
);
4807 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4808 * neighbor notifications, to see if they are of interest.
4810 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4811 struct interface
*br_if
)
4815 uint8_t bridge_vlan_aware
= 0;
4816 zebra_l3vni_t
*zl3vni
= NULL
;
4817 struct zebra_ns
*zns
= NULL
;
4818 struct route_node
*rn
= NULL
;
4819 struct zebra_if
*zif
= NULL
;
4820 struct interface
*tmp_if
= NULL
;
4821 struct zebra_l2info_bridge
*br
= NULL
;
4822 struct zebra_l2info_vxlan
*vxl
= NULL
;
4827 /* Make sure the linked interface is a bridge. */
4828 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4831 /* Determine if bridge is VLAN-aware or not */
4834 br
= &zif
->l2info
.br
;
4835 bridge_vlan_aware
= br
->vlan_aware
;
4836 if (bridge_vlan_aware
) {
4837 struct zebra_l2info_vlan
*vl
;
4839 if (!IS_ZEBRA_IF_VLAN(ifp
))
4844 vl
= &zif
->l2info
.vl
;
4848 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4849 /* TODO: Optimize with a hash. */
4850 zns
= zebra_ns_lookup(NS_DEFAULT
);
4851 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4852 tmp_if
= (struct interface
*)rn
->info
;
4856 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4858 if (!if_is_operative(tmp_if
))
4860 vxl
= &zif
->l2info
.vxl
;
4862 if (zif
->brslave_info
.br_if
!= br_if
)
4865 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4874 zl3vni
= zl3vni_lookup(vxl
->vni
);
4879 * Inform BGP about l3-vni.
4881 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4883 struct stream
*s
= NULL
;
4884 struct zserv
*client
= NULL
;
4885 struct ethaddr rmac
;
4886 char buf
[ETHER_ADDR_STRLEN
];
4888 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4889 /* BGP may not be running. */
4894 memset(&rmac
, 0, sizeof(struct ethaddr
));
4895 zl3vni_get_rmac(zl3vni
, &rmac
);
4897 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4899 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4900 stream_putl(s
, zl3vni
->vni
);
4901 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4902 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4903 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4904 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4906 /* Write packet size. */
4907 stream_putw_at(s
, 0, stream_get_endp(s
));
4909 if (IS_ZEBRA_DEBUG_VXLAN
)
4911 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4912 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4913 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4914 inet_ntoa(zl3vni
->local_vtep_ip
),
4915 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4916 ? "prefix-routes-only"
4918 zebra_route_string(client
->proto
));
4920 client
->l3vniadd_cnt
++;
4921 return zserv_send_message(client
, s
);
4925 * Inform BGP about local l3-VNI deletion.
4927 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4929 struct stream
*s
= NULL
;
4930 struct zserv
*client
= NULL
;
4932 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4933 /* BGP may not be running. */
4937 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4939 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4940 stream_putl(s
, zl3vni
->vni
);
4942 /* Write packet size. */
4943 stream_putw_at(s
, 0, stream_get_endp(s
));
4945 if (IS_ZEBRA_DEBUG_VXLAN
)
4946 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4947 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4948 zebra_route_string(client
->proto
));
4950 client
->l3vnidel_cnt
++;
4951 return zserv_send_message(client
, s
);
4954 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
4959 /* send l3vni add to BGP */
4960 zl3vni_send_add_to_client(zl3vni
);
4963 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
4968 /* send l3-vni del to BGP*/
4969 zl3vni_send_del_to_client(zl3vni
);
4972 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
4974 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
4975 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
4977 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
4978 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4982 * handle transition of vni from l2 to l3 and vice versa
4984 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
4987 zebra_vni_t
*zvni
= NULL
;
4989 /* There is a possibility that VNI notification was already received
4990 * from kernel and we programmed it as L2-VNI
4991 * In such a case we need to delete this L2-VNI first, so
4992 * that it can be reprogrammed as L3-VNI in the system. It is also
4993 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4994 * interface is still present in kernel. In this case to keep it
4995 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4998 /* Locate hash entry */
4999 zvni
= zvni_lookup(vni
);
5003 if (IS_ZEBRA_DEBUG_VXLAN
)
5004 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5006 /* Delete VNI from BGP. */
5007 zvni_send_del_to_client(zvni
->vni
);
5009 /* Free up all neighbors and MAC, if any. */
5010 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5011 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5013 /* Free up all remote VTEPs, if any. */
5014 zvni_vtep_del_all(zvni
, 0);
5016 /* Delete the hash entry. */
5017 if (zvni_del(zvni
)) {
5018 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5019 "Failed to del VNI hash %p, VNI %u", zvni
,
5024 /* TODO_MITESH: This needs to be thought through. We don't have
5025 * enough information at this point to reprogram the vni as
5026 * l2-vni. One way is to store the required info in l3-vni and
5027 * used it solely for this purpose
5034 /* delete and uninstall rmac hash entry */
5035 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5037 zebra_mac_t
*zrmac
= NULL
;
5038 zebra_l3vni_t
*zl3vni
= NULL
;
5040 zrmac
= (zebra_mac_t
*)bucket
->data
;
5041 zl3vni
= (zebra_l3vni_t
*)ctx
;
5042 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5043 zl3vni_rmac_del(zl3vni
, zrmac
);
5046 /* delete and uninstall nh hash entry */
5047 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5049 zebra_neigh_t
*n
= NULL
;
5050 zebra_l3vni_t
*zl3vni
= NULL
;
5052 n
= (zebra_neigh_t
*)bucket
->data
;
5053 zl3vni
= (zebra_l3vni_t
*)ctx
;
5054 zl3vni_nh_uninstall(zl3vni
, n
);
5055 zl3vni_nh_del(zl3vni
, n
);
5058 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5061 struct zserv
*client
= NULL
;
5062 struct stream
*s
= NULL
;
5063 char buf
[PREFIX_STRLEN
];
5065 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5066 /* BGP may not be running. */
5070 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5072 zclient_create_header(s
, cmd
, vrf_id
);
5073 stream_put(s
, p
, sizeof(struct prefix
));
5075 /* Write packet size. */
5076 stream_putw_at(s
, 0, stream_get_endp(s
));
5078 if (IS_ZEBRA_DEBUG_VXLAN
)
5079 zlog_debug("Send ip prefix %s %s on vrf %s",
5080 prefix2str(p
, buf
, sizeof(buf
)),
5081 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5082 vrf_id_to_name(vrf_id
));
5084 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5085 client
->prefixadd_cnt
++;
5087 client
->prefixdel_cnt
++;
5089 return zserv_send_message(client
, s
);
5092 /* re-add remote rmac if needed */
5093 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5094 struct ethaddr
*rmac
)
5096 char buf
[ETHER_ADDR_STRLEN
];
5097 zebra_mac_t
*zrmac
= NULL
;
5099 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5103 if (IS_ZEBRA_DEBUG_VXLAN
)
5104 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5105 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5107 zl3vni_rmac_install(zl3vni
, zrmac
);
5111 /* Process a remote MACIP add from BGP. */
5112 static void process_remote_macip_add(vni_t vni
,
5113 struct ethaddr
*macaddr
,
5115 struct ipaddr
*ipaddr
,
5118 struct in_addr vtep_ip
)
5121 zebra_vtep_t
*zvtep
;
5122 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5123 zebra_neigh_t
*n
= NULL
;
5124 int update_mac
= 0, update_neigh
= 0;
5125 char buf
[ETHER_ADDR_STRLEN
];
5126 char buf1
[INET6_ADDRSTRLEN
];
5127 struct interface
*ifp
= NULL
;
5128 struct zebra_if
*zif
= NULL
;
5129 struct zebra_vrf
*zvrf
;
5134 bool do_dad
= false;
5135 bool is_dup_detect
= false;
5137 /* Locate VNI hash entry - expected to exist. */
5138 zvni
= zvni_lookup(vni
);
5140 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5144 ifp
= zvni
->vxlan_if
;
5148 !if_is_operative(ifp
) ||
5150 !zif
->brslave_info
.br_if
) {
5151 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5156 /* The remote VTEP specified should normally exist, but it is
5157 * possible that when peering comes up, peer may advertise MACIP
5158 * routes before advertising type-3 routes.
5160 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5162 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
5164 EC_ZEBRA_VTEP_ADD_FAILED
,
5165 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5170 zvni_vtep_install(zvni
, &vtep_ip
);
5173 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5174 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5175 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5177 mac
= zvni_mac_lookup(zvni
, macaddr
);
5179 /* Ignore if the mac is already present as a gateway mac */
5181 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5182 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5183 if (IS_ZEBRA_DEBUG_VXLAN
)
5184 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5186 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5187 ipa_len
? " IP " : "",
5189 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5193 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5197 /* check if the remote MAC is unknown or has a change.
5198 * If so, that needs to be updated first. Note that client could
5199 * install MAC and MACIP separately or just install the latter.
5202 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5203 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5204 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5205 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5206 || seq
!= mac
->rem_seq
)
5211 mac
= zvni_mac_add(zvni
, macaddr
);
5214 "Failed to add MAC %s VNI %u Remote VTEP %s",
5215 prefix_mac2str(macaddr
, buf
,
5217 vni
, inet_ntoa(vtep_ip
));
5221 /* Is this MAC created for a MACIP? */
5223 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5225 const char *mac_type
;
5227 /* When host moves but changes its (MAC,IP)
5228 * binding, BGP may install a MACIP entry that
5229 * corresponds to "older" location of the host
5230 * in transient situations (because {IP1,M1}
5231 * is a different route from {IP1,M2}). Check
5232 * the sequence number and ignore this update
5235 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5236 tmp_seq
= mac
->loc_seq
;
5239 tmp_seq
= mac
->rem_seq
;
5240 mac_type
= "remote";
5242 if (seq
< tmp_seq
) {
5243 if (IS_ZEBRA_DEBUG_VXLAN
)
5244 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5246 prefix_mac2str(macaddr
,
5248 ipa_len
? " IP " : "",
5251 buf1
, sizeof(buf1
)) : "",
5258 /* Check MAC's curent state is local (this is the case
5259 * where MAC has moved from L->R) and check previous
5260 * detection started via local learning.
5261 * RFC-7432: A PE/VTEP that detects a MAC mobility
5262 * event via local learning starts an M-second timer.
5264 * VTEP-IP or seq. change alone is not considered
5265 * for dup. detection.
5267 * MAC is already marked duplicate set dad, then
5268 * is_dup_detect will be set to not install the entry.
5270 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5272 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5275 /* Remove local MAC from BGP. */
5276 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5277 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5279 /* Set "auto" and "remote" forwarding info. */
5280 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5281 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5282 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5283 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5286 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5288 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5291 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5293 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5295 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5296 mac
->fwd_info
.r_vtep_ip
,
5297 do_dad
, &is_dup_detect
,
5300 if (!is_dup_detect
) {
5301 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5302 /* Install the entry. */
5303 zvni_mac_install(zvni
, mac
);
5307 /* Update seq number. */
5310 /* If there is no IP, return after clearing AUTO flag of MAC. */
5312 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5319 /* Check if the remote neighbor itself is unknown or has a
5320 * change. If so, create or update and then install the entry.
5322 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5324 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5325 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5326 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5327 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5328 || seq
!= n
->rem_seq
)
5333 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5336 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5337 ipaddr2str(ipaddr
, buf1
,
5339 prefix_mac2str(macaddr
, buf
,
5341 vni
, inet_ntoa(vtep_ip
));
5348 /* When host moves but changes its (MAC,IP)
5349 * binding, BGP may install a MACIP entry that
5350 * corresponds to "older" location of the host
5351 * in transient situations (because {IP1,M1}
5352 * is a different route from {IP1,M2}). Check
5353 * the sequence number and ignore this update
5356 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5357 tmp_seq
= n
->loc_seq
;
5360 tmp_seq
= n
->rem_seq
;
5363 if (seq
< tmp_seq
) {
5364 if (IS_ZEBRA_DEBUG_VXLAN
)
5365 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5367 prefix_mac2str(macaddr
,
5370 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5375 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5376 /* MAC change, send a delete for old
5377 * neigh if learnt locally.
5379 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5380 IS_ZEBRA_NEIGH_ACTIVE(n
))
5381 zvni_neigh_send_del_to_client(
5383 &n
->emac
, 0, n
->state
);
5385 /* update neigh list for macs */
5386 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5388 listnode_delete(old_mac
->neigh_list
, n
);
5389 zvni_deref_ip2mac(zvni
, old_mac
);
5391 listnode_add_sort(mac
->neigh_list
, n
);
5392 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5394 /* Check Neigh's curent state is local
5395 * (this is the case where neigh/host has moved
5396 * from L->R) and check previous detction
5397 * started via local learning.
5399 * RFC-7432: A PE/VTEP that detects a MAC
5400 * mobilit event via local learning starts
5401 * an M-second timer.
5402 * VTEP-IP or seq. change along is not
5403 * considered for dup. detection.
5405 * Mobilty event scenario-B IP-MAC binding
5408 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5415 /* Set "remote" forwarding info. */
5416 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5417 n
->r_vtep_ip
= vtep_ip
;
5418 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5420 /* Set router flag (R-bit) to this Neighbor entry */
5421 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5422 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5424 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5426 /* Check old or new MAC detected as duplicate,
5427 * inherit duplicate flag to this neigh.
5429 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5431 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5432 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5434 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5435 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5438 /* Check duplicate address detection for IP */
5439 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5444 /* Install the entry. */
5446 zvni_neigh_install(zvni
, n
);
5449 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5451 /* Update seq number. */
5455 /* Process a remote MACIP delete from BGP. */
5456 static void process_remote_macip_del(vni_t vni
,
5457 struct ethaddr
*macaddr
,
5459 struct ipaddr
*ipaddr
,
5460 struct in_addr vtep_ip
)
5463 zebra_mac_t
*mac
= NULL
;
5464 zebra_neigh_t
*n
= NULL
;
5465 struct interface
*ifp
= NULL
;
5466 struct zebra_if
*zif
= NULL
;
5467 struct zebra_ns
*zns
;
5468 struct zebra_l2info_vxlan
*vxl
;
5469 struct zebra_vrf
*zvrf
;
5470 char buf
[ETHER_ADDR_STRLEN
];
5471 char buf1
[INET6_ADDRSTRLEN
];
5473 /* Locate VNI hash entry - expected to exist. */
5474 zvni
= zvni_lookup(vni
);
5476 if (IS_ZEBRA_DEBUG_VXLAN
)
5477 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5481 ifp
= zvni
->vxlan_if
;
5485 !if_is_operative(ifp
) ||
5487 !zif
->brslave_info
.br_if
) {
5488 if (IS_ZEBRA_DEBUG_VXLAN
)
5489 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5493 zns
= zebra_ns_lookup(NS_DEFAULT
);
5494 vxl
= &zif
->l2info
.vxl
;
5496 /* The remote VTEP specified is normally expected to exist, but
5497 * it is possible that the peer may delete the VTEP before deleting
5498 * any MACs referring to the VTEP, in which case the handler (see
5499 * remote_vtep_del) would have already deleted the MACs.
5501 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5504 mac
= zvni_mac_lookup(zvni
, macaddr
);
5506 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5509 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5510 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5511 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5515 /* If the remote mac or neighbor doesn't exist there is nothing
5516 * more to do. Otherwise, uninstall the entry and then remove it.
5521 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5523 /* Ignore the delete if this mac is a gateway mac-ip */
5524 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5525 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5527 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5529 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5530 ipa_len
? " IP " : "",
5532 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5536 /* Uninstall remote neighbor or MAC. */
5538 if (zvrf
->dad_freeze
&&
5539 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5540 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5541 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5542 struct interface
*vlan_if
;
5544 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5545 zif
->brslave_info
.br_if
);
5546 if (IS_ZEBRA_DEBUG_VXLAN
)
5547 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5548 __PRETTY_FUNCTION__
,
5549 ipaddr2str(ipaddr
, buf1
,
5550 sizeof(buf1
)), n
->flags
,
5552 neigh_read_specific_ip(ipaddr
, vlan_if
);
5555 /* When the MAC changes for an IP, it is possible the
5556 * client may update the new MAC before trying to delete the
5557 * "old" neighbor (as these are two different MACIP routes).
5558 * Do the delete only if the MAC matches.
5560 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5561 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5562 zvni_neigh_uninstall(zvni
, n
);
5563 zvni_neigh_del(zvni
, n
);
5564 zvni_deref_ip2mac(zvni
, mac
);
5567 /* DAD: when MAC is freeze state as remote learn event,
5568 * remote mac-ip delete event is received will result in freeze
5569 * entry removal, first fetch kernel for the same entry present
5570 * as LOCAL and reachable, avoid deleting this entry instead
5571 * use kerenel local entry to update during unfreeze time.
5573 if (zvrf
->dad_freeze
&&
5574 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5575 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5576 if (IS_ZEBRA_DEBUG_VXLAN
)
5577 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5578 __PRETTY_FUNCTION__
,
5579 prefix_mac2str(macaddr
, buf
,
5582 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5583 macaddr
, vxl
->access_vlan
);
5586 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5587 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5589 * the remote sequence number in the auto mac entry
5590 * needs to be reset to 0 as the mac entry may have
5591 * been removed on all VTEPs (including
5592 * the originating one)
5596 /* If all remote neighbors referencing a remote MAC
5597 * go away, we need to uninstall the MAC.
5599 if (remote_neigh_count(mac
) == 0) {
5600 zvni_mac_uninstall(zvni
, mac
);
5601 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5603 if (list_isempty(mac
->neigh_list
))
5604 zvni_mac_del(zvni
, mac
);
5606 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5612 /* Public functions */
5614 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5616 zebra_l3vni_t
*zl3vni
= NULL
;
5618 zl3vni
= zl3vni_lookup(vni
);
5622 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5625 /* handle evpn route in vrf table */
5626 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5627 struct ipaddr
*vtep_ip
,
5628 struct prefix
*host_prefix
)
5630 zebra_l3vni_t
*zl3vni
= NULL
;
5631 struct ipaddr ipv4_vtep
;
5633 zl3vni
= zl3vni_from_vrf(vrf_id
);
5634 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5638 * add the next hop neighbor -
5639 * neigh to be installed is the ipv6 nexthop neigh
5641 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5644 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5645 * address. Rmac is programmed against the ipv4 vtep because we only
5646 * support ipv4 tunnels in the h/w right now
5648 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5649 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5650 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5651 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5652 &(ipv4_vtep
.ipaddr_v4
));
5654 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5655 sizeof(struct in_addr
));
5658 * add the rmac - remote rmac to be installed is against the ipv4
5661 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5664 /* handle evpn vrf route delete */
5665 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5666 struct ipaddr
*vtep_ip
,
5667 struct prefix
*host_prefix
)
5669 zebra_l3vni_t
*zl3vni
= NULL
;
5670 zebra_neigh_t
*nh
= NULL
;
5671 zebra_mac_t
*zrmac
= NULL
;
5673 zl3vni
= zl3vni_from_vrf(vrf_id
);
5677 /* find the next hop entry and rmac entry */
5678 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5681 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5683 /* delete the next hop entry */
5684 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5686 /* delete the rmac entry */
5688 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5692 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5693 struct ethaddr
*rmac
, bool use_json
)
5695 zebra_l3vni_t
*zl3vni
= NULL
;
5696 zebra_mac_t
*zrmac
= NULL
;
5697 json_object
*json
= NULL
;
5699 if (!is_evpn_enabled()) {
5701 vty_out(vty
, "{}\n");
5706 json
= json_object_new_object();
5708 zl3vni
= zl3vni_lookup(l3vni
);
5711 vty_out(vty
, "{}\n");
5713 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5717 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5720 vty_out(vty
, "{}\n");
5723 "%% Requested RMAC doesn't exist in L3-VNI %u",
5728 zl3vni_print_rmac(zrmac
, vty
, json
);
5731 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5732 json
, JSON_C_TO_STRING_PRETTY
));
5733 json_object_free(json
);
5737 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5739 zebra_l3vni_t
*zl3vni
;
5741 struct rmac_walk_ctx wctx
;
5742 json_object
*json
= NULL
;
5744 if (!is_evpn_enabled())
5747 zl3vni
= zl3vni_lookup(l3vni
);
5750 vty_out(vty
, "{}\n");
5752 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5755 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5760 json
= json_object_new_object();
5762 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5766 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5768 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5770 json_object_int_add(json
, "numRmacs", num_rmacs
);
5772 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5775 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5776 json
, JSON_C_TO_STRING_PRETTY
));
5777 json_object_free(json
);
5781 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5783 json_object
*json
= NULL
;
5786 if (!is_evpn_enabled()) {
5788 vty_out(vty
, "{}\n");
5793 json
= json_object_new_object();
5797 hash_iterate(zrouter
.l3vni_table
,
5798 (void (*)(struct hash_bucket
*,
5799 void *))zl3vni_print_rmac_hash_all_vni
,
5803 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5804 json
, JSON_C_TO_STRING_PRETTY
));
5805 json_object_free(json
);
5809 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5810 struct ipaddr
*ip
, bool use_json
)
5812 zebra_l3vni_t
*zl3vni
= NULL
;
5813 zebra_neigh_t
*n
= NULL
;
5814 json_object
*json
= NULL
;
5816 if (!is_evpn_enabled()) {
5818 vty_out(vty
, "{}\n");
5823 json
= json_object_new_object();
5825 zl3vni
= zl3vni_lookup(l3vni
);
5828 vty_out(vty
, "{}\n");
5830 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5834 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5837 vty_out(vty
, "{}\n");
5840 "%% Requested next-hop not present for L3-VNI %u",
5845 zl3vni_print_nh(n
, vty
, json
);
5848 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5849 json
, JSON_C_TO_STRING_PRETTY
));
5850 json_object_free(json
);
5854 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5857 struct nh_walk_ctx wctx
;
5858 json_object
*json
= NULL
;
5859 zebra_l3vni_t
*zl3vni
= NULL
;
5861 if (!is_evpn_enabled())
5864 zl3vni
= zl3vni_lookup(l3vni
);
5867 vty_out(vty
, "{}\n");
5869 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5873 num_nh
= hashcount(zl3vni
->nh_table
);
5878 json
= json_object_new_object();
5883 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5885 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5887 json_object_int_add(json
, "numNextHops", num_nh
);
5889 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5892 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5893 json
, JSON_C_TO_STRING_PRETTY
));
5894 json_object_free(json
);
5898 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5900 json_object
*json
= NULL
;
5903 if (!is_evpn_enabled()) {
5905 vty_out(vty
, "{}\n");
5910 json
= json_object_new_object();
5914 hash_iterate(zrouter
.l3vni_table
,
5915 (void (*)(struct hash_bucket
*,
5916 void *))zl3vni_print_nh_hash_all_vni
,
5920 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5921 json
, JSON_C_TO_STRING_PRETTY
));
5922 json_object_free(json
);
5927 * Display L3 VNI information (VTY command handler).
5929 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5932 json_object
*json
= NULL
;
5933 zebra_l3vni_t
*zl3vni
= NULL
;
5935 if (!is_evpn_enabled()) {
5937 vty_out(vty
, "{}\n");
5941 zl3vni
= zl3vni_lookup(vni
);
5944 vty_out(vty
, "{}\n");
5946 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
5951 json
= json_object_new_object();
5955 zl3vni_print(zl3vni
, (void *)args
);
5958 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5959 json
, JSON_C_TO_STRING_PRETTY
));
5960 json_object_free(json
);
5964 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
5965 json_object
*json_vrfs
)
5967 char buf
[ETHER_ADDR_STRLEN
];
5968 zebra_l3vni_t
*zl3vni
= NULL
;
5970 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
5975 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5976 zvrf_name(zvrf
), zl3vni
->vni
,
5977 zl3vni_vxlan_if_name(zl3vni
),
5978 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
5979 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5981 json_object
*json_vrf
= NULL
;
5983 json_vrf
= json_object_new_object();
5984 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
5985 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
5986 json_object_string_add(json_vrf
, "vxlanIntf",
5987 zl3vni_vxlan_if_name(zl3vni
));
5988 json_object_string_add(json_vrf
, "sviIntf",
5989 zl3vni_svi_if_name(zl3vni
));
5990 json_object_string_add(json_vrf
, "state",
5991 zl3vni_state2str(zl3vni
));
5992 json_object_string_add(
5993 json_vrf
, "routerMac",
5994 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
5995 json_object_array_add(json_vrfs
, json_vrf
);
6000 * Display Neighbors for a VNI (VTY command handler).
6002 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6003 vni_t vni
, bool use_json
)
6007 struct neigh_walk_ctx wctx
;
6008 json_object
*json
= NULL
;
6010 if (!is_evpn_enabled())
6012 zvni
= zvni_lookup(vni
);
6015 vty_out(vty
, "{}\n");
6017 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6020 num_neigh
= hashcount(zvni
->neigh_table
);
6025 json
= json_object_new_object();
6027 /* Since we have IPv6 addresses to deal with which can vary widely in
6028 * size, we try to be a bit more elegant in display by first computing
6029 * the maximum width.
6031 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6034 wctx
.addr_width
= 15;
6036 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6040 "Number of ARPs (local and remote) known for this VNI: %u\n",
6042 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6043 -wctx
.addr_width
, "IP", "Type",
6044 "State", "MAC", "Remote VTEP");
6046 json_object_int_add(json
, "numArpNd", num_neigh
);
6048 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6050 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6051 json
, JSON_C_TO_STRING_PRETTY
));
6052 json_object_free(json
);
6057 * Display neighbors across all VNIs (VTY command handler).
6059 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6060 bool print_dup
, bool use_json
)
6062 json_object
*json
= NULL
;
6065 if (!is_evpn_enabled())
6069 json
= json_object_new_object();
6073 args
[2] = (void *)(ptrdiff_t)print_dup
;
6075 hash_iterate(zvrf
->vni_table
,
6076 (void (*)(struct hash_bucket
*,
6077 void *))zvni_print_neigh_hash_all_vni
,
6080 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6081 json
, JSON_C_TO_STRING_PRETTY
));
6082 json_object_free(json
);
6087 * Display neighbors across all VNIs in detail(VTY command handler).
6089 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6090 struct zebra_vrf
*zvrf
,
6091 bool print_dup
, bool use_json
)
6093 json_object
*json
= NULL
;
6096 if (!is_evpn_enabled())
6100 json
= json_object_new_object();
6104 args
[2] = (void *)(ptrdiff_t)print_dup
;
6106 hash_iterate(zvrf
->vni_table
,
6107 (void (*)(struct hash_bucket
*,
6108 void *))zvni_print_neigh_hash_all_vni_detail
,
6111 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6112 json
, JSON_C_TO_STRING_PRETTY
));
6113 json_object_free(json
);
6118 * Display specific neighbor for a VNI, if present (VTY command handler).
6120 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6121 struct zebra_vrf
*zvrf
, vni_t vni
,
6122 struct ipaddr
*ip
, bool use_json
)
6126 json_object
*json
= NULL
;
6128 if (!is_evpn_enabled())
6130 zvni
= zvni_lookup(vni
);
6133 vty_out(vty
, "{}\n");
6135 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6138 n
= zvni_neigh_lookup(zvni
, ip
);
6142 "%% Requested neighbor does not exist in VNI %u\n",
6147 json
= json_object_new_object();
6149 zvni_print_neigh(n
, vty
, json
);
6152 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6153 json
, JSON_C_TO_STRING_PRETTY
));
6154 json_object_free(json
);
6159 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6160 * By definition, these are remote neighbors.
6162 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6163 vni_t vni
, struct in_addr vtep_ip
,
6168 struct neigh_walk_ctx wctx
;
6169 json_object
*json
= NULL
;
6171 if (!is_evpn_enabled())
6173 zvni
= zvni_lookup(vni
);
6176 vty_out(vty
, "{}\n");
6178 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6181 num_neigh
= hashcount(zvni
->neigh_table
);
6185 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6188 wctx
.addr_width
= 15;
6189 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6190 wctx
.r_vtep_ip
= vtep_ip
;
6192 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6193 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6196 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6197 json
, JSON_C_TO_STRING_PRETTY
));
6198 json_object_free(json
);
6203 * Display Duplicate detected Neighbors for a VNI
6204 * (VTY command handler).
6206 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6207 struct zebra_vrf
*zvrf
,
6213 struct neigh_walk_ctx wctx
;
6214 json_object
*json
= NULL
;
6216 if (!is_evpn_enabled())
6219 zvni
= zvni_lookup(vni
);
6221 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6225 num_neigh
= hashcount(zvni
->neigh_table
);
6229 num_neigh
= num_dup_detected_neighs(zvni
);
6234 json
= json_object_new_object();
6236 /* Since we have IPv6 addresses to deal with which can vary widely in
6237 * size, we try to be a bit more elegant in display by first computing
6238 * the maximum width.
6240 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6243 wctx
.addr_width
= 15;
6245 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6249 "Number of ARPs (local and remote) known for this VNI: %u\n",
6251 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6252 -wctx
.addr_width
, "IP", "Type",
6253 "State", "MAC", "Remote VTEP");
6255 json_object_int_add(json
, "numArpNd", num_neigh
);
6257 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6260 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6261 json
, JSON_C_TO_STRING_PRETTY
));
6262 json_object_free(json
);
6267 * Display MACs for a VNI (VTY command handler).
6269 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6270 vni_t vni
, bool use_json
)
6274 struct mac_walk_ctx wctx
;
6275 json_object
*json
= NULL
;
6276 json_object
*json_mac
= NULL
;
6278 if (!is_evpn_enabled())
6280 zvni
= zvni_lookup(vni
);
6283 vty_out(vty
, "{}\n");
6285 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6288 num_macs
= num_valid_macs(zvni
);
6293 json
= json_object_new_object();
6294 json_mac
= json_object_new_object();
6297 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6300 wctx
.json
= json_mac
;
6304 "Number of MACs (local and remote) known for this VNI: %u\n",
6306 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6307 "Intf/Remote VTEP", "VLAN");
6309 json_object_int_add(json
, "numMacs", num_macs
);
6311 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6314 json_object_object_add(json
, "macs", json_mac
);
6315 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6316 json
, JSON_C_TO_STRING_PRETTY
));
6317 json_object_free(json
);
6322 * Display MACs for all VNIs (VTY command handler).
6324 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6325 bool print_dup
, bool use_json
)
6327 struct mac_walk_ctx wctx
;
6328 json_object
*json
= NULL
;
6330 if (!is_evpn_enabled()) {
6332 vty_out(vty
, "{}\n");
6336 json
= json_object_new_object();
6338 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6341 wctx
.print_dup
= print_dup
;
6342 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
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 in detail for all VNIs (VTY command handler).
6354 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6355 struct zebra_vrf
*zvrf
,
6356 bool print_dup
, bool use_json
)
6358 struct mac_walk_ctx wctx
;
6359 json_object
*json
= NULL
;
6361 if (!is_evpn_enabled()) {
6363 vty_out(vty
, "{}\n");
6367 json
= json_object_new_object();
6369 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6372 wctx
.print_dup
= print_dup
;
6373 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6377 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6378 json
, JSON_C_TO_STRING_PRETTY
));
6379 json_object_free(json
);
6384 * Display MACs for all VNIs (VTY command handler).
6386 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6387 struct zebra_vrf
*zvrf
,
6388 struct in_addr vtep_ip
, bool use_json
)
6390 struct mac_walk_ctx wctx
;
6391 json_object
*json
= NULL
;
6393 if (!is_evpn_enabled())
6397 json
= json_object_new_object();
6399 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6401 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6402 wctx
.r_vtep_ip
= vtep_ip
;
6404 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6407 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6408 json
, JSON_C_TO_STRING_PRETTY
));
6409 json_object_free(json
);
6414 * Display specific MAC for a VNI, if present (VTY command handler).
6416 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6417 vni_t vni
, struct ethaddr
*macaddr
,
6422 json_object
*json
= NULL
;
6424 if (!is_evpn_enabled())
6427 zvni
= zvni_lookup(vni
);
6430 vty_out(vty
, "{}\n");
6432 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6435 mac
= zvni_mac_lookup(zvni
, macaddr
);
6438 vty_out(vty
, "{}\n");
6441 "%% Requested MAC does not exist in VNI %u\n",
6447 json
= json_object_new_object();
6449 zvni_print_mac(mac
, vty
, json
);
6451 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6452 json
, JSON_C_TO_STRING_PRETTY
));
6453 json_object_free(json
);
6457 /* Print Duplicate MACs per VNI */
6458 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6459 struct zebra_vrf
*zvrf
,
6460 vni_t vni
, bool use_json
)
6463 struct mac_walk_ctx wctx
;
6465 json_object
*json
= NULL
;
6466 json_object
*json_mac
= NULL
;
6468 if (!is_evpn_enabled())
6471 zvni
= zvni_lookup(vni
);
6473 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6477 num_macs
= num_valid_macs(zvni
);
6481 num_macs
= num_dup_detected_macs(zvni
);
6486 json
= json_object_new_object();
6487 json_mac
= json_object_new_object();
6490 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6493 wctx
.json
= json_mac
;
6497 "Number of MACs (local and remote) known for this VNI: %u\n",
6499 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6500 "Intf/Remote VTEP", "VLAN");
6502 json_object_int_add(json
, "numMacs", num_macs
);
6504 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6507 json_object_object_add(json
, "macs", json_mac
);
6508 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6509 json
, JSON_C_TO_STRING_PRETTY
));
6510 json_object_free(json
);
6515 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6516 struct zebra_vrf
*zvrf
,
6517 vni_t vni
, struct ethaddr
*macaddr
)
6521 struct listnode
*node
= NULL
;
6522 zebra_neigh_t
*nbr
= NULL
;
6524 if (!is_evpn_enabled())
6527 zvni
= zvni_lookup(vni
);
6529 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6533 mac
= zvni_mac_lookup(zvni
, macaddr
);
6535 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6540 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6541 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6545 /* Remove all IPs as duplicate associcated with this MAC */
6546 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6547 /* For local neigh mark inactive so MACIP update is generated
6548 * to BGP. This is a scenario where MAC update received
6549 * and detected as duplicate which marked neigh as duplicate.
6550 * Later local neigh update did not get a chance to relay
6551 * to BGP. Similarly remote macip update, neigh needs to be
6552 * installed locally.
6554 if (zvrf
->dad_freeze
&&
6555 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6556 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6557 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6558 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6559 zvni_neigh_install(zvni
, nbr
);
6562 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6564 nbr
->detect_start_time
.tv_sec
= 0;
6565 nbr
->dad_dup_detect_time
= 0;
6568 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6570 mac
->detect_start_time
.tv_sec
= 0;
6571 mac
->detect_start_time
.tv_usec
= 0;
6572 mac
->dad_dup_detect_time
= 0;
6573 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6575 /* warn-only action return */
6576 if (!zvrf
->dad_freeze
)
6579 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6580 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6582 if (zvni_mac_send_add_to_client(zvni
->vni
,
6588 /* Process all neighbors associated with this MAC. */
6589 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6591 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6592 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6594 /* Install the entry. */
6595 zvni_mac_install(zvni
, mac
);
6601 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6602 struct zebra_vrf
*zvrf
,
6603 vni_t vni
, struct ipaddr
*ip
)
6608 char buf
[INET6_ADDRSTRLEN
];
6609 char buf2
[ETHER_ADDR_STRLEN
];
6611 if (!is_evpn_enabled())
6614 zvni
= zvni_lookup(vni
);
6616 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6620 nbr
= zvni_neigh_lookup(zvni
, ip
);
6623 "%% Requested host IP does not exist in VNI %u\n",
6628 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6630 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6632 "%% Requsted host IP %s is not duplicate detected\n",
6637 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6639 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6641 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6642 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6643 return CMD_WARNING_CONFIG_FAILED
;
6646 if (IS_ZEBRA_DEBUG_VXLAN
)
6647 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6648 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6651 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6653 nbr
->detect_start_time
.tv_sec
= 0;
6654 nbr
->detect_start_time
.tv_usec
= 0;
6655 nbr
->dad_dup_detect_time
= 0;
6656 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6658 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6659 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6661 nbr
->flags
, nbr
->loc_seq
);
6662 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6663 zvni_neigh_install(zvni
, nbr
);
6669 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6671 struct mac_walk_ctx
*wctx
= ctxt
;
6674 struct listnode
*node
= NULL
;
6675 zebra_neigh_t
*nbr
= NULL
;
6677 mac
= (zebra_mac_t
*)bucket
->data
;
6683 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6686 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6688 mac
->detect_start_time
.tv_sec
= 0;
6689 mac
->detect_start_time
.tv_usec
= 0;
6690 mac
->dad_dup_detect_time
= 0;
6691 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6693 /* Remove all IPs as duplicate associcated with this MAC */
6694 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6695 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6697 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6699 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6701 nbr
->detect_start_time
.tv_sec
= 0;
6702 nbr
->dad_dup_detect_time
= 0;
6705 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6706 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6708 if (zvni_mac_send_add_to_client(zvni
->vni
,
6710 mac
->flags
, mac
->loc_seq
))
6713 /* Process all neighbors associated with this MAC. */
6714 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6716 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6717 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6719 /* Install the entry. */
6720 zvni_mac_install(zvni
, mac
);
6724 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6726 struct neigh_walk_ctx
*wctx
= ctxt
;
6729 char buf
[INET6_ADDRSTRLEN
];
6731 nbr
= (zebra_neigh_t
*)bucket
->data
;
6737 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6740 if (IS_ZEBRA_DEBUG_VXLAN
) {
6741 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6743 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6744 __PRETTY_FUNCTION__
, buf
,
6745 nbr
->flags
, nbr
->loc_seq
);
6748 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6750 nbr
->detect_start_time
.tv_sec
= 0;
6751 nbr
->detect_start_time
.tv_usec
= 0;
6752 nbr
->dad_dup_detect_time
= 0;
6753 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6755 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6756 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6758 nbr
->flags
, nbr
->loc_seq
);
6759 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6760 zvni_neigh_install(zvni
, nbr
);
6764 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6769 struct zebra_vrf
*zvrf
;
6770 struct mac_walk_ctx m_wctx
;
6771 struct neigh_walk_ctx n_wctx
;
6773 zvni
= (zebra_vni_t
*)bucket
->data
;
6777 vty
= (struct vty
*)args
[0];
6778 zvrf
= (struct zebra_vrf
*)args
[1];
6780 if (hashcount(zvni
->neigh_table
)) {
6781 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6785 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6789 if (num_valid_macs(zvni
)) {
6790 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6794 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6799 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6800 struct zebra_vrf
*zvrf
)
6804 if (!is_evpn_enabled())
6810 hash_iterate(zvrf
->vni_table
,
6811 (void (*)(struct hash_bucket
*, void *))
6812 zvni_clear_dup_detect_hash_vni_all
, args
);
6817 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6818 struct zebra_vrf
*zvrf
,
6822 struct mac_walk_ctx m_wctx
;
6823 struct neigh_walk_ctx n_wctx
;
6825 if (!is_evpn_enabled())
6828 zvni
= zvni_lookup(vni
);
6830 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6834 if (hashcount(zvni
->neigh_table
)) {
6835 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6839 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6843 if (num_valid_macs(zvni
)) {
6844 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6848 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6855 * Display MACs for a VNI from specific VTEP (VTY command handler).
6857 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6858 vni_t vni
, struct in_addr vtep_ip
,
6863 struct mac_walk_ctx wctx
;
6864 json_object
*json
= NULL
;
6865 json_object
*json_mac
= NULL
;
6867 if (!is_evpn_enabled())
6869 zvni
= zvni_lookup(vni
);
6872 vty_out(vty
, "{}\n");
6874 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6877 num_macs
= num_valid_macs(zvni
);
6882 json
= json_object_new_object();
6883 json_mac
= json_object_new_object();
6886 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6889 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6890 wctx
.r_vtep_ip
= vtep_ip
;
6891 wctx
.json
= json_mac
;
6892 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6895 json_object_int_add(json
, "numMacs", wctx
.count
);
6897 json_object_object_add(json
, "macs", json_mac
);
6898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6899 json
, JSON_C_TO_STRING_PRETTY
));
6900 json_object_free(json
);
6906 * Display VNI information (VTY command handler).
6908 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6911 json_object
*json
= NULL
;
6913 zebra_l3vni_t
*zl3vni
= NULL
;
6914 zebra_vni_t
*zvni
= NULL
;
6916 if (!is_evpn_enabled())
6920 json
= json_object_new_object();
6924 zl3vni
= zl3vni_lookup(vni
);
6926 zl3vni_print(zl3vni
, (void *)args
);
6928 zvni
= zvni_lookup(vni
);
6931 vty_out(vty
, "{}\n");
6933 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6937 zvni_print(zvni
, (void *)args
);
6941 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6942 json
, JSON_C_TO_STRING_PRETTY
));
6943 json_object_free(json
);
6947 /* Display all global details for EVPN */
6948 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
6953 json_object
*json
= NULL
;
6954 struct zebra_vrf
*zvrf
= NULL
;
6956 if (!is_evpn_enabled())
6959 zvrf
= zebra_vrf_get_evpn();
6963 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
6964 num_l2vnis
= hashcount(zvrf
->vni_table
);
6965 num_vnis
= num_l2vnis
+ num_l3vnis
;
6968 json
= json_object_new_object();
6969 json_object_string_add(json
, "advertiseGatewayMacip",
6970 zvrf
->advertise_gw_macip
? "Yes" : "No");
6971 json_object_int_add(json
, "numVnis", num_vnis
);
6972 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
6973 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
6974 if (zvrf
->dup_addr_detect
)
6975 json_object_boolean_true_add(json
,
6976 "isDuplicateAddrDetection");
6978 json_object_boolean_false_add(json
,
6979 "isDuplicateAddrDetection");
6980 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
6981 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
6982 json_object_int_add(json
, "detectionFreezeTime",
6983 zvrf
->dad_freeze_time
);
6986 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
6987 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
6988 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
6989 zvrf
->advertise_gw_macip
? "Yes" : "No");
6990 vty_out(vty
, "Advertise svi mac-ip: %s\n",
6991 zvrf
->advertise_svi_macip
? "Yes" : "No");
6992 vty_out(vty
, "Duplicate address detection: %s\n",
6993 zvrf
->dup_addr_detect
? "Enable" : "Disable");
6994 vty_out(vty
, " Detection max-moves %u, time %d\n",
6995 zvrf
->dad_max_moves
, zvrf
->dad_time
);
6996 if (zvrf
->dad_freeze
) {
6997 if (zvrf
->dad_freeze_time
)
6998 vty_out(vty
, " Detection freeze %u\n",
6999 zvrf
->dad_freeze_time
);
7001 vty_out(vty
, " Detection freeze %s\n",
7007 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7008 json
, JSON_C_TO_STRING_PRETTY
));
7009 json_object_free(json
);
7014 * Display VNI hash table (VTY command handler).
7016 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7019 json_object
*json
= NULL
;
7022 if (!is_evpn_enabled())
7026 json
= json_object_new_object();
7028 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7029 "Type", "VxLAN IF", "# MACs", "# ARPs",
7030 "# Remote VTEPs", "Tenant VRF");
7035 /* Display all L2-VNIs */
7036 hash_iterate(zvrf
->vni_table
,
7037 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7040 /* Display all L3-VNIs */
7041 hash_iterate(zrouter
.l3vni_table
,
7042 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7046 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7047 json
, JSON_C_TO_STRING_PRETTY
));
7048 json_object_free(json
);
7052 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7056 uint32_t max_moves
= 0;
7057 uint32_t freeze_time
= 0;
7058 bool dup_addr_detect
= false;
7059 bool freeze
= false;
7062 STREAM_GETL(s
, dup_addr_detect
);
7063 STREAM_GETL(s
, time
);
7064 STREAM_GETL(s
, max_moves
);
7065 STREAM_GETL(s
, freeze
);
7066 STREAM_GETL(s
, freeze_time
);
7068 /* DAD previous state was enabled, and new state is disable,
7069 * clear all duplicate detected addresses.
7071 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7072 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7074 zvrf
->dup_addr_detect
= dup_addr_detect
;
7075 zvrf
->dad_time
= time
;
7076 zvrf
->dad_max_moves
= max_moves
;
7077 zvrf
->dad_freeze
= freeze
;
7078 zvrf
->dad_freeze_time
= freeze_time
;
7080 if (IS_ZEBRA_DEBUG_VXLAN
)
7082 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7083 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7084 zvrf
->dup_addr_detect
? "enable" : "disable",
7085 zvrf
->dad_max_moves
,
7087 zvrf
->dad_freeze
? "enable" : "disable",
7088 zvrf
->dad_freeze_time
);
7095 * Display VNI hash table in detail(VTY command handler).
7097 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7100 json_object
*json
= NULL
;
7101 struct zebra_ns
*zns
= NULL
;
7102 struct zvni_evpn_show zes
;
7104 if (!is_evpn_enabled())
7107 zns
= zebra_ns_lookup(NS_DEFAULT
);
7113 json
= json_object_new_object();
7119 /* Display all L2-VNIs */
7122 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7125 /* Display all L3-VNIs */
7126 hash_iterate(zrouter
.l3vni_table
,
7127 (void (*)(struct hash_bucket
*,
7128 void *))zl3vni_print_hash_detail
,
7132 vty_out(vty
, "%s\n",
7133 json_object_to_json_string_ext(
7134 json
, JSON_C_TO_STRING_PRETTY
));
7135 json_object_free(json
);
7140 * Handle neighbor delete notification from the kernel (on a VLAN device
7141 * / L3 interface). This may result in either the neighbor getting deleted
7142 * from our database or being re-added to the kernel (if it is a valid
7145 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7146 struct interface
*link_if
,
7149 char buf
[INET6_ADDRSTRLEN
];
7150 char buf2
[ETHER_ADDR_STRLEN
];
7151 zebra_neigh_t
*n
= NULL
;
7152 zebra_vni_t
*zvni
= NULL
;
7153 zebra_mac_t
*zmac
= NULL
;
7154 zebra_l3vni_t
*zl3vni
= NULL
;
7155 struct zebra_vrf
*zvrf
;
7157 /* check if this is a remote neigh entry corresponding to remote
7160 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7162 return zl3vni_local_nh_del(zl3vni
, ip
);
7164 /* We are only interested in neighbors on an SVI that resides on top
7165 * of a VxLAN bridge.
7167 zvni
= zvni_from_svi(ifp
, link_if
);
7171 if (!zvni
->vxlan_if
) {
7173 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7178 if (IS_ZEBRA_DEBUG_VXLAN
)
7179 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7180 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7181 ifp
->ifindex
, zvni
->vni
);
7183 /* If entry doesn't exist, nothing to do. */
7184 n
= zvni_neigh_lookup(zvni
, ip
);
7188 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7190 if (IS_ZEBRA_DEBUG_VXLAN
)
7192 "Trying to del a neigh %s without a mac %s on VNI %u",
7193 ipaddr2str(ip
, buf
, sizeof(buf
)),
7194 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7200 /* If it is a remote entry, the kernel has aged this out or someone has
7201 * deleted it, it needs to be re-installed as Quagga is the owner.
7203 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7204 zvni_neigh_install(zvni
, n
);
7208 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7210 zlog_debug("%s: VNI %u vrf lookup failed.",
7211 __PRETTY_FUNCTION__
, zvni
->vni
);
7215 /* In case of feeze action, if local neigh is in duplicate state,
7216 * Mark the Neigh as inactive before sending delete request to BGPd,
7217 * If BGPd has remote entry, it will re-install
7219 if (zvrf
->dad_freeze
&&
7220 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7221 ZEBRA_NEIGH_SET_INACTIVE(n
);
7223 /* Remove neighbor from BGP. */
7224 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7226 /* Delete this neighbor entry. */
7227 zvni_neigh_del(zvni
, n
);
7229 /* see if the AUTO mac needs to be deleted */
7230 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7231 && !listcount(zmac
->neigh_list
))
7232 zvni_mac_del(zvni
, zmac
);
7238 * Handle neighbor add or update notification from the kernel (on a VLAN
7239 * device / L3 interface). This is typically for a local neighbor but can
7240 * also be for a remote neighbor (e.g., ageout notification). It could
7241 * also be a "move" scenario.
7243 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7244 struct interface
*link_if
,
7246 struct ethaddr
*macaddr
,
7251 char buf
[ETHER_ADDR_STRLEN
];
7252 char buf2
[INET6_ADDRSTRLEN
];
7253 zebra_vni_t
*zvni
= NULL
;
7254 zebra_l3vni_t
*zl3vni
= NULL
;
7256 /* check if this is a remote neigh entry corresponding to remote
7259 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7261 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7263 /* We are only interested in neighbors on an SVI that resides on top
7264 * of a VxLAN bridge.
7266 zvni
= zvni_from_svi(ifp
, link_if
);
7270 if (IS_ZEBRA_DEBUG_VXLAN
)
7272 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7273 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7274 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7275 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7276 is_router
? "router " : "",
7279 /* Is this about a local neighbor or a remote one? */
7281 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7284 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7289 * Handle message from client to delete a remote MACIP for a VNI.
7291 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7295 struct ethaddr macaddr
;
7297 struct in_addr vtep_ip
;
7298 uint16_t l
= 0, ipa_len
;
7299 char buf
[ETHER_ADDR_STRLEN
];
7300 char buf1
[INET6_ADDRSTRLEN
];
7302 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7303 memset(&ip
, 0, sizeof(struct ipaddr
));
7304 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7308 while (l
< hdr
->length
) {
7309 /* Obtain each remote MACIP and process. */
7310 /* Message contains VNI, followed by MAC followed by IP (if any)
7311 * followed by remote VTEP IP.
7313 memset(&ip
, 0, sizeof(ip
));
7314 STREAM_GETL(s
, vni
);
7315 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7316 STREAM_GETL(s
, ipa_len
);
7318 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7320 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7322 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7323 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7324 l
+= IPV4_MAX_BYTELEN
;
7326 if (IS_ZEBRA_DEBUG_VXLAN
)
7328 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7330 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7331 ipa_len
? " IP " : "",
7333 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7335 zebra_route_string(client
->proto
));
7337 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7345 * Handle message from client to add a remote MACIP for a VNI. This
7346 * could be just the add of a MAC address or the add of a neighbor
7349 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7353 struct ethaddr macaddr
;
7355 struct in_addr vtep_ip
;
7356 uint16_t l
= 0, ipa_len
;
7359 char buf
[ETHER_ADDR_STRLEN
];
7360 char buf1
[INET6_ADDRSTRLEN
];
7362 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7363 memset(&ip
, 0, sizeof(struct ipaddr
));
7364 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7366 if (!EVPN_ENABLED(zvrf
)) {
7367 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7373 while (l
< hdr
->length
) {
7374 /* Obtain each remote MACIP and process. */
7375 /* Message contains VNI, followed by MAC followed by IP (if any)
7376 * followed by remote VTEP IP.
7378 memset(&ip
, 0, sizeof(ip
));
7379 STREAM_GETL(s
, vni
);
7380 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7381 STREAM_GETL(s
, ipa_len
);
7383 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7385 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7387 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7388 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7389 l
+= IPV4_MAX_BYTELEN
;
7391 /* Get flags - sticky mac and/or gateway mac */
7392 STREAM_GETC(s
, flags
);
7394 STREAM_GETL(s
, seq
);
7397 if (IS_ZEBRA_DEBUG_VXLAN
)
7399 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7401 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7402 ipa_len
? " IP " : "",
7404 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7405 flags
, seq
, inet_ntoa(vtep_ip
),
7406 zebra_route_string(client
->proto
));
7408 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7409 flags
, seq
, vtep_ip
);
7417 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7418 * us, this must involve a multihoming scenario. Treat this as implicit delete
7419 * of any prior local MAC.
7421 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7422 struct interface
*br_if
,
7423 struct ethaddr
*macaddr
, vlanid_t vid
)
7425 struct zebra_if
*zif
;
7426 struct zebra_l2info_vxlan
*vxl
;
7430 char buf
[ETHER_ADDR_STRLEN
];
7434 vxl
= &zif
->l2info
.vxl
;
7437 /* Check if EVPN is enabled. */
7438 if (!is_evpn_enabled())
7441 /* Locate hash entry; it is expected to exist. */
7442 zvni
= zvni_lookup(vni
);
7446 /* If entry doesn't exist, nothing to do. */
7447 mac
= zvni_mac_lookup(zvni
, macaddr
);
7451 /* Is it a local entry? */
7452 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7455 if (IS_ZEBRA_DEBUG_VXLAN
)
7457 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7458 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7461 /* Remove MAC from BGP. */
7462 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7465 * If there are no neigh associated with the mac delete the mac
7466 * else mark it as AUTO for forward reference
7468 if (!listcount(mac
->neigh_list
)) {
7469 zvni_mac_del(zvni
, mac
);
7471 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7472 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7479 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7480 * This can happen because the remote MAC entries are also added as "dynamic",
7481 * so the kernel can ageout the entry.
7483 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7484 struct interface
*br_if
,
7485 struct ethaddr
*macaddr
, vlanid_t vid
)
7487 struct zebra_if
*zif
= NULL
;
7488 struct zebra_l2info_vxlan
*vxl
= NULL
;
7490 zebra_vni_t
*zvni
= NULL
;
7491 zebra_l3vni_t
*zl3vni
= NULL
;
7492 zebra_mac_t
*mac
= NULL
;
7493 char buf
[ETHER_ADDR_STRLEN
];
7497 vxl
= &zif
->l2info
.vxl
;
7500 /* Check if EVPN is enabled. */
7501 if (!is_evpn_enabled())
7504 /* check if this is a remote RMAC and readd simillar to remote macs */
7505 zl3vni
= zl3vni_lookup(vni
);
7507 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7509 /* Locate hash entry; it is expected to exist. */
7510 zvni
= zvni_lookup(vni
);
7514 /* If entry doesn't exist, nothing to do. */
7515 mac
= zvni_mac_lookup(zvni
, macaddr
);
7519 /* Is it a remote entry? */
7520 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7523 if (IS_ZEBRA_DEBUG_VXLAN
)
7524 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7525 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7528 zvni_mac_install(zvni
, mac
);
7533 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7535 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7536 struct ethaddr
*macaddr
, vlanid_t vid
)
7540 char buf
[ETHER_ADDR_STRLEN
];
7542 /* We are interested in MACs only on ports or (port, VLAN) that
7545 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7548 if (!zvni
->vxlan_if
) {
7550 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7555 if (IS_ZEBRA_DEBUG_VXLAN
)
7556 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7557 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7558 ifp
->ifindex
, vid
, zvni
->vni
);
7560 /* If entry doesn't exist, nothing to do. */
7561 mac
= zvni_mac_lookup(zvni
, macaddr
);
7565 /* Is it a local entry? */
7566 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7569 /* Update all the neigh entries associated with this mac */
7570 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7572 /* Remove MAC from BGP. */
7573 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7576 * If there are no neigh associated with the mac delete the mac
7577 * else mark it as AUTO for forward reference
7579 if (!listcount(mac
->neigh_list
)) {
7580 zvni_mac_del(zvni
, mac
);
7582 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7583 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7590 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7592 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7593 struct interface
*br_if
,
7594 struct ethaddr
*macaddr
, vlanid_t vid
,
7599 struct zebra_vrf
*zvrf
;
7600 char buf
[ETHER_ADDR_STRLEN
];
7601 bool mac_sticky
= false;
7602 bool inform_client
= false;
7603 bool upd_neigh
= false;
7604 bool is_dup_detect
= false;
7605 struct in_addr vtep_ip
= {.s_addr
= 0};
7607 /* We are interested in MACs only on ports or (port, VLAN) that
7610 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7612 if (IS_ZEBRA_DEBUG_VXLAN
)
7614 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7615 sticky
? "sticky " : "",
7616 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7617 ifp
->name
, ifp
->ifindex
, vid
);
7621 if (!zvni
->vxlan_if
) {
7622 if (IS_ZEBRA_DEBUG_VXLAN
)
7624 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7629 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7631 if (IS_ZEBRA_DEBUG_VXLAN
)
7632 zlog_debug("\tNo Vrf found for vrf_id: %d",
7633 zvni
->vxlan_if
->vrf_id
);
7637 /* Check if we need to create or update or it is a NO-OP. */
7638 mac
= zvni_mac_lookup(zvni
, macaddr
);
7640 if (IS_ZEBRA_DEBUG_VXLAN
)
7642 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7643 sticky
? "sticky " : "",
7644 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7645 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7647 mac
= zvni_mac_add(zvni
, macaddr
);
7650 EC_ZEBRA_MAC_ADD_FAILED
,
7651 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7652 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7653 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7656 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7657 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7658 mac
->fwd_info
.local
.vid
= vid
;
7660 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7661 inform_client
= true;
7664 if (IS_ZEBRA_DEBUG_VXLAN
)
7666 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7667 sticky
? "sticky " : "",
7668 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7669 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7672 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7673 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7677 * Update any changes and if changes are relevant to
7680 if (mac_sticky
== sticky
7681 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7682 && mac
->fwd_info
.local
.vid
== vid
) {
7683 if (IS_ZEBRA_DEBUG_VXLAN
)
7685 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7686 "entry exists and has not changed ",
7687 sticky
? "sticky " : "",
7688 prefix_mac2str(macaddr
, buf
,
7690 ifp
->name
, ifp
->ifindex
, vid
,
7694 if (mac_sticky
!= sticky
) {
7696 SET_FLAG(mac
->flags
,
7699 UNSET_FLAG(mac
->flags
,
7701 inform_client
= true;
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 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7709 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7710 bool do_dad
= false;
7713 * MAC has either moved or was "internally" created due
7714 * to a neighbor learn and is now actually learnt. If
7715 * it was learnt as a remote sticky MAC, this is an
7718 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7720 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7721 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7722 prefix_mac2str(macaddr
, buf
,
7724 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7729 /* If an actual move, compute MAC's seq number */
7730 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7731 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7733 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7734 /* Trigger DAD for remote MAC */
7738 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7739 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7740 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7741 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7742 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7743 mac
->fwd_info
.local
.vid
= vid
;
7745 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7747 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7749 * We have to inform BGP of this MAC as well as process
7752 inform_client
= true;
7755 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7759 if (is_dup_detect
) {
7760 inform_client
= false;
7766 /* Inform BGP if required. */
7767 if (inform_client
) {
7768 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7769 mac
->flags
, mac
->loc_seq
))
7773 /* Process all neighbors associated with this MAC, if required. */
7775 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7781 * Handle message from client to delete a remote VTEP for a VNI.
7783 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7786 unsigned short l
= 0;
7788 struct in_addr vtep_ip
;
7790 zebra_vtep_t
*zvtep
;
7791 struct interface
*ifp
;
7792 struct zebra_if
*zif
;
7794 if (!is_evpn_enabled()) {
7796 "%s: EVPN is not enabled yet we have received a vtep del command",
7797 __PRETTY_FUNCTION__
);
7801 if (!EVPN_ENABLED(zvrf
)) {
7802 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7809 while (l
< hdr
->length
) {
7810 /* Obtain each remote VTEP and process. */
7811 STREAM_GETL(s
, vni
);
7813 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7814 l
+= IPV4_MAX_BYTELEN
;
7816 if (IS_ZEBRA_DEBUG_VXLAN
)
7817 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7818 inet_ntoa(vtep_ip
), vni
,
7819 zebra_route_string(client
->proto
));
7821 /* Locate VNI hash entry - expected to exist. */
7822 zvni
= zvni_lookup(vni
);
7824 if (IS_ZEBRA_DEBUG_VXLAN
)
7826 "Failed to locate VNI hash upon remote VTEP DEL, "
7832 ifp
= zvni
->vxlan_if
;
7835 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7841 /* If down or not mapped to a bridge, we're done. */
7842 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7845 /* If the remote VTEP does not exist, there's nothing more to
7847 * Otherwise, uninstall any remote MACs pointing to this VTEP
7849 * then, the VTEP entry itself and remove it.
7851 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7855 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7856 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7857 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7858 zvni_vtep_del(zvni
, zvtep
);
7866 * Handle message from client to add a remote VTEP for a VNI.
7868 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7871 unsigned short l
= 0;
7873 struct in_addr vtep_ip
;
7875 struct interface
*ifp
;
7876 struct zebra_if
*zif
;
7878 if (!is_evpn_enabled()) {
7880 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7881 __PRETTY_FUNCTION__
);
7885 if (!EVPN_ENABLED(zvrf
)) {
7886 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7893 while (l
< hdr
->length
) {
7894 /* Obtain each remote VTEP and process. */
7895 STREAM_GETL(s
, vni
);
7897 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7898 l
+= IPV4_MAX_BYTELEN
;
7900 if (IS_ZEBRA_DEBUG_VXLAN
)
7901 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7902 inet_ntoa(vtep_ip
), vni
,
7903 zebra_route_string(client
->proto
));
7905 /* Locate VNI hash entry - expected to exist. */
7906 zvni
= zvni_lookup(vni
);
7909 EC_ZEBRA_VTEP_ADD_FAILED
,
7910 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7915 ifp
= zvni
->vxlan_if
;
7918 EC_ZEBRA_VTEP_ADD_FAILED
,
7919 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7926 /* If down or not mapped to a bridge, we're done. */
7927 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7930 /* If the remote VTEP already exists,
7931 there's nothing more to do. */
7932 if (zvni_vtep_find(zvni
, &vtep_ip
))
7935 if (zvni_vtep_add(zvni
, &vtep_ip
) == NULL
) {
7936 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
7937 "Failed to add remote VTEP, VNI %u zvni %p",
7942 zvni_vtep_install(zvni
, &vtep_ip
);
7950 * Add/Del gateway macip to evpn
7952 * 1. SVI interface on a vlan aware bridge
7953 * 2. SVI interface on a vlan unaware bridge
7954 * 3. vrr interface (MACVLAN) associated to a SVI
7955 * We advertise macip routes for an interface if it is associated to VxLan vlan
7957 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
7961 struct ethaddr macaddr
;
7962 zebra_vni_t
*zvni
= NULL
;
7964 memset(&ip
, 0, sizeof(struct ipaddr
));
7965 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7967 /* Check if EVPN is enabled. */
7968 if (!is_evpn_enabled())
7971 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
7972 struct interface
*svi_if
=
7973 NULL
; /* SVI corresponding to the MACVLAN */
7974 struct zebra_if
*ifp_zif
=
7975 NULL
; /* Zebra daemon specific info for MACVLAN */
7976 struct zebra_if
*svi_if_zif
=
7977 NULL
; /* Zebra daemon specific info for SVI*/
7979 ifp_zif
= ifp
->info
;
7984 * for a MACVLAN interface the link represents the svi_if
7986 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
7987 ifp_zif
->link_ifindex
);
7989 zlog_debug("MACVLAN %s(%u) without link information",
7990 ifp
->name
, ifp
->ifindex
);
7994 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
7996 * If it is a vlan aware bridge then the link gives the
7997 * bridge information
7999 struct interface
*svi_if_link
= NULL
;
8001 svi_if_zif
= svi_if
->info
;
8003 svi_if_link
= if_lookup_by_index_per_ns(
8004 zebra_ns_lookup(NS_DEFAULT
),
8005 svi_if_zif
->link_ifindex
);
8006 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8008 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8010 * If it is a vlan unaware bridge then svi is the bridge
8013 zvni
= zvni_from_svi(svi_if
, svi_if
);
8015 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8016 struct zebra_if
*svi_if_zif
=
8017 NULL
; /* Zebra daemon specific info for SVI */
8018 struct interface
*svi_if_link
=
8019 NULL
; /* link info for the SVI = bridge info */
8021 svi_if_zif
= ifp
->info
;
8023 svi_if_link
= if_lookup_by_index_per_ns(
8024 zebra_ns_lookup(NS_DEFAULT
),
8025 svi_if_zif
->link_ifindex
);
8027 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8029 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8030 zvni
= zvni_from_svi(ifp
, ifp
);
8036 if (!zvni
->vxlan_if
) {
8037 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8043 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8045 if (p
->family
== AF_INET
) {
8046 ip
.ipa_type
= IPADDR_V4
;
8047 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8048 sizeof(struct in_addr
));
8049 } else if (p
->family
== AF_INET6
) {
8050 ip
.ipa_type
= IPADDR_V6
;
8051 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8052 sizeof(struct in6_addr
));
8057 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8059 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8065 * Handle SVI interface going down.
8066 * SVI can be associated to either L3-VNI or L2-VNI.
8067 * For L2-VNI: At this point, this is a NOP since
8068 * the kernel deletes the neighbor entries on this SVI (if any).
8069 * We only need to update the vrf corresponding to zvni.
8070 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8073 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8075 zebra_l3vni_t
*zl3vni
= NULL
;
8077 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8080 /* process l3-vni down */
8081 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8083 /* remove association with svi-if */
8084 zl3vni
->svi_if
= NULL
;
8086 zebra_vni_t
*zvni
= NULL
;
8088 /* since we dont have svi corresponding to zvni, we associate it
8089 * to default vrf. Note: the corresponding neigh entries on the
8090 * SVI would have already been deleted */
8091 zvni
= zvni_from_svi(ifp
, link_if
);
8093 zvni
->vrf_id
= VRF_DEFAULT
;
8095 /* update the tenant vrf in BGP */
8096 zvni_send_add_to_client(zvni
);
8103 * Handle SVI interface coming up.
8104 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8106 * For L2-VNI: we need to install any remote neighbors entried (used for
8108 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8110 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8112 zebra_vni_t
*zvni
= NULL
;
8113 zebra_l3vni_t
*zl3vni
= NULL
;
8115 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8118 /* associate with svi */
8119 zl3vni
->svi_if
= ifp
;
8121 /* process oper-up */
8122 if (is_l3vni_oper_up(zl3vni
))
8123 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8126 /* process SVI up for l2-vni */
8127 struct neigh_walk_ctx n_wctx
;
8129 zvni
= zvni_from_svi(ifp
, link_if
);
8133 if (!zvni
->vxlan_if
) {
8135 "VNI %u hash %p doesn't have intf upon SVI up",
8140 if (IS_ZEBRA_DEBUG_VXLAN
)
8142 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8143 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8144 vrf_id_to_name(ifp
->vrf_id
));
8146 /* update the vrf information for l2-vni and inform bgp */
8147 zvni
->vrf_id
= ifp
->vrf_id
;
8148 zvni_send_add_to_client(zvni
);
8150 /* Install any remote neighbors for this VNI. */
8151 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8153 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8161 * Handle VxLAN interface down
8163 int zebra_vxlan_if_down(struct interface
*ifp
)
8166 struct zebra_if
*zif
= NULL
;
8167 struct zebra_l2info_vxlan
*vxl
= NULL
;
8168 zebra_l3vni_t
*zl3vni
= NULL
;
8171 /* Check if EVPN is enabled. */
8172 if (!is_evpn_enabled())
8177 vxl
= &zif
->l2info
.vxl
;
8180 zl3vni
= zl3vni_lookup(vni
);
8182 /* process-if-down for l3-vni */
8183 if (IS_ZEBRA_DEBUG_VXLAN
)
8184 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8187 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8189 /* process if-down for l2-vni */
8190 if (IS_ZEBRA_DEBUG_VXLAN
)
8191 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8194 /* Locate hash entry; it is expected to exist. */
8195 zvni
= zvni_lookup(vni
);
8198 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8199 ifp
->name
, ifp
->ifindex
, vni
);
8203 assert(zvni
->vxlan_if
== ifp
);
8205 /* Delete this VNI from BGP. */
8206 zvni_send_del_to_client(zvni
->vni
);
8208 /* Free up all neighbors and MACs, if any. */
8209 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8210 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8212 /* Free up all remote VTEPs, if any. */
8213 zvni_vtep_del_all(zvni
, 1);
8219 * Handle VxLAN interface up - update BGP if required.
8221 int zebra_vxlan_if_up(struct interface
*ifp
)
8224 struct zebra_if
*zif
= NULL
;
8225 struct zebra_l2info_vxlan
*vxl
= NULL
;
8226 zebra_vni_t
*zvni
= NULL
;
8227 zebra_l3vni_t
*zl3vni
= NULL
;
8229 /* Check if EVPN is enabled. */
8230 if (!is_evpn_enabled())
8235 vxl
= &zif
->l2info
.vxl
;
8238 zl3vni
= zl3vni_lookup(vni
);
8241 if (IS_ZEBRA_DEBUG_VXLAN
)
8242 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8245 /* we need to associate with SVI, if any, we can associate with
8246 * svi-if only after association with vxlan-intf is complete
8248 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8250 if (is_l3vni_oper_up(zl3vni
))
8251 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8253 /* Handle L2-VNI add */
8254 struct interface
*vlan_if
= NULL
;
8256 if (IS_ZEBRA_DEBUG_VXLAN
)
8257 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8260 /* Locate hash entry; it is expected to exist. */
8261 zvni
= zvni_lookup(vni
);
8264 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8265 ifp
->name
, ifp
->ifindex
, vni
);
8269 assert(zvni
->vxlan_if
== ifp
);
8270 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8271 zif
->brslave_info
.br_if
);
8273 zvni
->vrf_id
= vlan_if
->vrf_id
;
8274 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8276 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8279 /* If part of a bridge, inform BGP about this VNI. */
8280 /* Also, read and populate local MACs and neighbors. */
8281 if (zif
->brslave_info
.br_if
) {
8282 zvni_send_add_to_client(zvni
);
8283 zvni_read_mac_neigh(zvni
, ifp
);
8291 * Handle VxLAN interface delete. Locate and remove entry in hash table
8292 * and update BGP, if required.
8294 int zebra_vxlan_if_del(struct interface
*ifp
)
8297 struct zebra_if
*zif
= NULL
;
8298 struct zebra_l2info_vxlan
*vxl
= NULL
;
8299 zebra_vni_t
*zvni
= NULL
;
8300 zebra_l3vni_t
*zl3vni
= NULL
;
8302 /* Check if EVPN is enabled. */
8303 if (!is_evpn_enabled())
8308 vxl
= &zif
->l2info
.vxl
;
8311 zl3vni
= zl3vni_lookup(vni
);
8314 if (IS_ZEBRA_DEBUG_VXLAN
)
8315 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8318 /* process oper-down for l3-vni */
8319 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8321 /* remove the association with vxlan_if */
8322 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8323 zl3vni
->vxlan_if
= NULL
;
8326 /* process if-del for l2-vni*/
8327 if (IS_ZEBRA_DEBUG_VXLAN
)
8328 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8331 /* Locate hash entry; it is expected to exist. */
8332 zvni
= zvni_lookup(vni
);
8335 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8336 ifp
->name
, ifp
->ifindex
, vni
);
8340 /* remove from l3-vni list */
8341 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8343 listnode_delete(zl3vni
->l2vnis
, zvni
);
8345 /* Delete VNI from BGP. */
8346 zvni_send_del_to_client(zvni
->vni
);
8348 /* Free up all neighbors and MAC, if any. */
8349 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8350 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8352 /* Free up all remote VTEPs, if any. */
8353 zvni_vtep_del_all(zvni
, 0);
8355 /* Delete the hash entry. */
8356 if (zvni_del(zvni
)) {
8357 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8358 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8359 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8367 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8369 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8372 struct zebra_if
*zif
= NULL
;
8373 struct zebra_l2info_vxlan
*vxl
= NULL
;
8374 zebra_vni_t
*zvni
= NULL
;
8375 zebra_l3vni_t
*zl3vni
= NULL
;
8377 /* Check if EVPN is enabled. */
8378 if (!is_evpn_enabled())
8383 vxl
= &zif
->l2info
.vxl
;
8386 zl3vni
= zl3vni_lookup(vni
);
8389 if (IS_ZEBRA_DEBUG_VXLAN
)
8391 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8392 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8393 inet_ntoa(vxl
->vtep_ip
),
8394 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8396 /* Removed from bridge? Cleanup and return */
8397 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8398 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8399 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8403 /* access-vlan change - process oper down, associate with new
8404 * svi_if and then process oper up again
8406 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8407 if (if_is_operative(ifp
)) {
8408 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8409 zl3vni
->svi_if
= NULL
;
8410 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8411 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8412 if (is_l3vni_oper_up(zl3vni
))
8413 zebra_vxlan_process_l3vni_oper_up(
8419 * local-ip change - process oper down, associate with new
8420 * local-ip and then process oper up again
8422 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8423 if (if_is_operative(ifp
)) {
8424 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8425 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8426 if (is_l3vni_oper_up(zl3vni
))
8427 zebra_vxlan_process_l3vni_oper_up(
8432 /* Update local tunnel IP. */
8433 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8435 /* if we have a valid new master, process l3-vni oper up */
8436 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8437 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8438 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8442 /* Update VNI hash. */
8443 zvni
= zvni_lookup(vni
);
8446 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8447 ifp
->name
, ifp
->ifindex
, vni
);
8451 if (IS_ZEBRA_DEBUG_VXLAN
)
8453 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8454 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8455 inet_ntoa(vxl
->vtep_ip
),
8456 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8458 /* Removed from bridge? Cleanup and return */
8459 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8460 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8461 /* Delete from client, remove all remote VTEPs */
8462 /* Also, free up all MACs and neighbors. */
8463 zvni_send_del_to_client(zvni
->vni
);
8464 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8465 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8466 zvni_vtep_del_all(zvni
, 1);
8470 /* Handle other changes. */
8471 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8472 /* Remove all existing local neigh and MACs for this VNI
8473 * (including from BGP)
8475 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8476 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8479 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8480 zvni
->vxlan_if
= ifp
;
8482 /* Take further actions needed.
8483 * Note that if we are here, there is a change of interest.
8485 /* If down or not mapped to a bridge, we're done. */
8486 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8489 /* Inform BGP, if there is a change of interest. */
8491 & (ZEBRA_VXLIF_MASTER_CHANGE
| ZEBRA_VXLIF_LOCAL_IP_CHANGE
))
8492 zvni_send_add_to_client(zvni
);
8494 /* If there is a valid new master or a VLAN mapping change,
8495 * read and populate local MACs and neighbors.
8496 * Also, reinstall any remote MACs and neighbors
8497 * for this VNI (based on new VLAN).
8499 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8500 zvni_read_mac_neigh(zvni
, ifp
);
8501 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8502 struct mac_walk_ctx m_wctx
;
8503 struct neigh_walk_ctx n_wctx
;
8505 zvni_read_mac_neigh(zvni
, ifp
);
8507 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8509 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8512 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8514 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8523 * Handle VxLAN interface add.
8525 int zebra_vxlan_if_add(struct interface
*ifp
)
8528 struct zebra_if
*zif
= NULL
;
8529 struct zebra_l2info_vxlan
*vxl
= NULL
;
8530 zebra_vni_t
*zvni
= NULL
;
8531 zebra_l3vni_t
*zl3vni
= NULL
;
8533 /* Check if EVPN is enabled. */
8534 if (!is_evpn_enabled())
8539 vxl
= &zif
->l2info
.vxl
;
8542 zl3vni
= zl3vni_lookup(vni
);
8545 /* process if-add for l3-vni*/
8546 if (IS_ZEBRA_DEBUG_VXLAN
)
8548 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8549 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8550 inet_ntoa(vxl
->vtep_ip
),
8551 zif
->brslave_info
.bridge_ifindex
);
8553 /* associate with vxlan_if */
8554 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8555 zl3vni
->vxlan_if
= ifp
;
8557 /* Associate with SVI, if any. We can associate with svi-if only
8558 * after association with vxlan_if is complete */
8559 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8561 if (is_l3vni_oper_up(zl3vni
))
8562 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8565 /* process if-add for l2-vni */
8566 struct interface
*vlan_if
= NULL
;
8568 /* Create or update VNI hash. */
8569 zvni
= zvni_lookup(vni
);
8571 zvni
= zvni_add(vni
);
8574 EC_ZEBRA_VNI_ADD_FAILED
,
8575 "Failed to add VNI hash, IF %s(%u) VNI %u",
8576 ifp
->name
, ifp
->ifindex
, vni
);
8581 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8582 zvni
->vxlan_if
= ifp
;
8583 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8584 zif
->brslave_info
.br_if
);
8586 zvni
->vrf_id
= vlan_if
->vrf_id
;
8587 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8589 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8592 if (IS_ZEBRA_DEBUG_VXLAN
)
8594 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8596 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8598 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8599 inet_ntoa(vxl
->vtep_ip
),
8600 zif
->brslave_info
.bridge_ifindex
);
8602 /* If down or not mapped to a bridge, we're done. */
8603 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8607 zvni_send_add_to_client(zvni
);
8609 /* Read and populate local MACs and neighbors */
8610 zvni_read_mac_neigh(zvni
, ifp
);
8616 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8617 char *err
, int err_str_sz
, int filter
,
8620 zebra_l3vni_t
*zl3vni
= NULL
;
8621 struct zebra_vrf
*zvrf_evpn
= NULL
;
8623 zvrf_evpn
= zebra_vrf_get_evpn();
8627 if (IS_ZEBRA_DEBUG_VXLAN
)
8628 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8629 add
? "ADD" : "DEL");
8633 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8635 /* check if the vni is already present under zvrf */
8637 snprintf(err
, err_str_sz
,
8638 "VNI is already configured under the vrf");
8642 /* check if this VNI is already present in the system */
8643 zl3vni
= zl3vni_lookup(vni
);
8645 snprintf(err
, err_str_sz
,
8646 "VNI is already configured as L3-VNI");
8650 /* add the L3-VNI to the global table */
8651 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8653 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8657 /* associate the vrf with vni */
8660 /* set the filter in l3vni to denote if we are using l3vni only
8664 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8666 /* associate with vxlan-intf;
8667 * we need to associate with the vxlan-intf first
8669 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8671 /* associate with corresponding SVI interface, we can associate
8672 * with svi-if only after vxlan interface association is
8675 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8677 /* formulate l2vni list */
8678 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8681 if (is_l3vni_oper_up(zl3vni
))
8682 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8685 zl3vni
= zl3vni_lookup(vni
);
8687 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8691 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8692 snprintf(err
, ERR_STR_SZ
,
8693 "prefix-routes-only is not set for the vni");
8697 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8699 /* delete and uninstall all rmacs */
8700 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8703 /* delete and uninstall all next-hops */
8704 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8710 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8715 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8717 zebra_l3vni_t
*zl3vni
= NULL
;
8720 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8724 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8725 if (is_l3vni_oper_up(zl3vni
))
8726 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8730 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8732 zebra_l3vni_t
*zl3vni
= NULL
;
8735 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8739 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8740 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8744 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8746 zebra_l3vni_t
*zl3vni
= NULL
;
8750 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8756 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8762 * Handle message from client to specify the flooding mechanism for
8763 * BUM packets. The default is to do head-end (ingress) replication
8764 * and the other supported option is to disable it. This applies to
8765 * all BUM traffic and disabling it applies to both the transmit and
8766 * receive direction.
8768 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8771 enum vxlan_flood_control flood_ctrl
;
8773 if (!EVPN_ENABLED(zvrf
)) {
8774 zlog_err("EVPN flood control for non-EVPN VRF %u",
8780 STREAM_GETC(s
, flood_ctrl
);
8782 if (IS_ZEBRA_DEBUG_VXLAN
)
8783 zlog_debug("EVPN flood control %u, currently %u",
8784 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8786 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8789 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8791 /* Install or uninstall flood entries corresponding to
8794 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8802 * Handle message from client to enable/disable advertisement of svi macip
8805 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8810 zebra_vni_t
*zvni
= NULL
;
8811 struct interface
*ifp
= NULL
;
8813 if (!EVPN_ENABLED(zvrf
)) {
8814 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8820 STREAM_GETC(s
, advertise
);
8821 STREAM_GETL(s
, vni
);
8824 if (IS_ZEBRA_DEBUG_VXLAN
)
8825 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8826 advertise
? "enabled" : "disabled",
8827 advertise_gw_macip_enabled(NULL
)
8831 if (zvrf
->advertise_svi_macip
== advertise
)
8836 zvrf
->advertise_svi_macip
= advertise
;
8837 hash_iterate(zvrf
->vni_table
,
8838 zvni_gw_macip_add_for_vni_hash
, NULL
);
8840 hash_iterate(zvrf
->vni_table
,
8841 zvni_svi_macip_del_for_vni_hash
, NULL
);
8842 zvrf
->advertise_svi_macip
= advertise
;
8846 struct zebra_if
*zif
= NULL
;
8847 struct zebra_l2info_vxlan zl2_info
;
8848 struct interface
*vlan_if
= NULL
;
8850 zvni
= zvni_lookup(vni
);
8854 if (IS_ZEBRA_DEBUG_VXLAN
)
8856 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8857 advertise
? "enabled" : "disabled", vni
,
8858 advertise_svi_macip_enabled(zvni
)
8862 if (zvni
->advertise_svi_macip
== advertise
)
8865 ifp
= zvni
->vxlan_if
;
8871 /* If down or not mapped to a bridge, we're done. */
8872 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8875 zl2_info
= zif
->l2info
.vxl
;
8877 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8878 zif
->brslave_info
.br_if
);
8883 zvni
->advertise_svi_macip
= advertise
;
8884 /* Add primary SVI MAC-IP */
8885 zvni_add_macip_for_intf(vlan_if
, zvni
);
8887 /* Del primary MAC-IP */
8888 zvni_del_macip_for_intf(vlan_if
, zvni
);
8889 zvni
->advertise_svi_macip
= advertise
;
8898 * Handle message from client to enable/disable advertisement of g/w macip
8901 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
8906 zebra_vni_t
*zvni
= NULL
;
8907 struct interface
*ifp
= NULL
;
8908 struct zebra_if
*zif
= NULL
;
8909 struct zebra_l2info_vxlan zl2_info
;
8910 struct interface
*vlan_if
= NULL
;
8912 if (!EVPN_ENABLED(zvrf
)) {
8913 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8919 STREAM_GETC(s
, advertise
);
8920 vni
= stream_get3(s
);
8922 zvni
= zvni_lookup(vni
);
8926 if (zvni
->advertise_subnet
== advertise
)
8929 if (IS_ZEBRA_DEBUG_VXLAN
)
8930 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8931 advertise
? "enabled" : "disabled", vni
,
8932 zvni
->advertise_subnet
? "enabled" : "disabled");
8935 zvni
->advertise_subnet
= advertise
;
8937 ifp
= zvni
->vxlan_if
;
8943 /* If down or not mapped to a bridge, we're done. */
8944 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8947 zl2_info
= zif
->l2info
.vxl
;
8950 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
8954 if (zvni
->advertise_subnet
)
8955 zvni_advertise_subnet(zvni
, vlan_if
, 1);
8957 zvni_advertise_subnet(zvni
, vlan_if
, 0);
8964 * Handle message from client to enable/disable advertisement of g/w macip
8967 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
8972 zebra_vni_t
*zvni
= NULL
;
8973 struct interface
*ifp
= NULL
;
8975 if (!EVPN_ENABLED(zvrf
)) {
8976 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8982 STREAM_GETC(s
, advertise
);
8983 STREAM_GETL(s
, vni
);
8986 if (IS_ZEBRA_DEBUG_VXLAN
)
8987 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8988 advertise
? "enabled" : "disabled",
8989 advertise_gw_macip_enabled(NULL
)
8993 if (zvrf
->advertise_gw_macip
== advertise
)
8996 zvrf
->advertise_gw_macip
= advertise
;
8998 if (advertise_gw_macip_enabled(zvni
))
8999 hash_iterate(zvrf
->vni_table
,
9000 zvni_gw_macip_add_for_vni_hash
, NULL
);
9002 hash_iterate(zvrf
->vni_table
,
9003 zvni_gw_macip_del_for_vni_hash
, NULL
);
9006 struct zebra_if
*zif
= NULL
;
9007 struct zebra_l2info_vxlan zl2_info
;
9008 struct interface
*vlan_if
= NULL
;
9009 struct interface
*vrr_if
= NULL
;
9011 zvni
= zvni_lookup(vni
);
9015 if (IS_ZEBRA_DEBUG_VXLAN
)
9017 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9018 advertise
? "enabled" : "disabled", vni
,
9019 advertise_gw_macip_enabled(zvni
) ? "enabled"
9022 if (zvni
->advertise_gw_macip
== advertise
)
9025 zvni
->advertise_gw_macip
= advertise
;
9027 ifp
= zvni
->vxlan_if
;
9033 /* If down or not mapped to a bridge, we're done. */
9034 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9037 zl2_info
= zif
->l2info
.vxl
;
9039 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9040 zif
->brslave_info
.br_if
);
9044 if (advertise_gw_macip_enabled(zvni
)) {
9045 /* Add primary SVI MAC-IP */
9046 zvni_add_macip_for_intf(vlan_if
, zvni
);
9048 /* Add VRR MAC-IP - if any*/
9049 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9051 zvni_add_macip_for_intf(vrr_if
, zvni
);
9053 /* Del primary MAC-IP */
9054 zvni_del_macip_for_intf(vlan_if
, zvni
);
9056 /* Del VRR MAC-IP - if any*/
9057 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9059 zvni_del_macip_for_intf(vrr_if
, zvni
);
9069 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9070 * When enabled, the VNI hash table will be built and MAC FDB table read;
9071 * when disabled, the entries should be deleted and remote VTEPs and MACs
9072 * uninstalled from the kernel.
9073 * This also informs the setting for BUM handling at the time this change
9074 * occurs; it is relevant only when specifying "learn".
9076 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9078 struct stream
*s
= NULL
;
9080 enum vxlan_flood_control flood_ctrl
;
9082 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9084 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9088 STREAM_GETC(s
, advertise
);
9089 STREAM_GETC(s
, flood_ctrl
);
9091 if (IS_ZEBRA_DEBUG_VXLAN
)
9092 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9093 zvrf_name(zvrf
), zvrf_id(zvrf
),
9094 advertise
? "enabled" : "disabled",
9095 is_evpn_enabled() ? "enabled" : "disabled",
9098 if (zvrf
->advertise_all_vni
== advertise
)
9101 zvrf
->advertise_all_vni
= advertise
;
9102 if (EVPN_ENABLED(zvrf
)) {
9103 zrouter
.evpn_vrf
= zvrf
;
9105 /* Note BUM handling */
9106 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9108 /* Build VNI hash table and inform BGP. */
9109 zvni_build_hash_table();
9111 /* Add all SVI (L3 GW) MACs to BGP*/
9112 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9115 /* Read the MAC FDB */
9116 macfdb_read(zvrf
->zns
);
9118 /* Read neighbors */
9119 neigh_read(zvrf
->zns
);
9121 /* Cleanup VTEPs for all VNIs - uninstall from
9122 * kernel and free entries.
9124 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9126 /* cleanup all l3vnis */
9127 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9129 /* Mark as "no EVPN VRF" */
9130 zrouter
.evpn_vrf
= NULL
;
9138 * Allocate VNI hash table for this VRF and do other initialization.
9139 * NOTE: Currently supported only for default VRF.
9141 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9145 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9146 "Zebra VRF VNI Table");
9149 /* Cleanup VNI info, but don't free the table. */
9150 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9154 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9157 /* Close all VNI handling */
9158 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9162 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9163 hash_free(zvrf
->vni_table
);
9166 /* init the l3vni table */
9167 void zebra_vxlan_init(void)
9169 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9170 "Zebra VRF L3 VNI table");
9171 zrouter
.evpn_vrf
= NULL
;
9174 /* free l3vni table */
9175 void zebra_vxlan_disable(void)
9177 hash_free(zrouter
.l3vni_table
);
9180 /* get the l3vni svi ifindex */
9181 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9183 zebra_l3vni_t
*zl3vni
= NULL
;
9185 zl3vni
= zl3vni_from_vrf(vrf_id
);
9186 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9189 return zl3vni
->svi_if
->ifindex
;
9192 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9194 struct zebra_vrf
*zvrf
= NULL
;
9195 zebra_neigh_t
*nbr
= NULL
;
9196 zebra_vni_t
*zvni
= NULL
;
9197 char buf1
[INET6_ADDRSTRLEN
];
9198 char buf2
[ETHER_ADDR_STRLEN
];
9200 nbr
= THREAD_ARG(t
);
9202 /* since this is asynchronous we need sanity checks*/
9203 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9207 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9211 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9215 if (IS_ZEBRA_DEBUG_VXLAN
)
9216 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9217 __PRETTY_FUNCTION__
,
9218 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9219 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9221 nbr
->dad_count
, zvni
->vni
);
9223 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9225 nbr
->detect_start_time
.tv_sec
= 0;
9226 nbr
->detect_start_time
.tv_usec
= 0;
9227 nbr
->dad_dup_detect_time
= 0;
9228 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9229 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9232 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9233 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9234 nbr
->flags
, nbr
->loc_seq
);
9235 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9236 zvni_neigh_install(zvni
, nbr
);
9242 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9244 struct zebra_vrf
*zvrf
= NULL
;
9245 zebra_mac_t
*mac
= NULL
;
9246 zebra_vni_t
*zvni
= NULL
;
9247 struct listnode
*node
= NULL
;
9248 zebra_neigh_t
*nbr
= NULL
;
9249 char buf
[ETHER_ADDR_STRLEN
];
9251 mac
= THREAD_ARG(t
);
9253 /* since this is asynchronous we need sanity checks*/
9254 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9258 zvni
= zvni_lookup(mac
->zvni
->vni
);
9262 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9266 if (IS_ZEBRA_DEBUG_VXLAN
)
9267 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9268 __PRETTY_FUNCTION__
,
9269 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9272 listcount(mac
->neigh_list
));
9274 /* Remove all IPs as duplicate associcated with this MAC */
9275 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9276 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9277 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9278 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9279 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9280 zvni_neigh_install(zvni
, nbr
);
9283 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9285 nbr
->detect_start_time
.tv_sec
= 0;
9286 nbr
->dad_dup_detect_time
= 0;
9289 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9291 mac
->detect_start_time
.tv_sec
= 0;
9292 mac
->detect_start_time
.tv_usec
= 0;
9293 mac
->dad_dup_detect_time
= 0;
9294 mac
->dad_mac_auto_recovery_timer
= NULL
;
9296 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9298 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9299 mac
->flags
, mac
->loc_seq
))
9302 /* Process all neighbors associated with this MAC. */
9303 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9305 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9306 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9308 /* Install the entry. */
9309 zvni_mac_install(zvni
, mac
);