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");
61 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
65 #define VXLAN_FLOOD_STR_NO_INFO "-"
66 #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO
67 static const struct message zvtep_flood_str
[] = {
68 {VXLAN_FLOOD_DISABLED
, VXLAN_FLOOD_STR_NO_INFO
},
69 {VXLAN_FLOOD_PIM_SM
, "PIM-SM"},
70 {VXLAN_FLOOD_HEAD_END_REPL
, "HER"},
75 /* static function declarations */
76 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
78 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
79 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
80 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
81 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
83 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
85 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
87 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
88 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
89 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
);
90 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
91 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
93 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
94 struct ipaddr
*ip
, uint8_t flags
,
95 uint32_t seq
, int state
, uint16_t cmd
);
96 static unsigned int neigh_hash_keymake(const void *p
);
97 static void *zvni_neigh_alloc(void *p
);
98 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
100 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
102 struct in_addr
*r_vtep_ip
);
103 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
105 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
106 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
107 struct ethaddr
*macaddr
,
108 uint8_t flags
, uint32_t seq
);
109 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
110 struct ethaddr
*macaddr
,
111 uint8_t flags
, int state
);
112 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
113 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
114 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
115 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
116 struct interface
*br_if
);
117 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
119 /* l3-vni next-hop neigh related APIs */
120 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
122 static void *zl3vni_nh_alloc(void *p
);
123 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
124 struct ipaddr
*vtep_ip
,
125 struct ethaddr
*rmac
);
126 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
127 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
128 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
130 /* l3-vni rmac related APIs */
131 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
132 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
133 struct ethaddr
*rmac
);
134 static void *zl3vni_rmac_alloc(void *p
);
135 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
136 struct ethaddr
*rmac
);
137 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
138 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
139 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
141 /* l3-vni related APIs*/
142 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
143 static void *zl3vni_alloc(void *p
);
144 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
145 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
146 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
147 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
148 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
149 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
151 static unsigned int mac_hash_keymake(const void *p
);
152 static bool mac_cmp(const void *p1
, const void *p2
);
153 static void *zvni_mac_alloc(void *p
);
154 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
155 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
156 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
157 struct in_addr
*r_vtep_ip
);
158 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
160 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
161 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
162 uint8_t flags
, uint32_t seq
);
163 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
164 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
165 struct interface
*br_if
, vlanid_t vid
);
166 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
167 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
168 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
170 static unsigned int vni_hash_keymake(const void *p
);
171 static void *zvni_alloc(void *p
);
172 static zebra_vni_t
*zvni_lookup(vni_t vni
);
173 static zebra_vni_t
*zvni_add(vni_t vni
);
174 static int zvni_del(zebra_vni_t
*zvni
);
175 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
176 static int zvni_send_del_to_client(vni_t vni
);
177 static void zvni_build_hash_table(void);
178 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
179 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
180 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
182 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
183 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
184 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
185 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
186 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
187 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
188 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
189 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
190 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
192 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
193 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
194 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
195 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
196 zebra_mac_t
*old_zmac
,
197 zebra_mac_t
*new_zmac
,
199 static int remote_neigh_count(zebra_mac_t
*zmac
);
200 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
201 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
202 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
203 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
205 struct in_addr vtep_ip
,
209 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
211 struct in_addr vtep_ip
,
215 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
216 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
217 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
218 struct in_addr sip
, struct in_addr mcast_grp
);
219 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
220 struct in_addr sip
, struct in_addr mcast_grp
);
221 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
222 struct in_addr mcast_grp
);
223 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
224 struct in_addr mcast_grp
);
225 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
);
227 /* Private functions */
228 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
229 const struct host_rb_entry
*hle2
)
231 if (hle1
->p
.family
< hle2
->p
.family
)
234 if (hle1
->p
.family
> hle2
->p
.family
)
237 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
240 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
243 if (hle1
->p
.family
== AF_INET
) {
244 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
247 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
251 } else if (hle1
->p
.family
== AF_INET6
) {
252 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
255 zlog_debug("%s: Unexpected family type: %d",
256 __PRETTY_FUNCTION__
, hle1
->p
.family
);
260 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
262 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
264 struct host_rb_entry
*hle
;
267 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
274 * Return number of valid MACs in a VNI's MAC hash table - all
275 * remote MACs and non-internal (auto) local MACs count.
277 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
280 uint32_t num_macs
= 0;
282 struct hash_bucket
*hb
;
285 hash
= zvni
->mac_table
;
288 for (i
= 0; i
< hash
->size
; i
++) {
289 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
290 mac
= (zebra_mac_t
*)hb
->data
;
291 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
292 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
293 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
301 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
304 uint32_t num_macs
= 0;
306 struct hash_bucket
*hb
;
309 hash
= zvni
->mac_table
;
312 for (i
= 0; i
< hash
->size
; i
++) {
313 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
314 mac
= (zebra_mac_t
*)hb
->data
;
315 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
323 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
326 uint32_t num_neighs
= 0;
328 struct hash_bucket
*hb
;
331 hash
= zvni
->neigh_table
;
334 for (i
= 0; i
< hash
->size
; i
++) {
335 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
336 nbr
= (zebra_neigh_t
*)hb
->data
;
337 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
345 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
347 struct zebra_vrf
*zvrf
;
349 zvrf
= zebra_vrf_get_evpn();
350 if (zvrf
&& zvrf
->advertise_gw_macip
)
353 if (zvni
&& zvni
->advertise_gw_macip
)
359 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
361 struct zebra_vrf
*zvrf
;
363 zvrf
= zebra_vrf_get_evpn();
364 if (zvrf
&& zvrf
->advertise_svi_macip
)
367 if (zvni
&& zvni
->advertise_svi_macip
)
373 /* As part Duplicate Address Detection (DAD) for IP mobility
374 * MAC binding changes, ensure to inherit duplicate flag
377 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
378 zebra_mac_t
*old_zmac
,
379 zebra_mac_t
*new_zmac
,
382 bool is_old_mac_dup
= false;
383 bool is_new_mac_dup
= false;
385 if (!zvrf
->dup_addr_detect
)
387 /* Check old or new MAC is detected as duplicate
388 * mark this neigh as duplicate
391 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
392 ZEBRA_MAC_DUPLICATE
);
394 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
395 ZEBRA_MAC_DUPLICATE
);
396 /* Old and/or new MAC can be in duplicate state,
397 * based on that IP/Neigh Inherits the flag.
398 * If New MAC is marked duplicate, inherit to the IP.
399 * If old MAC is duplicate but new MAC is not, clear
400 * duplicate flag for IP and reset detection params
401 * and let IP DAD retrigger.
403 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
404 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
405 /* Capture Duplicate detection time */
406 nbr
->dad_dup_detect_time
= monotime(NULL
);
407 /* Mark neigh inactive */
408 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
411 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
412 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
414 nbr
->detect_start_time
.tv_sec
= 0;
415 nbr
->detect_start_time
.tv_usec
= 0;
420 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
422 struct in_addr vtep_ip
,
428 struct listnode
*node
= NULL
;
429 struct timeval elapsed
= {0, 0};
430 char buf
[ETHER_ADDR_STRLEN
];
431 char buf1
[INET6_ADDRSTRLEN
];
432 bool reset_params
= false;
434 if (!(zvrf
->dup_addr_detect
&& do_dad
))
437 /* MAC is detected as duplicate,
438 * Local MAC event -> hold on advertising to BGP.
439 * Remote MAC event -> hold on installing it.
441 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
442 if (IS_ZEBRA_DEBUG_VXLAN
)
444 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
446 prefix_mac2str(&mac
->macaddr
, buf
,
448 mac
->flags
, mac
->dad_count
,
449 zvrf
->dad_freeze_time
);
451 /* For duplicate MAC do not update
452 * client but update neigh due to
455 if (zvrf
->dad_freeze
)
456 *is_dup_detect
= true;
461 /* Check if detection time (M-secs) expired.
462 * Reset learn count and detection start time.
464 monotime_since(&mac
->detect_start_time
, &elapsed
);
465 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
466 if (is_local
&& !reset_params
) {
467 /* RFC-7432: A PE/VTEP that detects a MAC mobility
468 * event via LOCAL learning starts an M-second timer.
470 * NOTE: This is the START of the probe with count is
471 * 0 during LOCAL learn event.
472 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
474 reset_params
= !mac
->dad_count
;
478 if (IS_ZEBRA_DEBUG_VXLAN
)
480 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
481 , __PRETTY_FUNCTION__
,
482 prefix_mac2str(&mac
->macaddr
, buf
,
484 mac
->flags
, mac
->dad_count
);
487 /* Start dup. addr detection (DAD) start time,
488 * ONLY during LOCAL learn.
491 monotime(&mac
->detect_start_time
);
493 } else if (!is_local
) {
494 /* For REMOTE MAC, increment detection count
495 * ONLY while in probe window, once window passed,
496 * next local learn event should trigger DAD.
501 /* For LOCAL MAC learn event, once count is reset above via either
502 * initial/start detection time or passed the probe time, the count
503 * needs to be incremented.
508 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
509 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
510 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
512 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
513 is_local
? "local update, last" :
514 "remote update, from", inet_ntoa(vtep_ip
));
516 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
518 /* Capture Duplicate detection time */
519 mac
->dad_dup_detect_time
= monotime(NULL
);
521 /* Mark all IPs/Neighs as duplicate
522 * associcated with this MAC
524 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
526 /* Ony Mark IPs which are Local */
527 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
530 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
532 nbr
->dad_dup_detect_time
= monotime(NULL
);
534 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
535 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
537 prefix_mac2str(&mac
->macaddr
,
539 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
540 is_local
? "local" : "remote");
543 /* Start auto recovery timer for this MAC */
544 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
545 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
546 if (IS_ZEBRA_DEBUG_VXLAN
)
548 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
549 , __PRETTY_FUNCTION__
,
550 prefix_mac2str(&mac
->macaddr
, buf
,
552 mac
->flags
, zvrf
->dad_freeze_time
);
554 thread_add_timer(zrouter
.master
,
555 zebra_vxlan_dad_mac_auto_recovery_exp
,
556 mac
, zvrf
->dad_freeze_time
,
557 &mac
->dad_mac_auto_recovery_timer
);
560 /* In case of local update, do not inform to client (BGPd),
561 * upd_neigh for neigh sequence change.
563 if (zvrf
->dad_freeze
)
564 *is_dup_detect
= true;
568 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
570 struct in_addr vtep_ip
,
576 struct timeval elapsed
= {0, 0};
577 char buf
[ETHER_ADDR_STRLEN
];
578 char buf1
[INET6_ADDRSTRLEN
];
579 bool reset_params
= false;
581 if (!zvrf
->dup_addr_detect
)
584 /* IP is detected as duplicate or inherit dup
585 * state, hold on to install as remote entry
586 * only if freeze is enabled.
588 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
589 if (IS_ZEBRA_DEBUG_VXLAN
)
591 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
593 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
594 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
595 nbr
->flags
, nbr
->dad_count
,
596 zvrf
->dad_freeze_time
);
598 if (zvrf
->dad_freeze
)
599 *is_dup_detect
= true;
601 /* warn-only action, neigh will be installed.
602 * freeze action, it wil not be installed.
610 /* Check if detection time (M-secs) expired.
611 * Reset learn count and detection start time.
612 * During remote mac add, count should already be 1
613 * via local learning.
615 monotime_since(&nbr
->detect_start_time
, &elapsed
);
616 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
618 if (is_local
&& !reset_params
) {
619 /* RFC-7432: A PE/VTEP that detects a MAC mobility
620 * event via LOCAL learning starts an M-second timer.
622 * NOTE: This is the START of the probe with count is
623 * 0 during LOCAL learn event.
625 reset_params
= !nbr
->dad_count
;
629 if (IS_ZEBRA_DEBUG_VXLAN
)
631 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
633 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
634 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
635 nbr
->flags
, nbr
->dad_count
);
636 /* Reset learn count but do not start detection
637 * during REMOTE learn event.
640 /* Start dup. addr detection (DAD) start time,
641 * ONLY during LOCAL learn.
644 monotime(&nbr
->detect_start_time
);
646 } else if (!is_local
) {
647 /* For REMOTE IP/Neigh, increment detection count
648 * ONLY while in probe window, once window passed,
649 * next local learn event should trigger DAD.
654 /* For LOCAL IP/Neigh learn event, once count is reset above via either
655 * initial/start detection time or passed the probe time, the count
656 * needs to be incremented.
661 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
662 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
663 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
665 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
666 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
667 is_local
? "local update, last" :
668 "remote update, from",
671 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
673 /* Capture Duplicate detection time */
674 nbr
->dad_dup_detect_time
= monotime(NULL
);
676 /* Start auto recovery timer for this IP */
677 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
678 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
679 if (IS_ZEBRA_DEBUG_VXLAN
)
681 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
683 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
684 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
685 nbr
->flags
, zvrf
->dad_freeze_time
);
687 thread_add_timer(zrouter
.master
,
688 zebra_vxlan_dad_ip_auto_recovery_exp
,
689 nbr
, zvrf
->dad_freeze_time
,
690 &nbr
->dad_ip_auto_recovery_timer
);
692 if (zvrf
->dad_freeze
)
693 *is_dup_detect
= true;
698 * Helper function to determine maximum width of neighbor IP address for
699 * display - just because we're dealing with IPv6 addresses that can
702 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
705 char buf
[INET6_ADDRSTRLEN
];
706 struct neigh_walk_ctx
*wctx
= ctxt
;
709 n
= (zebra_neigh_t
*)bucket
->data
;
711 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
713 if (width
> wctx
->addr_width
)
714 wctx
->addr_width
= width
;
719 * Print a specific neighbor entry.
721 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
724 char buf1
[ETHER_ADDR_STRLEN
];
725 char buf2
[INET6_ADDRSTRLEN
];
726 const char *type_str
;
727 const char *state_str
;
728 bool flags_present
= false;
729 struct zebra_vrf
*zvrf
= NULL
;
730 struct timeval detect_start_time
= {0, 0};
732 zvrf
= zebra_vrf_get_evpn();
736 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
737 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
738 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
740 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
741 vty
= (struct vty
*)ctxt
;
743 vty_out(vty
, "IP: %s\n",
744 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
745 vty_out(vty
, " Type: %s\n", type_str
);
746 vty_out(vty
, " State: %s\n", state_str
);
747 vty_out(vty
, " MAC: %s\n",
748 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
750 json_object_string_add(json
, "ip", buf2
);
751 json_object_string_add(json
, "type", type_str
);
752 json_object_string_add(json
, "state", state_str
);
753 json_object_string_add(json
, "mac", buf1
);
755 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
757 vty_out(vty
, " Remote VTEP: %s\n",
758 inet_ntoa(n
->r_vtep_ip
));
760 json_object_string_add(json
, "remoteVtep",
761 inet_ntoa(n
->r_vtep_ip
));
763 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
765 vty_out(vty
, " Flags: Default-gateway");
766 flags_present
= true;
768 json_object_boolean_true_add(json
, "defaultGateway");
770 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
773 flags_present
? " ,Router" : " Flags: Router");
774 flags_present
= true;
780 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
781 n
->loc_seq
, n
->rem_seq
);
783 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
784 vty_out(vty
, " Duplicate, detected at %s",
785 time_to_string(n
->dad_dup_detect_time
));
786 } else if (n
->dad_count
) {
787 monotime_since(&n
->detect_start_time
,
789 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
790 char *buf
= time_to_string(
791 n
->detect_start_time
.tv_sec
);
794 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
796 " Duplicate detection started at %s, detection count %u\n",
797 tmp_buf
, n
->dad_count
);
801 json_object_int_add(json
, "localSequence", n
->loc_seq
);
802 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
803 json_object_int_add(json
, "detectionCount",
805 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
806 json_object_boolean_true_add(json
, "isDuplicate");
808 json_object_boolean_false_add(json
, "isDuplicate");
815 * Print neighbor hash entry - called for display of all neighbors.
817 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
820 json_object
*json_vni
= NULL
, *json_row
= NULL
;
822 char buf1
[ETHER_ADDR_STRLEN
];
823 char buf2
[INET6_ADDRSTRLEN
];
824 struct neigh_walk_ctx
*wctx
= ctxt
;
825 const char *state_str
;
828 json_vni
= wctx
->json
;
829 n
= (zebra_neigh_t
*)bucket
->data
;
832 json_row
= json_object_new_object();
834 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
835 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
836 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
837 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
838 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
841 if (json_vni
== NULL
) {
842 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
843 -wctx
->addr_width
, buf2
, "local",
844 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
846 json_object_string_add(json_row
, "type", "local");
847 json_object_string_add(json_row
, "state", state_str
);
848 json_object_string_add(json_row
, "mac", buf1
);
849 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
850 json_object_boolean_true_add(
851 json_row
, "defaultGateway");
852 json_object_int_add(json_row
, "localSequence",
854 json_object_int_add(json_row
, "remoteSequence",
856 json_object_int_add(json_row
, "detectionCount",
858 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
859 json_object_boolean_true_add(json_row
,
862 json_object_boolean_false_add(json_row
,
866 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
867 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
868 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
871 if (json_vni
== NULL
) {
872 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
875 "%*s %-6s %-8s %-17s %-21s\n",
876 -wctx
->addr_width
, "Neighbor", "Type",
877 "State", "MAC", "Remote VTEP");
878 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
879 -wctx
->addr_width
, buf2
, "remote", state_str
,
880 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
882 json_object_string_add(json_row
, "type", "remote");
883 json_object_string_add(json_row
, "state", state_str
);
884 json_object_string_add(json_row
, "mac", buf1
);
885 json_object_string_add(json_row
, "remoteVtep",
886 inet_ntoa(n
->r_vtep_ip
));
887 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
888 json_object_boolean_true_add(json_row
,
890 json_object_int_add(json_row
, "localSequence",
892 json_object_int_add(json_row
, "remoteSequence",
894 json_object_int_add(json_row
, "detectionCount",
896 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
897 json_object_boolean_true_add(json_row
,
900 json_object_boolean_false_add(json_row
,
907 json_object_object_add(json_vni
, buf2
, json_row
);
911 * Print neighbor hash entry in detail - called for display of all neighbors.
913 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
916 json_object
*json_vni
= NULL
, *json_row
= NULL
;
918 char buf
[INET6_ADDRSTRLEN
];
919 struct neigh_walk_ctx
*wctx
= ctxt
;
922 json_vni
= wctx
->json
;
923 n
= (zebra_neigh_t
*)bucket
->data
;
927 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
929 json_row
= json_object_new_object();
931 zvni_print_neigh(n
, vty
, json_row
);
934 json_object_object_add(json_vni
, buf
, json_row
);
938 * Print neighbors for all VNI.
940 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
944 json_object
*json
= NULL
, *json_vni
= NULL
;
947 struct neigh_walk_ctx wctx
;
948 char vni_str
[VNI_STR_LEN
];
951 vty
= (struct vty
*)args
[0];
952 json
= (json_object
*)args
[1];
953 print_dup
= (uint32_t)(uintptr_t)args
[2];
955 zvni
= (zebra_vni_t
*)bucket
->data
;
957 num_neigh
= hashcount(zvni
->neigh_table
);
960 num_neigh
= num_dup_detected_neighs(zvni
);
964 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
965 zvni
->vni
, num_neigh
);
967 json_vni
= json_object_new_object();
968 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
969 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
974 json_object_object_add(json
, vni_str
, json_vni
);
978 /* Since we have IPv6 addresses to deal with which can vary widely in
979 * size, we try to be a bit more elegant in display by first computing
982 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
985 wctx
.addr_width
= 15;
986 wctx
.json
= json_vni
;
987 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
990 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
991 -wctx
.addr_width
, "IP", "Type",
992 "State", "MAC", "Remote VTEP", "Seq #'s");
995 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
998 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1001 json_object_object_add(json
, vni_str
, json_vni
);
1004 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1008 nbr
= (zebra_neigh_t
*)bucket
->data
;
1012 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1013 zvni_print_neigh_hash(bucket
, ctxt
);
1016 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1021 nbr
= (zebra_neigh_t
*)bucket
->data
;
1025 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1026 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1030 * Print neighbors for all VNIs in detail.
1032 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1036 json_object
*json
= NULL
, *json_vni
= NULL
;
1039 struct neigh_walk_ctx wctx
;
1040 char vni_str
[VNI_STR_LEN
];
1043 vty
= (struct vty
*)args
[0];
1044 json
= (json_object
*)args
[1];
1045 print_dup
= (uint32_t)(uintptr_t)args
[2];
1047 zvni
= (zebra_vni_t
*)bucket
->data
;
1050 vty_out(vty
, "{}\n");
1053 num_neigh
= hashcount(zvni
->neigh_table
);
1055 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1060 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1061 zvni
->vni
, num_neigh
);
1063 json_vni
= json_object_new_object();
1064 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1065 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1069 json_object_object_add(json
, vni_str
, json_vni
);
1073 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1076 wctx
.addr_width
= 15;
1077 wctx
.json
= json_vni
;
1080 hash_iterate(zvni
->neigh_table
,
1081 zvni_print_dad_neigh_hash_detail
, &wctx
);
1083 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1087 json_object_object_add(json
, vni_str
, json_vni
);
1090 /* print a specific next hop for an l3vni */
1091 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1094 char buf1
[ETHER_ADDR_STRLEN
];
1095 char buf2
[INET6_ADDRSTRLEN
];
1096 json_object
*json_hosts
= NULL
;
1097 struct host_rb_entry
*hle
;
1100 vty_out(vty
, "Ip: %s\n",
1101 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1102 vty_out(vty
, " RMAC: %s\n",
1103 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1104 vty_out(vty
, " Refcount: %d\n",
1105 rb_host_count(&n
->host_rb
));
1106 vty_out(vty
, " Prefixes:\n");
1107 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1108 vty_out(vty
, " %s\n",
1109 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1111 json_hosts
= json_object_new_array();
1112 json_object_string_add(
1113 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1114 json_object_string_add(
1116 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1117 json_object_int_add(json
, "refCount",
1118 rb_host_count(&n
->host_rb
));
1119 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1120 json_object_array_add(json_hosts
,
1121 json_object_new_string(prefix2str(
1122 &hle
->p
, buf2
, sizeof(buf2
))));
1123 json_object_object_add(json
, "prefixList", json_hosts
);
1127 /* Print a specific RMAC entry */
1128 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1131 char buf1
[ETHER_ADDR_STRLEN
];
1132 char buf2
[PREFIX_STRLEN
];
1133 json_object
*json_hosts
= NULL
;
1134 struct host_rb_entry
*hle
;
1137 vty_out(vty
, "MAC: %s\n",
1138 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1139 vty_out(vty
, " Remote VTEP: %s\n",
1140 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1141 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1142 vty_out(vty
, " Prefixes:\n");
1143 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1144 vty_out(vty
, " %s\n",
1145 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1147 json_hosts
= json_object_new_array();
1148 json_object_string_add(
1150 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1151 json_object_string_add(json
, "vtepIp",
1152 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1153 json_object_int_add(json
, "refCount",
1154 rb_host_count(&zrmac
->host_rb
));
1155 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1156 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1157 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1158 json_object_array_add(
1160 json_object_new_string(prefix2str(
1161 &hle
->p
, buf2
, sizeof(buf2
))));
1162 json_object_object_add(json
, "prefixList", json_hosts
);
1167 * Print a specific MAC entry.
1169 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1172 zebra_neigh_t
*n
= NULL
;
1173 struct listnode
*node
= NULL
;
1174 char buf1
[ETHER_ADDR_STRLEN
];
1175 char buf2
[INET6_ADDRSTRLEN
];
1176 struct zebra_vrf
*zvrf
;
1177 struct timeval detect_start_time
= {0, 0};
1179 zvrf
= zebra_vrf_get_evpn();
1183 vty
= (struct vty
*)ctxt
;
1184 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1187 json_object
*json_mac
= json_object_new_object();
1189 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1190 struct zebra_ns
*zns
;
1191 struct interface
*ifp
;
1194 ifindex
= mac
->fwd_info
.local
.ifindex
;
1195 zns
= zebra_ns_lookup(NS_DEFAULT
);
1196 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1199 json_object_string_add(json_mac
, "type", "local");
1200 json_object_string_add(json_mac
, "intf", ifp
->name
);
1201 json_object_int_add(json_mac
, "ifindex", ifindex
);
1202 if (mac
->fwd_info
.local
.vid
)
1203 json_object_int_add(json_mac
, "vlan",
1204 mac
->fwd_info
.local
.vid
);
1205 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1206 json_object_string_add(json_mac
, "type", "remote");
1207 json_object_string_add(
1208 json_mac
, "remoteVtep",
1209 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1210 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1211 json_object_string_add(json_mac
, "type", "auto");
1213 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1214 json_object_boolean_true_add(json_mac
, "stickyMac");
1216 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1217 json_object_boolean_true_add(json_mac
,
1220 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1221 json_object_boolean_true_add(json_mac
,
1222 "remoteGatewayMac");
1224 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1225 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1227 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1228 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1229 json_object_boolean_true_add(json_mac
, "isDuplicate");
1231 json_object_boolean_false_add(json_mac
, "isDuplicate");
1233 /* print all the associated neigh */
1234 if (!listcount(mac
->neigh_list
))
1235 json_object_string_add(json_mac
, "neighbors", "none");
1237 json_object
*json_active_nbrs
= json_object_new_array();
1238 json_object
*json_inactive_nbrs
=
1239 json_object_new_array();
1240 json_object
*json_nbrs
= json_object_new_object();
1242 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1243 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1244 json_object_array_add(
1246 json_object_new_string(
1251 json_object_array_add(
1253 json_object_new_string(
1259 json_object_object_add(json_nbrs
, "active",
1261 json_object_object_add(json_nbrs
, "inactive",
1262 json_inactive_nbrs
);
1263 json_object_object_add(json_mac
, "neighbors",
1267 json_object_object_add(json
, buf1
, json_mac
);
1269 vty_out(vty
, "MAC: %s\n", buf1
);
1271 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1272 struct zebra_ns
*zns
;
1273 struct interface
*ifp
;
1276 ifindex
= mac
->fwd_info
.local
.ifindex
;
1277 zns
= zebra_ns_lookup(NS_DEFAULT
);
1278 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1281 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1282 if (mac
->fwd_info
.local
.vid
)
1283 vty_out(vty
, " VLAN: %u",
1284 mac
->fwd_info
.local
.vid
);
1285 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1286 vty_out(vty
, " Remote VTEP: %s",
1287 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1288 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1289 vty_out(vty
, " Auto Mac ");
1292 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1293 vty_out(vty
, " Sticky Mac ");
1295 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1296 vty_out(vty
, " Default-gateway Mac ");
1298 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1299 vty_out(vty
, " Remote-gateway Mac ");
1302 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1306 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1307 vty_out(vty
, " Duplicate, detected at %s",
1308 time_to_string(mac
->dad_dup_detect_time
));
1309 } else if (mac
->dad_count
) {
1310 monotime_since(&mac
->detect_start_time
,
1311 &detect_start_time
);
1312 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1313 char *buf
= time_to_string(
1314 mac
->detect_start_time
.tv_sec
);
1317 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1319 " Duplicate detection started at %s, detection count %u\n",
1320 tmp_buf
, mac
->dad_count
);
1324 /* print all the associated neigh */
1325 vty_out(vty
, " Neighbors:\n");
1326 if (!listcount(mac
->neigh_list
))
1327 vty_out(vty
, " No Neighbors\n");
1329 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1330 vty_out(vty
, " %s %s\n",
1331 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1332 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1343 * Print MAC hash entry - called for display of all MACs.
1345 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1348 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1350 char buf1
[ETHER_ADDR_STRLEN
];
1351 struct mac_walk_ctx
*wctx
= ctxt
;
1354 json_mac_hdr
= wctx
->json
;
1355 mac
= (zebra_mac_t
*)bucket
->data
;
1357 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1360 json_mac
= json_object_new_object();
1362 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1363 struct zebra_ns
*zns
;
1365 struct interface
*ifp
;
1368 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1371 zns
= zebra_ns_lookup(NS_DEFAULT
);
1372 ifindex
= mac
->fwd_info
.local
.ifindex
;
1373 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1374 if (!ifp
) // unexpected
1376 vid
= mac
->fwd_info
.local
.vid
;
1377 if (json_mac_hdr
== NULL
)
1378 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1381 json_object_string_add(json_mac
, "type", "local");
1382 json_object_string_add(json_mac
, "intf", ifp
->name
);
1385 if (json_mac_hdr
== NULL
)
1386 vty_out(vty
, " %-5u", vid
);
1388 json_object_int_add(json_mac
, "vlan", vid
);
1390 if (json_mac_hdr
== NULL
) {
1393 json_object_int_add(json_mac
, "localSequence",
1395 json_object_int_add(json_mac
, "remoteSequence",
1397 json_object_int_add(json_mac
, "detectionCount",
1399 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1400 json_object_boolean_true_add(json_mac
,
1403 json_object_boolean_false_add(json_mac
,
1405 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1410 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1412 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1413 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1417 if (json_mac_hdr
== NULL
) {
1418 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1419 (wctx
->count
== 0)) {
1420 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1421 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1422 "Type", "Intf/Remote VTEP", "VLAN");
1424 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1425 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1427 json_object_string_add(json_mac
, "type", "remote");
1428 json_object_string_add(json_mac
, "remoteVtep",
1429 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1430 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1431 json_object_int_add(json_mac
, "localSequence",
1433 json_object_int_add(json_mac
, "remoteSequence",
1435 json_object_int_add(json_mac
, "detectionCount",
1437 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1438 json_object_boolean_true_add(json_mac
,
1441 json_object_boolean_false_add(json_mac
,
1450 /* Print Duplicate MAC */
1451 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1455 mac
= (zebra_mac_t
*)bucket
->data
;
1459 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1460 zvni_print_mac_hash(bucket
, ctxt
);
1464 * Print MAC hash entry in detail - called for display of all MACs.
1466 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1469 json_object
*json_mac_hdr
= NULL
;
1471 struct mac_walk_ctx
*wctx
= ctxt
;
1472 char buf1
[ETHER_ADDR_STRLEN
];
1475 json_mac_hdr
= wctx
->json
;
1476 mac
= (zebra_mac_t
*)bucket
->data
;
1481 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1483 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1486 /* Print Duplicate MAC in detail */
1487 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1492 mac
= (zebra_mac_t
*)bucket
->data
;
1496 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1497 zvni_print_mac_hash_detail(bucket
, ctxt
);
1501 * Print MACs for all VNI.
1503 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1506 json_object
*json
= NULL
, *json_vni
= NULL
;
1507 json_object
*json_mac
= NULL
;
1510 struct mac_walk_ctx
*wctx
= ctxt
;
1511 char vni_str
[VNI_STR_LEN
];
1513 vty
= (struct vty
*)wctx
->vty
;
1514 json
= (struct json_object
*)wctx
->json
;
1516 zvni
= (zebra_vni_t
*)bucket
->data
;
1519 /*We are iterating over a new VNI, set the count to 0*/
1522 num_macs
= num_valid_macs(zvni
);
1526 if (wctx
->print_dup
)
1527 num_macs
= num_dup_detected_macs(zvni
);
1530 json_vni
= json_object_new_object();
1531 json_mac
= json_object_new_object();
1532 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1535 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1537 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1538 zvni
->vni
, num_macs
);
1539 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1540 "Intf/Remote VTEP", "VLAN");
1542 json_object_int_add(json_vni
, "numMacs", num_macs
);
1547 json_object_int_add(json_vni
, "numMacs", num_macs
);
1548 json_object_object_add(json
, vni_str
, json_vni
);
1553 /* assign per-vni to wctx->json object to fill macs
1554 * under the vni. Re-assign primary json object to fill
1555 * next vni information.
1557 wctx
->json
= json_mac
;
1558 if (wctx
->print_dup
)
1559 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1561 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1565 json_object_object_add(json_vni
, "macs", json_mac
);
1566 json_object_object_add(json
, vni_str
, json_vni
);
1571 * Print MACs in detail for all VNI.
1573 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1577 json_object
*json
= NULL
, *json_vni
= NULL
;
1578 json_object
*json_mac
= NULL
;
1581 struct mac_walk_ctx
*wctx
= ctxt
;
1582 char vni_str
[VNI_STR_LEN
];
1584 vty
= (struct vty
*)wctx
->vty
;
1585 json
= (struct json_object
*)wctx
->json
;
1587 zvni
= (zebra_vni_t
*)bucket
->data
;
1590 vty_out(vty
, "{}\n");
1595 /*We are iterating over a new VNI, set the count to 0*/
1598 num_macs
= num_valid_macs(zvni
);
1602 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1606 json_vni
= json_object_new_object();
1607 json_mac
= json_object_new_object();
1608 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1611 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1613 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1614 zvni
->vni
, num_macs
);
1616 json_object_int_add(json_vni
, "numMacs", num_macs
);
1618 /* assign per-vni to wctx->json object to fill macs
1619 * under the vni. Re-assign primary json object to fill
1620 * next vni information.
1622 wctx
->json
= json_mac
;
1623 if (wctx
->print_dup
)
1624 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1627 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1631 json_object_object_add(json_vni
, "macs", json_mac
);
1632 json_object_object_add(json
, vni_str
, json_vni
);
1636 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1638 struct nh_walk_ctx
*wctx
= NULL
;
1639 struct vty
*vty
= NULL
;
1640 struct json_object
*json_vni
= NULL
;
1641 struct json_object
*json_nh
= NULL
;
1642 zebra_neigh_t
*n
= NULL
;
1643 char buf1
[ETHER_ADDR_STRLEN
];
1644 char buf2
[INET6_ADDRSTRLEN
];
1646 wctx
= (struct nh_walk_ctx
*)ctx
;
1648 json_vni
= wctx
->json
;
1650 json_nh
= json_object_new_object();
1651 n
= (zebra_neigh_t
*)bucket
->data
;
1654 vty_out(vty
, "%-15s %-17s\n",
1655 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1656 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1658 json_object_string_add(json_nh
, "nexthopIp",
1659 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1660 json_object_string_add(
1661 json_nh
, "routerMac",
1662 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1663 json_object_object_add(json_vni
,
1664 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1669 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1672 struct vty
*vty
= NULL
;
1673 json_object
*json
= NULL
;
1674 json_object
*json_vni
= NULL
;
1675 zebra_l3vni_t
*zl3vni
= NULL
;
1676 uint32_t num_nh
= 0;
1677 struct nh_walk_ctx wctx
;
1678 char vni_str
[VNI_STR_LEN
];
1680 vty
= (struct vty
*)args
[0];
1681 json
= (struct json_object
*)args
[1];
1683 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1685 num_nh
= hashcount(zl3vni
->nh_table
);
1690 json_vni
= json_object_new_object();
1691 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1695 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1696 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1698 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1700 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1702 wctx
.json
= json_vni
;
1703 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1705 json_object_object_add(json
, vni_str
, json_vni
);
1708 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1711 struct vty
*vty
= NULL
;
1712 json_object
*json
= NULL
;
1713 json_object
*json_vni
= NULL
;
1714 zebra_l3vni_t
*zl3vni
= NULL
;
1716 struct rmac_walk_ctx wctx
;
1717 char vni_str
[VNI_STR_LEN
];
1719 vty
= (struct vty
*)args
[0];
1720 json
= (struct json_object
*)args
[1];
1722 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1724 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1729 json_vni
= json_object_new_object();
1730 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1734 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1735 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1737 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1739 /* assign per-vni to wctx->json object to fill macs
1740 * under the vni. Re-assign primary json object to fill
1741 * next vni information.
1743 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1745 wctx
.json
= json_vni
;
1746 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1748 json_object_object_add(json
, vni_str
, json_vni
);
1751 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1753 zebra_mac_t
*zrmac
= NULL
;
1754 struct rmac_walk_ctx
*wctx
= NULL
;
1755 struct vty
*vty
= NULL
;
1756 struct json_object
*json
= NULL
;
1757 struct json_object
*json_rmac
= NULL
;
1758 char buf
[ETHER_ADDR_STRLEN
];
1760 wctx
= (struct rmac_walk_ctx
*)ctx
;
1764 json_rmac
= json_object_new_object();
1765 zrmac
= (zebra_mac_t
*)bucket
->data
;
1768 vty_out(vty
, "%-17s %-21s\n",
1769 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1770 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1772 json_object_string_add(
1773 json_rmac
, "routerMac",
1774 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1775 json_object_string_add(json_rmac
, "vtepIp",
1776 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1777 json_object_object_add(
1778 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1783 /* print a specific L3 VNI entry */
1784 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1786 char buf
[ETHER_ADDR_STRLEN
];
1787 struct vty
*vty
= NULL
;
1788 json_object
*json
= NULL
;
1789 zebra_vni_t
*zvni
= NULL
;
1790 json_object
*json_vni_list
= NULL
;
1791 struct listnode
*node
= NULL
, *nnode
= NULL
;
1797 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1798 vty_out(vty
, " Type: %s\n", "L3");
1799 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1800 vty_out(vty
, " Local Vtep Ip: %s\n",
1801 inet_ntoa(zl3vni
->local_vtep_ip
));
1802 vty_out(vty
, " Vxlan-Intf: %s\n",
1803 zl3vni_vxlan_if_name(zl3vni
));
1804 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1805 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1806 vty_out(vty
, " VNI Filter: %s\n",
1807 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1808 ? "prefix-routes-only"
1810 vty_out(vty
, " Router MAC: %s\n",
1811 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1812 vty_out(vty
, " L2 VNIs: ");
1813 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1814 vty_out(vty
, "%u ", zvni
->vni
);
1817 json_vni_list
= json_object_new_array();
1818 json_object_int_add(json
, "vni", zl3vni
->vni
);
1819 json_object_string_add(json
, "type", "L3");
1820 json_object_string_add(json
, "localVtepIp",
1821 inet_ntoa(zl3vni
->local_vtep_ip
));
1822 json_object_string_add(json
, "vxlanIntf",
1823 zl3vni_vxlan_if_name(zl3vni
));
1824 json_object_string_add(json
, "sviIntf",
1825 zl3vni_svi_if_name(zl3vni
));
1826 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1827 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1828 json_object_string_add(
1830 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1831 json_object_string_add(
1833 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1834 ? "prefix-routes-only"
1836 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1837 json_object_array_add(json_vni_list
,
1838 json_object_new_int(zvni
->vni
));
1840 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1845 * Print a specific VNI entry.
1847 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1850 zebra_vtep_t
*zvtep
;
1853 json_object
*json
= NULL
;
1854 json_object
*json_vtep_list
= NULL
;
1855 json_object
*json_ip_str
= NULL
;
1861 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1862 vty_out(vty
, " Type: %s\n", "L2");
1863 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1865 json_object_int_add(json
, "vni", zvni
->vni
);
1866 json_object_string_add(json
, "type", "L2");
1867 json_object_string_add(json
, "vrf",
1868 vrf_id_to_name(zvni
->vrf_id
));
1871 if (!zvni
->vxlan_if
) { // unexpected
1873 vty_out(vty
, " VxLAN interface: unknown\n");
1876 num_macs
= num_valid_macs(zvni
);
1877 num_neigh
= hashcount(zvni
->neigh_table
);
1879 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1880 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1881 vty_out(vty
, " Local VTEP IP: %s\n",
1882 inet_ntoa(zvni
->local_vtep_ip
));
1883 vty_out(vty
, " Mcast group: %s\n",
1884 inet_ntoa(zvni
->mcast_grp
));
1886 json_object_string_add(json
, "vxlanInterface",
1887 zvni
->vxlan_if
->name
);
1888 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1889 json_object_string_add(json
, "vtepIp",
1890 inet_ntoa(zvni
->local_vtep_ip
));
1891 json_object_string_add(json
, "mcastGroup",
1892 inet_ntoa(zvni
->mcast_grp
));
1893 json_object_string_add(json
, "advertiseGatewayMacip",
1894 zvni
->advertise_gw_macip
? "Yes" : "No");
1895 json_object_int_add(json
, "numMacs", num_macs
);
1896 json_object_int_add(json
, "numArpNd", num_neigh
);
1900 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1903 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1905 json_vtep_list
= json_object_new_array();
1906 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1907 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1908 zvtep
->flood_control
,
1909 VXLAN_FLOOD_STR_DEFAULT
);
1912 vty_out(vty
, " %s flood: %s\n",
1913 inet_ntoa(zvtep
->vtep_ip
),
1916 json_ip_str
= json_object_new_string(
1917 inet_ntoa(zvtep
->vtep_ip
));
1918 json_object_array_add(json_vtep_list
,
1923 json_object_object_add(json
, "numRemoteVteps",
1928 " Number of MACs (local and remote) known for this VNI: %u\n",
1931 " Number of ARPs (IPv4 and IPv6, local and remote) "
1932 "known for this VNI: %u\n",
1934 vty_out(vty
, " Advertise-gw-macip: %s\n",
1935 zvni
->advertise_gw_macip
? "Yes" : "No");
1939 /* print a L3 VNI hash entry */
1940 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1942 struct vty
*vty
= NULL
;
1943 json_object
*json
= NULL
;
1944 json_object
*json_vni
= NULL
;
1945 zebra_l3vni_t
*zl3vni
= NULL
;
1947 vty
= (struct vty
*)ctx
[0];
1948 json
= (json_object
*)ctx
[1];
1950 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1953 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1954 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1955 hashcount(zl3vni
->rmac_table
),
1956 hashcount(zl3vni
->nh_table
), "n/a",
1957 zl3vni_vrf_name(zl3vni
));
1959 char vni_str
[VNI_STR_LEN
];
1961 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1962 json_vni
= json_object_new_object();
1963 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1964 json_object_string_add(json_vni
, "vxlanIf",
1965 zl3vni_vxlan_if_name(zl3vni
));
1966 json_object_int_add(json_vni
, "numMacs",
1967 hashcount(zl3vni
->rmac_table
));
1968 json_object_int_add(json_vni
, "numArpNd",
1969 hashcount(zl3vni
->nh_table
));
1970 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1971 json_object_string_add(json_vni
, "type", "L3");
1972 json_object_string_add(json_vni
, "tenantVrf",
1973 zl3vni_vrf_name(zl3vni
));
1974 json_object_object_add(json
, vni_str
, json_vni
);
1978 /* Private Structure to pass callback data for hash iterator */
1979 struct zvni_evpn_show
{
1982 struct zebra_vrf
*zvrf
;
1985 /* print a L3 VNI hash entry in detail*/
1986 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1988 struct vty
*vty
= NULL
;
1989 zebra_l3vni_t
*zl3vni
= NULL
;
1990 json_object
*json
= NULL
;
1991 bool use_json
= false;
1992 struct zvni_evpn_show
*zes
= data
;
2000 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2002 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2008 * Print a VNI hash entry - called for display of all VNIs.
2010 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2014 zebra_vtep_t
*zvtep
;
2015 uint32_t num_vteps
= 0;
2016 uint32_t num_macs
= 0;
2017 uint32_t num_neigh
= 0;
2018 json_object
*json
= NULL
;
2019 json_object
*json_vni
= NULL
;
2020 json_object
*json_ip_str
= NULL
;
2021 json_object
*json_vtep_list
= NULL
;
2026 zvni
= (zebra_vni_t
*)bucket
->data
;
2028 zvtep
= zvni
->vteps
;
2031 zvtep
= zvtep
->next
;
2034 num_macs
= num_valid_macs(zvni
);
2035 num_neigh
= hashcount(zvni
->neigh_table
);
2037 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2039 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2040 num_macs
, num_neigh
, num_vteps
,
2041 vrf_id_to_name(zvni
->vrf_id
));
2043 char vni_str
[VNI_STR_LEN
];
2044 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2045 json_vni
= json_object_new_object();
2046 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2047 json_object_string_add(json_vni
, "type", "L2");
2048 json_object_string_add(json_vni
, "vxlanIf",
2049 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2051 json_object_int_add(json_vni
, "numMacs", num_macs
);
2052 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2053 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2054 json_object_string_add(json_vni
, "tenantVrf",
2055 vrf_id_to_name(zvni
->vrf_id
));
2057 json_vtep_list
= json_object_new_array();
2058 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2059 json_ip_str
= json_object_new_string(
2060 inet_ntoa(zvtep
->vtep_ip
));
2061 json_object_array_add(json_vtep_list
,
2064 json_object_object_add(json_vni
, "remoteVteps",
2067 json_object_object_add(json
, vni_str
, json_vni
);
2072 * Print a VNI hash entry in detail - called for display of all VNIs.
2074 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2078 json_object
*json
= NULL
;
2079 bool use_json
= false;
2080 struct zvni_evpn_show
*zes
= data
;
2088 zvni
= (zebra_vni_t
*)bucket
->data
;
2090 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2095 * Inform BGP about local MACIP.
2097 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2098 struct ipaddr
*ip
, uint8_t flags
,
2099 uint32_t seq
, int state
, uint16_t cmd
)
2101 char buf
[ETHER_ADDR_STRLEN
];
2102 char buf2
[INET6_ADDRSTRLEN
];
2104 struct zserv
*client
= NULL
;
2105 struct stream
*s
= NULL
;
2107 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2108 /* BGP may not be running. */
2112 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2114 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2115 stream_putl(s
, vni
);
2116 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2119 if (IS_IPADDR_V4(ip
))
2120 ipa_len
= IPV4_MAX_BYTELEN
;
2121 else if (IS_IPADDR_V6(ip
))
2122 ipa_len
= IPV6_MAX_BYTELEN
;
2124 stream_putl(s
, ipa_len
); /* IP address length */
2126 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2128 stream_putl(s
, 0); /* Just MAC. */
2130 if (cmd
== ZEBRA_MACIP_ADD
) {
2131 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2132 stream_putl(s
, seq
); /* sequence number */
2134 stream_putl(s
, state
); /* state - active/inactive */
2138 /* Write packet size. */
2139 stream_putw_at(s
, 0, stream_get_endp(s
));
2141 if (IS_ZEBRA_DEBUG_VXLAN
)
2143 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2144 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2145 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2146 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2147 zebra_route_string(client
->proto
));
2149 if (cmd
== ZEBRA_MACIP_ADD
)
2150 client
->macipadd_cnt
++;
2152 client
->macipdel_cnt
++;
2154 return zserv_send_message(client
, s
);
2158 * Make hash key for neighbors.
2160 static unsigned int neigh_hash_keymake(const void *p
)
2162 const zebra_neigh_t
*n
= p
;
2163 const struct ipaddr
*ip
= &n
->ip
;
2165 if (IS_IPADDR_V4(ip
))
2166 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2168 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2169 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2173 * Compare two neighbor hash structures.
2175 static bool neigh_cmp(const void *p1
, const void *p2
)
2177 const zebra_neigh_t
*n1
= p1
;
2178 const zebra_neigh_t
*n2
= p2
;
2180 if (n1
== NULL
&& n2
== NULL
)
2183 if (n1
== NULL
|| n2
== NULL
)
2186 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2189 static int neigh_list_cmp(void *p1
, void *p2
)
2191 const zebra_neigh_t
*n1
= p1
;
2192 const zebra_neigh_t
*n2
= p2
;
2194 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2198 * Callback to allocate neighbor hash entry.
2200 static void *zvni_neigh_alloc(void *p
)
2202 const zebra_neigh_t
*tmp_n
= p
;
2205 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2212 * Add neighbor entry.
2214 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2215 struct ethaddr
*mac
)
2217 zebra_neigh_t tmp_n
;
2218 zebra_neigh_t
*n
= NULL
;
2219 zebra_mac_t
*zmac
= NULL
;
2221 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2222 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2223 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2226 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2227 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2229 n
->dad_ip_auto_recovery_timer
= NULL
;
2231 /* Associate the neigh to mac */
2232 zmac
= zvni_mac_lookup(zvni
, mac
);
2234 listnode_add_sort(zmac
->neigh_list
, n
);
2240 * Delete neighbor entry.
2242 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2244 zebra_neigh_t
*tmp_n
;
2245 zebra_mac_t
*zmac
= NULL
;
2247 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2249 listnode_delete(zmac
->neigh_list
, n
);
2251 /* Cancel auto recovery */
2252 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2254 /* Free the VNI hash entry and allocated memory. */
2255 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2256 XFREE(MTYPE_NEIGH
, tmp_n
);
2262 * Free neighbor hash entry (callback)
2264 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2266 struct neigh_walk_ctx
*wctx
= arg
;
2267 zebra_neigh_t
*n
= bucket
->data
;
2269 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2270 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2271 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2272 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2273 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2274 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2275 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2276 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2277 &n
->emac
, 0, n
->state
);
2279 if (wctx
->uninstall
)
2280 zvni_neigh_uninstall(wctx
->zvni
, n
);
2282 zvni_neigh_del(wctx
->zvni
, n
);
2289 * Delete all neighbor entries from specific VTEP for a particular VNI.
2291 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2292 struct in_addr
*r_vtep_ip
)
2294 struct neigh_walk_ctx wctx
;
2296 if (!zvni
->neigh_table
)
2299 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2301 wctx
.uninstall
= uninstall
;
2302 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2303 wctx
.r_vtep_ip
= *r_vtep_ip
;
2305 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2309 * Delete all neighbor entries for this VNI.
2311 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2314 struct neigh_walk_ctx wctx
;
2316 if (!zvni
->neigh_table
)
2319 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2321 wctx
.uninstall
= uninstall
;
2322 wctx
.upd_client
= upd_client
;
2325 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2329 * Look up neighbor hash entry.
2331 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2336 memset(&tmp
, 0, sizeof(tmp
));
2337 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2338 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2344 * Process all neighbors associated with a MAC upon the MAC being learnt
2345 * locally or undergoing any other change (such as sequence number).
2347 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2351 zebra_neigh_t
*n
= NULL
;
2352 struct listnode
*node
= NULL
;
2353 struct zebra_vrf
*zvrf
= NULL
;
2354 char buf
[ETHER_ADDR_STRLEN
];
2356 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2358 if (IS_ZEBRA_DEBUG_VXLAN
)
2359 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2360 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2361 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2363 /* Walk all neighbors and mark any inactive local neighbors as
2364 * active and/or update sequence number upon a move, and inform BGP.
2365 * The action for remote neighbors is TBD.
2366 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2367 * accidentally end up deleting a just-learnt local neighbor.
2369 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2370 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2371 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2372 ZEBRA_NEIGH_SET_ACTIVE(n
);
2373 n
->loc_seq
= zmac
->loc_seq
;
2374 if (!(zvrf
->dup_addr_detect
&&
2375 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2376 ZEBRA_NEIGH_DUPLICATE
)))
2377 zvni_neigh_send_add_to_client(
2378 zvni
->vni
, &n
->ip
, &n
->emac
,
2379 n
->flags
, n
->loc_seq
);
2386 * Process all neighbors associated with a local MAC upon the MAC being
2389 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2392 zebra_neigh_t
*n
= NULL
;
2393 struct listnode
*node
= NULL
;
2394 char buf
[ETHER_ADDR_STRLEN
];
2396 if (IS_ZEBRA_DEBUG_VXLAN
)
2397 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2398 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2401 /* Walk all local neighbors and mark as inactive and inform
2403 * TBD: There is currently no handling for remote neighbors. We
2404 * don't expect them to exist, if they do, do we install the MAC
2405 * as a remote MAC and the neighbor as remote?
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 MAC upon the MAC being remotely
2423 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2426 zebra_neigh_t
*n
= NULL
;
2427 struct listnode
*node
= NULL
;
2428 char buf
[ETHER_ADDR_STRLEN
];
2430 if (IS_ZEBRA_DEBUG_VXLAN
)
2431 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2432 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2435 /* Walk all local neighbors and mark as inactive and inform
2438 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2439 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2440 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2441 ZEBRA_NEIGH_SET_INACTIVE(n
);
2443 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2444 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2451 * Process all neighbors associated with a remote MAC upon the MAC being
2454 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2457 /* NOTE: Currently a NO-OP. */
2460 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2462 zebra_neigh_t
*nbr
= NULL
;
2463 struct listnode
*node
= NULL
;
2465 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2466 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2467 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2468 zvni_neigh_probe(zvni
, nbr
);
2473 * Inform BGP about local neighbor addition.
2475 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2476 struct ethaddr
*macaddr
,
2477 uint8_t neigh_flags
,
2482 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2483 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2484 /* Set router flag (R-bit) based on local neigh entry add */
2485 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2486 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2488 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2489 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2493 * Inform BGP about local neighbor deletion.
2495 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2496 struct ethaddr
*macaddr
, uint8_t flags
,
2499 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2500 0, state
, ZEBRA_MACIP_DEL
);
2504 * Install remote neighbor into the kernel.
2506 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2508 struct zebra_if
*zif
;
2509 struct zebra_l2info_vxlan
*vxl
;
2510 struct interface
*vlan_if
;
2516 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2519 zif
= zvni
->vxlan_if
->info
;
2522 vxl
= &zif
->l2info
.vxl
;
2524 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2528 flags
= NTF_EXT_LEARNED
;
2529 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2530 flags
|= NTF_ROUTER
;
2531 ZEBRA_NEIGH_SET_ACTIVE(n
);
2532 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2538 * Uninstall remote neighbor from the kernel.
2540 static int zvni_neigh_uninstall(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 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2549 if (!zvni
->vxlan_if
) {
2550 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2555 zif
= zvni
->vxlan_if
->info
;
2558 vxl
= &zif
->l2info
.vxl
;
2559 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2563 ZEBRA_NEIGH_SET_INACTIVE(n
);
2565 return kernel_del_neigh(vlan_if
, &n
->ip
);
2569 * Probe neighbor from the kernel.
2571 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2573 struct zebra_if
*zif
;
2574 struct zebra_l2info_vxlan
*vxl
;
2575 struct interface
*vlan_if
;
2577 zif
= zvni
->vxlan_if
->info
;
2580 vxl
= &zif
->l2info
.vxl
;
2582 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2587 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2595 * Install neighbor hash entry - called upon access VLAN change.
2597 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2600 struct neigh_walk_ctx
*wctx
= ctxt
;
2602 n
= (zebra_neigh_t
*)bucket
->data
;
2604 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2605 zvni_neigh_install(wctx
->zvni
, n
);
2608 /* Get the VRR interface for SVI if any */
2609 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2611 struct zebra_vrf
*zvrf
= NULL
;
2612 struct interface
*tmp_if
= NULL
;
2613 struct zebra_if
*zif
= NULL
;
2615 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2618 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2623 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2626 if (zif
->link
== ifp
)
2633 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2635 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2636 struct connected
*c
= NULL
;
2637 struct ethaddr macaddr
;
2639 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2641 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2644 memset(&ip
, 0, sizeof(struct ipaddr
));
2645 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2648 if (c
->address
->family
== AF_INET
) {
2649 ip
.ipa_type
= IPADDR_V4
;
2650 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2651 sizeof(struct in_addr
));
2652 } else if (c
->address
->family
== AF_INET6
) {
2653 ip
.ipa_type
= IPADDR_V6
;
2654 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2655 sizeof(struct in6_addr
));
2660 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2666 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2668 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2669 struct connected
*c
= NULL
;
2670 struct ethaddr macaddr
;
2672 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2674 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2677 memset(&ip
, 0, sizeof(struct ipaddr
));
2678 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2681 if (c
->address
->family
== AF_INET
) {
2682 ip
.ipa_type
= IPADDR_V4
;
2683 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2684 sizeof(struct in_addr
));
2685 } else if (c
->address
->family
== AF_INET6
) {
2686 ip
.ipa_type
= IPADDR_V6
;
2687 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2688 sizeof(struct in6_addr
));
2693 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2699 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2702 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2703 struct connected
*c
= NULL
;
2704 struct ethaddr macaddr
;
2706 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2708 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2711 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2713 /* skip link local address */
2714 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2719 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2720 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2722 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2723 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2729 * zvni_gw_macip_add_to_client
2731 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2732 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2734 char buf
[ETHER_ADDR_STRLEN
];
2735 char buf2
[INET6_ADDRSTRLEN
];
2736 zebra_neigh_t
*n
= NULL
;
2737 zebra_mac_t
*mac
= NULL
;
2738 struct zebra_if
*zif
= NULL
;
2739 struct zebra_l2info_vxlan
*vxl
= NULL
;
2741 zif
= zvni
->vxlan_if
->info
;
2745 vxl
= &zif
->l2info
.vxl
;
2747 mac
= zvni_mac_lookup(zvni
, macaddr
);
2749 mac
= zvni_mac_add(zvni
, macaddr
);
2751 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2752 "Failed to add MAC %s intf %s(%u) VID %u",
2753 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2754 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2759 /* Set "local" forwarding info. */
2760 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2761 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2762 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2763 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2764 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2765 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2767 n
= zvni_neigh_lookup(zvni
, ip
);
2769 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2772 EC_ZEBRA_MAC_ADD_FAILED
,
2773 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2774 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2775 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2776 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2781 /* Set "local" forwarding info. */
2782 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2783 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2784 ZEBRA_NEIGH_SET_ACTIVE(n
);
2785 /* Set Router flag (R-bit) */
2786 if (ip
->ipa_type
== IPADDR_V6
)
2787 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2788 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2789 n
->ifindex
= ifp
->ifindex
;
2791 /* Only advertise in BGP if the knob is enabled */
2792 if (!advertise_gw_macip_enabled(zvni
))
2795 if (IS_ZEBRA_DEBUG_VXLAN
)
2797 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2798 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2799 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2800 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2802 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2803 n
->flags
, n
->loc_seq
);
2809 * zvni_gw_macip_del_from_client
2811 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2814 char buf1
[ETHER_ADDR_STRLEN
];
2815 char buf2
[INET6_ADDRSTRLEN
];
2816 zebra_neigh_t
*n
= NULL
;
2817 zebra_mac_t
*mac
= NULL
;
2819 /* If the neigh entry is not present nothing to do*/
2820 n
= zvni_neigh_lookup(zvni
, ip
);
2824 /* mac entry should be present */
2825 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2827 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2828 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2829 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2833 /* If the entry is not local nothing to do*/
2834 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2837 /* only need to delete the entry from bgp if we sent it before */
2838 if (IS_ZEBRA_DEBUG_VXLAN
)
2840 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2841 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2842 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2843 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2845 /* Remove neighbor from BGP. */
2846 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2847 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2849 /* Delete this neighbor entry. */
2850 zvni_neigh_del(zvni
, n
);
2852 /* see if the mac needs to be deleted as well*/
2854 zvni_deref_ip2mac(zvni
, mac
);
2859 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2862 zebra_vni_t
*zvni
= NULL
;
2863 struct zebra_if
*zif
= NULL
;
2864 struct zebra_l2info_vxlan zl2_info
;
2865 struct interface
*vlan_if
= NULL
;
2866 struct interface
*vrr_if
= NULL
;
2867 struct interface
*ifp
;
2869 /* Add primary SVI MAC*/
2870 zvni
= (zebra_vni_t
*)bucket
->data
;
2872 ifp
= zvni
->vxlan_if
;
2877 /* If down or not mapped to a bridge, we're done. */
2878 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2881 zl2_info
= zif
->l2info
.vxl
;
2884 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2888 /* Del primary MAC-IP */
2889 zvni_del_macip_for_intf(vlan_if
, zvni
);
2891 /* Del VRR MAC-IP - if any*/
2892 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2894 zvni_del_macip_for_intf(vrr_if
, zvni
);
2899 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2902 zebra_vni_t
*zvni
= NULL
;
2903 struct zebra_if
*zif
= NULL
;
2904 struct zebra_l2info_vxlan zl2_info
;
2905 struct interface
*vlan_if
= NULL
;
2906 struct interface
*vrr_if
= NULL
;
2907 struct interface
*ifp
= NULL
;
2909 zvni
= (zebra_vni_t
*)bucket
->data
;
2911 ifp
= zvni
->vxlan_if
;
2916 /* If down or not mapped to a bridge, we're done. */
2917 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2919 zl2_info
= zif
->l2info
.vxl
;
2922 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2926 /* Add primary SVI MAC-IP */
2927 zvni_add_macip_for_intf(vlan_if
, zvni
);
2929 if (advertise_gw_macip_enabled(zvni
)) {
2930 /* Add VRR MAC-IP - if any*/
2931 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2933 zvni_add_macip_for_intf(vrr_if
, zvni
);
2939 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2942 zebra_vni_t
*zvni
= NULL
;
2943 struct zebra_if
*zif
= NULL
;
2944 struct zebra_l2info_vxlan zl2_info
;
2945 struct interface
*vlan_if
= NULL
;
2946 struct interface
*ifp
;
2948 /* Add primary SVI MAC*/
2949 zvni
= (zebra_vni_t
*)bucket
->data
;
2953 ifp
= zvni
->vxlan_if
;
2958 /* If down or not mapped to a bridge, we're done. */
2959 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2962 zl2_info
= zif
->l2info
.vxl
;
2964 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2965 zif
->brslave_info
.br_if
);
2969 /* Del primary MAC-IP */
2970 zvni_del_macip_for_intf(vlan_if
, zvni
);
2975 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2976 struct interface
*ifp
,
2978 struct ethaddr
*macaddr
,
2981 char buf
[ETHER_ADDR_STRLEN
];
2982 char buf2
[INET6_ADDRSTRLEN
];
2983 struct zebra_vrf
*zvrf
;
2984 zebra_neigh_t
*n
= NULL
;
2985 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2986 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2987 bool upd_mac_seq
= false;
2988 bool neigh_mac_change
= false;
2989 bool neigh_on_hold
= false;
2990 bool neigh_was_remote
= false;
2991 bool do_dad
= false;
2992 struct in_addr vtep_ip
= {.s_addr
= 0};
2994 /* Check if the MAC exists. */
2995 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2997 /* create a dummy MAC if the MAC is not already present */
2998 if (IS_ZEBRA_DEBUG_VXLAN
)
3000 "AUTO MAC %s created for neigh %s on VNI %u",
3001 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3002 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3004 zmac
= zvni_mac_add(zvni
, macaddr
);
3006 zlog_debug("Failed to add MAC %s VNI %u",
3007 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3012 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3013 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3014 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3016 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3018 * We don't change the MAC to local upon a neighbor
3019 * learn event, we wait for the explicit local MAC
3020 * learn. However, we have to compute its sequence
3021 * number in preparation for when it actually turns
3028 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3030 if (IS_ZEBRA_DEBUG_VXLAN
)
3031 zlog_debug("\tUnable to find vrf for: %d",
3032 zvni
->vxlan_if
->vrf_id
);
3036 /* Check if the neighbor exists. */
3037 n
= zvni_neigh_lookup(zvni
, ip
);
3039 /* New neighbor - create */
3040 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3043 EC_ZEBRA_MAC_ADD_FAILED
,
3044 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3045 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3046 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3047 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3050 /* Set "local" forwarding info. */
3051 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3052 n
->ifindex
= ifp
->ifindex
;
3054 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3058 /* Note any changes and see if of interest to BGP. */
3059 mac_different
= (memcmp(n
->emac
.octet
,
3060 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3061 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3062 ZEBRA_NEIGH_ROUTER_FLAG
);
3063 if (!mac_different
&& is_router
== cur_is_router
) {
3064 if (IS_ZEBRA_DEBUG_VXLAN
)
3066 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3067 n
->ifindex
= ifp
->ifindex
;
3071 if (!mac_different
) {
3072 bool is_neigh_freezed
= false;
3074 /* Only the router flag has changed. */
3077 ZEBRA_NEIGH_ROUTER_FLAG
);
3079 UNSET_FLAG(n
->flags
,
3080 ZEBRA_NEIGH_ROUTER_FLAG
);
3082 /* Neigh is in freeze state and freeze action
3083 * is enabled, do not send update to client.
3085 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3087 CHECK_FLAG(n
->flags
,
3088 ZEBRA_NEIGH_DUPLICATE
));
3090 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3092 return zvni_neigh_send_add_to_client(
3093 zvni
->vni
, ip
, macaddr
,
3094 n
->flags
, n
->loc_seq
);
3096 if (IS_ZEBRA_DEBUG_VXLAN
)
3098 "\tNeighbor active and frozen");
3103 /* The MAC has changed, need to issue a delete
3104 * first as this means a different MACIP route.
3105 * Also, need to do some unlinking/relinking.
3106 * We also need to update the MAC's sequence number
3107 * in different situations.
3109 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3110 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3111 &n
->emac
, 0, n
->state
);
3112 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3114 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3116 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3117 neigh_mac_change
= upd_mac_seq
= true;
3118 listnode_delete(old_zmac
->neigh_list
, n
);
3119 zvni_deref_ip2mac(zvni
, old_zmac
);
3122 /* Update the forwarding info. */
3123 n
->ifindex
= ifp
->ifindex
;
3124 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3126 /* Link to new MAC */
3127 listnode_add_sort(zmac
->neigh_list
, n
);
3128 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3130 * Neighbor has moved from remote to local. Its
3131 * MAC could have also changed as part of the move.
3133 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3135 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3137 old_mac_seq
= CHECK_FLAG(
3142 neigh_mac_change
= upd_mac_seq
= true;
3143 listnode_delete(old_zmac
->neigh_list
,
3145 zvni_deref_ip2mac(zvni
, old_zmac
);
3148 /* Link to new MAC */
3149 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3150 listnode_add_sort(zmac
->neigh_list
, n
);
3152 /* Based on Mobility event Scenario-B from the
3153 * draft, neigh's previous state was remote treat this
3156 neigh_was_remote
= true;
3157 vtep_ip
= n
->r_vtep_ip
;
3158 /* Mark appropriately */
3159 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3160 n
->r_vtep_ip
.s_addr
= 0;
3161 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3162 n
->ifindex
= ifp
->ifindex
;
3166 /* If MAC was previously remote, or the neighbor had a different
3167 * MAC earlier, recompute the sequence number.
3170 uint32_t seq1
, seq2
;
3172 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3173 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3174 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3175 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3176 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3179 /* Mark Router flag (R-bit) */
3181 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3183 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3185 /* Check old and/or new MAC detected as duplicate mark
3186 * the neigh as duplicate
3188 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3189 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3190 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3192 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3193 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3196 /* For IP Duplicate Address Detection (DAD) is trigger,
3197 * when the event is extended mobility based on scenario-B
3198 * from the draft, IP/Neigh's MAC binding changed and
3199 * neigh's previous state was remote.
3201 if (neigh_mac_change
&& neigh_was_remote
)
3204 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3205 &neigh_on_hold
, true);
3207 /* Before we program this in BGP, we need to check if MAC is locally
3208 * learnt. If not, force neighbor to be inactive and reset its seq.
3210 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3211 ZEBRA_NEIGH_SET_INACTIVE(n
);
3213 zmac
->loc_seq
= mac_new_seq
;
3217 /* If the MAC's sequence number has changed, inform the MAC and all
3218 * neighbors associated with the MAC to BGP, else just inform this
3221 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3222 if (IS_ZEBRA_DEBUG_VXLAN
)
3223 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3224 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3225 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3226 zmac
->loc_seq
= mac_new_seq
;
3227 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3228 zmac
->flags
, zmac
->loc_seq
))
3230 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3234 n
->loc_seq
= zmac
->loc_seq
;
3236 if (!neigh_on_hold
) {
3237 ZEBRA_NEIGH_SET_ACTIVE(n
);
3239 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3240 n
->flags
, n
->loc_seq
);
3242 if (IS_ZEBRA_DEBUG_VXLAN
)
3243 zlog_debug("\tNeighbor on hold not sending");
3248 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3249 struct interface
*ifp
,
3251 struct ethaddr
*macaddr
,
3254 char buf
[ETHER_ADDR_STRLEN
];
3255 char buf2
[INET6_ADDRSTRLEN
];
3256 zebra_neigh_t
*n
= NULL
;
3257 zebra_mac_t
*zmac
= NULL
;
3259 /* If the neighbor is unknown, there is no further action. */
3260 n
= zvni_neigh_lookup(zvni
, ip
);
3264 /* If a remote entry, see if it needs to be refreshed */
3265 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3267 if (state
& NUD_STALE
)
3268 zvni_neigh_install(zvni
, n
);
3271 /* We got a "remote" neighbor notification for an entry
3272 * we think is local. This can happen in a multihoming
3273 * scenario - but only if the MAC is already "remote".
3274 * Just mark our entry as "remote".
3276 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3277 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3279 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3280 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3281 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3286 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3287 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3288 ZEBRA_NEIGH_SET_ACTIVE(n
);
3289 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3296 * Make hash key for MAC.
3298 static unsigned int mac_hash_keymake(const void *p
)
3300 const zebra_mac_t
*pmac
= p
;
3301 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3303 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3307 * Compare two MAC addresses.
3309 static bool mac_cmp(const void *p1
, const void *p2
)
3311 const zebra_mac_t
*pmac1
= p1
;
3312 const zebra_mac_t
*pmac2
= p2
;
3314 if (pmac1
== NULL
&& pmac2
== NULL
)
3317 if (pmac1
== NULL
|| pmac2
== NULL
)
3320 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3325 * Callback to allocate MAC hash entry.
3327 static void *zvni_mac_alloc(void *p
)
3329 const zebra_mac_t
*tmp_mac
= p
;
3332 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3335 return ((void *)mac
);
3341 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3343 zebra_mac_t tmp_mac
;
3344 zebra_mac_t
*mac
= NULL
;
3346 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3347 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3348 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3352 mac
->dad_mac_auto_recovery_timer
= NULL
;
3354 mac
->neigh_list
= list_new();
3355 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3363 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3365 zebra_mac_t
*tmp_mac
;
3367 /* Cancel auto recovery */
3368 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3370 list_delete(&mac
->neigh_list
);
3372 /* Free the VNI hash entry and allocated memory. */
3373 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3374 XFREE(MTYPE_MAC
, tmp_mac
);
3380 * Free MAC hash entry (callback)
3382 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3384 struct mac_walk_ctx
*wctx
= arg
;
3385 zebra_mac_t
*mac
= bucket
->data
;
3387 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3388 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3389 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3390 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3391 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3392 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3393 &wctx
->r_vtep_ip
))) {
3394 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3395 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3399 if (wctx
->uninstall
)
3400 zvni_mac_uninstall(wctx
->zvni
, mac
);
3402 zvni_mac_del(wctx
->zvni
, mac
);
3409 * Delete all MAC entries from specific VTEP for a particular VNI.
3411 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3412 struct in_addr
*r_vtep_ip
)
3414 struct mac_walk_ctx wctx
;
3416 if (!zvni
->mac_table
)
3419 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3421 wctx
.uninstall
= uninstall
;
3422 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3423 wctx
.r_vtep_ip
= *r_vtep_ip
;
3425 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3429 * Delete all MAC entries for this VNI.
3431 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3434 struct mac_walk_ctx wctx
;
3436 if (!zvni
->mac_table
)
3439 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3441 wctx
.uninstall
= uninstall
;
3442 wctx
.upd_client
= upd_client
;
3445 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3449 * Look up MAC hash entry.
3451 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3456 memset(&tmp
, 0, sizeof(tmp
));
3457 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3458 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3464 * Inform BGP about local MAC addition.
3466 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3467 uint8_t mac_flags
, uint32_t seq
)
3471 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3472 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3473 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3474 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3476 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3477 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3481 * Inform BGP about local MAC deletion.
3483 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3485 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3486 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3490 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3491 * notifications, to see if they are of interest.
3493 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3494 struct interface
*br_if
, vlanid_t vid
)
3496 struct zebra_ns
*zns
;
3497 struct route_node
*rn
;
3498 struct interface
*tmp_if
= NULL
;
3499 struct zebra_if
*zif
;
3500 struct zebra_l2info_bridge
*br
;
3501 struct zebra_l2info_vxlan
*vxl
= NULL
;
3502 uint8_t bridge_vlan_aware
;
3506 /* Determine if bridge is VLAN-aware or not */
3509 br
= &zif
->l2info
.br
;
3510 bridge_vlan_aware
= br
->vlan_aware
;
3512 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3513 /* TODO: Optimize with a hash. */
3514 zns
= zebra_ns_lookup(NS_DEFAULT
);
3515 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3516 tmp_if
= (struct interface
*)rn
->info
;
3520 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3522 if (!if_is_operative(tmp_if
))
3524 vxl
= &zif
->l2info
.vxl
;
3526 if (zif
->brslave_info
.br_if
!= br_if
)
3529 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3538 zvni
= zvni_lookup(vxl
->vni
);
3543 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3544 * neighbor notifications, to see if they are of interest.
3546 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3547 struct interface
*br_if
)
3549 struct zebra_ns
*zns
;
3550 struct route_node
*rn
;
3551 struct interface
*tmp_if
= NULL
;
3552 struct zebra_if
*zif
;
3553 struct zebra_l2info_bridge
*br
;
3554 struct zebra_l2info_vxlan
*vxl
= NULL
;
3555 uint8_t bridge_vlan_aware
;
3563 /* Make sure the linked interface is a bridge. */
3564 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3567 /* Determine if bridge is VLAN-aware or not */
3570 br
= &zif
->l2info
.br
;
3571 bridge_vlan_aware
= br
->vlan_aware
;
3572 if (bridge_vlan_aware
) {
3573 struct zebra_l2info_vlan
*vl
;
3575 if (!IS_ZEBRA_IF_VLAN(ifp
))
3580 vl
= &zif
->l2info
.vl
;
3584 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3585 /* TODO: Optimize with a hash. */
3586 zns
= zebra_ns_lookup(NS_DEFAULT
);
3587 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3588 tmp_if
= (struct interface
*)rn
->info
;
3592 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3594 if (!if_is_operative(tmp_if
))
3596 vxl
= &zif
->l2info
.vxl
;
3598 if (zif
->brslave_info
.br_if
!= br_if
)
3601 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3610 zvni
= zvni_lookup(vxl
->vni
);
3614 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3616 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3617 * linked to the bridge
3618 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3621 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3623 struct zebra_ns
*zns
;
3624 struct route_node
*rn
;
3625 struct interface
*tmp_if
= NULL
;
3626 struct zebra_if
*zif
;
3627 struct zebra_l2info_bridge
*br
;
3628 struct zebra_l2info_vlan
*vl
;
3629 uint8_t bridge_vlan_aware
;
3632 /* Defensive check, caller expected to invoke only with valid bridge. */
3636 /* Determine if bridge is VLAN-aware or not */
3639 br
= &zif
->l2info
.br
;
3640 bridge_vlan_aware
= br
->vlan_aware
;
3642 /* Check oper status of the SVI. */
3643 if (!bridge_vlan_aware
)
3644 return if_is_operative(br_if
) ? br_if
: NULL
;
3646 /* Identify corresponding VLAN interface. */
3647 /* TODO: Optimize with a hash. */
3648 zns
= zebra_ns_lookup(NS_DEFAULT
);
3649 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3650 tmp_if
= (struct interface
*)rn
->info
;
3651 /* Check oper status of the SVI. */
3652 if (!tmp_if
|| !if_is_operative(tmp_if
))
3655 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3656 || zif
->link
!= br_if
)
3658 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3660 if (vl
->vid
== vid
) {
3666 return found
? tmp_if
: NULL
;
3670 * Install remote MAC into the kernel.
3672 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3674 struct zebra_if
*zif
;
3675 struct zebra_l2info_vxlan
*vxl
;
3678 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3681 zif
= zvni
->vxlan_if
->info
;
3684 vxl
= &zif
->l2info
.vxl
;
3686 sticky
= !!CHECK_FLAG(mac
->flags
,
3687 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3689 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3690 mac
->fwd_info
.r_vtep_ip
, sticky
);
3694 * Uninstall remote MAC from the kernel.
3696 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3698 struct zebra_if
*zif
;
3699 struct zebra_l2info_vxlan
*vxl
;
3700 struct in_addr vtep_ip
;
3701 struct interface
*ifp
;
3703 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3706 if (!zvni
->vxlan_if
) {
3707 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3712 zif
= zvni
->vxlan_if
->info
;
3715 vxl
= &zif
->l2info
.vxl
;
3717 ifp
= zvni
->vxlan_if
;
3718 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3720 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3724 * Install MAC hash entry - called upon access VLAN change.
3726 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3729 struct mac_walk_ctx
*wctx
= ctxt
;
3731 mac
= (zebra_mac_t
*)bucket
->data
;
3733 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3734 zvni_mac_install(wctx
->zvni
, mac
);
3738 * Count of remote neighbors referencing this MAC.
3740 static int remote_neigh_count(zebra_mac_t
*zmac
)
3742 zebra_neigh_t
*n
= NULL
;
3743 struct listnode
*node
= NULL
;
3746 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3747 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3755 * Decrement neighbor refcount of MAC; uninstall and free it if
3758 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3760 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3763 /* If all remote neighbors referencing a remote MAC go away,
3764 * we need to uninstall the MAC.
3766 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3767 remote_neigh_count(mac
) == 0) {
3768 zvni_mac_uninstall(zvni
, mac
);
3769 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3772 /* If no neighbors, delete the MAC. */
3773 if (list_isempty(mac
->neigh_list
))
3774 zvni_mac_del(zvni
, mac
);
3778 * Read and populate local MACs and neighbors corresponding to this VNI.
3780 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3782 struct zebra_ns
*zns
;
3783 struct zebra_if
*zif
;
3784 struct interface
*vlan_if
;
3785 struct zebra_l2info_vxlan
*vxl
;
3786 struct interface
*vrr_if
;
3789 vxl
= &zif
->l2info
.vxl
;
3790 zns
= zebra_ns_lookup(NS_DEFAULT
);
3792 if (IS_ZEBRA_DEBUG_VXLAN
)
3794 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3795 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3796 zif
->brslave_info
.bridge_ifindex
);
3798 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3799 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3802 /* Add SVI MAC-IP */
3803 zvni_add_macip_for_intf(vlan_if
, zvni
);
3805 /* Add VRR MAC-IP - if any*/
3806 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3808 zvni_add_macip_for_intf(vrr_if
, zvni
);
3810 neigh_read_for_vlan(zns
, vlan_if
);
3815 * Hash function for VNI.
3817 static unsigned int vni_hash_keymake(const void *p
)
3819 const zebra_vni_t
*zvni
= p
;
3821 return (jhash_1word(zvni
->vni
, 0));
3825 * Compare 2 VNI hash entries.
3827 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3829 const zebra_vni_t
*zvni1
= p1
;
3830 const zebra_vni_t
*zvni2
= p2
;
3832 return (zvni1
->vni
== zvni2
->vni
);
3835 static int vni_list_cmp(void *p1
, void *p2
)
3837 const zebra_vni_t
*zvni1
= p1
;
3838 const zebra_vni_t
*zvni2
= p2
;
3840 if (zvni1
->vni
== zvni2
->vni
)
3842 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3846 * Callback to allocate VNI hash entry.
3848 static void *zvni_alloc(void *p
)
3850 const zebra_vni_t
*tmp_vni
= p
;
3853 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3854 zvni
->vni
= tmp_vni
->vni
;
3855 return ((void *)zvni
);
3859 * Look up VNI hash entry.
3861 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3863 struct zebra_vrf
*zvrf
;
3864 zebra_vni_t tmp_vni
;
3865 zebra_vni_t
*zvni
= NULL
;
3867 zvrf
= zebra_vrf_get_evpn();
3869 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3871 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3877 * Add VNI hash entry.
3879 static zebra_vni_t
*zvni_add(vni_t vni
)
3881 struct zebra_vrf
*zvrf
;
3882 zebra_vni_t tmp_zvni
;
3883 zebra_vni_t
*zvni
= NULL
;
3885 zvrf
= zebra_vrf_get_evpn();
3887 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3889 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3892 /* Create hash table for MAC */
3894 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3896 /* Create hash table for neighbors */
3897 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3898 "Zebra VNI Neighbor Table");
3904 * Delete VNI hash entry.
3906 static int zvni_del(zebra_vni_t
*zvni
)
3908 struct zebra_vrf
*zvrf
;
3909 zebra_vni_t
*tmp_zvni
;
3911 zvrf
= zebra_vrf_get_evpn();
3914 zvni
->vxlan_if
= NULL
;
3916 /* Remove references to the BUM mcast grp */
3917 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3919 /* Free the neighbor hash table. */
3920 hash_free(zvni
->neigh_table
);
3921 zvni
->neigh_table
= NULL
;
3923 /* Free the MAC hash table. */
3924 hash_free(zvni
->mac_table
);
3925 zvni
->mac_table
= NULL
;
3927 /* Free the VNI hash entry and allocated memory. */
3928 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3929 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3935 * Inform BGP about local VNI addition.
3937 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3939 struct zserv
*client
;
3942 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3943 /* BGP may not be running. */
3947 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3949 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3950 stream_putl(s
, zvni
->vni
);
3951 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3952 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3953 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3955 /* Write packet size. */
3956 stream_putw_at(s
, 0, stream_get_endp(s
));
3958 if (IS_ZEBRA_DEBUG_VXLAN
)
3959 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3960 inet_ntoa(zvni
->local_vtep_ip
),
3961 vrf_id_to_name(zvni
->vrf_id
),
3962 zebra_route_string(client
->proto
));
3964 client
->vniadd_cnt
++;
3965 return zserv_send_message(client
, s
);
3969 * Inform BGP about local VNI deletion.
3971 static int zvni_send_del_to_client(vni_t vni
)
3973 struct zserv
*client
;
3976 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3977 /* BGP may not be running. */
3981 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3984 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3985 stream_putl(s
, vni
);
3987 /* Write packet size. */
3988 stream_putw_at(s
, 0, stream_get_endp(s
));
3990 if (IS_ZEBRA_DEBUG_VXLAN
)
3991 zlog_debug("Send VNI_DEL %u to %s", vni
,
3992 zebra_route_string(client
->proto
));
3994 client
->vnidel_cnt
++;
3995 return zserv_send_message(client
, s
);
3999 * Build the VNI hash table by going over the VxLAN interfaces. This
4000 * is called when EVPN (advertise-all-vni) is enabled.
4002 static void zvni_build_hash_table(void)
4004 struct zebra_ns
*zns
;
4005 struct route_node
*rn
;
4006 struct interface
*ifp
;
4008 /* Walk VxLAN interfaces and create VNI hash. */
4009 zns
= zebra_ns_lookup(NS_DEFAULT
);
4010 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4012 zebra_vni_t
*zvni
= NULL
;
4013 zebra_l3vni_t
*zl3vni
= NULL
;
4014 struct zebra_if
*zif
;
4015 struct zebra_l2info_vxlan
*vxl
;
4017 ifp
= (struct interface
*)rn
->info
;
4021 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4024 vxl
= &zif
->l2info
.vxl
;
4027 /* L3-VNI and L2-VNI are handled seperately */
4028 zl3vni
= zl3vni_lookup(vni
);
4031 if (IS_ZEBRA_DEBUG_VXLAN
)
4033 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4034 ifp
->name
, ifp
->ifindex
, vni
);
4036 /* associate with vxlan_if */
4037 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4038 zl3vni
->vxlan_if
= ifp
;
4041 * we need to associate with SVI.
4042 * we can associate with svi-if only after association
4043 * with vxlan-intf is complete
4045 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4047 if (is_l3vni_oper_up(zl3vni
))
4048 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4051 struct interface
*vlan_if
= NULL
;
4053 if (IS_ZEBRA_DEBUG_VXLAN
)
4055 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4056 ifp
->name
, ifp
->ifindex
, vni
,
4057 inet_ntoa(vxl
->vtep_ip
));
4059 /* VNI hash entry is not expected to exist. */
4060 zvni
= zvni_lookup(vni
);
4063 "VNI hash already present for IF %s(%u) L2-VNI %u",
4064 ifp
->name
, ifp
->ifindex
, vni
);
4068 zvni
= zvni_add(vni
);
4071 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4072 ifp
->name
, ifp
->ifindex
, vni
);
4076 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
4077 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
4078 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
4080 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4082 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4083 zvni
->mcast_grp
= vxl
->mcast_grp
;
4085 zvni
->vxlan_if
= ifp
;
4086 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4087 zif
->brslave_info
.br_if
);
4089 zvni
->vrf_id
= vlan_if
->vrf_id
;
4090 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4092 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4096 /* Inform BGP if intf is up and mapped to bridge. */
4097 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4098 zvni_send_add_to_client(zvni
);
4104 * See if remote VTEP matches with prefix.
4106 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4108 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4112 * Locate remote VTEP in VNI hash table.
4114 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4116 zebra_vtep_t
*zvtep
;
4121 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4122 if (zvni_vtep_match(vtep_ip
, zvtep
))
4130 * Add remote VTEP to VNI hash table.
4132 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4136 zebra_vtep_t
*zvtep
;
4138 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4140 zvtep
->vtep_ip
= *vtep_ip
;
4141 zvtep
->flood_control
= flood_control
;
4144 zvni
->vteps
->prev
= zvtep
;
4145 zvtep
->next
= zvni
->vteps
;
4146 zvni
->vteps
= zvtep
;
4152 * Remove remote VTEP from VNI hash table.
4154 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4157 zvtep
->next
->prev
= zvtep
->prev
;
4159 zvtep
->prev
->next
= zvtep
->next
;
4161 zvni
->vteps
= zvtep
->next
;
4163 zvtep
->prev
= zvtep
->next
= NULL
;
4164 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4170 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4171 * uninstall from kernel if asked to.
4173 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4175 zebra_vtep_t
*zvtep
, *zvtep_next
;
4180 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4181 zvtep_next
= zvtep
->next
;
4183 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4184 zvni_vtep_del(zvni
, zvtep
);
4191 * Install remote VTEP into the kernel if the remote VTEP has asked
4192 * for head-end-replication.
4194 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4196 if (is_vxlan_flooding_head_end() &&
4197 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4198 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4204 * Uninstall remote VTEP from the kernel.
4206 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4208 if (!zvni
->vxlan_if
) {
4209 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4214 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4218 * Install or uninstall flood entries in the kernel corresponding to
4219 * remote VTEPs. This is invoked upon change to BUM handling.
4221 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4225 zebra_vtep_t
*zvtep
;
4227 zvni
= (zebra_vni_t
*)bucket
->data
;
4231 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4232 if (is_vxlan_flooding_head_end())
4233 zvni_vtep_install(zvni
, zvtep
);
4235 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4240 * Cleanup VNI/VTEP and update kernel
4242 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4244 zebra_vni_t
*zvni
= NULL
;
4245 zebra_l3vni_t
*zl3vni
= NULL
;
4246 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4248 zvni
= (zebra_vni_t
*)bucket
->data
;
4250 /* remove from l3-vni list */
4252 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4254 listnode_delete(zl3vni
->l2vnis
, zvni
);
4256 /* Free up all neighbors and MACs, if any. */
4257 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4258 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4260 /* Free up all remote VTEPs, if any. */
4261 zvni_vtep_del_all(zvni
, 1);
4263 /* Delete the hash entry. */
4268 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4270 zebra_l3vni_t
*zl3vni
= NULL
;
4272 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4274 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4277 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4278 struct prefix
*host
)
4280 struct host_rb_entry lookup
;
4281 struct host_rb_entry
*hle
;
4283 memset(&lookup
, 0, sizeof(lookup
));
4284 memcpy(&lookup
.p
, host
, sizeof(*host
));
4286 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4290 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4291 memcpy(hle
, &lookup
, sizeof(lookup
));
4293 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4296 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4298 struct host_rb_entry lookup
;
4299 struct host_rb_entry
*hle
;
4301 memset(&lookup
, 0, sizeof(lookup
));
4302 memcpy(&lookup
.p
, host
, sizeof(*host
));
4304 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4306 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4307 XFREE(MTYPE_HOST_PREFIX
, hle
);
4314 * Look up MAC hash entry.
4316 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4317 struct ethaddr
*rmac
)
4322 memset(&tmp
, 0, sizeof(tmp
));
4323 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4324 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4330 * Callback to allocate RMAC hash entry.
4332 static void *zl3vni_rmac_alloc(void *p
)
4334 const zebra_mac_t
*tmp_rmac
= p
;
4337 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4340 return ((void *)zrmac
);
4344 * Add RMAC entry to l3-vni
4346 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4348 zebra_mac_t tmp_rmac
;
4349 zebra_mac_t
*zrmac
= NULL
;
4351 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4352 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4353 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4356 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4358 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4359 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4367 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4369 zebra_mac_t
*tmp_rmac
;
4370 struct host_rb_entry
*hle
;
4372 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4373 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4375 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4376 XFREE(MTYPE_HOST_PREFIX
, hle
);
4379 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4380 XFREE(MTYPE_MAC
, tmp_rmac
);
4386 * Install remote RMAC into the kernel.
4388 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4390 struct zebra_if
*zif
= NULL
;
4391 struct zebra_l2info_vxlan
*vxl
= NULL
;
4393 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4394 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4397 zif
= zl3vni
->vxlan_if
->info
;
4401 vxl
= &zif
->l2info
.vxl
;
4403 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4404 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4408 * Uninstall remote RMAC from the kernel.
4410 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4412 char buf
[ETHER_ADDR_STRLEN
];
4413 struct zebra_if
*zif
= NULL
;
4414 struct zebra_l2info_vxlan
*vxl
= NULL
;
4416 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4417 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4420 if (!zl3vni
->vxlan_if
) {
4422 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4423 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4424 zl3vni
->vni
, zl3vni
);
4428 zif
= zl3vni
->vxlan_if
->info
;
4432 vxl
= &zif
->l2info
.vxl
;
4434 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4435 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4438 /* handle rmac add */
4439 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4440 struct ipaddr
*vtep_ip
,
4441 struct prefix
*host_prefix
)
4443 char buf
[ETHER_ADDR_STRLEN
];
4444 char buf1
[INET6_ADDRSTRLEN
];
4445 zebra_mac_t
*zrmac
= NULL
;
4447 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4450 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4453 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4454 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4456 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4459 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4460 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4462 /* install rmac in kernel */
4463 zl3vni_rmac_install(zl3vni
, zrmac
);
4466 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4472 /* handle rmac delete */
4473 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4474 struct prefix
*host_prefix
)
4476 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4478 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4479 /* uninstall from kernel */
4480 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4482 /* del the rmac entry */
4483 zl3vni_rmac_del(zl3vni
, zrmac
);
4488 * Look up nh hash entry on a l3-vni.
4490 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4495 memset(&tmp
, 0, sizeof(tmp
));
4496 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4497 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4504 * Callback to allocate NH hash entry on L3-VNI.
4506 static void *zl3vni_nh_alloc(void *p
)
4508 const zebra_neigh_t
*tmp_n
= p
;
4511 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4518 * Add neighbor entry.
4520 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4521 struct ethaddr
*mac
)
4523 zebra_neigh_t tmp_n
;
4524 zebra_neigh_t
*n
= NULL
;
4526 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4527 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4528 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4531 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4533 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4534 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4535 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4541 * Delete neighbor entry.
4543 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4545 zebra_neigh_t
*tmp_n
;
4546 struct host_rb_entry
*hle
;
4548 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4549 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4551 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4552 XFREE(MTYPE_HOST_PREFIX
, hle
);
4555 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4556 XFREE(MTYPE_NEIGH
, tmp_n
);
4562 * Install remote nh as neigh into the kernel.
4564 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4571 if (!is_l3vni_oper_up(zl3vni
))
4574 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4575 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4578 flags
= NTF_EXT_LEARNED
;
4579 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4580 flags
|= NTF_ROUTER
;
4581 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4587 * Uninstall remote nh from the kernel.
4589 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4591 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4592 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4595 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4598 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4601 /* add remote vtep as a neigh entry */
4602 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4603 struct ethaddr
*rmac
,
4604 struct prefix
*host_prefix
)
4606 char buf
[ETHER_ADDR_STRLEN
];
4607 char buf1
[INET6_ADDRSTRLEN
];
4608 zebra_neigh_t
*nh
= NULL
;
4610 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4612 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4616 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4617 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4618 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4623 /* install the nh neigh in kernel */
4624 zl3vni_nh_install(zl3vni
, nh
);
4627 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4632 /* handle nh neigh delete */
4633 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4634 struct prefix
*host_prefix
)
4636 rb_delete_host(&nh
->host_rb
, host_prefix
);
4638 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4639 /* uninstall from kernel */
4640 zl3vni_nh_uninstall(zl3vni
, nh
);
4642 /* delete the nh entry */
4643 zl3vni_nh_del(zl3vni
, nh
);
4647 /* handle neigh update from kernel - the only thing of interest is to
4648 * readd stale entries.
4650 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4654 zebra_neigh_t
*n
= NULL
;
4656 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4660 /* all next hop neigh are remote and installed by frr.
4661 * If the kernel has aged this entry, re-install.
4663 if (state
& NUD_STALE
)
4664 zl3vni_nh_install(zl3vni
, n
);
4669 /* handle neigh delete from kernel */
4670 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4672 zebra_neigh_t
*n
= NULL
;
4674 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4678 /* all next hop neigh are remote and installed by frr.
4679 * If we get an age out notification for these neigh entries, we have to
4682 zl3vni_nh_install(zl3vni
, n
);
4688 * Hash function for L3 VNI.
4690 static unsigned int l3vni_hash_keymake(const void *p
)
4692 const zebra_l3vni_t
*zl3vni
= p
;
4694 return jhash_1word(zl3vni
->vni
, 0);
4698 * Compare 2 L3 VNI hash entries.
4700 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4702 const zebra_l3vni_t
*zl3vni1
= p1
;
4703 const zebra_l3vni_t
*zl3vni2
= p2
;
4705 return (zl3vni1
->vni
== zl3vni2
->vni
);
4709 * Callback to allocate L3 VNI hash entry.
4711 static void *zl3vni_alloc(void *p
)
4713 zebra_l3vni_t
*zl3vni
= NULL
;
4714 const zebra_l3vni_t
*tmp_l3vni
= p
;
4716 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4717 zl3vni
->vni
= tmp_l3vni
->vni
;
4718 return ((void *)zl3vni
);
4722 * Look up L3 VNI hash entry.
4724 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4726 zebra_l3vni_t tmp_l3vni
;
4727 zebra_l3vni_t
*zl3vni
= NULL
;
4729 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4730 tmp_l3vni
.vni
= vni
;
4731 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4737 * Add L3 VNI hash entry.
4739 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4741 zebra_l3vni_t tmp_zl3vni
;
4742 zebra_l3vni_t
*zl3vni
= NULL
;
4744 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4745 tmp_zl3vni
.vni
= vni
;
4747 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4750 zl3vni
->vrf_id
= vrf_id
;
4751 zl3vni
->svi_if
= NULL
;
4752 zl3vni
->vxlan_if
= NULL
;
4753 zl3vni
->l2vnis
= list_new();
4754 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4756 /* Create hash table for remote RMAC */
4757 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4758 "Zebra L3-VNI RMAC-Table");
4760 /* Create hash table for neighbors */
4761 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4762 "Zebra L3-VNI next-hop table");
4768 * Delete L3 VNI hash entry.
4770 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4772 zebra_l3vni_t
*tmp_zl3vni
;
4774 /* free the list of l2vnis */
4775 list_delete(&zl3vni
->l2vnis
);
4776 zl3vni
->l2vnis
= NULL
;
4778 /* Free the rmac table */
4779 hash_free(zl3vni
->rmac_table
);
4780 zl3vni
->rmac_table
= NULL
;
4782 /* Free the nh table */
4783 hash_free(zl3vni
->nh_table
);
4784 zl3vni
->nh_table
= NULL
;
4786 /* Free the VNI hash entry and allocated memory. */
4787 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4788 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4793 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4795 struct zebra_ns
*zns
= NULL
;
4796 struct route_node
*rn
= NULL
;
4797 struct interface
*ifp
= NULL
;
4799 /* loop through all vxlan-interface */
4800 zns
= zebra_ns_lookup(NS_DEFAULT
);
4801 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4803 struct zebra_if
*zif
= NULL
;
4804 struct zebra_l2info_vxlan
*vxl
= NULL
;
4806 ifp
= (struct interface
*)rn
->info
;
4811 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4814 vxl
= &zif
->l2info
.vxl
;
4815 if (vxl
->vni
== zl3vni
->vni
) {
4816 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4824 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4826 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4827 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4832 if (!zl3vni
->vxlan_if
)
4835 zif
= zl3vni
->vxlan_if
->info
;
4839 vxl
= &zif
->l2info
.vxl
;
4841 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4844 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4846 struct zebra_vrf
*zvrf
= NULL
;
4848 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4852 return zl3vni_lookup(zvrf
->l3vni
);
4856 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4857 * neighbor notifications, to see if they are of interest.
4859 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4860 struct interface
*br_if
)
4864 uint8_t bridge_vlan_aware
= 0;
4865 zebra_l3vni_t
*zl3vni
= NULL
;
4866 struct zebra_ns
*zns
= NULL
;
4867 struct route_node
*rn
= NULL
;
4868 struct zebra_if
*zif
= NULL
;
4869 struct interface
*tmp_if
= NULL
;
4870 struct zebra_l2info_bridge
*br
= NULL
;
4871 struct zebra_l2info_vxlan
*vxl
= NULL
;
4876 /* Make sure the linked interface is a bridge. */
4877 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4880 /* Determine if bridge is VLAN-aware or not */
4883 br
= &zif
->l2info
.br
;
4884 bridge_vlan_aware
= br
->vlan_aware
;
4885 if (bridge_vlan_aware
) {
4886 struct zebra_l2info_vlan
*vl
;
4888 if (!IS_ZEBRA_IF_VLAN(ifp
))
4893 vl
= &zif
->l2info
.vl
;
4897 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4898 /* TODO: Optimize with a hash. */
4899 zns
= zebra_ns_lookup(NS_DEFAULT
);
4900 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4901 tmp_if
= (struct interface
*)rn
->info
;
4905 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4907 if (!if_is_operative(tmp_if
))
4909 vxl
= &zif
->l2info
.vxl
;
4911 if (zif
->brslave_info
.br_if
!= br_if
)
4914 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4923 zl3vni
= zl3vni_lookup(vxl
->vni
);
4928 * Inform BGP about l3-vni.
4930 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4932 struct stream
*s
= NULL
;
4933 struct zserv
*client
= NULL
;
4934 struct ethaddr rmac
;
4935 char buf
[ETHER_ADDR_STRLEN
];
4937 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4938 /* BGP may not be running. */
4943 memset(&rmac
, 0, sizeof(struct ethaddr
));
4944 zl3vni_get_rmac(zl3vni
, &rmac
);
4946 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4948 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4949 stream_putl(s
, zl3vni
->vni
);
4950 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4951 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4952 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4953 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4955 /* Write packet size. */
4956 stream_putw_at(s
, 0, stream_get_endp(s
));
4958 if (IS_ZEBRA_DEBUG_VXLAN
)
4960 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4961 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4962 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4963 inet_ntoa(zl3vni
->local_vtep_ip
),
4964 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4965 ? "prefix-routes-only"
4967 zebra_route_string(client
->proto
));
4969 client
->l3vniadd_cnt
++;
4970 return zserv_send_message(client
, s
);
4974 * Inform BGP about local l3-VNI deletion.
4976 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4978 struct stream
*s
= NULL
;
4979 struct zserv
*client
= NULL
;
4981 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4982 /* BGP may not be running. */
4986 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4988 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4989 stream_putl(s
, zl3vni
->vni
);
4991 /* Write packet size. */
4992 stream_putw_at(s
, 0, stream_get_endp(s
));
4994 if (IS_ZEBRA_DEBUG_VXLAN
)
4995 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4996 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4997 zebra_route_string(client
->proto
));
4999 client
->l3vnidel_cnt
++;
5000 return zserv_send_message(client
, s
);
5003 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5008 /* send l3vni add to BGP */
5009 zl3vni_send_add_to_client(zl3vni
);
5012 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5017 /* send l3-vni del to BGP*/
5018 zl3vni_send_del_to_client(zl3vni
);
5021 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5023 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5024 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5026 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5027 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5031 * handle transition of vni from l2 to l3 and vice versa
5033 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5036 zebra_vni_t
*zvni
= NULL
;
5038 /* There is a possibility that VNI notification was already received
5039 * from kernel and we programmed it as L2-VNI
5040 * In such a case we need to delete this L2-VNI first, so
5041 * that it can be reprogrammed as L3-VNI in the system. It is also
5042 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5043 * interface is still present in kernel. In this case to keep it
5044 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5047 /* Locate hash entry */
5048 zvni
= zvni_lookup(vni
);
5052 if (IS_ZEBRA_DEBUG_VXLAN
)
5053 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5055 /* Delete VNI from BGP. */
5056 zvni_send_del_to_client(zvni
->vni
);
5058 /* Free up all neighbors and MAC, if any. */
5059 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5060 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5062 /* Free up all remote VTEPs, if any. */
5063 zvni_vtep_del_all(zvni
, 0);
5065 /* Delete the hash entry. */
5066 if (zvni_del(zvni
)) {
5067 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5068 "Failed to del VNI hash %p, VNI %u", zvni
,
5073 /* TODO_MITESH: This needs to be thought through. We don't have
5074 * enough information at this point to reprogram the vni as
5075 * l2-vni. One way is to store the required info in l3-vni and
5076 * used it solely for this purpose
5083 /* delete and uninstall rmac hash entry */
5084 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5086 zebra_mac_t
*zrmac
= NULL
;
5087 zebra_l3vni_t
*zl3vni
= NULL
;
5089 zrmac
= (zebra_mac_t
*)bucket
->data
;
5090 zl3vni
= (zebra_l3vni_t
*)ctx
;
5091 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5092 zl3vni_rmac_del(zl3vni
, zrmac
);
5095 /* delete and uninstall nh hash entry */
5096 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5098 zebra_neigh_t
*n
= NULL
;
5099 zebra_l3vni_t
*zl3vni
= NULL
;
5101 n
= (zebra_neigh_t
*)bucket
->data
;
5102 zl3vni
= (zebra_l3vni_t
*)ctx
;
5103 zl3vni_nh_uninstall(zl3vni
, n
);
5104 zl3vni_nh_del(zl3vni
, n
);
5107 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5110 struct zserv
*client
= NULL
;
5111 struct stream
*s
= NULL
;
5112 char buf
[PREFIX_STRLEN
];
5114 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5115 /* BGP may not be running. */
5119 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5121 zclient_create_header(s
, cmd
, vrf_id
);
5122 stream_put(s
, p
, sizeof(struct prefix
));
5124 /* Write packet size. */
5125 stream_putw_at(s
, 0, stream_get_endp(s
));
5127 if (IS_ZEBRA_DEBUG_VXLAN
)
5128 zlog_debug("Send ip prefix %s %s on vrf %s",
5129 prefix2str(p
, buf
, sizeof(buf
)),
5130 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5131 vrf_id_to_name(vrf_id
));
5133 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5134 client
->prefixadd_cnt
++;
5136 client
->prefixdel_cnt
++;
5138 return zserv_send_message(client
, s
);
5141 /* re-add remote rmac if needed */
5142 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5143 struct ethaddr
*rmac
)
5145 char buf
[ETHER_ADDR_STRLEN
];
5146 zebra_mac_t
*zrmac
= NULL
;
5148 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5152 if (IS_ZEBRA_DEBUG_VXLAN
)
5153 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5154 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5156 zl3vni_rmac_install(zl3vni
, zrmac
);
5160 /* Process a remote MACIP add from BGP. */
5161 static void process_remote_macip_add(vni_t vni
,
5162 struct ethaddr
*macaddr
,
5164 struct ipaddr
*ipaddr
,
5167 struct in_addr vtep_ip
)
5170 zebra_vtep_t
*zvtep
;
5171 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5172 zebra_neigh_t
*n
= NULL
;
5173 int update_mac
= 0, update_neigh
= 0;
5174 char buf
[ETHER_ADDR_STRLEN
];
5175 char buf1
[INET6_ADDRSTRLEN
];
5176 struct interface
*ifp
= NULL
;
5177 struct zebra_if
*zif
= NULL
;
5178 struct zebra_vrf
*zvrf
;
5183 bool do_dad
= false;
5184 bool is_dup_detect
= false;
5186 /* Locate VNI hash entry - expected to exist. */
5187 zvni
= zvni_lookup(vni
);
5189 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5193 ifp
= zvni
->vxlan_if
;
5197 !if_is_operative(ifp
) ||
5199 !zif
->brslave_info
.br_if
) {
5200 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5205 /* The remote VTEP specified should normally exist, but it is
5206 * possible that when peering comes up, peer may advertise MACIP
5207 * routes before advertising type-3 routes.
5209 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5211 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5214 EC_ZEBRA_VTEP_ADD_FAILED
,
5215 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5220 zvni_vtep_install(zvni
, zvtep
);
5223 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5224 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5225 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5227 mac
= zvni_mac_lookup(zvni
, macaddr
);
5229 /* Ignore if the mac is already present as a gateway mac */
5231 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5232 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5233 if (IS_ZEBRA_DEBUG_VXLAN
)
5234 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5236 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5237 ipa_len
? " IP " : "",
5239 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5243 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5247 /* check if the remote MAC is unknown or has a change.
5248 * If so, that needs to be updated first. Note that client could
5249 * install MAC and MACIP separately or just install the latter.
5252 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5253 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5254 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5255 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5256 || seq
!= mac
->rem_seq
)
5261 mac
= zvni_mac_add(zvni
, macaddr
);
5264 "Failed to add MAC %s VNI %u Remote VTEP %s",
5265 prefix_mac2str(macaddr
, buf
,
5267 vni
, inet_ntoa(vtep_ip
));
5271 /* Is this MAC created for a MACIP? */
5273 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5275 const char *mac_type
;
5277 /* When host moves but changes its (MAC,IP)
5278 * binding, BGP may install a MACIP entry that
5279 * corresponds to "older" location of the host
5280 * in transient situations (because {IP1,M1}
5281 * is a different route from {IP1,M2}). Check
5282 * the sequence number and ignore this update
5285 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5286 tmp_seq
= mac
->loc_seq
;
5289 tmp_seq
= mac
->rem_seq
;
5290 mac_type
= "remote";
5292 if (seq
< tmp_seq
) {
5293 if (IS_ZEBRA_DEBUG_VXLAN
)
5294 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5296 prefix_mac2str(macaddr
,
5298 ipa_len
? " IP " : "",
5301 buf1
, sizeof(buf1
)) : "",
5308 /* Check MAC's curent state is local (this is the case
5309 * where MAC has moved from L->R) and check previous
5310 * detection started via local learning.
5311 * RFC-7432: A PE/VTEP that detects a MAC mobility
5312 * event via local learning starts an M-second timer.
5314 * VTEP-IP or seq. change alone is not considered
5315 * for dup. detection.
5317 * MAC is already marked duplicate set dad, then
5318 * is_dup_detect will be set to not install the entry.
5320 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5322 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5325 /* Remove local MAC from BGP. */
5326 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5327 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5329 /* Set "auto" and "remote" forwarding info. */
5330 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5331 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5332 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5333 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5336 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5338 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5341 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5343 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5345 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5346 mac
->fwd_info
.r_vtep_ip
,
5347 do_dad
, &is_dup_detect
,
5350 if (!is_dup_detect
) {
5351 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5352 /* Install the entry. */
5353 zvni_mac_install(zvni
, mac
);
5357 /* Update seq number. */
5360 /* If there is no IP, return after clearing AUTO flag of MAC. */
5362 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5369 /* Check if the remote neighbor itself is unknown or has a
5370 * change. If so, create or update and then install the entry.
5372 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5374 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5375 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5376 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5377 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5378 || seq
!= n
->rem_seq
)
5383 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5386 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5387 ipaddr2str(ipaddr
, buf1
,
5389 prefix_mac2str(macaddr
, buf
,
5391 vni
, inet_ntoa(vtep_ip
));
5398 /* When host moves but changes its (MAC,IP)
5399 * binding, BGP may install a MACIP entry that
5400 * corresponds to "older" location of the host
5401 * in transient situations (because {IP1,M1}
5402 * is a different route from {IP1,M2}). Check
5403 * the sequence number and ignore this update
5406 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5407 tmp_seq
= n
->loc_seq
;
5410 tmp_seq
= n
->rem_seq
;
5413 if (seq
< tmp_seq
) {
5414 if (IS_ZEBRA_DEBUG_VXLAN
)
5415 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5417 prefix_mac2str(macaddr
,
5420 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5425 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5426 /* MAC change, send a delete for old
5427 * neigh if learnt locally.
5429 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5430 IS_ZEBRA_NEIGH_ACTIVE(n
))
5431 zvni_neigh_send_del_to_client(
5433 &n
->emac
, 0, n
->state
);
5435 /* update neigh list for macs */
5436 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5438 listnode_delete(old_mac
->neigh_list
, n
);
5439 zvni_deref_ip2mac(zvni
, old_mac
);
5441 listnode_add_sort(mac
->neigh_list
, n
);
5442 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5444 /* Check Neigh's curent state is local
5445 * (this is the case where neigh/host has moved
5446 * from L->R) and check previous detction
5447 * started via local learning.
5449 * RFC-7432: A PE/VTEP that detects a MAC
5450 * mobilit event via local learning starts
5451 * an M-second timer.
5452 * VTEP-IP or seq. change along is not
5453 * considered for dup. detection.
5455 * Mobilty event scenario-B IP-MAC binding
5458 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5465 /* Set "remote" forwarding info. */
5466 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5467 n
->r_vtep_ip
= vtep_ip
;
5468 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5470 /* Set router flag (R-bit) to this Neighbor entry */
5471 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5472 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5474 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5476 /* Check old or new MAC detected as duplicate,
5477 * inherit duplicate flag to this neigh.
5479 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5481 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5482 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5484 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5485 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5488 /* Check duplicate address detection for IP */
5489 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5494 /* Install the entry. */
5496 zvni_neigh_install(zvni
, n
);
5499 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5501 /* Update seq number. */
5505 /* Process a remote MACIP delete from BGP. */
5506 static void process_remote_macip_del(vni_t vni
,
5507 struct ethaddr
*macaddr
,
5509 struct ipaddr
*ipaddr
,
5510 struct in_addr vtep_ip
)
5513 zebra_mac_t
*mac
= NULL
;
5514 zebra_neigh_t
*n
= NULL
;
5515 struct interface
*ifp
= NULL
;
5516 struct zebra_if
*zif
= NULL
;
5517 struct zebra_ns
*zns
;
5518 struct zebra_l2info_vxlan
*vxl
;
5519 struct zebra_vrf
*zvrf
;
5520 char buf
[ETHER_ADDR_STRLEN
];
5521 char buf1
[INET6_ADDRSTRLEN
];
5523 /* Locate VNI hash entry - expected to exist. */
5524 zvni
= zvni_lookup(vni
);
5526 if (IS_ZEBRA_DEBUG_VXLAN
)
5527 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5531 ifp
= zvni
->vxlan_if
;
5535 !if_is_operative(ifp
) ||
5537 !zif
->brslave_info
.br_if
) {
5538 if (IS_ZEBRA_DEBUG_VXLAN
)
5539 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5543 zns
= zebra_ns_lookup(NS_DEFAULT
);
5544 vxl
= &zif
->l2info
.vxl
;
5546 /* The remote VTEP specified is normally expected to exist, but
5547 * it is possible that the peer may delete the VTEP before deleting
5548 * any MACs referring to the VTEP, in which case the handler (see
5549 * remote_vtep_del) would have already deleted the MACs.
5551 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5554 mac
= zvni_mac_lookup(zvni
, macaddr
);
5556 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5559 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5560 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5561 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5565 /* If the remote mac or neighbor doesn't exist there is nothing
5566 * more to do. Otherwise, uninstall the entry and then remove it.
5571 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5573 /* Ignore the delete if this mac is a gateway mac-ip */
5574 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5575 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5577 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5579 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5580 ipa_len
? " IP " : "",
5582 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5586 /* Uninstall remote neighbor or MAC. */
5588 if (zvrf
->dad_freeze
&&
5589 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5590 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5591 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5592 struct interface
*vlan_if
;
5594 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5595 zif
->brslave_info
.br_if
);
5596 if (IS_ZEBRA_DEBUG_VXLAN
)
5597 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5598 __PRETTY_FUNCTION__
,
5599 ipaddr2str(ipaddr
, buf1
,
5600 sizeof(buf1
)), n
->flags
,
5602 neigh_read_specific_ip(ipaddr
, vlan_if
);
5605 /* When the MAC changes for an IP, it is possible the
5606 * client may update the new MAC before trying to delete the
5607 * "old" neighbor (as these are two different MACIP routes).
5608 * Do the delete only if the MAC matches.
5610 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5611 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5612 zvni_neigh_uninstall(zvni
, n
);
5613 zvni_neigh_del(zvni
, n
);
5614 zvni_deref_ip2mac(zvni
, mac
);
5617 /* DAD: when MAC is freeze state as remote learn event,
5618 * remote mac-ip delete event is received will result in freeze
5619 * entry removal, first fetch kernel for the same entry present
5620 * as LOCAL and reachable, avoid deleting this entry instead
5621 * use kerenel local entry to update during unfreeze time.
5623 if (zvrf
->dad_freeze
&&
5624 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5625 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5626 if (IS_ZEBRA_DEBUG_VXLAN
)
5627 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5628 __PRETTY_FUNCTION__
,
5629 prefix_mac2str(macaddr
, buf
,
5632 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5633 macaddr
, vxl
->access_vlan
);
5636 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5637 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5639 * the remote sequence number in the auto mac entry
5640 * needs to be reset to 0 as the mac entry may have
5641 * been removed on all VTEPs (including
5642 * the originating one)
5646 /* If all remote neighbors referencing a remote MAC
5647 * go away, we need to uninstall the MAC.
5649 if (remote_neigh_count(mac
) == 0) {
5650 zvni_mac_uninstall(zvni
, mac
);
5651 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5653 if (list_isempty(mac
->neigh_list
))
5654 zvni_mac_del(zvni
, mac
);
5656 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5662 /* Public functions */
5664 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5666 zebra_l3vni_t
*zl3vni
= NULL
;
5668 zl3vni
= zl3vni_lookup(vni
);
5672 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5675 /* handle evpn route in vrf table */
5676 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5677 struct ipaddr
*vtep_ip
,
5678 struct prefix
*host_prefix
)
5680 zebra_l3vni_t
*zl3vni
= NULL
;
5681 struct ipaddr ipv4_vtep
;
5683 zl3vni
= zl3vni_from_vrf(vrf_id
);
5684 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5688 * add the next hop neighbor -
5689 * neigh to be installed is the ipv6 nexthop neigh
5691 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5694 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5695 * address. Rmac is programmed against the ipv4 vtep because we only
5696 * support ipv4 tunnels in the h/w right now
5698 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5699 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5700 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5701 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5702 &(ipv4_vtep
.ipaddr_v4
));
5704 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5705 sizeof(struct in_addr
));
5708 * add the rmac - remote rmac to be installed is against the ipv4
5711 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5714 /* handle evpn vrf route delete */
5715 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5716 struct ipaddr
*vtep_ip
,
5717 struct prefix
*host_prefix
)
5719 zebra_l3vni_t
*zl3vni
= NULL
;
5720 zebra_neigh_t
*nh
= NULL
;
5721 zebra_mac_t
*zrmac
= NULL
;
5723 zl3vni
= zl3vni_from_vrf(vrf_id
);
5727 /* find the next hop entry and rmac entry */
5728 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5731 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5733 /* delete the next hop entry */
5734 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5736 /* delete the rmac entry */
5738 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5742 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5743 struct ethaddr
*rmac
, bool use_json
)
5745 zebra_l3vni_t
*zl3vni
= NULL
;
5746 zebra_mac_t
*zrmac
= NULL
;
5747 json_object
*json
= NULL
;
5749 if (!is_evpn_enabled()) {
5751 vty_out(vty
, "{}\n");
5756 json
= json_object_new_object();
5758 zl3vni
= zl3vni_lookup(l3vni
);
5761 vty_out(vty
, "{}\n");
5763 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5767 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5770 vty_out(vty
, "{}\n");
5773 "%% Requested RMAC doesn't exist in L3-VNI %u",
5778 zl3vni_print_rmac(zrmac
, vty
, json
);
5781 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5782 json
, JSON_C_TO_STRING_PRETTY
));
5783 json_object_free(json
);
5787 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5789 zebra_l3vni_t
*zl3vni
;
5791 struct rmac_walk_ctx wctx
;
5792 json_object
*json
= NULL
;
5794 if (!is_evpn_enabled())
5797 zl3vni
= zl3vni_lookup(l3vni
);
5800 vty_out(vty
, "{}\n");
5802 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5805 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5810 json
= json_object_new_object();
5812 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5816 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5818 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5820 json_object_int_add(json
, "numRmacs", num_rmacs
);
5822 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5825 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5826 json
, JSON_C_TO_STRING_PRETTY
));
5827 json_object_free(json
);
5831 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5833 json_object
*json
= NULL
;
5836 if (!is_evpn_enabled()) {
5838 vty_out(vty
, "{}\n");
5843 json
= json_object_new_object();
5847 hash_iterate(zrouter
.l3vni_table
,
5848 (void (*)(struct hash_bucket
*,
5849 void *))zl3vni_print_rmac_hash_all_vni
,
5853 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5854 json
, JSON_C_TO_STRING_PRETTY
));
5855 json_object_free(json
);
5859 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5860 struct ipaddr
*ip
, bool use_json
)
5862 zebra_l3vni_t
*zl3vni
= NULL
;
5863 zebra_neigh_t
*n
= NULL
;
5864 json_object
*json
= NULL
;
5866 if (!is_evpn_enabled()) {
5868 vty_out(vty
, "{}\n");
5873 json
= json_object_new_object();
5875 zl3vni
= zl3vni_lookup(l3vni
);
5878 vty_out(vty
, "{}\n");
5880 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5884 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5887 vty_out(vty
, "{}\n");
5890 "%% Requested next-hop not present for L3-VNI %u",
5895 zl3vni_print_nh(n
, vty
, json
);
5898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5899 json
, JSON_C_TO_STRING_PRETTY
));
5900 json_object_free(json
);
5904 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5907 struct nh_walk_ctx wctx
;
5908 json_object
*json
= NULL
;
5909 zebra_l3vni_t
*zl3vni
= NULL
;
5911 if (!is_evpn_enabled())
5914 zl3vni
= zl3vni_lookup(l3vni
);
5917 vty_out(vty
, "{}\n");
5919 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5923 num_nh
= hashcount(zl3vni
->nh_table
);
5928 json
= json_object_new_object();
5933 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5935 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5937 json_object_int_add(json
, "numNextHops", num_nh
);
5939 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5942 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5943 json
, JSON_C_TO_STRING_PRETTY
));
5944 json_object_free(json
);
5948 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5950 json_object
*json
= NULL
;
5953 if (!is_evpn_enabled()) {
5955 vty_out(vty
, "{}\n");
5960 json
= json_object_new_object();
5964 hash_iterate(zrouter
.l3vni_table
,
5965 (void (*)(struct hash_bucket
*,
5966 void *))zl3vni_print_nh_hash_all_vni
,
5970 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5971 json
, JSON_C_TO_STRING_PRETTY
));
5972 json_object_free(json
);
5977 * Display L3 VNI information (VTY command handler).
5979 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5982 json_object
*json
= NULL
;
5983 zebra_l3vni_t
*zl3vni
= NULL
;
5985 if (!is_evpn_enabled()) {
5987 vty_out(vty
, "{}\n");
5991 zl3vni
= zl3vni_lookup(vni
);
5994 vty_out(vty
, "{}\n");
5996 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6001 json
= json_object_new_object();
6005 zl3vni_print(zl3vni
, (void *)args
);
6008 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6009 json
, JSON_C_TO_STRING_PRETTY
));
6010 json_object_free(json
);
6014 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6015 json_object
*json_vrfs
)
6017 char buf
[ETHER_ADDR_STRLEN
];
6018 zebra_l3vni_t
*zl3vni
= NULL
;
6020 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6025 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6026 zvrf_name(zvrf
), zl3vni
->vni
,
6027 zl3vni_vxlan_if_name(zl3vni
),
6028 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6029 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6031 json_object
*json_vrf
= NULL
;
6033 json_vrf
= json_object_new_object();
6034 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6035 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6036 json_object_string_add(json_vrf
, "vxlanIntf",
6037 zl3vni_vxlan_if_name(zl3vni
));
6038 json_object_string_add(json_vrf
, "sviIntf",
6039 zl3vni_svi_if_name(zl3vni
));
6040 json_object_string_add(json_vrf
, "state",
6041 zl3vni_state2str(zl3vni
));
6042 json_object_string_add(
6043 json_vrf
, "routerMac",
6044 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6045 json_object_array_add(json_vrfs
, json_vrf
);
6050 * Display Neighbors for a VNI (VTY command handler).
6052 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6053 vni_t vni
, bool use_json
)
6057 struct neigh_walk_ctx wctx
;
6058 json_object
*json
= NULL
;
6060 if (!is_evpn_enabled())
6062 zvni
= zvni_lookup(vni
);
6065 vty_out(vty
, "{}\n");
6067 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6070 num_neigh
= hashcount(zvni
->neigh_table
);
6075 json
= json_object_new_object();
6077 /* Since we have IPv6 addresses to deal with which can vary widely in
6078 * size, we try to be a bit more elegant in display by first computing
6079 * the maximum width.
6081 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6084 wctx
.addr_width
= 15;
6086 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6090 "Number of ARPs (local and remote) known for this VNI: %u\n",
6092 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6093 -wctx
.addr_width
, "IP", "Type",
6094 "State", "MAC", "Remote VTEP");
6096 json_object_int_add(json
, "numArpNd", num_neigh
);
6098 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6100 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6101 json
, JSON_C_TO_STRING_PRETTY
));
6102 json_object_free(json
);
6107 * Display neighbors across all VNIs (VTY command handler).
6109 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6110 bool print_dup
, bool use_json
)
6112 json_object
*json
= NULL
;
6115 if (!is_evpn_enabled())
6119 json
= json_object_new_object();
6123 args
[2] = (void *)(ptrdiff_t)print_dup
;
6125 hash_iterate(zvrf
->vni_table
,
6126 (void (*)(struct hash_bucket
*,
6127 void *))zvni_print_neigh_hash_all_vni
,
6130 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6131 json
, JSON_C_TO_STRING_PRETTY
));
6132 json_object_free(json
);
6137 * Display neighbors across all VNIs in detail(VTY command handler).
6139 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6140 struct zebra_vrf
*zvrf
,
6141 bool print_dup
, bool use_json
)
6143 json_object
*json
= NULL
;
6146 if (!is_evpn_enabled())
6150 json
= json_object_new_object();
6154 args
[2] = (void *)(ptrdiff_t)print_dup
;
6156 hash_iterate(zvrf
->vni_table
,
6157 (void (*)(struct hash_bucket
*,
6158 void *))zvni_print_neigh_hash_all_vni_detail
,
6161 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6162 json
, JSON_C_TO_STRING_PRETTY
));
6163 json_object_free(json
);
6168 * Display specific neighbor for a VNI, if present (VTY command handler).
6170 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6171 struct zebra_vrf
*zvrf
, vni_t vni
,
6172 struct ipaddr
*ip
, bool use_json
)
6176 json_object
*json
= NULL
;
6178 if (!is_evpn_enabled())
6180 zvni
= zvni_lookup(vni
);
6183 vty_out(vty
, "{}\n");
6185 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6188 n
= zvni_neigh_lookup(zvni
, ip
);
6192 "%% Requested neighbor does not exist in VNI %u\n",
6197 json
= json_object_new_object();
6199 zvni_print_neigh(n
, vty
, json
);
6202 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6203 json
, JSON_C_TO_STRING_PRETTY
));
6204 json_object_free(json
);
6209 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6210 * By definition, these are remote neighbors.
6212 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6213 vni_t vni
, struct in_addr vtep_ip
,
6218 struct neigh_walk_ctx wctx
;
6219 json_object
*json
= NULL
;
6221 if (!is_evpn_enabled())
6223 zvni
= zvni_lookup(vni
);
6226 vty_out(vty
, "{}\n");
6228 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6231 num_neigh
= hashcount(zvni
->neigh_table
);
6235 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6238 wctx
.addr_width
= 15;
6239 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6240 wctx
.r_vtep_ip
= vtep_ip
;
6242 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6243 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6246 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6247 json
, JSON_C_TO_STRING_PRETTY
));
6248 json_object_free(json
);
6253 * Display Duplicate detected Neighbors for a VNI
6254 * (VTY command handler).
6256 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6257 struct zebra_vrf
*zvrf
,
6263 struct neigh_walk_ctx wctx
;
6264 json_object
*json
= NULL
;
6266 if (!is_evpn_enabled())
6269 zvni
= zvni_lookup(vni
);
6271 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6275 num_neigh
= hashcount(zvni
->neigh_table
);
6279 num_neigh
= num_dup_detected_neighs(zvni
);
6284 json
= json_object_new_object();
6286 /* Since we have IPv6 addresses to deal with which can vary widely in
6287 * size, we try to be a bit more elegant in display by first computing
6288 * the maximum width.
6290 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6293 wctx
.addr_width
= 15;
6295 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6299 "Number of ARPs (local and remote) known for this VNI: %u\n",
6301 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6302 -wctx
.addr_width
, "IP", "Type",
6303 "State", "MAC", "Remote VTEP");
6305 json_object_int_add(json
, "numArpNd", num_neigh
);
6307 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6310 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6311 json
, JSON_C_TO_STRING_PRETTY
));
6312 json_object_free(json
);
6317 * Display MACs for a VNI (VTY command handler).
6319 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6320 vni_t vni
, bool use_json
)
6324 struct mac_walk_ctx wctx
;
6325 json_object
*json
= NULL
;
6326 json_object
*json_mac
= NULL
;
6328 if (!is_evpn_enabled())
6330 zvni
= zvni_lookup(vni
);
6333 vty_out(vty
, "{}\n");
6335 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6338 num_macs
= num_valid_macs(zvni
);
6343 json
= json_object_new_object();
6344 json_mac
= json_object_new_object();
6347 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6350 wctx
.json
= json_mac
;
6354 "Number of MACs (local and remote) known for this VNI: %u\n",
6356 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6357 "Intf/Remote VTEP", "VLAN");
6359 json_object_int_add(json
, "numMacs", num_macs
);
6361 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6364 json_object_object_add(json
, "macs", json_mac
);
6365 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6366 json
, JSON_C_TO_STRING_PRETTY
));
6367 json_object_free(json
);
6372 * Display MACs for all VNIs (VTY command handler).
6374 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6375 bool print_dup
, bool use_json
)
6377 struct mac_walk_ctx wctx
;
6378 json_object
*json
= NULL
;
6380 if (!is_evpn_enabled()) {
6382 vty_out(vty
, "{}\n");
6386 json
= json_object_new_object();
6388 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6391 wctx
.print_dup
= print_dup
;
6392 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6395 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6396 json
, JSON_C_TO_STRING_PRETTY
));
6397 json_object_free(json
);
6402 * Display MACs in detail for all VNIs (VTY command handler).
6404 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6405 struct zebra_vrf
*zvrf
,
6406 bool print_dup
, bool use_json
)
6408 struct mac_walk_ctx wctx
;
6409 json_object
*json
= NULL
;
6411 if (!is_evpn_enabled()) {
6413 vty_out(vty
, "{}\n");
6417 json
= json_object_new_object();
6419 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6422 wctx
.print_dup
= print_dup
;
6423 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6427 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6428 json
, JSON_C_TO_STRING_PRETTY
));
6429 json_object_free(json
);
6434 * Display MACs for all VNIs (VTY command handler).
6436 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6437 struct zebra_vrf
*zvrf
,
6438 struct in_addr vtep_ip
, bool use_json
)
6440 struct mac_walk_ctx wctx
;
6441 json_object
*json
= NULL
;
6443 if (!is_evpn_enabled())
6447 json
= json_object_new_object();
6449 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6451 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6452 wctx
.r_vtep_ip
= vtep_ip
;
6454 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6457 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6458 json
, JSON_C_TO_STRING_PRETTY
));
6459 json_object_free(json
);
6464 * Display specific MAC for a VNI, if present (VTY command handler).
6466 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6467 vni_t vni
, struct ethaddr
*macaddr
,
6472 json_object
*json
= NULL
;
6474 if (!is_evpn_enabled())
6477 zvni
= zvni_lookup(vni
);
6480 vty_out(vty
, "{}\n");
6482 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6485 mac
= zvni_mac_lookup(zvni
, macaddr
);
6488 vty_out(vty
, "{}\n");
6491 "%% Requested MAC does not exist in VNI %u\n",
6497 json
= json_object_new_object();
6499 zvni_print_mac(mac
, vty
, json
);
6501 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6502 json
, JSON_C_TO_STRING_PRETTY
));
6503 json_object_free(json
);
6507 /* Print Duplicate MACs per VNI */
6508 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6509 struct zebra_vrf
*zvrf
,
6510 vni_t vni
, bool use_json
)
6513 struct mac_walk_ctx wctx
;
6515 json_object
*json
= NULL
;
6516 json_object
*json_mac
= NULL
;
6518 if (!is_evpn_enabled())
6521 zvni
= zvni_lookup(vni
);
6523 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6527 num_macs
= num_valid_macs(zvni
);
6531 num_macs
= num_dup_detected_macs(zvni
);
6536 json
= json_object_new_object();
6537 json_mac
= json_object_new_object();
6540 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6543 wctx
.json
= json_mac
;
6547 "Number of MACs (local and remote) known for this VNI: %u\n",
6549 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6550 "Intf/Remote VTEP", "VLAN");
6552 json_object_int_add(json
, "numMacs", num_macs
);
6554 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6557 json_object_object_add(json
, "macs", json_mac
);
6558 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6559 json
, JSON_C_TO_STRING_PRETTY
));
6560 json_object_free(json
);
6565 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6566 struct zebra_vrf
*zvrf
,
6567 vni_t vni
, struct ethaddr
*macaddr
)
6571 struct listnode
*node
= NULL
;
6572 zebra_neigh_t
*nbr
= NULL
;
6574 if (!is_evpn_enabled())
6577 zvni
= zvni_lookup(vni
);
6579 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6583 mac
= zvni_mac_lookup(zvni
, macaddr
);
6585 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6590 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6591 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6595 /* Remove all IPs as duplicate associcated with this MAC */
6596 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6597 /* For local neigh mark inactive so MACIP update is generated
6598 * to BGP. This is a scenario where MAC update received
6599 * and detected as duplicate which marked neigh as duplicate.
6600 * Later local neigh update did not get a chance to relay
6601 * to BGP. Similarly remote macip update, neigh needs to be
6602 * installed locally.
6604 if (zvrf
->dad_freeze
&&
6605 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6606 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6607 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6608 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6609 zvni_neigh_install(zvni
, nbr
);
6612 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6614 nbr
->detect_start_time
.tv_sec
= 0;
6615 nbr
->dad_dup_detect_time
= 0;
6618 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6620 mac
->detect_start_time
.tv_sec
= 0;
6621 mac
->detect_start_time
.tv_usec
= 0;
6622 mac
->dad_dup_detect_time
= 0;
6623 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6625 /* warn-only action return */
6626 if (!zvrf
->dad_freeze
)
6629 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6630 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6632 if (zvni_mac_send_add_to_client(zvni
->vni
,
6638 /* Process all neighbors associated with this MAC. */
6639 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6641 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6642 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6644 /* Install the entry. */
6645 zvni_mac_install(zvni
, mac
);
6651 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6652 struct zebra_vrf
*zvrf
,
6653 vni_t vni
, struct ipaddr
*ip
)
6658 char buf
[INET6_ADDRSTRLEN
];
6659 char buf2
[ETHER_ADDR_STRLEN
];
6661 if (!is_evpn_enabled())
6664 zvni
= zvni_lookup(vni
);
6666 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6670 nbr
= zvni_neigh_lookup(zvni
, ip
);
6673 "%% Requested host IP does not exist in VNI %u\n",
6678 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6680 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6682 "%% Requsted host IP %s is not duplicate detected\n",
6687 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6689 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6691 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6692 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6693 return CMD_WARNING_CONFIG_FAILED
;
6696 if (IS_ZEBRA_DEBUG_VXLAN
)
6697 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6698 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6701 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6703 nbr
->detect_start_time
.tv_sec
= 0;
6704 nbr
->detect_start_time
.tv_usec
= 0;
6705 nbr
->dad_dup_detect_time
= 0;
6706 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6708 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6709 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6711 nbr
->flags
, nbr
->loc_seq
);
6712 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6713 zvni_neigh_install(zvni
, nbr
);
6719 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6721 struct mac_walk_ctx
*wctx
= ctxt
;
6724 struct listnode
*node
= NULL
;
6725 zebra_neigh_t
*nbr
= NULL
;
6727 mac
= (zebra_mac_t
*)bucket
->data
;
6733 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6736 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6738 mac
->detect_start_time
.tv_sec
= 0;
6739 mac
->detect_start_time
.tv_usec
= 0;
6740 mac
->dad_dup_detect_time
= 0;
6741 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6743 /* Remove all IPs as duplicate associcated with this MAC */
6744 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6745 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6747 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6749 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6751 nbr
->detect_start_time
.tv_sec
= 0;
6752 nbr
->dad_dup_detect_time
= 0;
6755 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6756 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6758 if (zvni_mac_send_add_to_client(zvni
->vni
,
6760 mac
->flags
, mac
->loc_seq
))
6763 /* Process all neighbors associated with this MAC. */
6764 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6766 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6767 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6769 /* Install the entry. */
6770 zvni_mac_install(zvni
, mac
);
6774 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6776 struct neigh_walk_ctx
*wctx
= ctxt
;
6779 char buf
[INET6_ADDRSTRLEN
];
6781 nbr
= (zebra_neigh_t
*)bucket
->data
;
6787 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6790 if (IS_ZEBRA_DEBUG_VXLAN
) {
6791 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6793 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6794 __PRETTY_FUNCTION__
, buf
,
6795 nbr
->flags
, nbr
->loc_seq
);
6798 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6800 nbr
->detect_start_time
.tv_sec
= 0;
6801 nbr
->detect_start_time
.tv_usec
= 0;
6802 nbr
->dad_dup_detect_time
= 0;
6803 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6805 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6806 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6808 nbr
->flags
, nbr
->loc_seq
);
6809 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6810 zvni_neigh_install(zvni
, nbr
);
6814 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6819 struct zebra_vrf
*zvrf
;
6820 struct mac_walk_ctx m_wctx
;
6821 struct neigh_walk_ctx n_wctx
;
6823 zvni
= (zebra_vni_t
*)bucket
->data
;
6827 vty
= (struct vty
*)args
[0];
6828 zvrf
= (struct zebra_vrf
*)args
[1];
6830 if (hashcount(zvni
->neigh_table
)) {
6831 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6835 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6839 if (num_valid_macs(zvni
)) {
6840 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6844 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6849 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6850 struct zebra_vrf
*zvrf
)
6854 if (!is_evpn_enabled())
6860 hash_iterate(zvrf
->vni_table
,
6861 (void (*)(struct hash_bucket
*, void *))
6862 zvni_clear_dup_detect_hash_vni_all
, args
);
6867 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6868 struct zebra_vrf
*zvrf
,
6872 struct mac_walk_ctx m_wctx
;
6873 struct neigh_walk_ctx n_wctx
;
6875 if (!is_evpn_enabled())
6878 zvni
= zvni_lookup(vni
);
6880 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6884 if (hashcount(zvni
->neigh_table
)) {
6885 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6889 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6893 if (num_valid_macs(zvni
)) {
6894 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6898 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6905 * Display MACs for a VNI from specific VTEP (VTY command handler).
6907 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6908 vni_t vni
, struct in_addr vtep_ip
,
6913 struct mac_walk_ctx wctx
;
6914 json_object
*json
= NULL
;
6915 json_object
*json_mac
= NULL
;
6917 if (!is_evpn_enabled())
6919 zvni
= zvni_lookup(vni
);
6922 vty_out(vty
, "{}\n");
6924 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6927 num_macs
= num_valid_macs(zvni
);
6932 json
= json_object_new_object();
6933 json_mac
= json_object_new_object();
6936 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6939 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6940 wctx
.r_vtep_ip
= vtep_ip
;
6941 wctx
.json
= json_mac
;
6942 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6945 json_object_int_add(json
, "numMacs", wctx
.count
);
6947 json_object_object_add(json
, "macs", json_mac
);
6948 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6949 json
, JSON_C_TO_STRING_PRETTY
));
6950 json_object_free(json
);
6956 * Display VNI information (VTY command handler).
6958 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6961 json_object
*json
= NULL
;
6963 zebra_l3vni_t
*zl3vni
= NULL
;
6964 zebra_vni_t
*zvni
= NULL
;
6966 if (!is_evpn_enabled())
6970 json
= json_object_new_object();
6974 zl3vni
= zl3vni_lookup(vni
);
6976 zl3vni_print(zl3vni
, (void *)args
);
6978 zvni
= zvni_lookup(vni
);
6981 vty_out(vty
, "{}\n");
6983 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6987 zvni_print(zvni
, (void *)args
);
6991 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6992 json
, JSON_C_TO_STRING_PRETTY
));
6993 json_object_free(json
);
6997 /* Display all global details for EVPN */
6998 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7003 json_object
*json
= NULL
;
7004 struct zebra_vrf
*zvrf
= NULL
;
7006 if (!is_evpn_enabled())
7009 zvrf
= zebra_vrf_get_evpn();
7013 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7014 num_l2vnis
= hashcount(zvrf
->vni_table
);
7015 num_vnis
= num_l2vnis
+ num_l3vnis
;
7018 json
= json_object_new_object();
7019 json_object_string_add(json
, "advertiseGatewayMacip",
7020 zvrf
->advertise_gw_macip
? "Yes" : "No");
7021 json_object_int_add(json
, "numVnis", num_vnis
);
7022 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7023 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7024 if (zvrf
->dup_addr_detect
)
7025 json_object_boolean_true_add(json
,
7026 "isDuplicateAddrDetection");
7028 json_object_boolean_false_add(json
,
7029 "isDuplicateAddrDetection");
7030 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7031 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7032 json_object_int_add(json
, "detectionFreezeTime",
7033 zvrf
->dad_freeze_time
);
7036 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7037 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7038 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7039 zvrf
->advertise_gw_macip
? "Yes" : "No");
7040 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7041 zvrf
->advertise_svi_macip
? "Yes" : "No");
7042 vty_out(vty
, "Duplicate address detection: %s\n",
7043 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7044 vty_out(vty
, " Detection max-moves %u, time %d\n",
7045 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7046 if (zvrf
->dad_freeze
) {
7047 if (zvrf
->dad_freeze_time
)
7048 vty_out(vty
, " Detection freeze %u\n",
7049 zvrf
->dad_freeze_time
);
7051 vty_out(vty
, " Detection freeze %s\n",
7057 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7058 json
, JSON_C_TO_STRING_PRETTY
));
7059 json_object_free(json
);
7064 * Display VNI hash table (VTY command handler).
7066 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7069 json_object
*json
= NULL
;
7072 if (!is_evpn_enabled())
7076 json
= json_object_new_object();
7078 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7079 "Type", "VxLAN IF", "# MACs", "# ARPs",
7080 "# Remote VTEPs", "Tenant VRF");
7085 /* Display all L2-VNIs */
7086 hash_iterate(zvrf
->vni_table
,
7087 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7090 /* Display all L3-VNIs */
7091 hash_iterate(zrouter
.l3vni_table
,
7092 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7096 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7097 json
, JSON_C_TO_STRING_PRETTY
));
7098 json_object_free(json
);
7102 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7106 uint32_t max_moves
= 0;
7107 uint32_t freeze_time
= 0;
7108 bool dup_addr_detect
= false;
7109 bool freeze
= false;
7112 STREAM_GETL(s
, dup_addr_detect
);
7113 STREAM_GETL(s
, time
);
7114 STREAM_GETL(s
, max_moves
);
7115 STREAM_GETL(s
, freeze
);
7116 STREAM_GETL(s
, freeze_time
);
7118 /* DAD previous state was enabled, and new state is disable,
7119 * clear all duplicate detected addresses.
7121 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7122 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7124 zvrf
->dup_addr_detect
= dup_addr_detect
;
7125 zvrf
->dad_time
= time
;
7126 zvrf
->dad_max_moves
= max_moves
;
7127 zvrf
->dad_freeze
= freeze
;
7128 zvrf
->dad_freeze_time
= freeze_time
;
7130 if (IS_ZEBRA_DEBUG_VXLAN
)
7132 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7133 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7134 zvrf
->dup_addr_detect
? "enable" : "disable",
7135 zvrf
->dad_max_moves
,
7137 zvrf
->dad_freeze
? "enable" : "disable",
7138 zvrf
->dad_freeze_time
);
7145 * Display VNI hash table in detail(VTY command handler).
7147 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7150 json_object
*json
= NULL
;
7151 struct zebra_ns
*zns
= NULL
;
7152 struct zvni_evpn_show zes
;
7154 if (!is_evpn_enabled())
7157 zns
= zebra_ns_lookup(NS_DEFAULT
);
7163 json
= json_object_new_object();
7169 /* Display all L2-VNIs */
7172 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7175 /* Display all L3-VNIs */
7176 hash_iterate(zrouter
.l3vni_table
,
7177 (void (*)(struct hash_bucket
*,
7178 void *))zl3vni_print_hash_detail
,
7182 vty_out(vty
, "%s\n",
7183 json_object_to_json_string_ext(
7184 json
, JSON_C_TO_STRING_PRETTY
));
7185 json_object_free(json
);
7190 * Handle neighbor delete notification from the kernel (on a VLAN device
7191 * / L3 interface). This may result in either the neighbor getting deleted
7192 * from our database or being re-added to the kernel (if it is a valid
7195 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7196 struct interface
*link_if
,
7199 char buf
[INET6_ADDRSTRLEN
];
7200 char buf2
[ETHER_ADDR_STRLEN
];
7201 zebra_neigh_t
*n
= NULL
;
7202 zebra_vni_t
*zvni
= NULL
;
7203 zebra_mac_t
*zmac
= NULL
;
7204 zebra_l3vni_t
*zl3vni
= NULL
;
7205 struct zebra_vrf
*zvrf
;
7207 /* check if this is a remote neigh entry corresponding to remote
7210 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7212 return zl3vni_local_nh_del(zl3vni
, ip
);
7214 /* We are only interested in neighbors on an SVI that resides on top
7215 * of a VxLAN bridge.
7217 zvni
= zvni_from_svi(ifp
, link_if
);
7221 if (!zvni
->vxlan_if
) {
7223 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7228 if (IS_ZEBRA_DEBUG_VXLAN
)
7229 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7230 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7231 ifp
->ifindex
, zvni
->vni
);
7233 /* If entry doesn't exist, nothing to do. */
7234 n
= zvni_neigh_lookup(zvni
, ip
);
7238 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7240 if (IS_ZEBRA_DEBUG_VXLAN
)
7242 "Trying to del a neigh %s without a mac %s on VNI %u",
7243 ipaddr2str(ip
, buf
, sizeof(buf
)),
7244 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7250 /* If it is a remote entry, the kernel has aged this out or someone has
7251 * deleted it, it needs to be re-installed as Quagga is the owner.
7253 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7254 zvni_neigh_install(zvni
, n
);
7258 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7260 zlog_debug("%s: VNI %u vrf lookup failed.",
7261 __PRETTY_FUNCTION__
, zvni
->vni
);
7265 /* In case of feeze action, if local neigh is in duplicate state,
7266 * Mark the Neigh as inactive before sending delete request to BGPd,
7267 * If BGPd has remote entry, it will re-install
7269 if (zvrf
->dad_freeze
&&
7270 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7271 ZEBRA_NEIGH_SET_INACTIVE(n
);
7273 /* Remove neighbor from BGP. */
7274 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7276 /* Delete this neighbor entry. */
7277 zvni_neigh_del(zvni
, n
);
7279 /* see if the AUTO mac needs to be deleted */
7280 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7281 && !listcount(zmac
->neigh_list
))
7282 zvni_mac_del(zvni
, zmac
);
7288 * Handle neighbor add or update notification from the kernel (on a VLAN
7289 * device / L3 interface). This is typically for a local neighbor but can
7290 * also be for a remote neighbor (e.g., ageout notification). It could
7291 * also be a "move" scenario.
7293 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7294 struct interface
*link_if
,
7296 struct ethaddr
*macaddr
,
7301 char buf
[ETHER_ADDR_STRLEN
];
7302 char buf2
[INET6_ADDRSTRLEN
];
7303 zebra_vni_t
*zvni
= NULL
;
7304 zebra_l3vni_t
*zl3vni
= NULL
;
7306 /* check if this is a remote neigh entry corresponding to remote
7309 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7311 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7313 /* We are only interested in neighbors on an SVI that resides on top
7314 * of a VxLAN bridge.
7316 zvni
= zvni_from_svi(ifp
, link_if
);
7320 if (IS_ZEBRA_DEBUG_VXLAN
)
7322 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7323 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7324 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7325 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7326 is_router
? "router " : "",
7329 /* Is this about a local neighbor or a remote one? */
7331 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7334 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7339 * Handle message from client to delete a remote MACIP for a VNI.
7341 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7345 struct ethaddr macaddr
;
7347 struct in_addr vtep_ip
;
7348 uint16_t l
= 0, ipa_len
;
7349 char buf
[ETHER_ADDR_STRLEN
];
7350 char buf1
[INET6_ADDRSTRLEN
];
7352 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7353 memset(&ip
, 0, sizeof(struct ipaddr
));
7354 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7358 while (l
< hdr
->length
) {
7359 /* Obtain each remote MACIP and process. */
7360 /* Message contains VNI, followed by MAC followed by IP (if any)
7361 * followed by remote VTEP IP.
7363 memset(&ip
, 0, sizeof(ip
));
7364 STREAM_GETL(s
, vni
);
7365 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7366 STREAM_GETL(s
, ipa_len
);
7368 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7370 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7372 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7373 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7374 l
+= IPV4_MAX_BYTELEN
;
7376 if (IS_ZEBRA_DEBUG_VXLAN
)
7378 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7380 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7381 ipa_len
? " IP " : "",
7383 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7385 zebra_route_string(client
->proto
));
7387 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7395 * Handle message from client to add a remote MACIP for a VNI. This
7396 * could be just the add of a MAC address or the add of a neighbor
7399 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7403 struct ethaddr macaddr
;
7405 struct in_addr vtep_ip
;
7406 uint16_t l
= 0, ipa_len
;
7409 char buf
[ETHER_ADDR_STRLEN
];
7410 char buf1
[INET6_ADDRSTRLEN
];
7412 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7413 memset(&ip
, 0, sizeof(struct ipaddr
));
7414 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7416 if (!EVPN_ENABLED(zvrf
)) {
7417 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7423 while (l
< hdr
->length
) {
7424 /* Obtain each remote MACIP and process. */
7425 /* Message contains VNI, followed by MAC followed by IP (if any)
7426 * followed by remote VTEP IP.
7428 memset(&ip
, 0, sizeof(ip
));
7429 STREAM_GETL(s
, vni
);
7430 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7431 STREAM_GETL(s
, ipa_len
);
7433 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7435 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7437 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7438 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7439 l
+= IPV4_MAX_BYTELEN
;
7441 /* Get flags - sticky mac and/or gateway mac */
7442 STREAM_GETC(s
, flags
);
7444 STREAM_GETL(s
, seq
);
7447 if (IS_ZEBRA_DEBUG_VXLAN
)
7449 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7451 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7452 ipa_len
? " IP " : "",
7454 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7455 flags
, seq
, inet_ntoa(vtep_ip
),
7456 zebra_route_string(client
->proto
));
7458 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7459 flags
, seq
, vtep_ip
);
7467 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7468 * us, this must involve a multihoming scenario. Treat this as implicit delete
7469 * of any prior local MAC.
7471 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7472 struct interface
*br_if
,
7473 struct ethaddr
*macaddr
, vlanid_t vid
)
7475 struct zebra_if
*zif
;
7476 struct zebra_l2info_vxlan
*vxl
;
7480 char buf
[ETHER_ADDR_STRLEN
];
7484 vxl
= &zif
->l2info
.vxl
;
7487 /* Check if EVPN is enabled. */
7488 if (!is_evpn_enabled())
7491 /* Locate hash entry; it is expected to exist. */
7492 zvni
= zvni_lookup(vni
);
7496 /* If entry doesn't exist, nothing to do. */
7497 mac
= zvni_mac_lookup(zvni
, macaddr
);
7501 /* Is it a local entry? */
7502 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7505 if (IS_ZEBRA_DEBUG_VXLAN
)
7507 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7508 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7509 ifp
->ifindex
, vni
, mac
->flags
);
7511 /* Remove MAC from BGP. */
7512 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7515 * If there are no neigh associated with the mac delete the mac
7516 * else mark it as AUTO for forward reference
7518 if (!listcount(mac
->neigh_list
)) {
7519 zvni_mac_del(zvni
, mac
);
7521 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7522 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7523 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7530 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7531 * This can happen because the remote MAC entries are also added as "dynamic",
7532 * so the kernel can ageout the entry.
7534 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7535 struct interface
*br_if
,
7536 struct ethaddr
*macaddr
, vlanid_t vid
)
7538 struct zebra_if
*zif
= NULL
;
7539 struct zebra_l2info_vxlan
*vxl
= NULL
;
7541 zebra_vni_t
*zvni
= NULL
;
7542 zebra_l3vni_t
*zl3vni
= NULL
;
7543 zebra_mac_t
*mac
= NULL
;
7544 char buf
[ETHER_ADDR_STRLEN
];
7548 vxl
= &zif
->l2info
.vxl
;
7551 /* Check if EVPN is enabled. */
7552 if (!is_evpn_enabled())
7555 /* check if this is a remote RMAC and readd simillar to remote macs */
7556 zl3vni
= zl3vni_lookup(vni
);
7558 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7560 /* Locate hash entry; it is expected to exist. */
7561 zvni
= zvni_lookup(vni
);
7565 /* If entry doesn't exist, nothing to do. */
7566 mac
= zvni_mac_lookup(zvni
, macaddr
);
7570 /* Is it a remote entry? */
7571 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7574 if (IS_ZEBRA_DEBUG_VXLAN
)
7575 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7576 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7579 zvni_mac_install(zvni
, mac
);
7584 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7586 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7587 struct ethaddr
*macaddr
, vlanid_t vid
)
7591 char buf
[ETHER_ADDR_STRLEN
];
7593 /* We are interested in MACs only on ports or (port, VLAN) that
7596 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7599 if (!zvni
->vxlan_if
) {
7601 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7606 /* If entry doesn't exist, nothing to do. */
7607 mac
= zvni_mac_lookup(zvni
, macaddr
);
7611 /* Is it a local entry? */
7612 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7615 if (IS_ZEBRA_DEBUG_VXLAN
)
7616 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7617 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7618 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7620 /* Update all the neigh entries associated with this mac */
7621 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7623 /* Remove MAC from BGP. */
7624 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7627 * If there are no neigh associated with the mac delete the mac
7628 * else mark it as AUTO for forward reference
7630 if (!listcount(mac
->neigh_list
)) {
7631 zvni_mac_del(zvni
, mac
);
7633 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7634 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7635 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7642 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7644 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7645 struct interface
*br_if
,
7646 struct ethaddr
*macaddr
, vlanid_t vid
,
7651 struct zebra_vrf
*zvrf
;
7652 char buf
[ETHER_ADDR_STRLEN
];
7653 bool mac_sticky
= false;
7654 bool inform_client
= false;
7655 bool upd_neigh
= false;
7656 bool is_dup_detect
= false;
7657 struct in_addr vtep_ip
= {.s_addr
= 0};
7659 /* We are interested in MACs only on ports or (port, VLAN) that
7662 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7664 if (IS_ZEBRA_DEBUG_VXLAN
)
7666 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7667 sticky
? "sticky " : "",
7668 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7669 ifp
->name
, ifp
->ifindex
, vid
);
7673 if (!zvni
->vxlan_if
) {
7674 if (IS_ZEBRA_DEBUG_VXLAN
)
7676 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7681 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7683 if (IS_ZEBRA_DEBUG_VXLAN
)
7684 zlog_debug("\tNo Vrf found for vrf_id: %d",
7685 zvni
->vxlan_if
->vrf_id
);
7689 /* Check if we need to create or update or it is a NO-OP. */
7690 mac
= zvni_mac_lookup(zvni
, macaddr
);
7692 if (IS_ZEBRA_DEBUG_VXLAN
)
7694 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7695 sticky
? "sticky " : "",
7696 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7697 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7699 mac
= zvni_mac_add(zvni
, macaddr
);
7702 EC_ZEBRA_MAC_ADD_FAILED
,
7703 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7704 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7705 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7708 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7709 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7710 mac
->fwd_info
.local
.vid
= vid
;
7712 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7713 inform_client
= true;
7716 if (IS_ZEBRA_DEBUG_VXLAN
)
7718 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7719 sticky
? "sticky " : "",
7720 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7721 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7724 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7725 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7729 * Update any changes and if changes are relevant to
7732 if (mac_sticky
== sticky
7733 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7734 && mac
->fwd_info
.local
.vid
== vid
) {
7735 if (IS_ZEBRA_DEBUG_VXLAN
)
7737 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7738 "entry exists and has not changed ",
7739 sticky
? "sticky " : "",
7740 prefix_mac2str(macaddr
, buf
,
7742 ifp
->name
, ifp
->ifindex
, vid
,
7746 if (mac_sticky
!= sticky
) {
7748 SET_FLAG(mac
->flags
,
7751 UNSET_FLAG(mac
->flags
,
7753 inform_client
= true;
7756 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7757 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7758 mac
->fwd_info
.local
.vid
= vid
;
7760 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7761 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7762 bool do_dad
= false;
7765 * MAC has either moved or was "internally" created due
7766 * to a neighbor learn and is now actually learnt. If
7767 * it was learnt as a remote sticky MAC, this is an
7770 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7772 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7773 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7774 prefix_mac2str(macaddr
, buf
,
7776 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7781 /* If an actual move, compute MAC's seq number */
7782 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7783 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7785 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7786 /* Trigger DAD for remote MAC */
7790 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7791 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7792 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7793 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7794 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7795 mac
->fwd_info
.local
.vid
= vid
;
7797 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7799 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7801 * We have to inform BGP of this MAC as well as process
7804 inform_client
= true;
7807 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7811 if (is_dup_detect
) {
7812 inform_client
= false;
7818 /* Inform BGP if required. */
7819 if (inform_client
) {
7820 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7821 mac
->flags
, mac
->loc_seq
))
7825 /* Process all neighbors associated with this MAC, if required. */
7827 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7833 * Handle message from client to delete a remote VTEP for a VNI.
7835 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7838 unsigned short l
= 0;
7840 struct in_addr vtep_ip
;
7842 zebra_vtep_t
*zvtep
;
7843 struct interface
*ifp
;
7844 struct zebra_if
*zif
;
7846 if (!is_evpn_enabled()) {
7848 "%s: EVPN is not enabled yet we have received a vtep del command",
7849 __PRETTY_FUNCTION__
);
7853 if (!EVPN_ENABLED(zvrf
)) {
7854 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7861 while (l
< hdr
->length
) {
7862 int flood_control
__attribute__((unused
));
7864 /* Obtain each remote VTEP and process. */
7865 STREAM_GETL(s
, vni
);
7867 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7868 l
+= IPV4_MAX_BYTELEN
;
7870 /* Flood control is intentionally ignored right now */
7871 STREAM_GETL(s
, flood_control
);
7874 if (IS_ZEBRA_DEBUG_VXLAN
)
7875 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7876 inet_ntoa(vtep_ip
), vni
,
7877 zebra_route_string(client
->proto
));
7879 /* Locate VNI hash entry - expected to exist. */
7880 zvni
= zvni_lookup(vni
);
7882 if (IS_ZEBRA_DEBUG_VXLAN
)
7884 "Failed to locate VNI hash upon remote VTEP DEL, "
7890 ifp
= zvni
->vxlan_if
;
7893 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7899 /* If down or not mapped to a bridge, we're done. */
7900 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7903 /* If the remote VTEP does not exist, there's nothing more to
7905 * Otherwise, uninstall any remote MACs pointing to this VTEP
7907 * then, the VTEP entry itself and remove it.
7909 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7913 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7914 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7915 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7916 zvni_vtep_del(zvni
, zvtep
);
7924 * Handle message from client to add a remote VTEP for a VNI.
7926 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7929 unsigned short l
= 0;
7931 struct in_addr vtep_ip
;
7933 struct interface
*ifp
;
7934 struct zebra_if
*zif
;
7936 zebra_vtep_t
*zvtep
;
7938 if (!is_evpn_enabled()) {
7940 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7941 __PRETTY_FUNCTION__
);
7945 if (!EVPN_ENABLED(zvrf
)) {
7946 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7953 while (l
< hdr
->length
) {
7954 /* Obtain each remote VTEP and process. */
7955 STREAM_GETL(s
, vni
);
7957 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7958 STREAM_GETL(s
, flood_control
);
7959 l
+= IPV4_MAX_BYTELEN
+ 4;
7961 if (IS_ZEBRA_DEBUG_VXLAN
)
7962 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
7963 inet_ntoa(vtep_ip
), vni
, flood_control
,
7964 zebra_route_string(client
->proto
));
7966 /* Locate VNI hash entry - expected to exist. */
7967 zvni
= zvni_lookup(vni
);
7970 EC_ZEBRA_VTEP_ADD_FAILED
,
7971 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7976 ifp
= zvni
->vxlan_if
;
7979 EC_ZEBRA_VTEP_ADD_FAILED
,
7980 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7987 /* If down or not mapped to a bridge, we're done. */
7988 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7991 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7993 /* If the remote VTEP already exists check if
7994 * the flood mode has changed
7996 if (zvtep
->flood_control
!= flood_control
) {
7997 if (zvtep
->flood_control
7998 == VXLAN_FLOOD_DISABLED
)
7999 /* old mode was head-end-replication but
8000 * is no longer; get rid of the HER fdb
8001 * entry installed before
8003 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8004 zvtep
->flood_control
= flood_control
;
8005 zvni_vtep_install(zvni
, zvtep
);
8008 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8010 zvni_vtep_install(zvni
, zvtep
);
8012 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8013 "Failed to add remote VTEP, VNI %u zvni %p",
8023 * Add/Del gateway macip to evpn
8025 * 1. SVI interface on a vlan aware bridge
8026 * 2. SVI interface on a vlan unaware bridge
8027 * 3. vrr interface (MACVLAN) associated to a SVI
8028 * We advertise macip routes for an interface if it is associated to VxLan vlan
8030 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8034 struct ethaddr macaddr
;
8035 zebra_vni_t
*zvni
= NULL
;
8037 memset(&ip
, 0, sizeof(struct ipaddr
));
8038 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8040 /* Check if EVPN is enabled. */
8041 if (!is_evpn_enabled())
8044 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8045 struct interface
*svi_if
=
8046 NULL
; /* SVI corresponding to the MACVLAN */
8047 struct zebra_if
*ifp_zif
=
8048 NULL
; /* Zebra daemon specific info for MACVLAN */
8049 struct zebra_if
*svi_if_zif
=
8050 NULL
; /* Zebra daemon specific info for SVI*/
8052 ifp_zif
= ifp
->info
;
8057 * for a MACVLAN interface the link represents the svi_if
8059 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8060 ifp_zif
->link_ifindex
);
8062 zlog_debug("MACVLAN %s(%u) without link information",
8063 ifp
->name
, ifp
->ifindex
);
8067 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8069 * If it is a vlan aware bridge then the link gives the
8070 * bridge information
8072 struct interface
*svi_if_link
= NULL
;
8074 svi_if_zif
= svi_if
->info
;
8076 svi_if_link
= if_lookup_by_index_per_ns(
8077 zebra_ns_lookup(NS_DEFAULT
),
8078 svi_if_zif
->link_ifindex
);
8079 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8081 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8083 * If it is a vlan unaware bridge then svi is the bridge
8086 zvni
= zvni_from_svi(svi_if
, svi_if
);
8088 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8089 struct zebra_if
*svi_if_zif
=
8090 NULL
; /* Zebra daemon specific info for SVI */
8091 struct interface
*svi_if_link
=
8092 NULL
; /* link info for the SVI = bridge info */
8094 svi_if_zif
= ifp
->info
;
8096 svi_if_link
= if_lookup_by_index_per_ns(
8097 zebra_ns_lookup(NS_DEFAULT
),
8098 svi_if_zif
->link_ifindex
);
8100 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8102 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8103 zvni
= zvni_from_svi(ifp
, ifp
);
8109 if (!zvni
->vxlan_if
) {
8110 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8116 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8118 if (p
->family
== AF_INET
) {
8119 ip
.ipa_type
= IPADDR_V4
;
8120 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8121 sizeof(struct in_addr
));
8122 } else if (p
->family
== AF_INET6
) {
8123 ip
.ipa_type
= IPADDR_V6
;
8124 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8125 sizeof(struct in6_addr
));
8130 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8132 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8138 * Handle SVI interface going down.
8139 * SVI can be associated to either L3-VNI or L2-VNI.
8140 * For L2-VNI: At this point, this is a NOP since
8141 * the kernel deletes the neighbor entries on this SVI (if any).
8142 * We only need to update the vrf corresponding to zvni.
8143 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8146 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8148 zebra_l3vni_t
*zl3vni
= NULL
;
8150 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8153 /* process l3-vni down */
8154 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8156 /* remove association with svi-if */
8157 zl3vni
->svi_if
= NULL
;
8159 zebra_vni_t
*zvni
= NULL
;
8161 /* since we dont have svi corresponding to zvni, we associate it
8162 * to default vrf. Note: the corresponding neigh entries on the
8163 * SVI would have already been deleted */
8164 zvni
= zvni_from_svi(ifp
, link_if
);
8166 zvni
->vrf_id
= VRF_DEFAULT
;
8168 /* update the tenant vrf in BGP */
8169 zvni_send_add_to_client(zvni
);
8176 * Handle SVI interface coming up.
8177 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8179 * For L2-VNI: we need to install any remote neighbors entried (used for
8181 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8183 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8185 zebra_vni_t
*zvni
= NULL
;
8186 zebra_l3vni_t
*zl3vni
= NULL
;
8188 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8191 /* associate with svi */
8192 zl3vni
->svi_if
= ifp
;
8194 /* process oper-up */
8195 if (is_l3vni_oper_up(zl3vni
))
8196 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8199 /* process SVI up for l2-vni */
8200 struct neigh_walk_ctx n_wctx
;
8202 zvni
= zvni_from_svi(ifp
, link_if
);
8206 if (!zvni
->vxlan_if
) {
8208 "VNI %u hash %p doesn't have intf upon SVI up",
8213 if (IS_ZEBRA_DEBUG_VXLAN
)
8215 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8216 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8217 vrf_id_to_name(ifp
->vrf_id
));
8219 /* update the vrf information for l2-vni and inform bgp */
8220 zvni
->vrf_id
= ifp
->vrf_id
;
8221 zvni_send_add_to_client(zvni
);
8223 /* Install any remote neighbors for this VNI. */
8224 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8226 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8234 * Handle VxLAN interface down
8236 int zebra_vxlan_if_down(struct interface
*ifp
)
8239 struct zebra_if
*zif
= NULL
;
8240 struct zebra_l2info_vxlan
*vxl
= NULL
;
8241 zebra_l3vni_t
*zl3vni
= NULL
;
8244 /* Check if EVPN is enabled. */
8245 if (!is_evpn_enabled())
8250 vxl
= &zif
->l2info
.vxl
;
8253 zl3vni
= zl3vni_lookup(vni
);
8255 /* process-if-down for l3-vni */
8256 if (IS_ZEBRA_DEBUG_VXLAN
)
8257 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8260 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8262 /* process if-down for l2-vni */
8263 if (IS_ZEBRA_DEBUG_VXLAN
)
8264 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8267 /* Locate hash entry; it is expected to exist. */
8268 zvni
= zvni_lookup(vni
);
8271 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8272 ifp
->name
, ifp
->ifindex
, vni
);
8276 assert(zvni
->vxlan_if
== ifp
);
8278 /* Delete this VNI from BGP. */
8279 zvni_send_del_to_client(zvni
->vni
);
8281 /* Free up all neighbors and MACs, if any. */
8282 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8283 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8285 /* Free up all remote VTEPs, if any. */
8286 zvni_vtep_del_all(zvni
, 1);
8292 * Handle VxLAN interface up - update BGP if required.
8294 int zebra_vxlan_if_up(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("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8318 /* we need to associate with SVI, if any, we can associate with
8319 * svi-if only after association with vxlan-intf is complete
8321 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8323 if (is_l3vni_oper_up(zl3vni
))
8324 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8326 /* Handle L2-VNI add */
8327 struct interface
*vlan_if
= NULL
;
8329 if (IS_ZEBRA_DEBUG_VXLAN
)
8330 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8333 /* Locate hash entry; it is expected to exist. */
8334 zvni
= zvni_lookup(vni
);
8337 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8338 ifp
->name
, ifp
->ifindex
, vni
);
8342 assert(zvni
->vxlan_if
== ifp
);
8343 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8344 zif
->brslave_info
.br_if
);
8346 zvni
->vrf_id
= vlan_if
->vrf_id
;
8347 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8349 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8352 /* If part of a bridge, inform BGP about this VNI. */
8353 /* Also, read and populate local MACs and neighbors. */
8354 if (zif
->brslave_info
.br_if
) {
8355 zvni_send_add_to_client(zvni
);
8356 zvni_read_mac_neigh(zvni
, ifp
);
8364 * Handle VxLAN interface delete. Locate and remove entry in hash table
8365 * and update BGP, if required.
8367 int zebra_vxlan_if_del(struct interface
*ifp
)
8370 struct zebra_if
*zif
= NULL
;
8371 struct zebra_l2info_vxlan
*vxl
= NULL
;
8372 zebra_vni_t
*zvni
= NULL
;
8373 zebra_l3vni_t
*zl3vni
= NULL
;
8375 /* Check if EVPN is enabled. */
8376 if (!is_evpn_enabled())
8381 vxl
= &zif
->l2info
.vxl
;
8384 zl3vni
= zl3vni_lookup(vni
);
8387 if (IS_ZEBRA_DEBUG_VXLAN
)
8388 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8391 /* process oper-down for l3-vni */
8392 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8394 /* remove the association with vxlan_if */
8395 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8396 zl3vni
->vxlan_if
= NULL
;
8399 /* process if-del for l2-vni*/
8400 if (IS_ZEBRA_DEBUG_VXLAN
)
8401 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8404 /* Locate hash entry; it is expected to exist. */
8405 zvni
= zvni_lookup(vni
);
8408 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8409 ifp
->name
, ifp
->ifindex
, vni
);
8413 /* remove from l3-vni list */
8414 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8416 listnode_delete(zl3vni
->l2vnis
, zvni
);
8418 /* Delete VNI from BGP. */
8419 zvni_send_del_to_client(zvni
->vni
);
8421 /* Free up all neighbors and MAC, if any. */
8422 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8423 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8425 /* Free up all remote VTEPs, if any. */
8426 zvni_vtep_del_all(zvni
, 0);
8428 /* Delete the hash entry. */
8429 if (zvni_del(zvni
)) {
8430 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8431 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8432 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8440 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8442 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8445 struct zebra_if
*zif
= NULL
;
8446 struct zebra_l2info_vxlan
*vxl
= NULL
;
8447 zebra_vni_t
*zvni
= NULL
;
8448 zebra_l3vni_t
*zl3vni
= NULL
;
8450 /* Check if EVPN is enabled. */
8451 if (!is_evpn_enabled())
8456 vxl
= &zif
->l2info
.vxl
;
8459 zl3vni
= zl3vni_lookup(vni
);
8462 if (IS_ZEBRA_DEBUG_VXLAN
)
8464 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8465 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8466 inet_ntoa(vxl
->vtep_ip
),
8467 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8469 /* Removed from bridge? Cleanup and return */
8470 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8471 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8472 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8476 /* access-vlan change - process oper down, associate with new
8477 * svi_if and then process oper up again
8479 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8480 if (if_is_operative(ifp
)) {
8481 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8482 zl3vni
->svi_if
= NULL
;
8483 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8484 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8485 if (is_l3vni_oper_up(zl3vni
))
8486 zebra_vxlan_process_l3vni_oper_up(
8492 * local-ip change - process oper down, associate with new
8493 * local-ip and then process oper up again
8495 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8496 if (if_is_operative(ifp
)) {
8497 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8498 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8499 if (is_l3vni_oper_up(zl3vni
))
8500 zebra_vxlan_process_l3vni_oper_up(
8505 /* Update local tunnel IP. */
8506 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8508 /* if we have a valid new master, process l3-vni oper up */
8509 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8510 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8511 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8515 /* Update VNI hash. */
8516 zvni
= zvni_lookup(vni
);
8519 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8520 ifp
->name
, ifp
->ifindex
, vni
);
8524 if (IS_ZEBRA_DEBUG_VXLAN
)
8526 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8527 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8528 inet_ntoa(vxl
->vtep_ip
),
8529 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8531 /* Removed from bridge? Cleanup and return */
8532 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8533 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8534 /* Delete from client, remove all remote VTEPs */
8535 /* Also, free up all MACs and neighbors. */
8536 zvni_send_del_to_client(zvni
->vni
);
8537 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8538 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8539 zvni_vtep_del_all(zvni
, 1);
8543 /* Handle other changes. */
8544 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8545 /* Remove all existing local neigh and MACs for this VNI
8546 * (including from BGP)
8548 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8549 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8552 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8553 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8554 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8556 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8557 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8558 zvni
->mcast_grp
= vxl
->mcast_grp
;
8560 zvni
->vxlan_if
= ifp
;
8562 /* Take further actions needed.
8563 * Note that if we are here, there is a change of interest.
8565 /* If down or not mapped to a bridge, we're done. */
8566 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8569 /* Inform BGP, if there is a change of interest. */
8571 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8572 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8573 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8574 zvni_send_add_to_client(zvni
);
8576 /* If there is a valid new master or a VLAN mapping change,
8577 * read and populate local MACs and neighbors.
8578 * Also, reinstall any remote MACs and neighbors
8579 * for this VNI (based on new VLAN).
8581 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8582 zvni_read_mac_neigh(zvni
, ifp
);
8583 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8584 struct mac_walk_ctx m_wctx
;
8585 struct neigh_walk_ctx n_wctx
;
8587 zvni_read_mac_neigh(zvni
, ifp
);
8589 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8591 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8594 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8596 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8605 * Handle VxLAN interface add.
8607 int zebra_vxlan_if_add(struct interface
*ifp
)
8610 struct zebra_if
*zif
= NULL
;
8611 struct zebra_l2info_vxlan
*vxl
= NULL
;
8612 zebra_vni_t
*zvni
= NULL
;
8613 zebra_l3vni_t
*zl3vni
= NULL
;
8615 /* Check if EVPN is enabled. */
8616 if (!is_evpn_enabled())
8621 vxl
= &zif
->l2info
.vxl
;
8624 zl3vni
= zl3vni_lookup(vni
);
8627 /* process if-add for l3-vni*/
8628 if (IS_ZEBRA_DEBUG_VXLAN
)
8630 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8631 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8632 inet_ntoa(vxl
->vtep_ip
),
8633 zif
->brslave_info
.bridge_ifindex
);
8635 /* associate with vxlan_if */
8636 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8637 zl3vni
->vxlan_if
= ifp
;
8639 /* Associate with SVI, if any. We can associate with svi-if only
8640 * after association with vxlan_if is complete */
8641 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8643 if (is_l3vni_oper_up(zl3vni
))
8644 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8647 /* process if-add for l2-vni */
8648 struct interface
*vlan_if
= NULL
;
8650 /* Create or update VNI hash. */
8651 zvni
= zvni_lookup(vni
);
8653 zvni
= zvni_add(vni
);
8656 EC_ZEBRA_VNI_ADD_FAILED
,
8657 "Failed to add VNI hash, IF %s(%u) VNI %u",
8658 ifp
->name
, ifp
->ifindex
, vni
);
8663 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8664 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8665 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8667 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8668 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8669 zvni
->mcast_grp
= vxl
->mcast_grp
;
8671 zvni
->vxlan_if
= ifp
;
8672 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8673 zif
->brslave_info
.br_if
);
8675 zvni
->vrf_id
= vlan_if
->vrf_id
;
8676 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8678 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8681 if (IS_ZEBRA_DEBUG_VXLAN
) {
8682 char addr_buf1
[INET_ADDRSTRLEN
];
8683 char addr_buf2
[INET_ADDRSTRLEN
];
8685 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8686 addr_buf1
, INET_ADDRSTRLEN
);
8687 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8688 addr_buf2
, INET_ADDRSTRLEN
);
8691 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8693 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8695 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8696 addr_buf1
, addr_buf2
,
8697 zif
->brslave_info
.bridge_ifindex
);
8700 /* If down or not mapped to a bridge, we're done. */
8701 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8705 zvni_send_add_to_client(zvni
);
8707 /* Read and populate local MACs and neighbors */
8708 zvni_read_mac_neigh(zvni
, ifp
);
8714 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8715 char *err
, int err_str_sz
, int filter
,
8718 zebra_l3vni_t
*zl3vni
= NULL
;
8719 struct zebra_vrf
*zvrf_evpn
= NULL
;
8721 zvrf_evpn
= zebra_vrf_get_evpn();
8725 if (IS_ZEBRA_DEBUG_VXLAN
)
8726 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8727 add
? "ADD" : "DEL");
8731 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8733 /* check if the vni is already present under zvrf */
8735 snprintf(err
, err_str_sz
,
8736 "VNI is already configured under the vrf");
8740 /* check if this VNI is already present in the system */
8741 zl3vni
= zl3vni_lookup(vni
);
8743 snprintf(err
, err_str_sz
,
8744 "VNI is already configured as L3-VNI");
8748 /* add the L3-VNI to the global table */
8749 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8751 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8755 /* associate the vrf with vni */
8758 /* set the filter in l3vni to denote if we are using l3vni only
8762 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8764 /* associate with vxlan-intf;
8765 * we need to associate with the vxlan-intf first
8767 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8769 /* associate with corresponding SVI interface, we can associate
8770 * with svi-if only after vxlan interface association is
8773 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8775 /* formulate l2vni list */
8776 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8779 if (is_l3vni_oper_up(zl3vni
))
8780 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8783 zl3vni
= zl3vni_lookup(vni
);
8785 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8789 if (zvrf
->l3vni
!= vni
) {
8790 snprintf(err
, err_str_sz
,
8791 "VNI %d doesn't exist in VRF: %s",
8792 vni
, zvrf
->vrf
->name
);
8796 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8797 snprintf(err
, ERR_STR_SZ
,
8798 "prefix-routes-only is not set for the vni");
8802 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8804 /* delete and uninstall all rmacs */
8805 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8808 /* delete and uninstall all next-hops */
8809 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8815 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8820 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8822 zebra_l3vni_t
*zl3vni
= NULL
;
8825 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8829 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8830 if (is_l3vni_oper_up(zl3vni
))
8831 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8835 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8837 zebra_l3vni_t
*zl3vni
= NULL
;
8840 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8844 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8845 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8849 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8851 zebra_l3vni_t
*zl3vni
= NULL
;
8855 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8861 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8867 * Handle message from client to specify the flooding mechanism for
8868 * BUM packets. The default is to do head-end (ingress) replication
8869 * and the other supported option is to disable it. This applies to
8870 * all BUM traffic and disabling it applies to both the transmit and
8871 * receive direction.
8873 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8876 enum vxlan_flood_control flood_ctrl
;
8878 if (!EVPN_ENABLED(zvrf
)) {
8879 zlog_err("EVPN flood control for non-EVPN VRF %u",
8885 STREAM_GETC(s
, flood_ctrl
);
8887 if (IS_ZEBRA_DEBUG_VXLAN
)
8888 zlog_debug("EVPN flood control %u, currently %u",
8889 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8891 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8894 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8896 /* Install or uninstall flood entries corresponding to
8899 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8907 * Handle message from client to enable/disable advertisement of svi macip
8910 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8915 zebra_vni_t
*zvni
= NULL
;
8916 struct interface
*ifp
= NULL
;
8918 if (!EVPN_ENABLED(zvrf
)) {
8919 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8925 STREAM_GETC(s
, advertise
);
8926 STREAM_GETL(s
, vni
);
8929 if (IS_ZEBRA_DEBUG_VXLAN
)
8930 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8931 advertise
? "enabled" : "disabled",
8932 advertise_gw_macip_enabled(NULL
)
8936 if (zvrf
->advertise_svi_macip
== advertise
)
8941 zvrf
->advertise_svi_macip
= advertise
;
8942 hash_iterate(zvrf
->vni_table
,
8943 zvni_gw_macip_add_for_vni_hash
, NULL
);
8945 hash_iterate(zvrf
->vni_table
,
8946 zvni_svi_macip_del_for_vni_hash
, NULL
);
8947 zvrf
->advertise_svi_macip
= advertise
;
8951 struct zebra_if
*zif
= NULL
;
8952 struct zebra_l2info_vxlan zl2_info
;
8953 struct interface
*vlan_if
= NULL
;
8955 zvni
= zvni_lookup(vni
);
8959 if (IS_ZEBRA_DEBUG_VXLAN
)
8961 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8962 advertise
? "enabled" : "disabled", vni
,
8963 advertise_svi_macip_enabled(zvni
)
8967 if (zvni
->advertise_svi_macip
== advertise
)
8970 ifp
= zvni
->vxlan_if
;
8976 /* If down or not mapped to a bridge, we're done. */
8977 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8980 zl2_info
= zif
->l2info
.vxl
;
8982 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8983 zif
->brslave_info
.br_if
);
8988 zvni
->advertise_svi_macip
= advertise
;
8989 /* Add primary SVI MAC-IP */
8990 zvni_add_macip_for_intf(vlan_if
, zvni
);
8992 /* Del primary MAC-IP */
8993 zvni_del_macip_for_intf(vlan_if
, zvni
);
8994 zvni
->advertise_svi_macip
= advertise
;
9003 * Handle message from client to enable/disable advertisement of g/w macip
9006 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9011 zebra_vni_t
*zvni
= NULL
;
9012 struct interface
*ifp
= NULL
;
9013 struct zebra_if
*zif
= NULL
;
9014 struct zebra_l2info_vxlan zl2_info
;
9015 struct interface
*vlan_if
= NULL
;
9017 if (!EVPN_ENABLED(zvrf
)) {
9018 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9024 STREAM_GETC(s
, advertise
);
9025 vni
= stream_get3(s
);
9027 zvni
= zvni_lookup(vni
);
9031 if (zvni
->advertise_subnet
== advertise
)
9034 if (IS_ZEBRA_DEBUG_VXLAN
)
9035 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9036 advertise
? "enabled" : "disabled", vni
,
9037 zvni
->advertise_subnet
? "enabled" : "disabled");
9040 zvni
->advertise_subnet
= advertise
;
9042 ifp
= zvni
->vxlan_if
;
9048 /* If down or not mapped to a bridge, we're done. */
9049 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9052 zl2_info
= zif
->l2info
.vxl
;
9055 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9059 if (zvni
->advertise_subnet
)
9060 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9062 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9069 * Handle message from client to enable/disable advertisement of g/w macip
9072 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9077 zebra_vni_t
*zvni
= NULL
;
9078 struct interface
*ifp
= NULL
;
9080 if (!EVPN_ENABLED(zvrf
)) {
9081 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9087 STREAM_GETC(s
, advertise
);
9088 STREAM_GETL(s
, vni
);
9091 if (IS_ZEBRA_DEBUG_VXLAN
)
9092 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9093 advertise
? "enabled" : "disabled",
9094 advertise_gw_macip_enabled(NULL
)
9098 if (zvrf
->advertise_gw_macip
== advertise
)
9101 zvrf
->advertise_gw_macip
= advertise
;
9103 if (advertise_gw_macip_enabled(zvni
))
9104 hash_iterate(zvrf
->vni_table
,
9105 zvni_gw_macip_add_for_vni_hash
, NULL
);
9107 hash_iterate(zvrf
->vni_table
,
9108 zvni_gw_macip_del_for_vni_hash
, NULL
);
9111 struct zebra_if
*zif
= NULL
;
9112 struct zebra_l2info_vxlan zl2_info
;
9113 struct interface
*vlan_if
= NULL
;
9114 struct interface
*vrr_if
= NULL
;
9116 zvni
= zvni_lookup(vni
);
9120 if (IS_ZEBRA_DEBUG_VXLAN
)
9122 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9123 advertise
? "enabled" : "disabled", vni
,
9124 advertise_gw_macip_enabled(zvni
) ? "enabled"
9127 if (zvni
->advertise_gw_macip
== advertise
)
9130 zvni
->advertise_gw_macip
= advertise
;
9132 ifp
= zvni
->vxlan_if
;
9138 /* If down or not mapped to a bridge, we're done. */
9139 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9142 zl2_info
= zif
->l2info
.vxl
;
9144 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9145 zif
->brslave_info
.br_if
);
9149 if (advertise_gw_macip_enabled(zvni
)) {
9150 /* Add primary SVI MAC-IP */
9151 zvni_add_macip_for_intf(vlan_if
, zvni
);
9153 /* Add VRR MAC-IP - if any*/
9154 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9156 zvni_add_macip_for_intf(vrr_if
, zvni
);
9158 /* Del primary MAC-IP */
9159 zvni_del_macip_for_intf(vlan_if
, zvni
);
9161 /* Del VRR MAC-IP - if any*/
9162 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9164 zvni_del_macip_for_intf(vrr_if
, zvni
);
9174 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9175 * When enabled, the VNI hash table will be built and MAC FDB table read;
9176 * when disabled, the entries should be deleted and remote VTEPs and MACs
9177 * uninstalled from the kernel.
9178 * This also informs the setting for BUM handling at the time this change
9179 * occurs; it is relevant only when specifying "learn".
9181 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9183 struct stream
*s
= NULL
;
9185 enum vxlan_flood_control flood_ctrl
;
9187 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9189 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9193 STREAM_GETC(s
, advertise
);
9194 STREAM_GETC(s
, flood_ctrl
);
9196 if (IS_ZEBRA_DEBUG_VXLAN
)
9197 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9198 zvrf_name(zvrf
), zvrf_id(zvrf
),
9199 advertise
? "enabled" : "disabled",
9200 is_evpn_enabled() ? "enabled" : "disabled",
9203 if (zvrf
->advertise_all_vni
== advertise
)
9206 zvrf
->advertise_all_vni
= advertise
;
9207 if (EVPN_ENABLED(zvrf
)) {
9208 zrouter
.evpn_vrf
= zvrf
;
9210 /* Note BUM handling */
9211 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9213 /* Build VNI hash table and inform BGP. */
9214 zvni_build_hash_table();
9216 /* Add all SVI (L3 GW) MACs to BGP*/
9217 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9220 /* Read the MAC FDB */
9221 macfdb_read(zvrf
->zns
);
9223 /* Read neighbors */
9224 neigh_read(zvrf
->zns
);
9226 /* Cleanup VTEPs for all VNIs - uninstall from
9227 * kernel and free entries.
9229 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9231 /* cleanup all l3vnis */
9232 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9234 /* Mark as "no EVPN VRF" */
9235 zrouter
.evpn_vrf
= NULL
;
9243 * Allocate VNI hash table for this VRF and do other initialization.
9244 * NOTE: Currently supported only for default VRF.
9246 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9250 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9251 "Zebra VRF VNI Table");
9252 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9253 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9256 /* Cleanup VNI info, but don't free the table. */
9257 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9261 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9262 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9265 /* Close all VNI handling */
9266 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9270 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9271 hash_free(zvrf
->vni_table
);
9274 /* init the l3vni table */
9275 void zebra_vxlan_init(void)
9277 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9278 "Zebra VRF L3 VNI table");
9279 zrouter
.evpn_vrf
= NULL
;
9282 /* free l3vni table */
9283 void zebra_vxlan_disable(void)
9285 hash_free(zrouter
.l3vni_table
);
9288 /* get the l3vni svi ifindex */
9289 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9291 zebra_l3vni_t
*zl3vni
= NULL
;
9293 zl3vni
= zl3vni_from_vrf(vrf_id
);
9294 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9297 return zl3vni
->svi_if
->ifindex
;
9300 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9302 struct zebra_vrf
*zvrf
= NULL
;
9303 zebra_neigh_t
*nbr
= NULL
;
9304 zebra_vni_t
*zvni
= NULL
;
9305 char buf1
[INET6_ADDRSTRLEN
];
9306 char buf2
[ETHER_ADDR_STRLEN
];
9308 nbr
= THREAD_ARG(t
);
9310 /* since this is asynchronous we need sanity checks*/
9311 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9315 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9319 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9323 if (IS_ZEBRA_DEBUG_VXLAN
)
9324 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9325 __PRETTY_FUNCTION__
,
9326 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9327 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9329 nbr
->dad_count
, zvni
->vni
);
9331 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9333 nbr
->detect_start_time
.tv_sec
= 0;
9334 nbr
->detect_start_time
.tv_usec
= 0;
9335 nbr
->dad_dup_detect_time
= 0;
9336 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9337 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9340 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9341 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9342 nbr
->flags
, nbr
->loc_seq
);
9343 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9344 zvni_neigh_install(zvni
, nbr
);
9350 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9352 struct zebra_vrf
*zvrf
= NULL
;
9353 zebra_mac_t
*mac
= NULL
;
9354 zebra_vni_t
*zvni
= NULL
;
9355 struct listnode
*node
= NULL
;
9356 zebra_neigh_t
*nbr
= NULL
;
9357 char buf
[ETHER_ADDR_STRLEN
];
9359 mac
= THREAD_ARG(t
);
9361 /* since this is asynchronous we need sanity checks*/
9362 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9366 zvni
= zvni_lookup(mac
->zvni
->vni
);
9370 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9374 if (IS_ZEBRA_DEBUG_VXLAN
)
9375 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9376 __PRETTY_FUNCTION__
,
9377 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9380 listcount(mac
->neigh_list
));
9382 /* Remove all IPs as duplicate associcated with this MAC */
9383 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9384 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9385 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9386 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9387 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9388 zvni_neigh_install(zvni
, nbr
);
9391 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9393 nbr
->detect_start_time
.tv_sec
= 0;
9394 nbr
->dad_dup_detect_time
= 0;
9397 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9399 mac
->detect_start_time
.tv_sec
= 0;
9400 mac
->detect_start_time
.tv_usec
= 0;
9401 mac
->dad_dup_detect_time
= 0;
9402 mac
->dad_mac_auto_recovery_timer
= NULL
;
9404 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9406 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9407 mac
->flags
, mac
->loc_seq
))
9410 /* Process all neighbors associated with this MAC. */
9411 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9413 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9414 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9416 /* Install the entry. */
9417 zvni_mac_install(zvni
, mac
);
9423 /************************** vxlan SG cache management ************************/
9424 /* Inform PIM about the mcast group */
9425 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9426 char *sg_str
, uint16_t cmd
)
9428 struct zserv
*client
= NULL
;
9429 struct stream
*s
= NULL
;
9431 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9435 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9437 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9438 stream_putl(s
, IPV4_MAX_BYTELEN
);
9439 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9440 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9442 /* Write packet size. */
9443 stream_putw_at(s
, 0, stream_get_endp(s
));
9445 if (IS_ZEBRA_DEBUG_VXLAN
)
9448 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9449 zebra_route_string(client
->proto
));
9451 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9452 client
->vxlan_sg_add_cnt
++;
9454 client
->vxlan_sg_del_cnt
++;
9456 return zserv_send_message(client
, s
);
9459 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9461 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9463 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9464 vxlan_sg
->sg
.grp
.s_addr
, 0));
9467 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9469 const zebra_vxlan_sg_t
*sg1
= p1
;
9470 const zebra_vxlan_sg_t
*sg2
= p2
;
9472 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9473 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9476 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9477 struct prefix_sg
*sg
)
9479 zebra_vxlan_sg_t
*vxlan_sg
;
9481 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9483 vxlan_sg
->zvrf
= zvrf
;
9485 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9487 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9489 if (IS_ZEBRA_DEBUG_VXLAN
)
9490 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9495 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9496 struct prefix_sg
*sg
)
9498 zebra_vxlan_sg_t lookup
;
9501 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9504 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9505 struct prefix_sg
*sg
)
9507 zebra_vxlan_sg_t
*vxlan_sg
;
9508 zebra_vxlan_sg_t
*parent
= NULL
;
9511 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9515 /* create a *G entry for every BUM group implicitly -
9516 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9517 * 2. the XG entry is used by pimd to setup the
9518 * vxlan-termination-mroute
9520 if (sg
->src
.s_addr
) {
9521 memset(&sip
, 0, sizeof(sip
));
9522 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9527 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9530 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9534 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9539 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9542 struct zebra_vrf
*zvrf
;
9544 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9548 /* On SG entry deletion remove the reference to its parent XG
9551 if (vxlan_sg
->sg
.src
.s_addr
) {
9552 memset(&sip
, 0, sizeof(sip
));
9553 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9556 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9557 ZEBRA_VXLAN_SG_DEL
);
9559 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9561 if (IS_ZEBRA_DEBUG_VXLAN
)
9562 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9564 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9567 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9568 struct in_addr sip
, struct in_addr mcast_grp
)
9570 zebra_vxlan_sg_t
*vxlan_sg
;
9571 struct prefix_sg sg
;
9573 sg
.family
= AF_INET
;
9574 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9577 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9581 if (vxlan_sg
->ref_cnt
)
9582 --vxlan_sg
->ref_cnt
;
9584 if (!vxlan_sg
->ref_cnt
)
9585 zebra_vxlan_sg_del(vxlan_sg
);
9588 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9589 struct in_addr sip
, struct in_addr mcast_grp
)
9591 zebra_vxlan_sg_t
*vxlan_sg
;
9592 struct prefix_sg sg
;
9594 sg
.family
= AF_INET
;
9595 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9598 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9600 ++vxlan_sg
->ref_cnt
;
9605 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9606 struct in_addr mcast_grp
)
9608 struct zebra_vrf
*zvrf
;
9610 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9613 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9617 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9620 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9621 struct in_addr mcast_grp
)
9623 struct zebra_vrf
*zvrf
;
9625 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9628 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9631 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9634 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9636 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9638 zebra_vxlan_sg_del(vxlan_sg
);