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(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 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t
);
147 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
148 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
149 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
150 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
152 static unsigned int mac_hash_keymake(void *p
);
153 static bool mac_cmp(const void *p1
, const void *p2
);
154 static void *zvni_mac_alloc(void *p
);
155 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
156 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
157 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
158 struct in_addr
*r_vtep_ip
);
159 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
161 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
162 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
163 uint8_t flags
, uint32_t seq
);
164 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
165 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
166 struct interface
*br_if
, vlanid_t vid
);
167 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
168 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
169 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
171 static unsigned int vni_hash_keymake(void *p
);
172 static void *zvni_alloc(void *p
);
173 static zebra_vni_t
*zvni_lookup(vni_t vni
);
174 static zebra_vni_t
*zvni_add(vni_t vni
);
175 static int zvni_del(zebra_vni_t
*zvni
);
176 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
177 static int zvni_send_del_to_client(vni_t vni
);
178 static void zvni_build_hash_table(void);
179 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
180 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
181 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
183 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
184 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
185 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
186 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
187 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
188 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
189 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
190 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
191 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
193 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
194 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
195 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
196 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
197 zebra_mac_t
*old_zmac
,
198 zebra_mac_t
*new_zmac
,
200 static int remote_neigh_count(zebra_mac_t
*zmac
);
201 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
202 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
203 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
204 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
206 struct in_addr vtep_ip
,
210 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
212 struct in_addr vtep_ip
,
216 static unsigned int zebra_vxlan_sg_hash_key_make(void *p
);
217 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
218 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
219 struct in_addr sip
, struct in_addr mcast_grp
);
220 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
221 struct in_addr sip
, struct in_addr mcast_grp
);
222 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
223 struct in_addr mcast_grp
);
224 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
225 struct in_addr mcast_grp
);
226 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
);
228 /* Private functions */
229 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
230 const struct host_rb_entry
*hle2
)
232 if (hle1
->p
.family
< hle2
->p
.family
)
235 if (hle1
->p
.family
> hle2
->p
.family
)
238 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
241 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
244 if (hle1
->p
.family
== AF_INET
) {
245 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
248 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
252 } else if (hle1
->p
.family
== AF_INET6
) {
253 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
256 zlog_debug("%s: Unexpected family type: %d",
257 __PRETTY_FUNCTION__
, hle1
->p
.family
);
261 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
263 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
265 struct host_rb_entry
*hle
;
268 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
275 * Return number of valid MACs in a VNI's MAC hash table - all
276 * remote MACs and non-internal (auto) local MACs count.
278 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
281 uint32_t num_macs
= 0;
283 struct hash_bucket
*hb
;
286 hash
= zvni
->mac_table
;
289 for (i
= 0; i
< hash
->size
; i
++) {
290 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
291 mac
= (zebra_mac_t
*)hb
->data
;
292 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
293 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
294 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
302 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
305 uint32_t num_macs
= 0;
307 struct hash_bucket
*hb
;
310 hash
= zvni
->mac_table
;
313 for (i
= 0; i
< hash
->size
; i
++) {
314 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
315 mac
= (zebra_mac_t
*)hb
->data
;
316 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
324 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
327 uint32_t num_neighs
= 0;
329 struct hash_bucket
*hb
;
332 hash
= zvni
->neigh_table
;
335 for (i
= 0; i
< hash
->size
; i
++) {
336 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
337 nbr
= (zebra_neigh_t
*)hb
->data
;
338 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
346 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
348 struct zebra_vrf
*zvrf
;
350 zvrf
= zebra_vrf_get_evpn();
351 if (zvrf
&& zvrf
->advertise_gw_macip
)
354 if (zvni
&& zvni
->advertise_gw_macip
)
360 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
362 struct zebra_vrf
*zvrf
;
364 zvrf
= zebra_vrf_get_evpn();
365 if (zvrf
&& zvrf
->advertise_svi_macip
)
368 if (zvni
&& zvni
->advertise_svi_macip
)
374 /* As part Duplicate Address Detection (DAD) for IP mobility
375 * MAC binding changes, ensure to inherit duplicate flag
378 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
379 zebra_mac_t
*old_zmac
,
380 zebra_mac_t
*new_zmac
,
383 bool is_old_mac_dup
= false;
384 bool is_new_mac_dup
= false;
386 if (!zvrf
->dup_addr_detect
)
388 /* Check old or new MAC is detected as duplicate
389 * mark this neigh as duplicate
392 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
393 ZEBRA_MAC_DUPLICATE
);
395 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
396 ZEBRA_MAC_DUPLICATE
);
397 /* Old and/or new MAC can be in duplicate state,
398 * based on that IP/Neigh Inherits the flag.
399 * If New MAC is marked duplicate, inherit to the IP.
400 * If old MAC is duplicate but new MAC is not, clear
401 * duplicate flag for IP and reset detection params
402 * and let IP DAD retrigger.
404 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
405 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
406 /* Capture Duplicate detection time */
407 nbr
->dad_dup_detect_time
= monotime(NULL
);
408 /* Mark neigh inactive */
409 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
412 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
413 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
415 nbr
->detect_start_time
.tv_sec
= 0;
416 nbr
->detect_start_time
.tv_usec
= 0;
421 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
423 struct in_addr vtep_ip
,
429 struct listnode
*node
= NULL
;
430 struct timeval elapsed
= {0, 0};
431 char buf
[ETHER_ADDR_STRLEN
];
432 char buf1
[INET6_ADDRSTRLEN
];
433 bool reset_params
= false;
435 if (!(zvrf
->dup_addr_detect
&& do_dad
))
438 /* MAC is detected as duplicate,
439 * Local MAC event -> hold on advertising to BGP.
440 * Remote MAC event -> hold on installing it.
442 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
443 if (IS_ZEBRA_DEBUG_VXLAN
)
445 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
447 prefix_mac2str(&mac
->macaddr
, buf
,
449 mac
->flags
, mac
->dad_count
,
450 zvrf
->dad_freeze_time
);
452 /* For duplicate MAC do not update
453 * client but update neigh due to
456 if (zvrf
->dad_freeze
)
457 *is_dup_detect
= true;
462 /* Check if detection time (M-secs) expired.
463 * Reset learn count and detection start time.
465 monotime_since(&mac
->detect_start_time
, &elapsed
);
466 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
467 if (is_local
&& !reset_params
) {
468 /* RFC-7432: A PE/VTEP that detects a MAC mobility
469 * event via LOCAL learning starts an M-second timer.
471 * NOTE: This is the START of the probe with count is
472 * 0 during LOCAL learn event.
473 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
475 reset_params
= !mac
->dad_count
;
479 if (IS_ZEBRA_DEBUG_VXLAN
)
481 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
482 , __PRETTY_FUNCTION__
,
483 prefix_mac2str(&mac
->macaddr
, buf
,
485 mac
->flags
, mac
->dad_count
);
488 /* Start dup. addr detection (DAD) start time,
489 * ONLY during LOCAL learn.
492 monotime(&mac
->detect_start_time
);
494 } else if (!is_local
) {
495 /* For REMOTE MAC, increment detection count
496 * ONLY while in probe window, once window passed,
497 * next local learn event should trigger DAD.
502 /* For LOCAL MAC learn event, once count is reset above via either
503 * initial/start detection time or passed the probe time, the count
504 * needs to be incremented.
509 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
510 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
511 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
513 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
514 is_local
? "local update, last" :
515 "remote update, from", inet_ntoa(vtep_ip
));
517 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
519 /* Capture Duplicate detection time */
520 mac
->dad_dup_detect_time
= monotime(NULL
);
522 /* Mark all IPs/Neighs as duplicate
523 * associcated with this MAC
525 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
527 /* Ony Mark IPs which are Local */
528 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
531 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
533 nbr
->dad_dup_detect_time
= monotime(NULL
);
535 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
536 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
538 prefix_mac2str(&mac
->macaddr
,
540 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
541 is_local
? "local" : "remote");
544 /* Start auto recovery timer for this MAC */
545 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
546 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
547 if (IS_ZEBRA_DEBUG_VXLAN
)
549 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
550 , __PRETTY_FUNCTION__
,
551 prefix_mac2str(&mac
->macaddr
, buf
,
553 mac
->flags
, zvrf
->dad_freeze_time
);
555 thread_add_timer(zrouter
.master
,
556 zebra_vxlan_dad_mac_auto_recovery_exp
,
557 mac
, zvrf
->dad_freeze_time
,
558 &mac
->dad_mac_auto_recovery_timer
);
561 /* In case of local update, do not inform to client (BGPd),
562 * upd_neigh for neigh sequence change.
564 if (zvrf
->dad_freeze
)
565 *is_dup_detect
= true;
569 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
571 struct in_addr vtep_ip
,
577 struct timeval elapsed
= {0, 0};
578 char buf
[ETHER_ADDR_STRLEN
];
579 char buf1
[INET6_ADDRSTRLEN
];
580 bool reset_params
= false;
582 if (!zvrf
->dup_addr_detect
)
585 /* IP is detected as duplicate or inherit dup
586 * state, hold on to install as remote entry
587 * only if freeze is enabled.
589 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
590 if (IS_ZEBRA_DEBUG_VXLAN
)
592 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
594 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
595 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
596 nbr
->flags
, nbr
->dad_count
,
597 zvrf
->dad_freeze_time
);
599 if (zvrf
->dad_freeze
)
600 *is_dup_detect
= true;
602 /* warn-only action, neigh will be installed.
603 * freeze action, it wil not be installed.
611 /* Check if detection time (M-secs) expired.
612 * Reset learn count and detection start time.
613 * During remote mac add, count should already be 1
614 * via local learning.
616 monotime_since(&nbr
->detect_start_time
, &elapsed
);
617 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
619 if (is_local
&& !reset_params
) {
620 /* RFC-7432: A PE/VTEP that detects a MAC mobility
621 * event via LOCAL learning starts an M-second timer.
623 * NOTE: This is the START of the probe with count is
624 * 0 during LOCAL learn event.
626 reset_params
= !nbr
->dad_count
;
630 if (IS_ZEBRA_DEBUG_VXLAN
)
632 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
634 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
635 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
636 nbr
->flags
, nbr
->dad_count
);
637 /* Reset learn count but do not start detection
638 * during REMOTE learn event.
641 /* Start dup. addr detection (DAD) start time,
642 * ONLY during LOCAL learn.
645 monotime(&nbr
->detect_start_time
);
647 } else if (!is_local
) {
648 /* For REMOTE IP/Neigh, increment detection count
649 * ONLY while in probe window, once window passed,
650 * next local learn event should trigger DAD.
655 /* For LOCAL IP/Neigh learn event, once count is reset above via either
656 * initial/start detection time or passed the probe time, the count
657 * needs to be incremented.
662 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
663 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
664 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
666 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
667 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
668 is_local
? "local update, last" :
669 "remote update, from",
672 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
674 /* Capture Duplicate detection time */
675 nbr
->dad_dup_detect_time
= monotime(NULL
);
677 /* Start auto recovery timer for this IP */
678 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
679 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
680 if (IS_ZEBRA_DEBUG_VXLAN
)
682 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
684 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
685 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
686 nbr
->flags
, zvrf
->dad_freeze_time
);
688 thread_add_timer(zrouter
.master
,
689 zebra_vxlan_dad_ip_auto_recovery_exp
,
690 nbr
, zvrf
->dad_freeze_time
,
691 &nbr
->dad_ip_auto_recovery_timer
);
693 if (zvrf
->dad_freeze
)
694 *is_dup_detect
= true;
699 * Helper function to determine maximum width of neighbor IP address for
700 * display - just because we're dealing with IPv6 addresses that can
703 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
706 char buf
[INET6_ADDRSTRLEN
];
707 struct neigh_walk_ctx
*wctx
= ctxt
;
710 n
= (zebra_neigh_t
*)bucket
->data
;
712 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
714 if (width
> wctx
->addr_width
)
715 wctx
->addr_width
= width
;
720 * Print a specific neighbor entry.
722 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
725 char buf1
[ETHER_ADDR_STRLEN
];
726 char buf2
[INET6_ADDRSTRLEN
];
727 const char *type_str
;
728 const char *state_str
;
729 bool flags_present
= false;
730 struct zebra_vrf
*zvrf
= NULL
;
731 struct timeval detect_start_time
= {0, 0};
733 zvrf
= zebra_vrf_get_evpn();
737 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
738 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
739 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
741 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
742 vty
= (struct vty
*)ctxt
;
744 vty_out(vty
, "IP: %s\n",
745 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
746 vty_out(vty
, " Type: %s\n", type_str
);
747 vty_out(vty
, " State: %s\n", state_str
);
748 vty_out(vty
, " MAC: %s\n",
749 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
751 json_object_string_add(json
, "ip", buf2
);
752 json_object_string_add(json
, "type", type_str
);
753 json_object_string_add(json
, "state", state_str
);
754 json_object_string_add(json
, "mac", buf1
);
756 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
758 vty_out(vty
, " Remote VTEP: %s\n",
759 inet_ntoa(n
->r_vtep_ip
));
761 json_object_string_add(json
, "remoteVtep",
762 inet_ntoa(n
->r_vtep_ip
));
764 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
766 vty_out(vty
, " Flags: Default-gateway");
767 flags_present
= true;
769 json_object_boolean_true_add(json
, "defaultGateway");
771 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
774 flags_present
? " ,Router" : " Flags: Router");
775 flags_present
= true;
781 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
782 n
->loc_seq
, n
->rem_seq
);
784 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
785 vty_out(vty
, " Duplicate, detected at %s",
786 time_to_string(n
->dad_dup_detect_time
));
787 } else if (n
->dad_count
) {
788 monotime_since(&n
->detect_start_time
,
790 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
791 char *buf
= time_to_string(
792 n
->detect_start_time
.tv_sec
);
795 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
797 " Duplicate detection started at %s, detection count %u\n",
798 tmp_buf
, n
->dad_count
);
802 json_object_int_add(json
, "localSequence", n
->loc_seq
);
803 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
804 json_object_int_add(json
, "detectionCount",
806 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
807 json_object_boolean_true_add(json
, "isDuplicate");
809 json_object_boolean_false_add(json
, "isDuplicate");
816 * Print neighbor hash entry - called for display of all neighbors.
818 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
821 json_object
*json_vni
= NULL
, *json_row
= NULL
;
823 char buf1
[ETHER_ADDR_STRLEN
];
824 char buf2
[INET6_ADDRSTRLEN
];
825 struct neigh_walk_ctx
*wctx
= ctxt
;
826 const char *state_str
;
829 json_vni
= wctx
->json
;
830 n
= (zebra_neigh_t
*)bucket
->data
;
833 json_row
= json_object_new_object();
835 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
836 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
837 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
838 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
839 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
842 if (json_vni
== NULL
) {
843 vty_out(vty
, "%*s %-6s %-8s %-17s\n",
844 -wctx
->addr_width
, buf2
, "local",
847 json_object_string_add(json_row
, "type", "local");
848 json_object_string_add(json_row
, "state", state_str
);
849 json_object_string_add(json_row
, "mac", buf1
);
850 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
851 json_object_boolean_true_add(
852 json_row
, "defaultGateway");
853 json_object_int_add(json_row
, "localSequence",
855 json_object_int_add(json_row
, "remoteSequence",
857 json_object_int_add(json_row
, "detectionCount",
859 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
860 json_object_boolean_true_add(json_row
,
863 json_object_boolean_false_add(json_row
,
867 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
868 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
869 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
872 if (json_vni
== NULL
) {
873 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
876 "%*s %-6s %-8s %-17s %-21s\n",
877 -wctx
->addr_width
, "Neighbor", "Type",
878 "State", "MAC", "Remote VTEP");
879 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
880 -wctx
->addr_width
, buf2
, "remote", state_str
,
881 buf1
, inet_ntoa(n
->r_vtep_ip
));
883 json_object_string_add(json_row
, "type", "remote");
884 json_object_string_add(json_row
, "state", state_str
);
885 json_object_string_add(json_row
, "mac", buf1
);
886 json_object_string_add(json_row
, "remoteVtep",
887 inet_ntoa(n
->r_vtep_ip
));
888 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
889 json_object_boolean_true_add(json_row
,
891 json_object_int_add(json_row
, "localSequence",
893 json_object_int_add(json_row
, "remoteSequence",
895 json_object_int_add(json_row
, "detectionCount",
897 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
898 json_object_boolean_true_add(json_row
,
901 json_object_boolean_false_add(json_row
,
908 json_object_object_add(json_vni
, buf2
, json_row
);
912 * Print neighbor hash entry in detail - called for display of all neighbors.
914 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
917 json_object
*json_vni
= NULL
, *json_row
= NULL
;
919 char buf
[INET6_ADDRSTRLEN
];
920 struct neigh_walk_ctx
*wctx
= ctxt
;
923 json_vni
= wctx
->json
;
924 n
= (zebra_neigh_t
*)bucket
->data
;
928 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
930 json_row
= json_object_new_object();
932 zvni_print_neigh(n
, vty
, json_row
);
935 json_object_object_add(json_vni
, buf
, json_row
);
939 * Print neighbors for all VNI.
941 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
945 json_object
*json
= NULL
, *json_vni
= NULL
;
948 struct neigh_walk_ctx wctx
;
949 char vni_str
[VNI_STR_LEN
];
952 vty
= (struct vty
*)args
[0];
953 json
= (json_object
*)args
[1];
954 print_dup
= (uint32_t)(uintptr_t)args
[2];
956 zvni
= (zebra_vni_t
*)bucket
->data
;
958 num_neigh
= hashcount(zvni
->neigh_table
);
961 num_neigh
= num_dup_detected_neighs(zvni
);
965 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
966 zvni
->vni
, num_neigh
);
968 json_vni
= json_object_new_object();
969 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
970 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
975 json_object_object_add(json
, vni_str
, json_vni
);
979 /* Since we have IPv6 addresses to deal with which can vary widely in
980 * size, we try to be a bit more elegant in display by first computing
983 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
986 wctx
.addr_width
= 15;
987 wctx
.json
= json_vni
;
988 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
991 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
992 -wctx
.addr_width
, "IP", "Type",
993 "State", "MAC", "Remote VTEP");
996 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
999 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1002 json_object_object_add(json
, vni_str
, json_vni
);
1005 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1009 nbr
= (zebra_neigh_t
*)bucket
->data
;
1013 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1014 zvni_print_neigh_hash(bucket
, ctxt
);
1017 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1022 nbr
= (zebra_neigh_t
*)bucket
->data
;
1026 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1027 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1031 * Print neighbors for all VNIs in detail.
1033 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1037 json_object
*json
= NULL
, *json_vni
= NULL
;
1040 struct neigh_walk_ctx wctx
;
1041 char vni_str
[VNI_STR_LEN
];
1044 vty
= (struct vty
*)args
[0];
1045 json
= (json_object
*)args
[1];
1046 print_dup
= (uint32_t)(uintptr_t)args
[2];
1048 zvni
= (zebra_vni_t
*)bucket
->data
;
1051 vty_out(vty
, "{}\n");
1054 num_neigh
= hashcount(zvni
->neigh_table
);
1056 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1061 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1062 zvni
->vni
, num_neigh
);
1064 json_vni
= json_object_new_object();
1065 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1066 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1070 json_object_object_add(json
, vni_str
, json_vni
);
1074 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1077 wctx
.addr_width
= 15;
1078 wctx
.json
= json_vni
;
1081 hash_iterate(zvni
->neigh_table
,
1082 zvni_print_dad_neigh_hash_detail
, &wctx
);
1084 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1088 json_object_object_add(json
, vni_str
, json_vni
);
1091 /* print a specific next hop for an l3vni */
1092 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1095 char buf1
[ETHER_ADDR_STRLEN
];
1096 char buf2
[INET6_ADDRSTRLEN
];
1097 json_object
*json_hosts
= NULL
;
1098 struct host_rb_entry
*hle
;
1101 vty_out(vty
, "Ip: %s\n",
1102 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1103 vty_out(vty
, " RMAC: %s\n",
1104 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1105 vty_out(vty
, " Refcount: %d\n",
1106 rb_host_count(&n
->host_rb
));
1107 vty_out(vty
, " Prefixes:\n");
1108 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1109 vty_out(vty
, " %s\n",
1110 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1112 json_hosts
= json_object_new_array();
1113 json_object_string_add(
1114 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1115 json_object_string_add(
1117 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1118 json_object_int_add(json
, "refCount",
1119 rb_host_count(&n
->host_rb
));
1120 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1121 json_object_array_add(json_hosts
,
1122 json_object_new_string(prefix2str(
1123 &hle
->p
, buf2
, sizeof(buf2
))));
1124 json_object_object_add(json
, "prefixList", json_hosts
);
1128 /* Print a specific RMAC entry */
1129 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1132 char buf1
[ETHER_ADDR_STRLEN
];
1133 char buf2
[PREFIX_STRLEN
];
1134 json_object
*json_hosts
= NULL
;
1135 struct host_rb_entry
*hle
;
1138 vty_out(vty
, "MAC: %s\n",
1139 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1140 vty_out(vty
, " Remote VTEP: %s\n",
1141 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1142 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1143 vty_out(vty
, " Prefixes:\n");
1144 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1145 vty_out(vty
, " %s\n",
1146 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1148 json_hosts
= json_object_new_array();
1149 json_object_string_add(
1151 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1152 json_object_string_add(json
, "vtepIp",
1153 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1154 json_object_int_add(json
, "refCount",
1155 rb_host_count(&zrmac
->host_rb
));
1156 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1157 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1158 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1159 json_object_array_add(
1161 json_object_new_string(prefix2str(
1162 &hle
->p
, buf2
, sizeof(buf2
))));
1163 json_object_object_add(json
, "prefixList", json_hosts
);
1168 * Print a specific MAC entry.
1170 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1173 zebra_neigh_t
*n
= NULL
;
1174 struct listnode
*node
= NULL
;
1175 char buf1
[ETHER_ADDR_STRLEN
];
1176 char buf2
[INET6_ADDRSTRLEN
];
1177 struct zebra_vrf
*zvrf
;
1178 struct timeval detect_start_time
= {0, 0};
1180 zvrf
= zebra_vrf_get_evpn();
1184 vty
= (struct vty
*)ctxt
;
1185 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1188 json_object
*json_mac
= json_object_new_object();
1190 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1191 struct zebra_ns
*zns
;
1192 struct interface
*ifp
;
1195 ifindex
= mac
->fwd_info
.local
.ifindex
;
1196 zns
= zebra_ns_lookup(NS_DEFAULT
);
1197 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1200 json_object_string_add(json_mac
, "type", "local");
1201 json_object_string_add(json_mac
, "intf", ifp
->name
);
1202 json_object_int_add(json_mac
, "ifindex", ifindex
);
1203 if (mac
->fwd_info
.local
.vid
)
1204 json_object_int_add(json_mac
, "vlan",
1205 mac
->fwd_info
.local
.vid
);
1206 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1207 json_object_string_add(json_mac
, "type", "remote");
1208 json_object_string_add(
1209 json_mac
, "remoteVtep",
1210 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1211 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1212 json_object_string_add(json_mac
, "type", "auto");
1214 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1215 json_object_boolean_true_add(json_mac
, "stickyMac");
1217 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1218 json_object_boolean_true_add(json_mac
,
1221 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1222 json_object_boolean_true_add(json_mac
,
1223 "remoteGatewayMac");
1225 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1226 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1228 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1229 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1230 json_object_boolean_true_add(json_mac
, "isDuplicate");
1232 json_object_boolean_false_add(json_mac
, "isDuplicate");
1234 /* print all the associated neigh */
1235 if (!listcount(mac
->neigh_list
))
1236 json_object_string_add(json_mac
, "neighbors", "none");
1238 json_object
*json_active_nbrs
= json_object_new_array();
1239 json_object
*json_inactive_nbrs
=
1240 json_object_new_array();
1241 json_object
*json_nbrs
= json_object_new_object();
1243 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1244 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1245 json_object_array_add(
1247 json_object_new_string(
1252 json_object_array_add(
1254 json_object_new_string(
1260 json_object_object_add(json_nbrs
, "active",
1262 json_object_object_add(json_nbrs
, "inactive",
1263 json_inactive_nbrs
);
1264 json_object_object_add(json_mac
, "neighbors",
1268 json_object_object_add(json
, buf1
, json_mac
);
1270 vty_out(vty
, "MAC: %s\n", buf1
);
1272 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1273 struct zebra_ns
*zns
;
1274 struct interface
*ifp
;
1277 ifindex
= mac
->fwd_info
.local
.ifindex
;
1278 zns
= zebra_ns_lookup(NS_DEFAULT
);
1279 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1282 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1283 if (mac
->fwd_info
.local
.vid
)
1284 vty_out(vty
, " VLAN: %u",
1285 mac
->fwd_info
.local
.vid
);
1286 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1287 vty_out(vty
, " Remote VTEP: %s",
1288 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1289 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1290 vty_out(vty
, " Auto Mac ");
1293 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1294 vty_out(vty
, " Sticky Mac ");
1296 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1297 vty_out(vty
, " Default-gateway Mac ");
1299 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1300 vty_out(vty
, " Remote-gateway Mac ");
1303 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1307 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1308 vty_out(vty
, " Duplicate, detected at %s",
1309 time_to_string(mac
->dad_dup_detect_time
));
1310 } else if (mac
->dad_count
) {
1311 monotime_since(&mac
->detect_start_time
,
1312 &detect_start_time
);
1313 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1314 char *buf
= time_to_string(
1315 mac
->detect_start_time
.tv_sec
);
1318 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1320 " Duplicate detection started at %s, detection count %u\n",
1321 tmp_buf
, mac
->dad_count
);
1325 /* print all the associated neigh */
1326 vty_out(vty
, " Neighbors:\n");
1327 if (!listcount(mac
->neigh_list
))
1328 vty_out(vty
, " No Neighbors\n");
1330 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1331 vty_out(vty
, " %s %s\n",
1332 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1333 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1344 * Print MAC hash entry - called for display of all MACs.
1346 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1349 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1351 char buf1
[ETHER_ADDR_STRLEN
];
1352 struct mac_walk_ctx
*wctx
= ctxt
;
1355 json_mac_hdr
= wctx
->json
;
1356 mac
= (zebra_mac_t
*)bucket
->data
;
1358 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1361 json_mac
= json_object_new_object();
1363 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1364 struct zebra_ns
*zns
;
1366 struct interface
*ifp
;
1369 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1372 zns
= zebra_ns_lookup(NS_DEFAULT
);
1373 ifindex
= mac
->fwd_info
.local
.ifindex
;
1374 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1375 if (!ifp
) // unexpected
1377 vid
= mac
->fwd_info
.local
.vid
;
1378 if (json_mac_hdr
== NULL
)
1379 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1382 json_object_string_add(json_mac
, "type", "local");
1383 json_object_string_add(json_mac
, "intf", ifp
->name
);
1386 if (json_mac_hdr
== NULL
)
1387 vty_out(vty
, " %-5u", vid
);
1389 json_object_int_add(json_mac
, "vlan", vid
);
1391 if (json_mac_hdr
== NULL
) {
1394 json_object_int_add(json_mac
, "localSequence",
1396 json_object_int_add(json_mac
, "remoteSequence",
1398 json_object_int_add(json_mac
, "detectionCount",
1400 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1401 json_object_boolean_true_add(json_mac
,
1404 json_object_boolean_false_add(json_mac
,
1406 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1411 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1413 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1414 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1418 if (json_mac_hdr
== NULL
) {
1419 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1420 (wctx
->count
== 0)) {
1421 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1422 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1423 "Type", "Intf/Remote VTEP", "VLAN");
1425 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1426 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1428 json_object_string_add(json_mac
, "type", "remote");
1429 json_object_string_add(json_mac
, "remoteVtep",
1430 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1431 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1432 json_object_int_add(json_mac
, "localSequence",
1434 json_object_int_add(json_mac
, "remoteSequence",
1436 json_object_int_add(json_mac
, "detectionCount",
1438 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1439 json_object_boolean_true_add(json_mac
,
1442 json_object_boolean_false_add(json_mac
,
1451 /* Print Duplicate MAC */
1452 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1456 mac
= (zebra_mac_t
*)bucket
->data
;
1460 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1461 zvni_print_mac_hash(bucket
, ctxt
);
1465 * Print MAC hash entry in detail - called for display of all MACs.
1467 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1470 json_object
*json_mac_hdr
= NULL
;
1472 struct mac_walk_ctx
*wctx
= ctxt
;
1473 char buf1
[ETHER_ADDR_STRLEN
];
1476 json_mac_hdr
= wctx
->json
;
1477 mac
= (zebra_mac_t
*)bucket
->data
;
1482 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1484 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1487 /* Print Duplicate MAC in detail */
1488 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1493 mac
= (zebra_mac_t
*)bucket
->data
;
1497 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1498 zvni_print_mac_hash_detail(bucket
, ctxt
);
1502 * Print MACs for all VNI.
1504 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1507 json_object
*json
= NULL
, *json_vni
= NULL
;
1508 json_object
*json_mac
= NULL
;
1511 struct mac_walk_ctx
*wctx
= ctxt
;
1512 char vni_str
[VNI_STR_LEN
];
1514 vty
= (struct vty
*)wctx
->vty
;
1515 json
= (struct json_object
*)wctx
->json
;
1517 zvni
= (zebra_vni_t
*)bucket
->data
;
1520 /*We are iterating over a new VNI, set the count to 0*/
1523 num_macs
= num_valid_macs(zvni
);
1527 if (wctx
->print_dup
)
1528 num_macs
= num_dup_detected_macs(zvni
);
1531 json_vni
= json_object_new_object();
1532 json_mac
= json_object_new_object();
1533 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1536 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1538 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1539 zvni
->vni
, num_macs
);
1540 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1541 "Intf/Remote VTEP", "VLAN");
1543 json_object_int_add(json_vni
, "numMacs", num_macs
);
1548 json_object_int_add(json_vni
, "numMacs", num_macs
);
1549 json_object_object_add(json
, vni_str
, json_vni
);
1554 /* assign per-vni to wctx->json object to fill macs
1555 * under the vni. Re-assign primary json object to fill
1556 * next vni information.
1558 wctx
->json
= json_mac
;
1559 if (wctx
->print_dup
)
1560 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1562 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1566 json_object_object_add(json_vni
, "macs", json_mac
);
1567 json_object_object_add(json
, vni_str
, json_vni
);
1572 * Print MACs in detail for all VNI.
1574 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1578 json_object
*json
= NULL
, *json_vni
= NULL
;
1579 json_object
*json_mac
= NULL
;
1582 struct mac_walk_ctx
*wctx
= ctxt
;
1583 char vni_str
[VNI_STR_LEN
];
1585 vty
= (struct vty
*)wctx
->vty
;
1586 json
= (struct json_object
*)wctx
->json
;
1588 zvni
= (zebra_vni_t
*)bucket
->data
;
1591 vty_out(vty
, "{}\n");
1596 /*We are iterating over a new VNI, set the count to 0*/
1599 num_macs
= num_valid_macs(zvni
);
1603 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1607 json_vni
= json_object_new_object();
1608 json_mac
= json_object_new_object();
1609 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1612 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1614 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1615 zvni
->vni
, num_macs
);
1617 json_object_int_add(json_vni
, "numMacs", num_macs
);
1619 /* assign per-vni to wctx->json object to fill macs
1620 * under the vni. Re-assign primary json object to fill
1621 * next vni information.
1623 wctx
->json
= json_mac
;
1624 if (wctx
->print_dup
)
1625 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1628 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1632 json_object_object_add(json_vni
, "macs", json_mac
);
1633 json_object_object_add(json
, vni_str
, json_vni
);
1637 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1639 struct nh_walk_ctx
*wctx
= NULL
;
1640 struct vty
*vty
= NULL
;
1641 struct json_object
*json_vni
= NULL
;
1642 struct json_object
*json_nh
= NULL
;
1643 zebra_neigh_t
*n
= NULL
;
1644 char buf1
[ETHER_ADDR_STRLEN
];
1645 char buf2
[INET6_ADDRSTRLEN
];
1647 wctx
= (struct nh_walk_ctx
*)ctx
;
1649 json_vni
= wctx
->json
;
1651 json_nh
= json_object_new_object();
1652 n
= (zebra_neigh_t
*)bucket
->data
;
1655 vty_out(vty
, "%-15s %-17s\n",
1656 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1657 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1659 json_object_string_add(json_nh
, "nexthopIp",
1660 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1661 json_object_string_add(
1662 json_nh
, "routerMac",
1663 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1664 json_object_object_add(json_vni
,
1665 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1670 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1673 struct vty
*vty
= NULL
;
1674 json_object
*json
= NULL
;
1675 json_object
*json_vni
= NULL
;
1676 zebra_l3vni_t
*zl3vni
= NULL
;
1677 uint32_t num_nh
= 0;
1678 struct nh_walk_ctx wctx
;
1679 char vni_str
[VNI_STR_LEN
];
1681 vty
= (struct vty
*)args
[0];
1682 json
= (struct json_object
*)args
[1];
1684 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1686 num_nh
= hashcount(zl3vni
->nh_table
);
1691 json_vni
= json_object_new_object();
1692 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1696 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1697 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1699 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1701 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1703 wctx
.json
= json_vni
;
1704 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1706 json_object_object_add(json
, vni_str
, json_vni
);
1709 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1712 struct vty
*vty
= NULL
;
1713 json_object
*json
= NULL
;
1714 json_object
*json_vni
= NULL
;
1715 zebra_l3vni_t
*zl3vni
= NULL
;
1717 struct rmac_walk_ctx wctx
;
1718 char vni_str
[VNI_STR_LEN
];
1720 vty
= (struct vty
*)args
[0];
1721 json
= (struct json_object
*)args
[1];
1723 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1725 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1730 json_vni
= json_object_new_object();
1731 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1735 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1736 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1738 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1740 /* assign per-vni to wctx->json object to fill macs
1741 * under the vni. Re-assign primary json object to fill
1742 * next vni information.
1744 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1746 wctx
.json
= json_vni
;
1747 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1749 json_object_object_add(json
, vni_str
, json_vni
);
1752 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1754 zebra_mac_t
*zrmac
= NULL
;
1755 struct rmac_walk_ctx
*wctx
= NULL
;
1756 struct vty
*vty
= NULL
;
1757 struct json_object
*json
= NULL
;
1758 struct json_object
*json_rmac
= NULL
;
1759 char buf
[ETHER_ADDR_STRLEN
];
1761 wctx
= (struct rmac_walk_ctx
*)ctx
;
1765 json_rmac
= json_object_new_object();
1766 zrmac
= (zebra_mac_t
*)bucket
->data
;
1769 vty_out(vty
, "%-17s %-21s\n",
1770 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1771 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1773 json_object_string_add(
1774 json_rmac
, "routerMac",
1775 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1776 json_object_string_add(json_rmac
, "vtepIp",
1777 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1778 json_object_object_add(
1779 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1784 /* print a specific L3 VNI entry */
1785 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1787 char buf
[ETHER_ADDR_STRLEN
];
1788 struct vty
*vty
= NULL
;
1789 json_object
*json
= NULL
;
1790 zebra_vni_t
*zvni
= NULL
;
1791 json_object
*json_vni_list
= NULL
;
1792 struct listnode
*node
= NULL
, *nnode
= NULL
;
1798 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1799 vty_out(vty
, " Type: %s\n", "L3");
1800 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1801 vty_out(vty
, " Local Vtep Ip: %s\n",
1802 inet_ntoa(zl3vni
->local_vtep_ip
));
1803 vty_out(vty
, " Vxlan-Intf: %s\n",
1804 zl3vni_vxlan_if_name(zl3vni
));
1805 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1806 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1807 vty_out(vty
, " VNI Filter: %s\n",
1808 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1809 ? "prefix-routes-only"
1811 vty_out(vty
, " Router MAC: %s\n",
1812 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1813 vty_out(vty
, " L2 VNIs: ");
1814 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1815 vty_out(vty
, "%u ", zvni
->vni
);
1818 json_vni_list
= json_object_new_array();
1819 json_object_int_add(json
, "vni", zl3vni
->vni
);
1820 json_object_string_add(json
, "type", "L3");
1821 json_object_string_add(json
, "localVtepIp",
1822 inet_ntoa(zl3vni
->local_vtep_ip
));
1823 json_object_string_add(json
, "vxlanIntf",
1824 zl3vni_vxlan_if_name(zl3vni
));
1825 json_object_string_add(json
, "sviIntf",
1826 zl3vni_svi_if_name(zl3vni
));
1827 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1828 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1829 json_object_string_add(
1831 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1832 json_object_string_add(
1834 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1835 ? "prefix-routes-only"
1837 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1838 json_object_array_add(json_vni_list
,
1839 json_object_new_int(zvni
->vni
));
1841 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1846 * Print a specific VNI entry.
1848 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1851 zebra_vtep_t
*zvtep
;
1854 json_object
*json
= NULL
;
1855 json_object
*json_vtep_list
= NULL
;
1856 json_object
*json_ip_str
= NULL
;
1862 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1863 vty_out(vty
, " Type: %s\n", "L2");
1864 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1866 json_object_int_add(json
, "vni", zvni
->vni
);
1867 json_object_string_add(json
, "type", "L2");
1868 json_object_string_add(json
, "vrf",
1869 vrf_id_to_name(zvni
->vrf_id
));
1872 if (!zvni
->vxlan_if
) { // unexpected
1874 vty_out(vty
, " VxLAN interface: unknown\n");
1877 num_macs
= num_valid_macs(zvni
);
1878 num_neigh
= hashcount(zvni
->neigh_table
);
1880 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1881 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1882 vty_out(vty
, " Local VTEP IP: %s\n",
1883 inet_ntoa(zvni
->local_vtep_ip
));
1884 vty_out(vty
, " Mcast group: %s\n",
1885 inet_ntoa(zvni
->mcast_grp
));
1887 json_object_string_add(json
, "vxlanInterface",
1888 zvni
->vxlan_if
->name
);
1889 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1890 json_object_string_add(json
, "vtepIp",
1891 inet_ntoa(zvni
->local_vtep_ip
));
1892 json_object_string_add(json
, "mcastGroup",
1893 inet_ntoa(zvni
->mcast_grp
));
1894 json_object_string_add(json
, "advertiseGatewayMacip",
1895 zvni
->advertise_gw_macip
? "Yes" : "No");
1896 json_object_int_add(json
, "numMacs", num_macs
);
1897 json_object_int_add(json
, "numArpNd", num_neigh
);
1901 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1904 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1906 json_vtep_list
= json_object_new_array();
1907 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1908 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1909 zvtep
->flood_control
,
1910 VXLAN_FLOOD_STR_DEFAULT
);
1913 vty_out(vty
, " %s flood: %s\n",
1914 inet_ntoa(zvtep
->vtep_ip
),
1917 json_ip_str
= json_object_new_string(
1918 inet_ntoa(zvtep
->vtep_ip
));
1919 json_object_array_add(json_vtep_list
,
1924 json_object_object_add(json
, "numRemoteVteps",
1929 " Number of MACs (local and remote) known for this VNI: %u\n",
1932 " Number of ARPs (IPv4 and IPv6, local and remote) "
1933 "known for this VNI: %u\n",
1935 vty_out(vty
, " Advertise-gw-macip: %s\n",
1936 zvni
->advertise_gw_macip
? "Yes" : "No");
1940 /* print a L3 VNI hash entry */
1941 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1943 struct vty
*vty
= NULL
;
1944 json_object
*json
= NULL
;
1945 json_object
*json_vni
= NULL
;
1946 zebra_l3vni_t
*zl3vni
= NULL
;
1948 vty
= (struct vty
*)ctx
[0];
1949 json
= (json_object
*)ctx
[1];
1951 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1954 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1955 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1956 hashcount(zl3vni
->rmac_table
),
1957 hashcount(zl3vni
->nh_table
), "n/a",
1958 zl3vni_vrf_name(zl3vni
));
1960 char vni_str
[VNI_STR_LEN
];
1962 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1963 json_vni
= json_object_new_object();
1964 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1965 json_object_string_add(json_vni
, "vxlanIf",
1966 zl3vni_vxlan_if_name(zl3vni
));
1967 json_object_int_add(json_vni
, "numMacs",
1968 hashcount(zl3vni
->rmac_table
));
1969 json_object_int_add(json_vni
, "numArpNd",
1970 hashcount(zl3vni
->nh_table
));
1971 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1972 json_object_string_add(json_vni
, "type", "L3");
1973 json_object_string_add(json_vni
, "tenantVrf",
1974 zl3vni_vrf_name(zl3vni
));
1975 json_object_object_add(json
, vni_str
, json_vni
);
1979 /* Private Structure to pass callback data for hash iterator */
1980 struct zvni_evpn_show
{
1983 struct zebra_vrf
*zvrf
;
1986 /* print a L3 VNI hash entry in detail*/
1987 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1989 struct vty
*vty
= NULL
;
1990 zebra_l3vni_t
*zl3vni
= NULL
;
1991 json_object
*json
= NULL
;
1992 bool use_json
= false;
1993 struct zvni_evpn_show
*zes
= data
;
2001 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2003 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2009 * Print a VNI hash entry - called for display of all VNIs.
2011 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2015 zebra_vtep_t
*zvtep
;
2016 uint32_t num_vteps
= 0;
2017 uint32_t num_macs
= 0;
2018 uint32_t num_neigh
= 0;
2019 json_object
*json
= NULL
;
2020 json_object
*json_vni
= NULL
;
2021 json_object
*json_ip_str
= NULL
;
2022 json_object
*json_vtep_list
= NULL
;
2027 zvni
= (zebra_vni_t
*)bucket
->data
;
2029 zvtep
= zvni
->vteps
;
2032 zvtep
= zvtep
->next
;
2035 num_macs
= num_valid_macs(zvni
);
2036 num_neigh
= hashcount(zvni
->neigh_table
);
2038 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2040 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2041 num_macs
, num_neigh
, num_vteps
,
2042 vrf_id_to_name(zvni
->vrf_id
));
2044 char vni_str
[VNI_STR_LEN
];
2045 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2046 json_vni
= json_object_new_object();
2047 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2048 json_object_string_add(json_vni
, "type", "L2");
2049 json_object_string_add(json_vni
, "vxlanIf",
2050 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2052 json_object_int_add(json_vni
, "numMacs", num_macs
);
2053 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2054 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2055 json_object_string_add(json_vni
, "tenantVrf",
2056 vrf_id_to_name(zvni
->vrf_id
));
2058 json_vtep_list
= json_object_new_array();
2059 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2060 json_ip_str
= json_object_new_string(
2061 inet_ntoa(zvtep
->vtep_ip
));
2062 json_object_array_add(json_vtep_list
,
2065 json_object_object_add(json_vni
, "remoteVteps",
2068 json_object_object_add(json
, vni_str
, json_vni
);
2073 * Print a VNI hash entry in detail - called for display of all VNIs.
2075 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2079 json_object
*json
= NULL
;
2080 bool use_json
= false;
2081 struct zvni_evpn_show
*zes
= data
;
2089 zvni
= (zebra_vni_t
*)bucket
->data
;
2091 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2096 * Inform BGP about local MACIP.
2098 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2099 struct ipaddr
*ip
, uint8_t flags
,
2100 uint32_t seq
, int state
, uint16_t cmd
)
2102 char buf
[ETHER_ADDR_STRLEN
];
2103 char buf2
[INET6_ADDRSTRLEN
];
2105 struct zserv
*client
= NULL
;
2106 struct stream
*s
= NULL
;
2108 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2109 /* BGP may not be running. */
2113 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2115 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2116 stream_putl(s
, vni
);
2117 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2120 if (IS_IPADDR_V4(ip
))
2121 ipa_len
= IPV4_MAX_BYTELEN
;
2122 else if (IS_IPADDR_V6(ip
))
2123 ipa_len
= IPV6_MAX_BYTELEN
;
2125 stream_putl(s
, ipa_len
); /* IP address length */
2127 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2129 stream_putl(s
, 0); /* Just MAC. */
2131 if (cmd
== ZEBRA_MACIP_ADD
) {
2132 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2133 stream_putl(s
, seq
); /* sequence number */
2135 stream_putl(s
, state
); /* state - active/inactive */
2139 /* Write packet size. */
2140 stream_putw_at(s
, 0, stream_get_endp(s
));
2142 if (IS_ZEBRA_DEBUG_VXLAN
)
2144 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2145 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2146 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2147 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2148 zebra_route_string(client
->proto
));
2150 if (cmd
== ZEBRA_MACIP_ADD
)
2151 client
->macipadd_cnt
++;
2153 client
->macipdel_cnt
++;
2155 return zserv_send_message(client
, s
);
2159 * Make hash key for neighbors.
2161 static unsigned int neigh_hash_keymake(void *p
)
2163 zebra_neigh_t
*n
= p
;
2164 struct ipaddr
*ip
= &n
->ip
;
2166 if (IS_IPADDR_V4(ip
))
2167 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2169 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2170 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2174 * Compare two neighbor hash structures.
2176 static bool neigh_cmp(const void *p1
, const void *p2
)
2178 const zebra_neigh_t
*n1
= p1
;
2179 const zebra_neigh_t
*n2
= p2
;
2181 if (n1
== NULL
&& n2
== NULL
)
2184 if (n1
== NULL
|| n2
== NULL
)
2187 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2190 static int neigh_list_cmp(void *p1
, void *p2
)
2192 const zebra_neigh_t
*n1
= p1
;
2193 const zebra_neigh_t
*n2
= p2
;
2195 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2199 * Callback to allocate neighbor hash entry.
2201 static void *zvni_neigh_alloc(void *p
)
2203 const zebra_neigh_t
*tmp_n
= p
;
2206 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2213 * Add neighbor entry.
2215 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2216 struct ethaddr
*mac
)
2218 zebra_neigh_t tmp_n
;
2219 zebra_neigh_t
*n
= NULL
;
2220 zebra_mac_t
*zmac
= NULL
;
2222 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2223 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2224 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2227 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2228 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2230 n
->dad_ip_auto_recovery_timer
= NULL
;
2232 /* Associate the neigh to mac */
2233 zmac
= zvni_mac_lookup(zvni
, mac
);
2235 listnode_add_sort(zmac
->neigh_list
, n
);
2241 * Delete neighbor entry.
2243 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2245 zebra_neigh_t
*tmp_n
;
2246 zebra_mac_t
*zmac
= NULL
;
2248 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2250 listnode_delete(zmac
->neigh_list
, n
);
2252 /* Cancel auto recovery */
2253 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2255 /* Free the VNI hash entry and allocated memory. */
2256 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2257 XFREE(MTYPE_NEIGH
, tmp_n
);
2263 * Free neighbor hash entry (callback)
2265 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2267 struct neigh_walk_ctx
*wctx
= arg
;
2268 zebra_neigh_t
*n
= bucket
->data
;
2270 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2271 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2272 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2273 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2274 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2275 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2276 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2277 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2278 &n
->emac
, 0, n
->state
);
2280 if (wctx
->uninstall
)
2281 zvni_neigh_uninstall(wctx
->zvni
, n
);
2283 zvni_neigh_del(wctx
->zvni
, n
);
2290 * Delete all neighbor entries from specific VTEP for a particular VNI.
2292 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2293 struct in_addr
*r_vtep_ip
)
2295 struct neigh_walk_ctx wctx
;
2297 if (!zvni
->neigh_table
)
2300 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2302 wctx
.uninstall
= uninstall
;
2303 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2304 wctx
.r_vtep_ip
= *r_vtep_ip
;
2306 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2310 * Delete all neighbor entries for this VNI.
2312 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2315 struct neigh_walk_ctx wctx
;
2317 if (!zvni
->neigh_table
)
2320 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2322 wctx
.uninstall
= uninstall
;
2323 wctx
.upd_client
= upd_client
;
2326 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2330 * Look up neighbor hash entry.
2332 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2337 memset(&tmp
, 0, sizeof(tmp
));
2338 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2339 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2345 * Process all neighbors associated with a MAC upon the MAC being learnt
2346 * locally or undergoing any other change (such as sequence number).
2348 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2352 zebra_neigh_t
*n
= NULL
;
2353 struct listnode
*node
= NULL
;
2354 struct zebra_vrf
*zvrf
= NULL
;
2355 char buf
[ETHER_ADDR_STRLEN
];
2357 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2359 if (IS_ZEBRA_DEBUG_VXLAN
)
2360 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2361 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2362 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2364 /* Walk all neighbors and mark any inactive local neighbors as
2365 * active and/or update sequence number upon a move, and inform BGP.
2366 * The action for remote neighbors is TBD.
2367 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2368 * accidentally end up deleting a just-learnt local neighbor.
2370 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2371 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2372 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2373 ZEBRA_NEIGH_SET_ACTIVE(n
);
2374 n
->loc_seq
= zmac
->loc_seq
;
2375 if (!(zvrf
->dup_addr_detect
&&
2376 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2377 ZEBRA_NEIGH_DUPLICATE
)))
2378 zvni_neigh_send_add_to_client(
2379 zvni
->vni
, &n
->ip
, &n
->emac
,
2380 n
->flags
, n
->loc_seq
);
2387 * Process all neighbors associated with a local MAC upon the MAC being
2390 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2393 zebra_neigh_t
*n
= NULL
;
2394 struct listnode
*node
= NULL
;
2395 char buf
[ETHER_ADDR_STRLEN
];
2397 if (IS_ZEBRA_DEBUG_VXLAN
)
2398 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2399 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2402 /* Walk all local neighbors and mark as inactive and inform
2404 * TBD: There is currently no handling for remote neighbors. We
2405 * don't expect them to exist, if they do, do we install the MAC
2406 * as a remote MAC and the neighbor as remote?
2408 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2409 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2410 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2411 ZEBRA_NEIGH_SET_INACTIVE(n
);
2413 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2414 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2421 * Process all neighbors associated with a MAC upon the MAC being remotely
2424 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2427 zebra_neigh_t
*n
= NULL
;
2428 struct listnode
*node
= NULL
;
2429 char buf
[ETHER_ADDR_STRLEN
];
2431 if (IS_ZEBRA_DEBUG_VXLAN
)
2432 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2433 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2436 /* Walk all local neighbors and mark as inactive and inform
2439 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2440 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2441 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2442 ZEBRA_NEIGH_SET_INACTIVE(n
);
2444 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2445 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2452 * Process all neighbors associated with a remote MAC upon the MAC being
2455 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2458 /* NOTE: Currently a NO-OP. */
2461 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2463 zebra_neigh_t
*nbr
= NULL
;
2464 struct listnode
*node
= NULL
;
2466 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2467 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2468 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2469 zvni_neigh_probe(zvni
, nbr
);
2474 * Inform BGP about local neighbor addition.
2476 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2477 struct ethaddr
*macaddr
,
2478 uint8_t neigh_flags
,
2483 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2484 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2485 /* Set router flag (R-bit) based on local neigh entry add */
2486 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2487 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2489 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2490 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2494 * Inform BGP about local neighbor deletion.
2496 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2497 struct ethaddr
*macaddr
, uint8_t flags
,
2500 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2501 0, state
, ZEBRA_MACIP_DEL
);
2505 * Install remote neighbor into the kernel.
2507 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2509 struct zebra_if
*zif
;
2510 struct zebra_l2info_vxlan
*vxl
;
2511 struct interface
*vlan_if
;
2517 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2520 zif
= zvni
->vxlan_if
->info
;
2523 vxl
= &zif
->l2info
.vxl
;
2525 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2529 flags
= NTF_EXT_LEARNED
;
2530 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2531 flags
|= NTF_ROUTER
;
2532 ZEBRA_NEIGH_SET_ACTIVE(n
);
2533 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2539 * Uninstall remote neighbor from the kernel.
2541 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2543 struct zebra_if
*zif
;
2544 struct zebra_l2info_vxlan
*vxl
;
2545 struct interface
*vlan_if
;
2547 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2550 if (!zvni
->vxlan_if
) {
2551 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2556 zif
= zvni
->vxlan_if
->info
;
2559 vxl
= &zif
->l2info
.vxl
;
2560 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2564 ZEBRA_NEIGH_SET_INACTIVE(n
);
2566 return kernel_del_neigh(vlan_if
, &n
->ip
);
2570 * Probe neighbor from the kernel.
2572 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2574 struct zebra_if
*zif
;
2575 struct zebra_l2info_vxlan
*vxl
;
2576 struct interface
*vlan_if
;
2578 zif
= zvni
->vxlan_if
->info
;
2581 vxl
= &zif
->l2info
.vxl
;
2583 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2588 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2596 * Install neighbor hash entry - called upon access VLAN change.
2598 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2601 struct neigh_walk_ctx
*wctx
= ctxt
;
2603 n
= (zebra_neigh_t
*)bucket
->data
;
2605 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2606 zvni_neigh_install(wctx
->zvni
, n
);
2609 /* Get the VRR interface for SVI if any */
2610 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2612 struct zebra_vrf
*zvrf
= NULL
;
2613 struct interface
*tmp_if
= NULL
;
2614 struct zebra_if
*zif
= NULL
;
2616 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2619 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2624 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2627 if (zif
->link
== ifp
)
2634 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2636 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2637 struct connected
*c
= NULL
;
2638 struct ethaddr macaddr
;
2640 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2642 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2645 memset(&ip
, 0, sizeof(struct ipaddr
));
2646 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2649 if (c
->address
->family
== AF_INET
) {
2650 ip
.ipa_type
= IPADDR_V4
;
2651 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2652 sizeof(struct in_addr
));
2653 } else if (c
->address
->family
== AF_INET6
) {
2654 ip
.ipa_type
= IPADDR_V6
;
2655 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2656 sizeof(struct in6_addr
));
2661 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2667 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2669 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2670 struct connected
*c
= NULL
;
2671 struct ethaddr macaddr
;
2673 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2675 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2678 memset(&ip
, 0, sizeof(struct ipaddr
));
2679 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2682 if (c
->address
->family
== AF_INET
) {
2683 ip
.ipa_type
= IPADDR_V4
;
2684 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2685 sizeof(struct in_addr
));
2686 } else if (c
->address
->family
== AF_INET6
) {
2687 ip
.ipa_type
= IPADDR_V6
;
2688 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2689 sizeof(struct in6_addr
));
2694 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2700 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2703 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2704 struct connected
*c
= NULL
;
2705 struct ethaddr macaddr
;
2707 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2709 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2712 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2714 /* skip link local address */
2715 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2720 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2721 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2723 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2724 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2730 * zvni_gw_macip_add_to_client
2732 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2733 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2735 char buf
[ETHER_ADDR_STRLEN
];
2736 char buf2
[INET6_ADDRSTRLEN
];
2737 zebra_neigh_t
*n
= NULL
;
2738 zebra_mac_t
*mac
= NULL
;
2739 struct zebra_if
*zif
= NULL
;
2740 struct zebra_l2info_vxlan
*vxl
= NULL
;
2742 zif
= zvni
->vxlan_if
->info
;
2746 vxl
= &zif
->l2info
.vxl
;
2748 mac
= zvni_mac_lookup(zvni
, macaddr
);
2750 mac
= zvni_mac_add(zvni
, macaddr
);
2752 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2753 "Failed to add MAC %s intf %s(%u) VID %u",
2754 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2755 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2760 /* Set "local" forwarding info. */
2761 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2762 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2763 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2764 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2765 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2766 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2768 n
= zvni_neigh_lookup(zvni
, ip
);
2770 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2773 EC_ZEBRA_MAC_ADD_FAILED
,
2774 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2775 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2776 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2777 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2782 /* Set "local" forwarding info. */
2783 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2784 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2785 ZEBRA_NEIGH_SET_ACTIVE(n
);
2786 /* Set Router flag (R-bit) */
2787 if (ip
->ipa_type
== IPADDR_V6
)
2788 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2789 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2790 n
->ifindex
= ifp
->ifindex
;
2792 /* Only advertise in BGP if the knob is enabled */
2793 if (!advertise_gw_macip_enabled(zvni
))
2796 if (IS_ZEBRA_DEBUG_VXLAN
)
2798 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2799 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2800 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2801 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2803 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2804 n
->flags
, n
->loc_seq
);
2810 * zvni_gw_macip_del_from_client
2812 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2815 char buf1
[ETHER_ADDR_STRLEN
];
2816 char buf2
[INET6_ADDRSTRLEN
];
2817 zebra_neigh_t
*n
= NULL
;
2818 zebra_mac_t
*mac
= NULL
;
2820 /* If the neigh entry is not present nothing to do*/
2821 n
= zvni_neigh_lookup(zvni
, ip
);
2825 /* mac entry should be present */
2826 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2828 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2829 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2830 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2834 /* If the entry is not local nothing to do*/
2835 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2838 /* only need to delete the entry from bgp if we sent it before */
2839 if (IS_ZEBRA_DEBUG_VXLAN
)
2841 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2842 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2843 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2844 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2846 /* Remove neighbor from BGP. */
2847 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2848 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2850 /* Delete this neighbor entry. */
2851 zvni_neigh_del(zvni
, n
);
2853 /* see if the mac needs to be deleted as well*/
2855 zvni_deref_ip2mac(zvni
, mac
);
2860 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2863 zebra_vni_t
*zvni
= NULL
;
2864 struct zebra_if
*zif
= NULL
;
2865 struct zebra_l2info_vxlan zl2_info
;
2866 struct interface
*vlan_if
= NULL
;
2867 struct interface
*vrr_if
= NULL
;
2868 struct interface
*ifp
;
2870 /* Add primary SVI MAC*/
2871 zvni
= (zebra_vni_t
*)bucket
->data
;
2873 ifp
= zvni
->vxlan_if
;
2878 /* If down or not mapped to a bridge, we're done. */
2879 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2882 zl2_info
= zif
->l2info
.vxl
;
2885 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2889 /* Del primary MAC-IP */
2890 zvni_del_macip_for_intf(vlan_if
, zvni
);
2892 /* Del VRR MAC-IP - if any*/
2893 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2895 zvni_del_macip_for_intf(vrr_if
, zvni
);
2900 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2903 zebra_vni_t
*zvni
= NULL
;
2904 struct zebra_if
*zif
= NULL
;
2905 struct zebra_l2info_vxlan zl2_info
;
2906 struct interface
*vlan_if
= NULL
;
2907 struct interface
*vrr_if
= NULL
;
2908 struct interface
*ifp
= NULL
;
2910 zvni
= (zebra_vni_t
*)bucket
->data
;
2912 ifp
= zvni
->vxlan_if
;
2917 /* If down or not mapped to a bridge, we're done. */
2918 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2920 zl2_info
= zif
->l2info
.vxl
;
2923 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2927 /* Add primary SVI MAC-IP */
2928 zvni_add_macip_for_intf(vlan_if
, zvni
);
2930 if (advertise_gw_macip_enabled(zvni
)) {
2931 /* Add VRR MAC-IP - if any*/
2932 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2934 zvni_add_macip_for_intf(vrr_if
, zvni
);
2940 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2943 zebra_vni_t
*zvni
= NULL
;
2944 struct zebra_if
*zif
= NULL
;
2945 struct zebra_l2info_vxlan zl2_info
;
2946 struct interface
*vlan_if
= NULL
;
2947 struct interface
*ifp
;
2949 /* Add primary SVI MAC*/
2950 zvni
= (zebra_vni_t
*)bucket
->data
;
2954 ifp
= zvni
->vxlan_if
;
2959 /* If down or not mapped to a bridge, we're done. */
2960 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2963 zl2_info
= zif
->l2info
.vxl
;
2965 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2966 zif
->brslave_info
.br_if
);
2970 /* Del primary MAC-IP */
2971 zvni_del_macip_for_intf(vlan_if
, zvni
);
2976 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2977 struct interface
*ifp
,
2979 struct ethaddr
*macaddr
,
2982 char buf
[ETHER_ADDR_STRLEN
];
2983 char buf2
[INET6_ADDRSTRLEN
];
2984 struct zebra_vrf
*zvrf
;
2985 zebra_neigh_t
*n
= NULL
;
2986 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2987 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2988 bool upd_mac_seq
= false;
2989 bool neigh_mac_change
= false;
2990 bool neigh_on_hold
= false;
2991 bool neigh_was_remote
= false;
2992 bool do_dad
= false;
2993 struct in_addr vtep_ip
= {.s_addr
= 0};
2995 /* Check if the MAC exists. */
2996 zmac
= zvni_mac_lookup(zvni
, macaddr
);
2998 /* create a dummy MAC if the MAC is not already present */
2999 if (IS_ZEBRA_DEBUG_VXLAN
)
3001 "AUTO MAC %s created for neigh %s on VNI %u",
3002 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3003 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3005 zmac
= zvni_mac_add(zvni
, macaddr
);
3007 zlog_debug("Failed to add MAC %s VNI %u",
3008 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3013 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3014 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3015 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3017 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3019 * We don't change the MAC to local upon a neighbor
3020 * learn event, we wait for the explicit local MAC
3021 * learn. However, we have to compute its sequence
3022 * number in preparation for when it actually turns
3029 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3031 if (IS_ZEBRA_DEBUG_VXLAN
)
3032 zlog_debug("\tUnable to find vrf for: %d",
3033 zvni
->vxlan_if
->vrf_id
);
3037 /* Check if the neighbor exists. */
3038 n
= zvni_neigh_lookup(zvni
, ip
);
3040 /* New neighbor - create */
3041 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3044 EC_ZEBRA_MAC_ADD_FAILED
,
3045 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3046 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3047 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3048 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3051 /* Set "local" forwarding info. */
3052 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3053 n
->ifindex
= ifp
->ifindex
;
3055 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3059 /* Note any changes and see if of interest to BGP. */
3060 mac_different
= (memcmp(n
->emac
.octet
,
3061 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3062 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3063 ZEBRA_NEIGH_ROUTER_FLAG
);
3064 if (!mac_different
&& is_router
== cur_is_router
) {
3065 if (IS_ZEBRA_DEBUG_VXLAN
)
3067 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3068 n
->ifindex
= ifp
->ifindex
;
3072 if (!mac_different
) {
3073 bool is_neigh_freezed
= false;
3075 /* Only the router flag has changed. */
3078 ZEBRA_NEIGH_ROUTER_FLAG
);
3080 UNSET_FLAG(n
->flags
,
3081 ZEBRA_NEIGH_ROUTER_FLAG
);
3083 /* Neigh is in freeze state and freeze action
3084 * is enabled, do not send update to client.
3086 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3088 CHECK_FLAG(n
->flags
,
3089 ZEBRA_NEIGH_DUPLICATE
));
3091 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3093 return zvni_neigh_send_add_to_client(
3094 zvni
->vni
, ip
, macaddr
,
3095 n
->flags
, n
->loc_seq
);
3097 if (IS_ZEBRA_DEBUG_VXLAN
)
3099 "\tNeighbor active and frozen");
3104 /* The MAC has changed, need to issue a delete
3105 * first as this means a different MACIP route.
3106 * Also, need to do some unlinking/relinking.
3107 * We also need to update the MAC's sequence number
3108 * in different situations.
3110 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3111 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3112 &n
->emac
, 0, n
->state
);
3113 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3115 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3117 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3118 neigh_mac_change
= upd_mac_seq
= true;
3119 listnode_delete(old_zmac
->neigh_list
, n
);
3120 zvni_deref_ip2mac(zvni
, old_zmac
);
3123 /* Update the forwarding info. */
3124 n
->ifindex
= ifp
->ifindex
;
3125 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3127 /* Link to new MAC */
3128 listnode_add_sort(zmac
->neigh_list
, n
);
3129 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3131 * Neighbor has moved from remote to local. Its
3132 * MAC could have also changed as part of the move.
3134 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3136 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3138 old_mac_seq
= CHECK_FLAG(
3143 neigh_mac_change
= upd_mac_seq
= true;
3144 listnode_delete(old_zmac
->neigh_list
,
3146 zvni_deref_ip2mac(zvni
, old_zmac
);
3149 /* Link to new MAC */
3150 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3151 listnode_add_sort(zmac
->neigh_list
, n
);
3153 /* Based on Mobility event Scenario-B from the
3154 * draft, neigh's previous state was remote treat this
3157 neigh_was_remote
= true;
3158 vtep_ip
= n
->r_vtep_ip
;
3159 /* Mark appropriately */
3160 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3161 n
->r_vtep_ip
.s_addr
= 0;
3162 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3163 n
->ifindex
= ifp
->ifindex
;
3167 /* If MAC was previously remote, or the neighbor had a different
3168 * MAC earlier, recompute the sequence number.
3171 uint32_t seq1
, seq2
;
3173 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3174 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3175 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3176 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3177 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3180 /* Mark Router flag (R-bit) */
3182 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3184 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3186 /* Check old and/or new MAC detected as duplicate mark
3187 * the neigh as duplicate
3189 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3190 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3191 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3193 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3194 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3197 /* For IP Duplicate Address Detection (DAD) is trigger,
3198 * when the event is extended mobility based on scenario-B
3199 * from the draft, IP/Neigh's MAC binding changed and
3200 * neigh's previous state was remote.
3202 if (neigh_mac_change
&& neigh_was_remote
)
3205 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3206 &neigh_on_hold
, true);
3208 /* Before we program this in BGP, we need to check if MAC is locally
3209 * learnt. If not, force neighbor to be inactive and reset its seq.
3211 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3212 ZEBRA_NEIGH_SET_INACTIVE(n
);
3214 zmac
->loc_seq
= mac_new_seq
;
3218 /* If the MAC's sequence number has changed, inform the MAC and all
3219 * neighbors associated with the MAC to BGP, else just inform this
3222 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3223 if (IS_ZEBRA_DEBUG_VXLAN
)
3224 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3225 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3226 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3227 zmac
->loc_seq
= mac_new_seq
;
3228 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3229 zmac
->flags
, zmac
->loc_seq
))
3231 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3235 n
->loc_seq
= zmac
->loc_seq
;
3237 if (!neigh_on_hold
) {
3238 ZEBRA_NEIGH_SET_ACTIVE(n
);
3240 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3241 n
->flags
, n
->loc_seq
);
3243 if (IS_ZEBRA_DEBUG_VXLAN
)
3244 zlog_debug("\tNeighbor on hold not sending");
3249 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3250 struct interface
*ifp
,
3252 struct ethaddr
*macaddr
,
3255 char buf
[ETHER_ADDR_STRLEN
];
3256 char buf2
[INET6_ADDRSTRLEN
];
3257 zebra_neigh_t
*n
= NULL
;
3258 zebra_mac_t
*zmac
= NULL
;
3260 /* If the neighbor is unknown, there is no further action. */
3261 n
= zvni_neigh_lookup(zvni
, ip
);
3265 /* If a remote entry, see if it needs to be refreshed */
3266 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3268 if (state
& NUD_STALE
)
3269 zvni_neigh_install(zvni
, n
);
3272 /* We got a "remote" neighbor notification for an entry
3273 * we think is local. This can happen in a multihoming
3274 * scenario - but only if the MAC is already "remote".
3275 * Just mark our entry as "remote".
3277 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3278 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3280 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3281 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3282 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3287 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3288 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3289 ZEBRA_NEIGH_SET_ACTIVE(n
);
3290 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3297 * Make hash key for MAC.
3299 static unsigned int mac_hash_keymake(void *p
)
3301 zebra_mac_t
*pmac
= p
;
3302 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3304 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3308 * Compare two MAC addresses.
3310 static bool mac_cmp(const void *p1
, const void *p2
)
3312 const zebra_mac_t
*pmac1
= p1
;
3313 const zebra_mac_t
*pmac2
= p2
;
3315 if (pmac1
== NULL
&& pmac2
== NULL
)
3318 if (pmac1
== NULL
|| pmac2
== NULL
)
3321 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3326 * Callback to allocate MAC hash entry.
3328 static void *zvni_mac_alloc(void *p
)
3330 const zebra_mac_t
*tmp_mac
= p
;
3333 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3336 return ((void *)mac
);
3342 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3344 zebra_mac_t tmp_mac
;
3345 zebra_mac_t
*mac
= NULL
;
3347 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3348 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3349 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3353 mac
->dad_mac_auto_recovery_timer
= NULL
;
3355 mac
->neigh_list
= list_new();
3356 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3364 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3366 zebra_mac_t
*tmp_mac
;
3368 /* Cancel auto recovery */
3369 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3371 list_delete(&mac
->neigh_list
);
3373 /* Free the VNI hash entry and allocated memory. */
3374 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3375 XFREE(MTYPE_MAC
, tmp_mac
);
3381 * Free MAC hash entry (callback)
3383 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3385 struct mac_walk_ctx
*wctx
= arg
;
3386 zebra_mac_t
*mac
= bucket
->data
;
3388 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3389 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3390 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3391 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3392 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3393 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3394 &wctx
->r_vtep_ip
))) {
3395 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3396 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3400 if (wctx
->uninstall
)
3401 zvni_mac_uninstall(wctx
->zvni
, mac
);
3403 zvni_mac_del(wctx
->zvni
, mac
);
3410 * Delete all MAC entries from specific VTEP for a particular VNI.
3412 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3413 struct in_addr
*r_vtep_ip
)
3415 struct mac_walk_ctx wctx
;
3417 if (!zvni
->mac_table
)
3420 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3422 wctx
.uninstall
= uninstall
;
3423 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3424 wctx
.r_vtep_ip
= *r_vtep_ip
;
3426 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3430 * Delete all MAC entries for this VNI.
3432 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3435 struct mac_walk_ctx wctx
;
3437 if (!zvni
->mac_table
)
3440 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3442 wctx
.uninstall
= uninstall
;
3443 wctx
.upd_client
= upd_client
;
3446 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3450 * Look up MAC hash entry.
3452 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3457 memset(&tmp
, 0, sizeof(tmp
));
3458 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3459 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3465 * Inform BGP about local MAC addition.
3467 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3468 uint8_t mac_flags
, uint32_t seq
)
3472 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3473 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3474 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3475 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3477 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3478 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3482 * Inform BGP about local MAC deletion.
3484 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3486 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3487 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3491 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3492 * notifications, to see if they are of interest.
3494 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3495 struct interface
*br_if
, vlanid_t vid
)
3497 struct zebra_ns
*zns
;
3498 struct route_node
*rn
;
3499 struct interface
*tmp_if
= NULL
;
3500 struct zebra_if
*zif
;
3501 struct zebra_l2info_bridge
*br
;
3502 struct zebra_l2info_vxlan
*vxl
= NULL
;
3503 uint8_t bridge_vlan_aware
;
3507 /* Determine if bridge is VLAN-aware or not */
3510 br
= &zif
->l2info
.br
;
3511 bridge_vlan_aware
= br
->vlan_aware
;
3513 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3514 /* TODO: Optimize with a hash. */
3515 zns
= zebra_ns_lookup(NS_DEFAULT
);
3516 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3517 tmp_if
= (struct interface
*)rn
->info
;
3521 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3523 if (!if_is_operative(tmp_if
))
3525 vxl
= &zif
->l2info
.vxl
;
3527 if (zif
->brslave_info
.br_if
!= br_if
)
3530 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3539 zvni
= zvni_lookup(vxl
->vni
);
3544 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3545 * neighbor notifications, to see if they are of interest.
3547 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3548 struct interface
*br_if
)
3550 struct zebra_ns
*zns
;
3551 struct route_node
*rn
;
3552 struct interface
*tmp_if
= NULL
;
3553 struct zebra_if
*zif
;
3554 struct zebra_l2info_bridge
*br
;
3555 struct zebra_l2info_vxlan
*vxl
= NULL
;
3556 uint8_t bridge_vlan_aware
;
3564 /* Make sure the linked interface is a bridge. */
3565 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3568 /* Determine if bridge is VLAN-aware or not */
3571 br
= &zif
->l2info
.br
;
3572 bridge_vlan_aware
= br
->vlan_aware
;
3573 if (bridge_vlan_aware
) {
3574 struct zebra_l2info_vlan
*vl
;
3576 if (!IS_ZEBRA_IF_VLAN(ifp
))
3581 vl
= &zif
->l2info
.vl
;
3585 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3586 /* TODO: Optimize with a hash. */
3587 zns
= zebra_ns_lookup(NS_DEFAULT
);
3588 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3589 tmp_if
= (struct interface
*)rn
->info
;
3593 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3595 if (!if_is_operative(tmp_if
))
3597 vxl
= &zif
->l2info
.vxl
;
3599 if (zif
->brslave_info
.br_if
!= br_if
)
3602 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3611 zvni
= zvni_lookup(vxl
->vni
);
3615 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3617 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3618 * linked to the bridge
3619 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3622 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3624 struct zebra_ns
*zns
;
3625 struct route_node
*rn
;
3626 struct interface
*tmp_if
= NULL
;
3627 struct zebra_if
*zif
;
3628 struct zebra_l2info_bridge
*br
;
3629 struct zebra_l2info_vlan
*vl
;
3630 uint8_t bridge_vlan_aware
;
3633 /* Defensive check, caller expected to invoke only with valid bridge. */
3637 /* Determine if bridge is VLAN-aware or not */
3640 br
= &zif
->l2info
.br
;
3641 bridge_vlan_aware
= br
->vlan_aware
;
3643 /* Check oper status of the SVI. */
3644 if (!bridge_vlan_aware
)
3645 return if_is_operative(br_if
) ? br_if
: NULL
;
3647 /* Identify corresponding VLAN interface. */
3648 /* TODO: Optimize with a hash. */
3649 zns
= zebra_ns_lookup(NS_DEFAULT
);
3650 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3651 tmp_if
= (struct interface
*)rn
->info
;
3652 /* Check oper status of the SVI. */
3653 if (!tmp_if
|| !if_is_operative(tmp_if
))
3656 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3657 || zif
->link
!= br_if
)
3659 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3661 if (vl
->vid
== vid
) {
3667 return found
? tmp_if
: NULL
;
3671 * Install remote MAC into the kernel.
3673 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3675 struct zebra_if
*zif
;
3676 struct zebra_l2info_vxlan
*vxl
;
3679 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3682 zif
= zvni
->vxlan_if
->info
;
3685 vxl
= &zif
->l2info
.vxl
;
3687 sticky
= !!CHECK_FLAG(mac
->flags
,
3688 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3690 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3691 mac
->fwd_info
.r_vtep_ip
, sticky
);
3695 * Uninstall remote MAC from the kernel.
3697 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3699 struct zebra_if
*zif
;
3700 struct zebra_l2info_vxlan
*vxl
;
3701 struct in_addr vtep_ip
;
3702 struct interface
*ifp
;
3704 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3707 if (!zvni
->vxlan_if
) {
3708 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3713 zif
= zvni
->vxlan_if
->info
;
3716 vxl
= &zif
->l2info
.vxl
;
3718 ifp
= zvni
->vxlan_if
;
3719 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3721 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3725 * Install MAC hash entry - called upon access VLAN change.
3727 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3730 struct mac_walk_ctx
*wctx
= ctxt
;
3732 mac
= (zebra_mac_t
*)bucket
->data
;
3734 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3735 zvni_mac_install(wctx
->zvni
, mac
);
3739 * Count of remote neighbors referencing this MAC.
3741 static int remote_neigh_count(zebra_mac_t
*zmac
)
3743 zebra_neigh_t
*n
= NULL
;
3744 struct listnode
*node
= NULL
;
3747 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3748 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3756 * Decrement neighbor refcount of MAC; uninstall and free it if
3759 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3761 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3764 /* If all remote neighbors referencing a remote MAC go away,
3765 * we need to uninstall the MAC.
3767 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3768 remote_neigh_count(mac
) == 0) {
3769 zvni_mac_uninstall(zvni
, mac
);
3770 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3773 /* If no neighbors, delete the MAC. */
3774 if (list_isempty(mac
->neigh_list
))
3775 zvni_mac_del(zvni
, mac
);
3779 * Read and populate local MACs and neighbors corresponding to this VNI.
3781 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3783 struct zebra_ns
*zns
;
3784 struct zebra_if
*zif
;
3785 struct interface
*vlan_if
;
3786 struct zebra_l2info_vxlan
*vxl
;
3787 struct interface
*vrr_if
;
3790 vxl
= &zif
->l2info
.vxl
;
3791 zns
= zebra_ns_lookup(NS_DEFAULT
);
3793 if (IS_ZEBRA_DEBUG_VXLAN
)
3795 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3796 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3797 zif
->brslave_info
.bridge_ifindex
);
3799 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3800 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3803 /* Add SVI MAC-IP */
3804 zvni_add_macip_for_intf(vlan_if
, zvni
);
3806 /* Add VRR MAC-IP - if any*/
3807 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3809 zvni_add_macip_for_intf(vrr_if
, zvni
);
3811 neigh_read_for_vlan(zns
, vlan_if
);
3816 * Hash function for VNI.
3818 static unsigned int vni_hash_keymake(void *p
)
3820 const zebra_vni_t
*zvni
= p
;
3822 return (jhash_1word(zvni
->vni
, 0));
3826 * Compare 2 VNI hash entries.
3828 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3830 const zebra_vni_t
*zvni1
= p1
;
3831 const zebra_vni_t
*zvni2
= p2
;
3833 return (zvni1
->vni
== zvni2
->vni
);
3836 static int vni_list_cmp(void *p1
, void *p2
)
3838 const zebra_vni_t
*zvni1
= p1
;
3839 const zebra_vni_t
*zvni2
= p2
;
3841 if (zvni1
->vni
== zvni2
->vni
)
3843 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3847 * Callback to allocate VNI hash entry.
3849 static void *zvni_alloc(void *p
)
3851 const zebra_vni_t
*tmp_vni
= p
;
3854 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3855 zvni
->vni
= tmp_vni
->vni
;
3856 return ((void *)zvni
);
3860 * Look up VNI hash entry.
3862 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3864 struct zebra_vrf
*zvrf
;
3865 zebra_vni_t tmp_vni
;
3866 zebra_vni_t
*zvni
= NULL
;
3868 zvrf
= zebra_vrf_get_evpn();
3870 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3872 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3878 * Add VNI hash entry.
3880 static zebra_vni_t
*zvni_add(vni_t vni
)
3882 struct zebra_vrf
*zvrf
;
3883 zebra_vni_t tmp_zvni
;
3884 zebra_vni_t
*zvni
= NULL
;
3886 zvrf
= zebra_vrf_get_evpn();
3888 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3890 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3893 /* Create hash table for MAC */
3895 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3897 /* Create hash table for neighbors */
3898 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3899 "Zebra VNI Neighbor Table");
3905 * Delete VNI hash entry.
3907 static int zvni_del(zebra_vni_t
*zvni
)
3909 struct zebra_vrf
*zvrf
;
3910 zebra_vni_t
*tmp_zvni
;
3912 zvrf
= zebra_vrf_get_evpn();
3915 zvni
->vxlan_if
= NULL
;
3917 /* Remove references to the BUM mcast grp */
3918 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3920 /* Free the neighbor hash table. */
3921 hash_free(zvni
->neigh_table
);
3922 zvni
->neigh_table
= NULL
;
3924 /* Free the MAC hash table. */
3925 hash_free(zvni
->mac_table
);
3926 zvni
->mac_table
= NULL
;
3928 /* Free the VNI hash entry and allocated memory. */
3929 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3930 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3936 * Inform BGP about local VNI addition.
3938 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3940 struct zserv
*client
;
3943 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3944 /* BGP may not be running. */
3948 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3950 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3951 stream_putl(s
, zvni
->vni
);
3952 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3953 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3954 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3956 /* Write packet size. */
3957 stream_putw_at(s
, 0, stream_get_endp(s
));
3959 if (IS_ZEBRA_DEBUG_VXLAN
)
3960 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3961 inet_ntoa(zvni
->local_vtep_ip
),
3962 vrf_id_to_name(zvni
->vrf_id
),
3963 zebra_route_string(client
->proto
));
3965 client
->vniadd_cnt
++;
3966 return zserv_send_message(client
, s
);
3970 * Inform BGP about local VNI deletion.
3972 static int zvni_send_del_to_client(vni_t vni
)
3974 struct zserv
*client
;
3977 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3978 /* BGP may not be running. */
3982 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3985 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3986 stream_putl(s
, vni
);
3988 /* Write packet size. */
3989 stream_putw_at(s
, 0, stream_get_endp(s
));
3991 if (IS_ZEBRA_DEBUG_VXLAN
)
3992 zlog_debug("Send VNI_DEL %u to %s", vni
,
3993 zebra_route_string(client
->proto
));
3995 client
->vnidel_cnt
++;
3996 return zserv_send_message(client
, s
);
4000 * Build the VNI hash table by going over the VxLAN interfaces. This
4001 * is called when EVPN (advertise-all-vni) is enabled.
4003 static void zvni_build_hash_table(void)
4005 struct zebra_ns
*zns
;
4006 struct route_node
*rn
;
4007 struct interface
*ifp
;
4009 /* Walk VxLAN interfaces and create VNI hash. */
4010 zns
= zebra_ns_lookup(NS_DEFAULT
);
4011 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4013 zebra_vni_t
*zvni
= NULL
;
4014 zebra_l3vni_t
*zl3vni
= NULL
;
4015 struct zebra_if
*zif
;
4016 struct zebra_l2info_vxlan
*vxl
;
4018 ifp
= (struct interface
*)rn
->info
;
4022 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4025 vxl
= &zif
->l2info
.vxl
;
4028 /* L3-VNI and L2-VNI are handled seperately */
4029 zl3vni
= zl3vni_lookup(vni
);
4032 if (IS_ZEBRA_DEBUG_VXLAN
)
4034 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4035 ifp
->name
, ifp
->ifindex
, vni
);
4037 /* associate with vxlan_if */
4038 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4039 zl3vni
->vxlan_if
= ifp
;
4042 * we need to associate with SVI.
4043 * we can associate with svi-if only after association
4044 * with vxlan-intf is complete
4046 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4048 if (is_l3vni_oper_up(zl3vni
))
4049 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4052 struct interface
*vlan_if
= NULL
;
4054 if (IS_ZEBRA_DEBUG_VXLAN
)
4056 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4057 ifp
->name
, ifp
->ifindex
, vni
,
4058 inet_ntoa(vxl
->vtep_ip
));
4060 /* VNI hash entry is not expected to exist. */
4061 zvni
= zvni_lookup(vni
);
4064 "VNI hash already present for IF %s(%u) L2-VNI %u",
4065 ifp
->name
, ifp
->ifindex
, vni
);
4069 zvni
= zvni_add(vni
);
4072 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4073 ifp
->name
, ifp
->ifindex
, vni
);
4077 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
4078 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
4079 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
4081 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4083 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4084 zvni
->mcast_grp
= vxl
->mcast_grp
;
4086 zvni
->vxlan_if
= ifp
;
4087 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4088 zif
->brslave_info
.br_if
);
4090 zvni
->vrf_id
= vlan_if
->vrf_id
;
4091 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4093 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4097 /* Inform BGP if intf is up and mapped to bridge. */
4098 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4099 zvni_send_add_to_client(zvni
);
4105 * See if remote VTEP matches with prefix.
4107 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4109 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4113 * Locate remote VTEP in VNI hash table.
4115 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4117 zebra_vtep_t
*zvtep
;
4122 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4123 if (zvni_vtep_match(vtep_ip
, zvtep
))
4131 * Add remote VTEP to VNI hash table.
4133 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4137 zebra_vtep_t
*zvtep
;
4139 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4141 zvtep
->vtep_ip
= *vtep_ip
;
4142 zvtep
->flood_control
= flood_control
;
4145 zvni
->vteps
->prev
= zvtep
;
4146 zvtep
->next
= zvni
->vteps
;
4147 zvni
->vteps
= zvtep
;
4153 * Remove remote VTEP from VNI hash table.
4155 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4158 zvtep
->next
->prev
= zvtep
->prev
;
4160 zvtep
->prev
->next
= zvtep
->next
;
4162 zvni
->vteps
= zvtep
->next
;
4164 zvtep
->prev
= zvtep
->next
= NULL
;
4165 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4171 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4172 * uninstall from kernel if asked to.
4174 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4176 zebra_vtep_t
*zvtep
, *zvtep_next
;
4181 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4182 zvtep_next
= zvtep
->next
;
4184 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4185 zvni_vtep_del(zvni
, zvtep
);
4192 * Install remote VTEP into the kernel if the remote VTEP has asked
4193 * for head-end-replication.
4195 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4197 if (is_vxlan_flooding_head_end() &&
4198 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4199 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4205 * Uninstall remote VTEP from the kernel.
4207 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4209 if (!zvni
->vxlan_if
) {
4210 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4215 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4219 * Install or uninstall flood entries in the kernel corresponding to
4220 * remote VTEPs. This is invoked upon change to BUM handling.
4222 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4226 zebra_vtep_t
*zvtep
;
4228 zvni
= (zebra_vni_t
*)bucket
->data
;
4232 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4233 if (is_vxlan_flooding_head_end())
4234 zvni_vtep_install(zvni
, zvtep
);
4236 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4241 * Cleanup VNI/VTEP and update kernel
4243 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4245 zebra_vni_t
*zvni
= NULL
;
4246 zebra_l3vni_t
*zl3vni
= NULL
;
4247 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4249 zvni
= (zebra_vni_t
*)bucket
->data
;
4251 /* remove from l3-vni list */
4253 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4255 listnode_delete(zl3vni
->l2vnis
, zvni
);
4257 /* Free up all neighbors and MACs, if any. */
4258 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4259 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4261 /* Free up all remote VTEPs, if any. */
4262 zvni_vtep_del_all(zvni
, 1);
4264 /* Delete the hash entry. */
4269 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4271 zebra_l3vni_t
*zl3vni
= NULL
;
4273 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4275 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4278 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4279 struct prefix
*host
)
4281 struct host_rb_entry lookup
;
4282 struct host_rb_entry
*hle
;
4284 memset(&lookup
, 0, sizeof(lookup
));
4285 memcpy(&lookup
.p
, host
, sizeof(*host
));
4287 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4291 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4292 memcpy(hle
, &lookup
, sizeof(lookup
));
4294 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4297 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4299 struct host_rb_entry lookup
;
4300 struct host_rb_entry
*hle
;
4302 memset(&lookup
, 0, sizeof(lookup
));
4303 memcpy(&lookup
.p
, host
, sizeof(*host
));
4305 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4307 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4308 XFREE(MTYPE_HOST_PREFIX
, hle
);
4315 * Look up MAC hash entry.
4317 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4318 struct ethaddr
*rmac
)
4323 memset(&tmp
, 0, sizeof(tmp
));
4324 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4325 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4331 * Callback to allocate RMAC hash entry.
4333 static void *zl3vni_rmac_alloc(void *p
)
4335 const zebra_mac_t
*tmp_rmac
= p
;
4338 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4341 return ((void *)zrmac
);
4345 * Add RMAC entry to l3-vni
4347 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4349 zebra_mac_t tmp_rmac
;
4350 zebra_mac_t
*zrmac
= NULL
;
4352 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4353 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4354 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4357 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4359 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4360 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4368 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4370 zebra_mac_t
*tmp_rmac
;
4371 struct host_rb_entry
*hle
;
4373 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4374 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4376 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4377 XFREE(MTYPE_HOST_PREFIX
, hle
);
4380 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4381 XFREE(MTYPE_MAC
, tmp_rmac
);
4387 * Install remote RMAC into the kernel.
4389 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4391 struct zebra_if
*zif
= NULL
;
4392 struct zebra_l2info_vxlan
*vxl
= NULL
;
4394 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4395 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4398 zif
= zl3vni
->vxlan_if
->info
;
4402 vxl
= &zif
->l2info
.vxl
;
4404 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4405 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4409 * Uninstall remote RMAC from the kernel.
4411 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4413 char buf
[ETHER_ADDR_STRLEN
];
4414 struct zebra_if
*zif
= NULL
;
4415 struct zebra_l2info_vxlan
*vxl
= NULL
;
4417 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4418 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4421 if (!zl3vni
->vxlan_if
) {
4423 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4424 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4425 zl3vni
->vni
, zl3vni
);
4429 zif
= zl3vni
->vxlan_if
->info
;
4433 vxl
= &zif
->l2info
.vxl
;
4435 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4436 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4439 /* handle rmac add */
4440 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4441 struct ipaddr
*vtep_ip
,
4442 struct prefix
*host_prefix
)
4444 char buf
[ETHER_ADDR_STRLEN
];
4445 char buf1
[INET6_ADDRSTRLEN
];
4446 zebra_mac_t
*zrmac
= NULL
;
4448 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4451 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4454 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4455 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4457 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4460 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4461 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4463 /* install rmac in kernel */
4464 zl3vni_rmac_install(zl3vni
, zrmac
);
4467 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4473 /* handle rmac delete */
4474 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4475 struct prefix
*host_prefix
)
4477 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4479 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4480 /* uninstall from kernel */
4481 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4483 /* del the rmac entry */
4484 zl3vni_rmac_del(zl3vni
, zrmac
);
4489 * Look up nh hash entry on a l3-vni.
4491 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4496 memset(&tmp
, 0, sizeof(tmp
));
4497 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4498 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4505 * Callback to allocate NH hash entry on L3-VNI.
4507 static void *zl3vni_nh_alloc(void *p
)
4509 const zebra_neigh_t
*tmp_n
= p
;
4512 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4519 * Add neighbor entry.
4521 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4522 struct ethaddr
*mac
)
4524 zebra_neigh_t tmp_n
;
4525 zebra_neigh_t
*n
= NULL
;
4527 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4528 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4529 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4532 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4534 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4535 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4536 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4542 * Delete neighbor entry.
4544 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4546 zebra_neigh_t
*tmp_n
;
4547 struct host_rb_entry
*hle
;
4549 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4550 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4552 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4553 XFREE(MTYPE_HOST_PREFIX
, hle
);
4556 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4557 XFREE(MTYPE_NEIGH
, tmp_n
);
4563 * Install remote nh as neigh into the kernel.
4565 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4572 if (!is_l3vni_oper_up(zl3vni
))
4575 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4576 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4579 flags
= NTF_EXT_LEARNED
;
4580 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4581 flags
|= NTF_ROUTER
;
4582 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4588 * Uninstall remote nh from the kernel.
4590 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4592 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4593 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4596 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4599 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4602 /* add remote vtep as a neigh entry */
4603 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4604 struct ethaddr
*rmac
,
4605 struct prefix
*host_prefix
)
4607 char buf
[ETHER_ADDR_STRLEN
];
4608 char buf1
[INET6_ADDRSTRLEN
];
4609 zebra_neigh_t
*nh
= NULL
;
4611 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4613 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4617 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4618 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4619 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4624 /* install the nh neigh in kernel */
4625 zl3vni_nh_install(zl3vni
, nh
);
4628 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4633 /* handle nh neigh delete */
4634 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4635 struct prefix
*host_prefix
)
4637 rb_delete_host(&nh
->host_rb
, host_prefix
);
4639 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4640 /* uninstall from kernel */
4641 zl3vni_nh_uninstall(zl3vni
, nh
);
4643 /* delete the nh entry */
4644 zl3vni_nh_del(zl3vni
, nh
);
4648 /* handle neigh update from kernel - the only thing of interest is to
4649 * readd stale entries.
4651 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4655 zebra_neigh_t
*n
= NULL
;
4657 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4661 /* all next hop neigh are remote and installed by frr.
4662 * If the kernel has aged this entry, re-install.
4664 if (state
& NUD_STALE
)
4665 zl3vni_nh_install(zl3vni
, n
);
4670 /* handle neigh delete from kernel */
4671 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4673 zebra_neigh_t
*n
= NULL
;
4675 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4679 /* all next hop neigh are remote and installed by frr.
4680 * If we get an age out notification for these neigh entries, we have to
4683 zl3vni_nh_install(zl3vni
, n
);
4689 * Hash function for L3 VNI.
4691 static unsigned int l3vni_hash_keymake(void *p
)
4693 const zebra_l3vni_t
*zl3vni
= p
;
4695 return jhash_1word(zl3vni
->vni
, 0);
4699 * Compare 2 L3 VNI hash entries.
4701 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4703 const zebra_l3vni_t
*zl3vni1
= p1
;
4704 const zebra_l3vni_t
*zl3vni2
= p2
;
4706 return (zl3vni1
->vni
== zl3vni2
->vni
);
4710 * Callback to allocate L3 VNI hash entry.
4712 static void *zl3vni_alloc(void *p
)
4714 zebra_l3vni_t
*zl3vni
= NULL
;
4715 const zebra_l3vni_t
*tmp_l3vni
= p
;
4717 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4718 zl3vni
->vni
= tmp_l3vni
->vni
;
4719 return ((void *)zl3vni
);
4723 * Look up L3 VNI hash entry.
4725 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4727 zebra_l3vni_t tmp_l3vni
;
4728 zebra_l3vni_t
*zl3vni
= NULL
;
4730 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4731 tmp_l3vni
.vni
= vni
;
4732 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4738 * Add L3 VNI hash entry.
4740 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4742 zebra_l3vni_t tmp_zl3vni
;
4743 zebra_l3vni_t
*zl3vni
= NULL
;
4745 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4746 tmp_zl3vni
.vni
= vni
;
4748 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4751 zl3vni
->vrf_id
= vrf_id
;
4752 zl3vni
->svi_if
= NULL
;
4753 zl3vni
->vxlan_if
= NULL
;
4754 zl3vni
->l2vnis
= list_new();
4755 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4757 /* Create hash table for remote RMAC */
4758 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4759 "Zebra L3-VNI RMAC-Table");
4761 /* Create hash table for neighbors */
4762 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4763 "Zebra L3-VNI next-hop table");
4769 * Delete L3 VNI hash entry.
4771 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4773 zebra_l3vni_t
*tmp_zl3vni
;
4775 /* free the list of l2vnis */
4776 list_delete(&zl3vni
->l2vnis
);
4777 zl3vni
->l2vnis
= NULL
;
4779 /* Free the rmac table */
4780 hash_free(zl3vni
->rmac_table
);
4781 zl3vni
->rmac_table
= NULL
;
4783 /* Free the nh table */
4784 hash_free(zl3vni
->nh_table
);
4785 zl3vni
->nh_table
= NULL
;
4787 /* Free the VNI hash entry and allocated memory. */
4788 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4789 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4794 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4796 struct zebra_ns
*zns
= NULL
;
4797 struct route_node
*rn
= NULL
;
4798 struct interface
*ifp
= NULL
;
4800 /* loop through all vxlan-interface */
4801 zns
= zebra_ns_lookup(NS_DEFAULT
);
4802 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4804 struct zebra_if
*zif
= NULL
;
4805 struct zebra_l2info_vxlan
*vxl
= NULL
;
4807 ifp
= (struct interface
*)rn
->info
;
4812 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4815 vxl
= &zif
->l2info
.vxl
;
4816 if (vxl
->vni
== zl3vni
->vni
) {
4817 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4825 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4827 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4828 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4833 if (!zl3vni
->vxlan_if
)
4836 zif
= zl3vni
->vxlan_if
->info
;
4840 vxl
= &zif
->l2info
.vxl
;
4842 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4845 static zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4847 struct zebra_vrf
*zvrf
= NULL
;
4849 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4853 return zl3vni_lookup(zvrf
->l3vni
);
4857 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4858 * neighbor notifications, to see if they are of interest.
4860 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4861 struct interface
*br_if
)
4865 uint8_t bridge_vlan_aware
= 0;
4866 zebra_l3vni_t
*zl3vni
= NULL
;
4867 struct zebra_ns
*zns
= NULL
;
4868 struct route_node
*rn
= NULL
;
4869 struct zebra_if
*zif
= NULL
;
4870 struct interface
*tmp_if
= NULL
;
4871 struct zebra_l2info_bridge
*br
= NULL
;
4872 struct zebra_l2info_vxlan
*vxl
= NULL
;
4877 /* Make sure the linked interface is a bridge. */
4878 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4881 /* Determine if bridge is VLAN-aware or not */
4884 br
= &zif
->l2info
.br
;
4885 bridge_vlan_aware
= br
->vlan_aware
;
4886 if (bridge_vlan_aware
) {
4887 struct zebra_l2info_vlan
*vl
;
4889 if (!IS_ZEBRA_IF_VLAN(ifp
))
4894 vl
= &zif
->l2info
.vl
;
4898 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4899 /* TODO: Optimize with a hash. */
4900 zns
= zebra_ns_lookup(NS_DEFAULT
);
4901 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4902 tmp_if
= (struct interface
*)rn
->info
;
4906 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4908 if (!if_is_operative(tmp_if
))
4910 vxl
= &zif
->l2info
.vxl
;
4912 if (zif
->brslave_info
.br_if
!= br_if
)
4915 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4924 zl3vni
= zl3vni_lookup(vxl
->vni
);
4929 * Inform BGP about l3-vni.
4931 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4933 struct stream
*s
= NULL
;
4934 struct zserv
*client
= NULL
;
4935 struct ethaddr rmac
;
4936 char buf
[ETHER_ADDR_STRLEN
];
4938 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4939 /* BGP may not be running. */
4944 memset(&rmac
, 0, sizeof(struct ethaddr
));
4945 zl3vni_get_rmac(zl3vni
, &rmac
);
4947 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4949 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4950 stream_putl(s
, zl3vni
->vni
);
4951 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4952 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4953 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4954 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4956 /* Write packet size. */
4957 stream_putw_at(s
, 0, stream_get_endp(s
));
4959 if (IS_ZEBRA_DEBUG_VXLAN
)
4961 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4962 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4963 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4964 inet_ntoa(zl3vni
->local_vtep_ip
),
4965 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4966 ? "prefix-routes-only"
4968 zebra_route_string(client
->proto
));
4970 client
->l3vniadd_cnt
++;
4971 return zserv_send_message(client
, s
);
4975 * Inform BGP about local l3-VNI deletion.
4977 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4979 struct stream
*s
= NULL
;
4980 struct zserv
*client
= NULL
;
4982 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4983 /* BGP may not be running. */
4987 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4989 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4990 stream_putl(s
, zl3vni
->vni
);
4992 /* Write packet size. */
4993 stream_putw_at(s
, 0, stream_get_endp(s
));
4995 if (IS_ZEBRA_DEBUG_VXLAN
)
4996 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
4997 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4998 zebra_route_string(client
->proto
));
5000 client
->l3vnidel_cnt
++;
5001 return zserv_send_message(client
, s
);
5004 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5009 /* send l3vni add to BGP */
5010 zl3vni_send_add_to_client(zl3vni
);
5013 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5018 /* send l3-vni del to BGP*/
5019 zl3vni_send_del_to_client(zl3vni
);
5022 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5024 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5025 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5027 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5028 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5032 * handle transition of vni from l2 to l3 and vice versa
5034 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5037 zebra_vni_t
*zvni
= NULL
;
5039 /* There is a possibility that VNI notification was already received
5040 * from kernel and we programmed it as L2-VNI
5041 * In such a case we need to delete this L2-VNI first, so
5042 * that it can be reprogrammed as L3-VNI in the system. It is also
5043 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5044 * interface is still present in kernel. In this case to keep it
5045 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5048 /* Locate hash entry */
5049 zvni
= zvni_lookup(vni
);
5053 if (IS_ZEBRA_DEBUG_VXLAN
)
5054 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5056 /* Delete VNI from BGP. */
5057 zvni_send_del_to_client(zvni
->vni
);
5059 /* Free up all neighbors and MAC, if any. */
5060 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5061 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5063 /* Free up all remote VTEPs, if any. */
5064 zvni_vtep_del_all(zvni
, 0);
5066 /* Delete the hash entry. */
5067 if (zvni_del(zvni
)) {
5068 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5069 "Failed to del VNI hash %p, VNI %u", zvni
,
5074 /* TODO_MITESH: This needs to be thought through. We don't have
5075 * enough information at this point to reprogram the vni as
5076 * l2-vni. One way is to store the required info in l3-vni and
5077 * used it solely for this purpose
5084 /* delete and uninstall rmac hash entry */
5085 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5087 zebra_mac_t
*zrmac
= NULL
;
5088 zebra_l3vni_t
*zl3vni
= NULL
;
5090 zrmac
= (zebra_mac_t
*)bucket
->data
;
5091 zl3vni
= (zebra_l3vni_t
*)ctx
;
5092 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5093 zl3vni_rmac_del(zl3vni
, zrmac
);
5096 /* delete and uninstall nh hash entry */
5097 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5099 zebra_neigh_t
*n
= NULL
;
5100 zebra_l3vni_t
*zl3vni
= NULL
;
5102 n
= (zebra_neigh_t
*)bucket
->data
;
5103 zl3vni
= (zebra_l3vni_t
*)ctx
;
5104 zl3vni_nh_uninstall(zl3vni
, n
);
5105 zl3vni_nh_del(zl3vni
, n
);
5108 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5111 struct zserv
*client
= NULL
;
5112 struct stream
*s
= NULL
;
5113 char buf
[PREFIX_STRLEN
];
5115 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5116 /* BGP may not be running. */
5120 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5122 zclient_create_header(s
, cmd
, vrf_id
);
5123 stream_put(s
, p
, sizeof(struct prefix
));
5125 /* Write packet size. */
5126 stream_putw_at(s
, 0, stream_get_endp(s
));
5128 if (IS_ZEBRA_DEBUG_VXLAN
)
5129 zlog_debug("Send ip prefix %s %s on vrf %s",
5130 prefix2str(p
, buf
, sizeof(buf
)),
5131 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5132 vrf_id_to_name(vrf_id
));
5134 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5135 client
->prefixadd_cnt
++;
5137 client
->prefixdel_cnt
++;
5139 return zserv_send_message(client
, s
);
5142 /* re-add remote rmac if needed */
5143 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5144 struct ethaddr
*rmac
)
5146 char buf
[ETHER_ADDR_STRLEN
];
5147 zebra_mac_t
*zrmac
= NULL
;
5149 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5153 if (IS_ZEBRA_DEBUG_VXLAN
)
5154 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5155 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5157 zl3vni_rmac_install(zl3vni
, zrmac
);
5161 /* Process a remote MACIP add from BGP. */
5162 static void process_remote_macip_add(vni_t vni
,
5163 struct ethaddr
*macaddr
,
5165 struct ipaddr
*ipaddr
,
5168 struct in_addr vtep_ip
)
5171 zebra_vtep_t
*zvtep
;
5172 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5173 zebra_neigh_t
*n
= NULL
;
5174 int update_mac
= 0, update_neigh
= 0;
5175 char buf
[ETHER_ADDR_STRLEN
];
5176 char buf1
[INET6_ADDRSTRLEN
];
5177 struct interface
*ifp
= NULL
;
5178 struct zebra_if
*zif
= NULL
;
5179 struct zebra_vrf
*zvrf
;
5184 bool do_dad
= false;
5185 bool is_dup_detect
= false;
5187 /* Locate VNI hash entry - expected to exist. */
5188 zvni
= zvni_lookup(vni
);
5190 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5194 ifp
= zvni
->vxlan_if
;
5198 !if_is_operative(ifp
) ||
5200 !zif
->brslave_info
.br_if
) {
5201 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5206 /* The remote VTEP specified should normally exist, but it is
5207 * possible that when peering comes up, peer may advertise MACIP
5208 * routes before advertising type-3 routes.
5210 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5212 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5215 EC_ZEBRA_VTEP_ADD_FAILED
,
5216 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5221 zvni_vtep_install(zvni
, zvtep
);
5224 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5225 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5226 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5228 mac
= zvni_mac_lookup(zvni
, macaddr
);
5230 /* Ignore if the mac is already present as a gateway mac */
5232 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5233 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5234 if (IS_ZEBRA_DEBUG_VXLAN
)
5235 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5237 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5238 ipa_len
? " IP " : "",
5240 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5244 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5248 /* check if the remote MAC is unknown or has a change.
5249 * If so, that needs to be updated first. Note that client could
5250 * install MAC and MACIP separately or just install the latter.
5253 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5254 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5255 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5256 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5257 || seq
!= mac
->rem_seq
)
5262 mac
= zvni_mac_add(zvni
, macaddr
);
5265 "Failed to add MAC %s VNI %u Remote VTEP %s",
5266 prefix_mac2str(macaddr
, buf
,
5268 vni
, inet_ntoa(vtep_ip
));
5272 /* Is this MAC created for a MACIP? */
5274 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5276 const char *mac_type
;
5278 /* When host moves but changes its (MAC,IP)
5279 * binding, BGP may install a MACIP entry that
5280 * corresponds to "older" location of the host
5281 * in transient situations (because {IP1,M1}
5282 * is a different route from {IP1,M2}). Check
5283 * the sequence number and ignore this update
5286 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5287 tmp_seq
= mac
->loc_seq
;
5290 tmp_seq
= mac
->rem_seq
;
5291 mac_type
= "remote";
5293 if (seq
< tmp_seq
) {
5294 if (IS_ZEBRA_DEBUG_VXLAN
)
5295 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5297 prefix_mac2str(macaddr
,
5299 ipa_len
? " IP " : "",
5302 buf1
, sizeof(buf1
)) : "",
5309 /* Check MAC's curent state is local (this is the case
5310 * where MAC has moved from L->R) and check previous
5311 * detection started via local learning.
5312 * RFC-7432: A PE/VTEP that detects a MAC mobility
5313 * event via local learning starts an M-second timer.
5315 * VTEP-IP or seq. change alone is not considered
5316 * for dup. detection.
5318 * MAC is already marked duplicate set dad, then
5319 * is_dup_detect will be set to not install the entry.
5321 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5323 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5326 /* Remove local MAC from BGP. */
5327 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5328 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5330 /* Set "auto" and "remote" forwarding info. */
5331 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5332 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5333 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5334 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5337 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5339 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5342 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5344 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5346 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5347 mac
->fwd_info
.r_vtep_ip
,
5348 do_dad
, &is_dup_detect
,
5351 if (!is_dup_detect
) {
5352 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5353 /* Install the entry. */
5354 zvni_mac_install(zvni
, mac
);
5358 /* Update seq number. */
5361 /* If there is no IP, return after clearing AUTO flag of MAC. */
5363 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5370 /* Check if the remote neighbor itself is unknown or has a
5371 * change. If so, create or update and then install the entry.
5373 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5375 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5376 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5377 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5378 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5379 || seq
!= n
->rem_seq
)
5384 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5387 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5388 ipaddr2str(ipaddr
, buf1
,
5390 prefix_mac2str(macaddr
, buf
,
5392 vni
, inet_ntoa(vtep_ip
));
5399 /* When host moves but changes its (MAC,IP)
5400 * binding, BGP may install a MACIP entry that
5401 * corresponds to "older" location of the host
5402 * in transient situations (because {IP1,M1}
5403 * is a different route from {IP1,M2}). Check
5404 * the sequence number and ignore this update
5407 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5408 tmp_seq
= n
->loc_seq
;
5411 tmp_seq
= n
->rem_seq
;
5414 if (seq
< tmp_seq
) {
5415 if (IS_ZEBRA_DEBUG_VXLAN
)
5416 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5418 prefix_mac2str(macaddr
,
5421 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5426 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5427 /* MAC change, send a delete for old
5428 * neigh if learnt locally.
5430 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5431 IS_ZEBRA_NEIGH_ACTIVE(n
))
5432 zvni_neigh_send_del_to_client(
5434 &n
->emac
, 0, n
->state
);
5436 /* update neigh list for macs */
5437 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5439 listnode_delete(old_mac
->neigh_list
, n
);
5440 zvni_deref_ip2mac(zvni
, old_mac
);
5442 listnode_add_sort(mac
->neigh_list
, n
);
5443 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5445 /* Check Neigh's curent state is local
5446 * (this is the case where neigh/host has moved
5447 * from L->R) and check previous detction
5448 * started via local learning.
5450 * RFC-7432: A PE/VTEP that detects a MAC
5451 * mobilit event via local learning starts
5452 * an M-second timer.
5453 * VTEP-IP or seq. change along is not
5454 * considered for dup. detection.
5456 * Mobilty event scenario-B IP-MAC binding
5459 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5466 /* Set "remote" forwarding info. */
5467 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5468 n
->r_vtep_ip
= vtep_ip
;
5469 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5471 /* Set router flag (R-bit) to this Neighbor entry */
5472 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5473 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5475 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5477 /* Check old or new MAC detected as duplicate,
5478 * inherit duplicate flag to this neigh.
5480 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5482 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5483 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5485 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5486 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5489 /* Check duplicate address detection for IP */
5490 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5495 /* Install the entry. */
5497 zvni_neigh_install(zvni
, n
);
5500 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5502 /* Update seq number. */
5506 /* Process a remote MACIP delete from BGP. */
5507 static void process_remote_macip_del(vni_t vni
,
5508 struct ethaddr
*macaddr
,
5510 struct ipaddr
*ipaddr
,
5511 struct in_addr vtep_ip
)
5514 zebra_mac_t
*mac
= NULL
;
5515 zebra_neigh_t
*n
= NULL
;
5516 struct interface
*ifp
= NULL
;
5517 struct zebra_if
*zif
= NULL
;
5518 struct zebra_ns
*zns
;
5519 struct zebra_l2info_vxlan
*vxl
;
5520 struct zebra_vrf
*zvrf
;
5521 char buf
[ETHER_ADDR_STRLEN
];
5522 char buf1
[INET6_ADDRSTRLEN
];
5524 /* Locate VNI hash entry - expected to exist. */
5525 zvni
= zvni_lookup(vni
);
5527 if (IS_ZEBRA_DEBUG_VXLAN
)
5528 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5532 ifp
= zvni
->vxlan_if
;
5536 !if_is_operative(ifp
) ||
5538 !zif
->brslave_info
.br_if
) {
5539 if (IS_ZEBRA_DEBUG_VXLAN
)
5540 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5544 zns
= zebra_ns_lookup(NS_DEFAULT
);
5545 vxl
= &zif
->l2info
.vxl
;
5547 /* The remote VTEP specified is normally expected to exist, but
5548 * it is possible that the peer may delete the VTEP before deleting
5549 * any MACs referring to the VTEP, in which case the handler (see
5550 * remote_vtep_del) would have already deleted the MACs.
5552 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5555 mac
= zvni_mac_lookup(zvni
, macaddr
);
5557 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5560 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5561 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5562 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5566 /* If the remote mac or neighbor doesn't exist there is nothing
5567 * more to do. Otherwise, uninstall the entry and then remove it.
5572 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5574 /* Ignore the delete if this mac is a gateway mac-ip */
5575 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5576 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5578 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5580 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5581 ipa_len
? " IP " : "",
5583 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5587 /* Uninstall remote neighbor or MAC. */
5589 if (zvrf
->dad_freeze
&&
5590 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5591 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5592 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5593 struct interface
*vlan_if
;
5595 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5596 zif
->brslave_info
.br_if
);
5597 if (IS_ZEBRA_DEBUG_VXLAN
)
5598 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5599 __PRETTY_FUNCTION__
,
5600 ipaddr2str(ipaddr
, buf1
,
5601 sizeof(buf1
)), n
->flags
,
5603 neigh_read_specific_ip(ipaddr
, vlan_if
);
5606 /* When the MAC changes for an IP, it is possible the
5607 * client may update the new MAC before trying to delete the
5608 * "old" neighbor (as these are two different MACIP routes).
5609 * Do the delete only if the MAC matches.
5611 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5612 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5613 zvni_neigh_uninstall(zvni
, n
);
5614 zvni_neigh_del(zvni
, n
);
5615 zvni_deref_ip2mac(zvni
, mac
);
5618 /* DAD: when MAC is freeze state as remote learn event,
5619 * remote mac-ip delete event is received will result in freeze
5620 * entry removal, first fetch kernel for the same entry present
5621 * as LOCAL and reachable, avoid deleting this entry instead
5622 * use kerenel local entry to update during unfreeze time.
5624 if (zvrf
->dad_freeze
&&
5625 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5626 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5627 if (IS_ZEBRA_DEBUG_VXLAN
)
5628 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5629 __PRETTY_FUNCTION__
,
5630 prefix_mac2str(macaddr
, buf
,
5633 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5634 macaddr
, vxl
->access_vlan
);
5637 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5638 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5640 * the remote sequence number in the auto mac entry
5641 * needs to be reset to 0 as the mac entry may have
5642 * been removed on all VTEPs (including
5643 * the originating one)
5647 /* If all remote neighbors referencing a remote MAC
5648 * go away, we need to uninstall the MAC.
5650 if (remote_neigh_count(mac
) == 0) {
5651 zvni_mac_uninstall(zvni
, mac
);
5652 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5654 if (list_isempty(mac
->neigh_list
))
5655 zvni_mac_del(zvni
, mac
);
5657 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5663 /* Public functions */
5665 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5667 zebra_l3vni_t
*zl3vni
= NULL
;
5669 zl3vni
= zl3vni_lookup(vni
);
5673 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5676 /* handle evpn route in vrf table */
5677 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5678 struct ipaddr
*vtep_ip
,
5679 struct prefix
*host_prefix
)
5681 zebra_l3vni_t
*zl3vni
= NULL
;
5682 struct ipaddr ipv4_vtep
;
5684 zl3vni
= zl3vni_from_vrf(vrf_id
);
5685 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5689 * add the next hop neighbor -
5690 * neigh to be installed is the ipv6 nexthop neigh
5692 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5695 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5696 * address. Rmac is programmed against the ipv4 vtep because we only
5697 * support ipv4 tunnels in the h/w right now
5699 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5700 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5701 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5702 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5703 &(ipv4_vtep
.ipaddr_v4
));
5705 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5706 sizeof(struct in_addr
));
5709 * add the rmac - remote rmac to be installed is against the ipv4
5712 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5715 /* handle evpn vrf route delete */
5716 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5717 struct ipaddr
*vtep_ip
,
5718 struct prefix
*host_prefix
)
5720 zebra_l3vni_t
*zl3vni
= NULL
;
5721 zebra_neigh_t
*nh
= NULL
;
5722 zebra_mac_t
*zrmac
= NULL
;
5724 zl3vni
= zl3vni_from_vrf(vrf_id
);
5728 /* find the next hop entry and rmac entry */
5729 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5732 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5734 /* delete the next hop entry */
5735 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5737 /* delete the rmac entry */
5739 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5743 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5744 struct ethaddr
*rmac
, bool use_json
)
5746 zebra_l3vni_t
*zl3vni
= NULL
;
5747 zebra_mac_t
*zrmac
= NULL
;
5748 json_object
*json
= NULL
;
5750 if (!is_evpn_enabled()) {
5752 vty_out(vty
, "{}\n");
5757 json
= json_object_new_object();
5759 zl3vni
= zl3vni_lookup(l3vni
);
5762 vty_out(vty
, "{}\n");
5764 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5768 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5771 vty_out(vty
, "{}\n");
5774 "%% Requested RMAC doesn't exist in L3-VNI %u",
5779 zl3vni_print_rmac(zrmac
, vty
, json
);
5782 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5783 json
, JSON_C_TO_STRING_PRETTY
));
5784 json_object_free(json
);
5788 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5790 zebra_l3vni_t
*zl3vni
;
5792 struct rmac_walk_ctx wctx
;
5793 json_object
*json
= NULL
;
5795 if (!is_evpn_enabled())
5798 zl3vni
= zl3vni_lookup(l3vni
);
5801 vty_out(vty
, "{}\n");
5803 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5806 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5811 json
= json_object_new_object();
5813 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5817 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5819 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5821 json_object_int_add(json
, "numRmacs", num_rmacs
);
5823 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5826 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5827 json
, JSON_C_TO_STRING_PRETTY
));
5828 json_object_free(json
);
5832 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5834 json_object
*json
= NULL
;
5837 if (!is_evpn_enabled()) {
5839 vty_out(vty
, "{}\n");
5844 json
= json_object_new_object();
5848 hash_iterate(zrouter
.l3vni_table
,
5849 (void (*)(struct hash_bucket
*,
5850 void *))zl3vni_print_rmac_hash_all_vni
,
5854 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5855 json
, JSON_C_TO_STRING_PRETTY
));
5856 json_object_free(json
);
5860 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5861 struct ipaddr
*ip
, bool use_json
)
5863 zebra_l3vni_t
*zl3vni
= NULL
;
5864 zebra_neigh_t
*n
= NULL
;
5865 json_object
*json
= NULL
;
5867 if (!is_evpn_enabled()) {
5869 vty_out(vty
, "{}\n");
5874 json
= json_object_new_object();
5876 zl3vni
= zl3vni_lookup(l3vni
);
5879 vty_out(vty
, "{}\n");
5881 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5885 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5888 vty_out(vty
, "{}\n");
5891 "%% Requested next-hop not present for L3-VNI %u",
5896 zl3vni_print_nh(n
, vty
, json
);
5899 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5900 json
, JSON_C_TO_STRING_PRETTY
));
5901 json_object_free(json
);
5905 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5908 struct nh_walk_ctx wctx
;
5909 json_object
*json
= NULL
;
5910 zebra_l3vni_t
*zl3vni
= NULL
;
5912 if (!is_evpn_enabled())
5915 zl3vni
= zl3vni_lookup(l3vni
);
5918 vty_out(vty
, "{}\n");
5920 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5924 num_nh
= hashcount(zl3vni
->nh_table
);
5929 json
= json_object_new_object();
5934 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5936 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5938 json_object_int_add(json
, "numNextHops", num_nh
);
5940 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5943 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5944 json
, JSON_C_TO_STRING_PRETTY
));
5945 json_object_free(json
);
5949 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5951 json_object
*json
= NULL
;
5954 if (!is_evpn_enabled()) {
5956 vty_out(vty
, "{}\n");
5961 json
= json_object_new_object();
5965 hash_iterate(zrouter
.l3vni_table
,
5966 (void (*)(struct hash_bucket
*,
5967 void *))zl3vni_print_nh_hash_all_vni
,
5971 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5972 json
, JSON_C_TO_STRING_PRETTY
));
5973 json_object_free(json
);
5978 * Display L3 VNI information (VTY command handler).
5980 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5983 json_object
*json
= NULL
;
5984 zebra_l3vni_t
*zl3vni
= NULL
;
5986 if (!is_evpn_enabled()) {
5988 vty_out(vty
, "{}\n");
5992 zl3vni
= zl3vni_lookup(vni
);
5995 vty_out(vty
, "{}\n");
5997 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6002 json
= json_object_new_object();
6006 zl3vni_print(zl3vni
, (void *)args
);
6009 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6010 json
, JSON_C_TO_STRING_PRETTY
));
6011 json_object_free(json
);
6015 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6016 json_object
*json_vrfs
)
6018 char buf
[ETHER_ADDR_STRLEN
];
6019 zebra_l3vni_t
*zl3vni
= NULL
;
6021 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6026 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6027 zvrf_name(zvrf
), zl3vni
->vni
,
6028 zl3vni_vxlan_if_name(zl3vni
),
6029 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6030 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6032 json_object
*json_vrf
= NULL
;
6034 json_vrf
= json_object_new_object();
6035 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6036 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6037 json_object_string_add(json_vrf
, "vxlanIntf",
6038 zl3vni_vxlan_if_name(zl3vni
));
6039 json_object_string_add(json_vrf
, "sviIntf",
6040 zl3vni_svi_if_name(zl3vni
));
6041 json_object_string_add(json_vrf
, "state",
6042 zl3vni_state2str(zl3vni
));
6043 json_object_string_add(
6044 json_vrf
, "routerMac",
6045 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6046 json_object_array_add(json_vrfs
, json_vrf
);
6051 * Display Neighbors for a VNI (VTY command handler).
6053 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6054 vni_t vni
, bool use_json
)
6058 struct neigh_walk_ctx wctx
;
6059 json_object
*json
= NULL
;
6061 if (!is_evpn_enabled())
6063 zvni
= zvni_lookup(vni
);
6066 vty_out(vty
, "{}\n");
6068 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6071 num_neigh
= hashcount(zvni
->neigh_table
);
6076 json
= json_object_new_object();
6078 /* Since we have IPv6 addresses to deal with which can vary widely in
6079 * size, we try to be a bit more elegant in display by first computing
6080 * the maximum width.
6082 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6085 wctx
.addr_width
= 15;
6087 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6091 "Number of ARPs (local and remote) known for this VNI: %u\n",
6093 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6094 -wctx
.addr_width
, "IP", "Type",
6095 "State", "MAC", "Remote VTEP");
6097 json_object_int_add(json
, "numArpNd", num_neigh
);
6099 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6101 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6102 json
, JSON_C_TO_STRING_PRETTY
));
6103 json_object_free(json
);
6108 * Display neighbors across all VNIs (VTY command handler).
6110 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6111 bool print_dup
, bool use_json
)
6113 json_object
*json
= NULL
;
6116 if (!is_evpn_enabled())
6120 json
= json_object_new_object();
6124 args
[2] = (void *)(ptrdiff_t)print_dup
;
6126 hash_iterate(zvrf
->vni_table
,
6127 (void (*)(struct hash_bucket
*,
6128 void *))zvni_print_neigh_hash_all_vni
,
6131 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6132 json
, JSON_C_TO_STRING_PRETTY
));
6133 json_object_free(json
);
6138 * Display neighbors across all VNIs in detail(VTY command handler).
6140 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6141 struct zebra_vrf
*zvrf
,
6142 bool print_dup
, bool use_json
)
6144 json_object
*json
= NULL
;
6147 if (!is_evpn_enabled())
6151 json
= json_object_new_object();
6155 args
[2] = (void *)(ptrdiff_t)print_dup
;
6157 hash_iterate(zvrf
->vni_table
,
6158 (void (*)(struct hash_bucket
*,
6159 void *))zvni_print_neigh_hash_all_vni_detail
,
6162 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6163 json
, JSON_C_TO_STRING_PRETTY
));
6164 json_object_free(json
);
6169 * Display specific neighbor for a VNI, if present (VTY command handler).
6171 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6172 struct zebra_vrf
*zvrf
, vni_t vni
,
6173 struct ipaddr
*ip
, bool use_json
)
6177 json_object
*json
= NULL
;
6179 if (!is_evpn_enabled())
6181 zvni
= zvni_lookup(vni
);
6184 vty_out(vty
, "{}\n");
6186 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6189 n
= zvni_neigh_lookup(zvni
, ip
);
6193 "%% Requested neighbor does not exist in VNI %u\n",
6198 json
= json_object_new_object();
6200 zvni_print_neigh(n
, vty
, json
);
6203 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6204 json
, JSON_C_TO_STRING_PRETTY
));
6205 json_object_free(json
);
6210 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6211 * By definition, these are remote neighbors.
6213 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6214 vni_t vni
, struct in_addr vtep_ip
,
6219 struct neigh_walk_ctx wctx
;
6220 json_object
*json
= NULL
;
6222 if (!is_evpn_enabled())
6224 zvni
= zvni_lookup(vni
);
6227 vty_out(vty
, "{}\n");
6229 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6232 num_neigh
= hashcount(zvni
->neigh_table
);
6236 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6239 wctx
.addr_width
= 15;
6240 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6241 wctx
.r_vtep_ip
= vtep_ip
;
6243 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6244 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6247 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6248 json
, JSON_C_TO_STRING_PRETTY
));
6249 json_object_free(json
);
6254 * Display Duplicate detected Neighbors for a VNI
6255 * (VTY command handler).
6257 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6258 struct zebra_vrf
*zvrf
,
6264 struct neigh_walk_ctx wctx
;
6265 json_object
*json
= NULL
;
6267 if (!is_evpn_enabled())
6270 zvni
= zvni_lookup(vni
);
6272 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6276 num_neigh
= hashcount(zvni
->neigh_table
);
6280 num_neigh
= num_dup_detected_neighs(zvni
);
6285 json
= json_object_new_object();
6287 /* Since we have IPv6 addresses to deal with which can vary widely in
6288 * size, we try to be a bit more elegant in display by first computing
6289 * the maximum width.
6291 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6294 wctx
.addr_width
= 15;
6296 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6300 "Number of ARPs (local and remote) known for this VNI: %u\n",
6302 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6303 -wctx
.addr_width
, "IP", "Type",
6304 "State", "MAC", "Remote VTEP");
6306 json_object_int_add(json
, "numArpNd", num_neigh
);
6308 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6311 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6312 json
, JSON_C_TO_STRING_PRETTY
));
6313 json_object_free(json
);
6318 * Display MACs for a VNI (VTY command handler).
6320 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6321 vni_t vni
, bool use_json
)
6325 struct mac_walk_ctx wctx
;
6326 json_object
*json
= NULL
;
6327 json_object
*json_mac
= NULL
;
6329 if (!is_evpn_enabled())
6331 zvni
= zvni_lookup(vni
);
6334 vty_out(vty
, "{}\n");
6336 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6339 num_macs
= num_valid_macs(zvni
);
6344 json
= json_object_new_object();
6345 json_mac
= json_object_new_object();
6348 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6351 wctx
.json
= json_mac
;
6355 "Number of MACs (local and remote) known for this VNI: %u\n",
6357 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6358 "Intf/Remote VTEP", "VLAN");
6360 json_object_int_add(json
, "numMacs", num_macs
);
6362 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6365 json_object_object_add(json
, "macs", json_mac
);
6366 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6367 json
, JSON_C_TO_STRING_PRETTY
));
6368 json_object_free(json
);
6373 * Display MACs for all VNIs (VTY command handler).
6375 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6376 bool print_dup
, bool use_json
)
6378 struct mac_walk_ctx wctx
;
6379 json_object
*json
= NULL
;
6381 if (!is_evpn_enabled()) {
6383 vty_out(vty
, "{}\n");
6387 json
= json_object_new_object();
6389 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6392 wctx
.print_dup
= print_dup
;
6393 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6396 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6397 json
, JSON_C_TO_STRING_PRETTY
));
6398 json_object_free(json
);
6403 * Display MACs in detail for all VNIs (VTY command handler).
6405 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6406 struct zebra_vrf
*zvrf
,
6407 bool print_dup
, bool use_json
)
6409 struct mac_walk_ctx wctx
;
6410 json_object
*json
= NULL
;
6412 if (!is_evpn_enabled()) {
6414 vty_out(vty
, "{}\n");
6418 json
= json_object_new_object();
6420 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6423 wctx
.print_dup
= print_dup
;
6424 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6428 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6429 json
, JSON_C_TO_STRING_PRETTY
));
6430 json_object_free(json
);
6435 * Display MACs for all VNIs (VTY command handler).
6437 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6438 struct zebra_vrf
*zvrf
,
6439 struct in_addr vtep_ip
, bool use_json
)
6441 struct mac_walk_ctx wctx
;
6442 json_object
*json
= NULL
;
6444 if (!is_evpn_enabled())
6448 json
= json_object_new_object();
6450 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6452 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6453 wctx
.r_vtep_ip
= vtep_ip
;
6455 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6458 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6459 json
, JSON_C_TO_STRING_PRETTY
));
6460 json_object_free(json
);
6465 * Display specific MAC for a VNI, if present (VTY command handler).
6467 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6468 vni_t vni
, struct ethaddr
*macaddr
,
6473 json_object
*json
= NULL
;
6475 if (!is_evpn_enabled())
6478 zvni
= zvni_lookup(vni
);
6481 vty_out(vty
, "{}\n");
6483 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6486 mac
= zvni_mac_lookup(zvni
, macaddr
);
6489 vty_out(vty
, "{}\n");
6492 "%% Requested MAC does not exist in VNI %u\n",
6498 json
= json_object_new_object();
6500 zvni_print_mac(mac
, vty
, json
);
6502 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6503 json
, JSON_C_TO_STRING_PRETTY
));
6504 json_object_free(json
);
6508 /* Print Duplicate MACs per VNI */
6509 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6510 struct zebra_vrf
*zvrf
,
6511 vni_t vni
, bool use_json
)
6514 struct mac_walk_ctx wctx
;
6516 json_object
*json
= NULL
;
6517 json_object
*json_mac
= NULL
;
6519 if (!is_evpn_enabled())
6522 zvni
= zvni_lookup(vni
);
6524 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6528 num_macs
= num_valid_macs(zvni
);
6532 num_macs
= num_dup_detected_macs(zvni
);
6537 json
= json_object_new_object();
6538 json_mac
= json_object_new_object();
6541 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6544 wctx
.json
= json_mac
;
6548 "Number of MACs (local and remote) known for this VNI: %u\n",
6550 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6551 "Intf/Remote VTEP", "VLAN");
6553 json_object_int_add(json
, "numMacs", num_macs
);
6555 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6558 json_object_object_add(json
, "macs", json_mac
);
6559 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6560 json
, JSON_C_TO_STRING_PRETTY
));
6561 json_object_free(json
);
6566 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6567 struct zebra_vrf
*zvrf
,
6568 vni_t vni
, struct ethaddr
*macaddr
)
6572 struct listnode
*node
= NULL
;
6573 zebra_neigh_t
*nbr
= NULL
;
6575 if (!is_evpn_enabled())
6578 zvni
= zvni_lookup(vni
);
6580 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6584 mac
= zvni_mac_lookup(zvni
, macaddr
);
6586 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6591 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6592 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6596 /* Remove all IPs as duplicate associcated with this MAC */
6597 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6598 /* For local neigh mark inactive so MACIP update is generated
6599 * to BGP. This is a scenario where MAC update received
6600 * and detected as duplicate which marked neigh as duplicate.
6601 * Later local neigh update did not get a chance to relay
6602 * to BGP. Similarly remote macip update, neigh needs to be
6603 * installed locally.
6605 if (zvrf
->dad_freeze
&&
6606 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6607 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6608 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6609 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6610 zvni_neigh_install(zvni
, nbr
);
6613 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6615 nbr
->detect_start_time
.tv_sec
= 0;
6616 nbr
->dad_dup_detect_time
= 0;
6619 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6621 mac
->detect_start_time
.tv_sec
= 0;
6622 mac
->detect_start_time
.tv_usec
= 0;
6623 mac
->dad_dup_detect_time
= 0;
6624 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6626 /* warn-only action return */
6627 if (!zvrf
->dad_freeze
)
6630 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6631 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6633 if (zvni_mac_send_add_to_client(zvni
->vni
,
6639 /* Process all neighbors associated with this MAC. */
6640 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6642 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6643 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6645 /* Install the entry. */
6646 zvni_mac_install(zvni
, mac
);
6652 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6653 struct zebra_vrf
*zvrf
,
6654 vni_t vni
, struct ipaddr
*ip
)
6659 char buf
[INET6_ADDRSTRLEN
];
6660 char buf2
[ETHER_ADDR_STRLEN
];
6662 if (!is_evpn_enabled())
6665 zvni
= zvni_lookup(vni
);
6667 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6671 nbr
= zvni_neigh_lookup(zvni
, ip
);
6674 "%% Requested host IP does not exist in VNI %u\n",
6679 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6681 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6683 "%% Requsted host IP %s is not duplicate detected\n",
6688 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6690 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6692 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6693 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6694 return CMD_WARNING_CONFIG_FAILED
;
6697 if (IS_ZEBRA_DEBUG_VXLAN
)
6698 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6699 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6702 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6704 nbr
->detect_start_time
.tv_sec
= 0;
6705 nbr
->detect_start_time
.tv_usec
= 0;
6706 nbr
->dad_dup_detect_time
= 0;
6707 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6709 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6710 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6712 nbr
->flags
, nbr
->loc_seq
);
6713 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6714 zvni_neigh_install(zvni
, nbr
);
6720 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6722 struct mac_walk_ctx
*wctx
= ctxt
;
6725 struct listnode
*node
= NULL
;
6726 zebra_neigh_t
*nbr
= NULL
;
6728 mac
= (zebra_mac_t
*)bucket
->data
;
6734 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6737 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6739 mac
->detect_start_time
.tv_sec
= 0;
6740 mac
->detect_start_time
.tv_usec
= 0;
6741 mac
->dad_dup_detect_time
= 0;
6742 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6744 /* Remove all IPs as duplicate associcated with this MAC */
6745 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6746 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6748 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6750 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6752 nbr
->detect_start_time
.tv_sec
= 0;
6753 nbr
->dad_dup_detect_time
= 0;
6756 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6757 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6759 if (zvni_mac_send_add_to_client(zvni
->vni
,
6761 mac
->flags
, mac
->loc_seq
))
6764 /* Process all neighbors associated with this MAC. */
6765 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6767 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6768 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6770 /* Install the entry. */
6771 zvni_mac_install(zvni
, mac
);
6775 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6777 struct neigh_walk_ctx
*wctx
= ctxt
;
6780 char buf
[INET6_ADDRSTRLEN
];
6782 nbr
= (zebra_neigh_t
*)bucket
->data
;
6788 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6791 if (IS_ZEBRA_DEBUG_VXLAN
) {
6792 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6794 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6795 __PRETTY_FUNCTION__
, buf
,
6796 nbr
->flags
, nbr
->loc_seq
);
6799 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6801 nbr
->detect_start_time
.tv_sec
= 0;
6802 nbr
->detect_start_time
.tv_usec
= 0;
6803 nbr
->dad_dup_detect_time
= 0;
6804 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6806 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6807 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6809 nbr
->flags
, nbr
->loc_seq
);
6810 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6811 zvni_neigh_install(zvni
, nbr
);
6815 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6820 struct zebra_vrf
*zvrf
;
6821 struct mac_walk_ctx m_wctx
;
6822 struct neigh_walk_ctx n_wctx
;
6824 zvni
= (zebra_vni_t
*)bucket
->data
;
6828 vty
= (struct vty
*)args
[0];
6829 zvrf
= (struct zebra_vrf
*)args
[1];
6831 if (hashcount(zvni
->neigh_table
)) {
6832 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6836 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6840 if (num_valid_macs(zvni
)) {
6841 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6845 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6850 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6851 struct zebra_vrf
*zvrf
)
6855 if (!is_evpn_enabled())
6861 hash_iterate(zvrf
->vni_table
,
6862 (void (*)(struct hash_bucket
*, void *))
6863 zvni_clear_dup_detect_hash_vni_all
, args
);
6868 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6869 struct zebra_vrf
*zvrf
,
6873 struct mac_walk_ctx m_wctx
;
6874 struct neigh_walk_ctx n_wctx
;
6876 if (!is_evpn_enabled())
6879 zvni
= zvni_lookup(vni
);
6881 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6885 if (hashcount(zvni
->neigh_table
)) {
6886 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6890 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6894 if (num_valid_macs(zvni
)) {
6895 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6899 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6906 * Display MACs for a VNI from specific VTEP (VTY command handler).
6908 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6909 vni_t vni
, struct in_addr vtep_ip
,
6914 struct mac_walk_ctx wctx
;
6915 json_object
*json
= NULL
;
6916 json_object
*json_mac
= NULL
;
6918 if (!is_evpn_enabled())
6920 zvni
= zvni_lookup(vni
);
6923 vty_out(vty
, "{}\n");
6925 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6928 num_macs
= num_valid_macs(zvni
);
6933 json
= json_object_new_object();
6934 json_mac
= json_object_new_object();
6937 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6940 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6941 wctx
.r_vtep_ip
= vtep_ip
;
6942 wctx
.json
= json_mac
;
6943 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6946 json_object_int_add(json
, "numMacs", wctx
.count
);
6948 json_object_object_add(json
, "macs", json_mac
);
6949 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6950 json
, JSON_C_TO_STRING_PRETTY
));
6951 json_object_free(json
);
6957 * Display VNI information (VTY command handler).
6959 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6962 json_object
*json
= NULL
;
6964 zebra_l3vni_t
*zl3vni
= NULL
;
6965 zebra_vni_t
*zvni
= NULL
;
6967 if (!is_evpn_enabled())
6971 json
= json_object_new_object();
6975 zl3vni
= zl3vni_lookup(vni
);
6977 zl3vni_print(zl3vni
, (void *)args
);
6979 zvni
= zvni_lookup(vni
);
6982 vty_out(vty
, "{}\n");
6984 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6988 zvni_print(zvni
, (void *)args
);
6992 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6993 json
, JSON_C_TO_STRING_PRETTY
));
6994 json_object_free(json
);
6998 /* Display all global details for EVPN */
6999 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7004 json_object
*json
= NULL
;
7005 struct zebra_vrf
*zvrf
= NULL
;
7007 if (!is_evpn_enabled())
7010 zvrf
= zebra_vrf_get_evpn();
7014 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7015 num_l2vnis
= hashcount(zvrf
->vni_table
);
7016 num_vnis
= num_l2vnis
+ num_l3vnis
;
7019 json
= json_object_new_object();
7020 json_object_string_add(json
, "advertiseGatewayMacip",
7021 zvrf
->advertise_gw_macip
? "Yes" : "No");
7022 json_object_int_add(json
, "numVnis", num_vnis
);
7023 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7024 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7025 if (zvrf
->dup_addr_detect
)
7026 json_object_boolean_true_add(json
,
7027 "isDuplicateAddrDetection");
7029 json_object_boolean_false_add(json
,
7030 "isDuplicateAddrDetection");
7031 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7032 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7033 json_object_int_add(json
, "detectionFreezeTime",
7034 zvrf
->dad_freeze_time
);
7037 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7038 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7039 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7040 zvrf
->advertise_gw_macip
? "Yes" : "No");
7041 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7042 zvrf
->advertise_svi_macip
? "Yes" : "No");
7043 vty_out(vty
, "Duplicate address detection: %s\n",
7044 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7045 vty_out(vty
, " Detection max-moves %u, time %d\n",
7046 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7047 if (zvrf
->dad_freeze
) {
7048 if (zvrf
->dad_freeze_time
)
7049 vty_out(vty
, " Detection freeze %u\n",
7050 zvrf
->dad_freeze_time
);
7052 vty_out(vty
, " Detection freeze %s\n",
7058 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7059 json
, JSON_C_TO_STRING_PRETTY
));
7060 json_object_free(json
);
7065 * Display VNI hash table (VTY command handler).
7067 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7070 json_object
*json
= NULL
;
7073 if (!is_evpn_enabled())
7077 json
= json_object_new_object();
7079 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7080 "Type", "VxLAN IF", "# MACs", "# ARPs",
7081 "# Remote VTEPs", "Tenant VRF");
7086 /* Display all L2-VNIs */
7087 hash_iterate(zvrf
->vni_table
,
7088 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7091 /* Display all L3-VNIs */
7092 hash_iterate(zrouter
.l3vni_table
,
7093 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7097 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7098 json
, JSON_C_TO_STRING_PRETTY
));
7099 json_object_free(json
);
7103 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7107 uint32_t max_moves
= 0;
7108 uint32_t freeze_time
= 0;
7109 bool dup_addr_detect
= false;
7110 bool freeze
= false;
7113 STREAM_GETL(s
, dup_addr_detect
);
7114 STREAM_GETL(s
, time
);
7115 STREAM_GETL(s
, max_moves
);
7116 STREAM_GETL(s
, freeze
);
7117 STREAM_GETL(s
, freeze_time
);
7119 /* DAD previous state was enabled, and new state is disable,
7120 * clear all duplicate detected addresses.
7122 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7123 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7125 zvrf
->dup_addr_detect
= dup_addr_detect
;
7126 zvrf
->dad_time
= time
;
7127 zvrf
->dad_max_moves
= max_moves
;
7128 zvrf
->dad_freeze
= freeze
;
7129 zvrf
->dad_freeze_time
= freeze_time
;
7131 if (IS_ZEBRA_DEBUG_VXLAN
)
7133 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7134 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7135 zvrf
->dup_addr_detect
? "enable" : "disable",
7136 zvrf
->dad_max_moves
,
7138 zvrf
->dad_freeze
? "enable" : "disable",
7139 zvrf
->dad_freeze_time
);
7146 * Display VNI hash table in detail(VTY command handler).
7148 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7151 json_object
*json
= NULL
;
7152 struct zebra_ns
*zns
= NULL
;
7153 struct zvni_evpn_show zes
;
7155 if (!is_evpn_enabled())
7158 zns
= zebra_ns_lookup(NS_DEFAULT
);
7164 json
= json_object_new_object();
7170 /* Display all L2-VNIs */
7173 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7176 /* Display all L3-VNIs */
7177 hash_iterate(zrouter
.l3vni_table
,
7178 (void (*)(struct hash_bucket
*,
7179 void *))zl3vni_print_hash_detail
,
7183 vty_out(vty
, "%s\n",
7184 json_object_to_json_string_ext(
7185 json
, JSON_C_TO_STRING_PRETTY
));
7186 json_object_free(json
);
7191 * Handle neighbor delete notification from the kernel (on a VLAN device
7192 * / L3 interface). This may result in either the neighbor getting deleted
7193 * from our database or being re-added to the kernel (if it is a valid
7196 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7197 struct interface
*link_if
,
7200 char buf
[INET6_ADDRSTRLEN
];
7201 char buf2
[ETHER_ADDR_STRLEN
];
7202 zebra_neigh_t
*n
= NULL
;
7203 zebra_vni_t
*zvni
= NULL
;
7204 zebra_mac_t
*zmac
= NULL
;
7205 zebra_l3vni_t
*zl3vni
= NULL
;
7206 struct zebra_vrf
*zvrf
;
7208 /* check if this is a remote neigh entry corresponding to remote
7211 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7213 return zl3vni_local_nh_del(zl3vni
, ip
);
7215 /* We are only interested in neighbors on an SVI that resides on top
7216 * of a VxLAN bridge.
7218 zvni
= zvni_from_svi(ifp
, link_if
);
7222 if (!zvni
->vxlan_if
) {
7224 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7229 if (IS_ZEBRA_DEBUG_VXLAN
)
7230 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7231 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7232 ifp
->ifindex
, zvni
->vni
);
7234 /* If entry doesn't exist, nothing to do. */
7235 n
= zvni_neigh_lookup(zvni
, ip
);
7239 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7241 if (IS_ZEBRA_DEBUG_VXLAN
)
7243 "Trying to del a neigh %s without a mac %s on VNI %u",
7244 ipaddr2str(ip
, buf
, sizeof(buf
)),
7245 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7251 /* If it is a remote entry, the kernel has aged this out or someone has
7252 * deleted it, it needs to be re-installed as Quagga is the owner.
7254 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7255 zvni_neigh_install(zvni
, n
);
7259 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7261 zlog_debug("%s: VNI %u vrf lookup failed.",
7262 __PRETTY_FUNCTION__
, zvni
->vni
);
7266 /* In case of feeze action, if local neigh is in duplicate state,
7267 * Mark the Neigh as inactive before sending delete request to BGPd,
7268 * If BGPd has remote entry, it will re-install
7270 if (zvrf
->dad_freeze
&&
7271 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7272 ZEBRA_NEIGH_SET_INACTIVE(n
);
7274 /* Remove neighbor from BGP. */
7275 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7277 /* Delete this neighbor entry. */
7278 zvni_neigh_del(zvni
, n
);
7280 /* see if the AUTO mac needs to be deleted */
7281 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7282 && !listcount(zmac
->neigh_list
))
7283 zvni_mac_del(zvni
, zmac
);
7289 * Handle neighbor add or update notification from the kernel (on a VLAN
7290 * device / L3 interface). This is typically for a local neighbor but can
7291 * also be for a remote neighbor (e.g., ageout notification). It could
7292 * also be a "move" scenario.
7294 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7295 struct interface
*link_if
,
7297 struct ethaddr
*macaddr
,
7302 char buf
[ETHER_ADDR_STRLEN
];
7303 char buf2
[INET6_ADDRSTRLEN
];
7304 zebra_vni_t
*zvni
= NULL
;
7305 zebra_l3vni_t
*zl3vni
= NULL
;
7307 /* check if this is a remote neigh entry corresponding to remote
7310 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7312 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7314 /* We are only interested in neighbors on an SVI that resides on top
7315 * of a VxLAN bridge.
7317 zvni
= zvni_from_svi(ifp
, link_if
);
7321 if (IS_ZEBRA_DEBUG_VXLAN
)
7323 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7324 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7325 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7326 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7327 is_router
? "router " : "",
7330 /* Is this about a local neighbor or a remote one? */
7332 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7335 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7340 * Handle message from client to delete a remote MACIP for a VNI.
7342 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7346 struct ethaddr macaddr
;
7348 struct in_addr vtep_ip
;
7349 uint16_t l
= 0, ipa_len
;
7350 char buf
[ETHER_ADDR_STRLEN
];
7351 char buf1
[INET6_ADDRSTRLEN
];
7353 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7354 memset(&ip
, 0, sizeof(struct ipaddr
));
7355 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7359 while (l
< hdr
->length
) {
7360 /* Obtain each remote MACIP and process. */
7361 /* Message contains VNI, followed by MAC followed by IP (if any)
7362 * followed by remote VTEP IP.
7364 memset(&ip
, 0, sizeof(ip
));
7365 STREAM_GETL(s
, vni
);
7366 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7367 STREAM_GETL(s
, ipa_len
);
7369 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7371 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7373 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7374 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7375 l
+= IPV4_MAX_BYTELEN
;
7377 if (IS_ZEBRA_DEBUG_VXLAN
)
7379 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7381 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7382 ipa_len
? " IP " : "",
7384 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7386 zebra_route_string(client
->proto
));
7388 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7396 * Handle message from client to add a remote MACIP for a VNI. This
7397 * could be just the add of a MAC address or the add of a neighbor
7400 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7404 struct ethaddr macaddr
;
7406 struct in_addr vtep_ip
;
7407 uint16_t l
= 0, ipa_len
;
7410 char buf
[ETHER_ADDR_STRLEN
];
7411 char buf1
[INET6_ADDRSTRLEN
];
7413 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7414 memset(&ip
, 0, sizeof(struct ipaddr
));
7415 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7417 if (!EVPN_ENABLED(zvrf
)) {
7418 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7424 while (l
< hdr
->length
) {
7425 /* Obtain each remote MACIP and process. */
7426 /* Message contains VNI, followed by MAC followed by IP (if any)
7427 * followed by remote VTEP IP.
7429 memset(&ip
, 0, sizeof(ip
));
7430 STREAM_GETL(s
, vni
);
7431 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7432 STREAM_GETL(s
, ipa_len
);
7434 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7436 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7438 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7439 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7440 l
+= IPV4_MAX_BYTELEN
;
7442 /* Get flags - sticky mac and/or gateway mac */
7443 STREAM_GETC(s
, flags
);
7445 STREAM_GETL(s
, seq
);
7448 if (IS_ZEBRA_DEBUG_VXLAN
)
7450 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7452 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7453 ipa_len
? " IP " : "",
7455 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7456 flags
, seq
, inet_ntoa(vtep_ip
),
7457 zebra_route_string(client
->proto
));
7459 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7460 flags
, seq
, vtep_ip
);
7468 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7469 * us, this must involve a multihoming scenario. Treat this as implicit delete
7470 * of any prior local MAC.
7472 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7473 struct interface
*br_if
,
7474 struct ethaddr
*macaddr
, vlanid_t vid
)
7476 struct zebra_if
*zif
;
7477 struct zebra_l2info_vxlan
*vxl
;
7481 char buf
[ETHER_ADDR_STRLEN
];
7485 vxl
= &zif
->l2info
.vxl
;
7488 /* Check if EVPN is enabled. */
7489 if (!is_evpn_enabled())
7492 /* Locate hash entry; it is expected to exist. */
7493 zvni
= zvni_lookup(vni
);
7497 /* If entry doesn't exist, nothing to do. */
7498 mac
= zvni_mac_lookup(zvni
, macaddr
);
7502 /* Is it a local entry? */
7503 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7506 if (IS_ZEBRA_DEBUG_VXLAN
)
7508 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7509 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7510 ifp
->ifindex
, vni
, mac
->flags
);
7512 /* Remove MAC from BGP. */
7513 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7516 * If there are no neigh associated with the mac delete the mac
7517 * else mark it as AUTO for forward reference
7519 if (!listcount(mac
->neigh_list
)) {
7520 zvni_mac_del(zvni
, mac
);
7522 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7523 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7524 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7531 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7532 * This can happen because the remote MAC entries are also added as "dynamic",
7533 * so the kernel can ageout the entry.
7535 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7536 struct interface
*br_if
,
7537 struct ethaddr
*macaddr
, vlanid_t vid
)
7539 struct zebra_if
*zif
= NULL
;
7540 struct zebra_l2info_vxlan
*vxl
= NULL
;
7542 zebra_vni_t
*zvni
= NULL
;
7543 zebra_l3vni_t
*zl3vni
= NULL
;
7544 zebra_mac_t
*mac
= NULL
;
7545 char buf
[ETHER_ADDR_STRLEN
];
7549 vxl
= &zif
->l2info
.vxl
;
7552 /* Check if EVPN is enabled. */
7553 if (!is_evpn_enabled())
7556 /* check if this is a remote RMAC and readd simillar to remote macs */
7557 zl3vni
= zl3vni_lookup(vni
);
7559 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7561 /* Locate hash entry; it is expected to exist. */
7562 zvni
= zvni_lookup(vni
);
7566 /* If entry doesn't exist, nothing to do. */
7567 mac
= zvni_mac_lookup(zvni
, macaddr
);
7571 /* Is it a remote entry? */
7572 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7575 if (IS_ZEBRA_DEBUG_VXLAN
)
7576 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7577 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7580 zvni_mac_install(zvni
, mac
);
7585 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7587 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7588 struct ethaddr
*macaddr
, vlanid_t vid
)
7592 char buf
[ETHER_ADDR_STRLEN
];
7594 /* We are interested in MACs only on ports or (port, VLAN) that
7597 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7600 if (!zvni
->vxlan_if
) {
7602 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7607 /* If entry doesn't exist, nothing to do. */
7608 mac
= zvni_mac_lookup(zvni
, macaddr
);
7612 /* Is it a local entry? */
7613 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7616 if (IS_ZEBRA_DEBUG_VXLAN
)
7617 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7618 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7619 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7621 /* Update all the neigh entries associated with this mac */
7622 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7624 /* Remove MAC from BGP. */
7625 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7628 * If there are no neigh associated with the mac delete the mac
7629 * else mark it as AUTO for forward reference
7631 if (!listcount(mac
->neigh_list
)) {
7632 zvni_mac_del(zvni
, mac
);
7634 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7635 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7636 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7643 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7645 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7646 struct interface
*br_if
,
7647 struct ethaddr
*macaddr
, vlanid_t vid
,
7652 struct zebra_vrf
*zvrf
;
7653 char buf
[ETHER_ADDR_STRLEN
];
7654 bool mac_sticky
= false;
7655 bool inform_client
= false;
7656 bool upd_neigh
= false;
7657 bool is_dup_detect
= false;
7658 struct in_addr vtep_ip
= {.s_addr
= 0};
7660 /* We are interested in MACs only on ports or (port, VLAN) that
7663 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7665 if (IS_ZEBRA_DEBUG_VXLAN
)
7667 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7668 sticky
? "sticky " : "",
7669 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7670 ifp
->name
, ifp
->ifindex
, vid
);
7674 if (!zvni
->vxlan_if
) {
7675 if (IS_ZEBRA_DEBUG_VXLAN
)
7677 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7682 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7684 if (IS_ZEBRA_DEBUG_VXLAN
)
7685 zlog_debug("\tNo Vrf found for vrf_id: %d",
7686 zvni
->vxlan_if
->vrf_id
);
7690 /* Check if we need to create or update or it is a NO-OP. */
7691 mac
= zvni_mac_lookup(zvni
, macaddr
);
7693 if (IS_ZEBRA_DEBUG_VXLAN
)
7695 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7696 sticky
? "sticky " : "",
7697 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7698 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7700 mac
= zvni_mac_add(zvni
, macaddr
);
7703 EC_ZEBRA_MAC_ADD_FAILED
,
7704 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7705 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7706 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7709 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7710 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7711 mac
->fwd_info
.local
.vid
= vid
;
7713 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7714 inform_client
= true;
7717 if (IS_ZEBRA_DEBUG_VXLAN
)
7719 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7720 sticky
? "sticky " : "",
7721 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7722 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7725 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7726 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7730 * Update any changes and if changes are relevant to
7733 if (mac_sticky
== sticky
7734 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7735 && mac
->fwd_info
.local
.vid
== vid
) {
7736 if (IS_ZEBRA_DEBUG_VXLAN
)
7738 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7739 "entry exists and has not changed ",
7740 sticky
? "sticky " : "",
7741 prefix_mac2str(macaddr
, buf
,
7743 ifp
->name
, ifp
->ifindex
, vid
,
7747 if (mac_sticky
!= sticky
) {
7749 SET_FLAG(mac
->flags
,
7752 UNSET_FLAG(mac
->flags
,
7754 inform_client
= true;
7757 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7758 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7759 mac
->fwd_info
.local
.vid
= vid
;
7761 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7762 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7763 bool do_dad
= false;
7766 * MAC has either moved or was "internally" created due
7767 * to a neighbor learn and is now actually learnt. If
7768 * it was learnt as a remote sticky MAC, this is an
7771 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7773 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7774 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7775 prefix_mac2str(macaddr
, buf
,
7777 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7782 /* If an actual move, compute MAC's seq number */
7783 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7784 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7786 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7787 /* Trigger DAD for remote MAC */
7791 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7792 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7793 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7794 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7795 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7796 mac
->fwd_info
.local
.vid
= vid
;
7798 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7800 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7802 * We have to inform BGP of this MAC as well as process
7805 inform_client
= true;
7808 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7812 if (is_dup_detect
) {
7813 inform_client
= false;
7819 /* Inform BGP if required. */
7820 if (inform_client
) {
7821 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7822 mac
->flags
, mac
->loc_seq
))
7826 /* Process all neighbors associated with this MAC, if required. */
7828 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7834 * Handle message from client to delete a remote VTEP for a VNI.
7836 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7839 unsigned short l
= 0;
7841 struct in_addr vtep_ip
;
7843 zebra_vtep_t
*zvtep
;
7844 struct interface
*ifp
;
7845 struct zebra_if
*zif
;
7847 if (!is_evpn_enabled()) {
7849 "%s: EVPN is not enabled yet we have received a vtep del command",
7850 __PRETTY_FUNCTION__
);
7854 if (!EVPN_ENABLED(zvrf
)) {
7855 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7862 while (l
< hdr
->length
) {
7863 int flood_control
__attribute__((unused
));
7865 /* Obtain each remote VTEP and process. */
7866 STREAM_GETL(s
, vni
);
7868 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7869 l
+= IPV4_MAX_BYTELEN
;
7871 /* Flood control is intentionally ignored right now */
7872 STREAM_GETL(s
, flood_control
);
7875 if (IS_ZEBRA_DEBUG_VXLAN
)
7876 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7877 inet_ntoa(vtep_ip
), vni
,
7878 zebra_route_string(client
->proto
));
7880 /* Locate VNI hash entry - expected to exist. */
7881 zvni
= zvni_lookup(vni
);
7883 if (IS_ZEBRA_DEBUG_VXLAN
)
7885 "Failed to locate VNI hash upon remote VTEP DEL, "
7891 ifp
= zvni
->vxlan_if
;
7894 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7900 /* If down or not mapped to a bridge, we're done. */
7901 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7904 /* If the remote VTEP does not exist, there's nothing more to
7906 * Otherwise, uninstall any remote MACs pointing to this VTEP
7908 * then, the VTEP entry itself and remove it.
7910 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7914 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7915 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7916 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7917 zvni_vtep_del(zvni
, zvtep
);
7925 * Handle message from client to add a remote VTEP for a VNI.
7927 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7930 unsigned short l
= 0;
7932 struct in_addr vtep_ip
;
7934 struct interface
*ifp
;
7935 struct zebra_if
*zif
;
7937 zebra_vtep_t
*zvtep
;
7939 if (!is_evpn_enabled()) {
7941 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7942 __PRETTY_FUNCTION__
);
7946 if (!EVPN_ENABLED(zvrf
)) {
7947 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7954 while (l
< hdr
->length
) {
7955 /* Obtain each remote VTEP and process. */
7956 STREAM_GETL(s
, vni
);
7958 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7959 STREAM_GETL(s
, flood_control
);
7960 l
+= IPV4_MAX_BYTELEN
+ 4;
7962 if (IS_ZEBRA_DEBUG_VXLAN
)
7963 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
7964 inet_ntoa(vtep_ip
), vni
, flood_control
,
7965 zebra_route_string(client
->proto
));
7967 /* Locate VNI hash entry - expected to exist. */
7968 zvni
= zvni_lookup(vni
);
7971 EC_ZEBRA_VTEP_ADD_FAILED
,
7972 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7977 ifp
= zvni
->vxlan_if
;
7980 EC_ZEBRA_VTEP_ADD_FAILED
,
7981 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7988 /* If down or not mapped to a bridge, we're done. */
7989 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7992 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7994 /* If the remote VTEP already exists check if
7995 * the flood mode has changed
7997 if (zvtep
->flood_control
!= flood_control
) {
7998 if (zvtep
->flood_control
7999 == VXLAN_FLOOD_DISABLED
)
8000 /* old mode was head-end-replication but
8001 * is no longer; get rid of the HER fdb
8002 * entry installed before
8004 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8005 zvtep
->flood_control
= flood_control
;
8006 zvni_vtep_install(zvni
, zvtep
);
8009 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8011 zvni_vtep_install(zvni
, zvtep
);
8013 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8014 "Failed to add remote VTEP, VNI %u zvni %p",
8024 * Add/Del gateway macip to evpn
8026 * 1. SVI interface on a vlan aware bridge
8027 * 2. SVI interface on a vlan unaware bridge
8028 * 3. vrr interface (MACVLAN) associated to a SVI
8029 * We advertise macip routes for an interface if it is associated to VxLan vlan
8031 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8035 struct ethaddr macaddr
;
8036 zebra_vni_t
*zvni
= NULL
;
8038 memset(&ip
, 0, sizeof(struct ipaddr
));
8039 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8041 /* Check if EVPN is enabled. */
8042 if (!is_evpn_enabled())
8045 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8046 struct interface
*svi_if
=
8047 NULL
; /* SVI corresponding to the MACVLAN */
8048 struct zebra_if
*ifp_zif
=
8049 NULL
; /* Zebra daemon specific info for MACVLAN */
8050 struct zebra_if
*svi_if_zif
=
8051 NULL
; /* Zebra daemon specific info for SVI*/
8053 ifp_zif
= ifp
->info
;
8058 * for a MACVLAN interface the link represents the svi_if
8060 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8061 ifp_zif
->link_ifindex
);
8063 zlog_debug("MACVLAN %s(%u) without link information",
8064 ifp
->name
, ifp
->ifindex
);
8068 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8070 * If it is a vlan aware bridge then the link gives the
8071 * bridge information
8073 struct interface
*svi_if_link
= NULL
;
8075 svi_if_zif
= svi_if
->info
;
8077 svi_if_link
= if_lookup_by_index_per_ns(
8078 zebra_ns_lookup(NS_DEFAULT
),
8079 svi_if_zif
->link_ifindex
);
8080 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8082 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8084 * If it is a vlan unaware bridge then svi is the bridge
8087 zvni
= zvni_from_svi(svi_if
, svi_if
);
8089 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8090 struct zebra_if
*svi_if_zif
=
8091 NULL
; /* Zebra daemon specific info for SVI */
8092 struct interface
*svi_if_link
=
8093 NULL
; /* link info for the SVI = bridge info */
8095 svi_if_zif
= ifp
->info
;
8097 svi_if_link
= if_lookup_by_index_per_ns(
8098 zebra_ns_lookup(NS_DEFAULT
),
8099 svi_if_zif
->link_ifindex
);
8101 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8103 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8104 zvni
= zvni_from_svi(ifp
, ifp
);
8110 if (!zvni
->vxlan_if
) {
8111 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8117 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8119 if (p
->family
== AF_INET
) {
8120 ip
.ipa_type
= IPADDR_V4
;
8121 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8122 sizeof(struct in_addr
));
8123 } else if (p
->family
== AF_INET6
) {
8124 ip
.ipa_type
= IPADDR_V6
;
8125 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8126 sizeof(struct in6_addr
));
8131 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8133 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8139 * Handle SVI interface going down.
8140 * SVI can be associated to either L3-VNI or L2-VNI.
8141 * For L2-VNI: At this point, this is a NOP since
8142 * the kernel deletes the neighbor entries on this SVI (if any).
8143 * We only need to update the vrf corresponding to zvni.
8144 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8147 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8149 zebra_l3vni_t
*zl3vni
= NULL
;
8151 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8154 /* process l3-vni down */
8155 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8157 /* remove association with svi-if */
8158 zl3vni
->svi_if
= NULL
;
8160 zebra_vni_t
*zvni
= NULL
;
8162 /* since we dont have svi corresponding to zvni, we associate it
8163 * to default vrf. Note: the corresponding neigh entries on the
8164 * SVI would have already been deleted */
8165 zvni
= zvni_from_svi(ifp
, link_if
);
8167 zvni
->vrf_id
= VRF_DEFAULT
;
8169 /* update the tenant vrf in BGP */
8170 zvni_send_add_to_client(zvni
);
8177 * Handle SVI interface coming up.
8178 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8180 * For L2-VNI: we need to install any remote neighbors entried (used for
8182 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8184 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8186 zebra_vni_t
*zvni
= NULL
;
8187 zebra_l3vni_t
*zl3vni
= NULL
;
8189 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8192 /* associate with svi */
8193 zl3vni
->svi_if
= ifp
;
8195 /* process oper-up */
8196 if (is_l3vni_oper_up(zl3vni
))
8197 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8200 /* process SVI up for l2-vni */
8201 struct neigh_walk_ctx n_wctx
;
8203 zvni
= zvni_from_svi(ifp
, link_if
);
8207 if (!zvni
->vxlan_if
) {
8209 "VNI %u hash %p doesn't have intf upon SVI up",
8214 if (IS_ZEBRA_DEBUG_VXLAN
)
8216 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8217 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8218 vrf_id_to_name(ifp
->vrf_id
));
8220 /* update the vrf information for l2-vni and inform bgp */
8221 zvni
->vrf_id
= ifp
->vrf_id
;
8222 zvni_send_add_to_client(zvni
);
8224 /* Install any remote neighbors for this VNI. */
8225 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8227 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8235 * Handle VxLAN interface down
8237 int zebra_vxlan_if_down(struct interface
*ifp
)
8240 struct zebra_if
*zif
= NULL
;
8241 struct zebra_l2info_vxlan
*vxl
= NULL
;
8242 zebra_l3vni_t
*zl3vni
= NULL
;
8245 /* Check if EVPN is enabled. */
8246 if (!is_evpn_enabled())
8251 vxl
= &zif
->l2info
.vxl
;
8254 zl3vni
= zl3vni_lookup(vni
);
8256 /* process-if-down for l3-vni */
8257 if (IS_ZEBRA_DEBUG_VXLAN
)
8258 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8261 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8263 /* process if-down for l2-vni */
8264 if (IS_ZEBRA_DEBUG_VXLAN
)
8265 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8268 /* Locate hash entry; it is expected to exist. */
8269 zvni
= zvni_lookup(vni
);
8272 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8273 ifp
->name
, ifp
->ifindex
, vni
);
8277 assert(zvni
->vxlan_if
== ifp
);
8279 /* Delete this VNI from BGP. */
8280 zvni_send_del_to_client(zvni
->vni
);
8282 /* Free up all neighbors and MACs, if any. */
8283 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8284 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8286 /* Free up all remote VTEPs, if any. */
8287 zvni_vtep_del_all(zvni
, 1);
8293 * Handle VxLAN interface up - update BGP if required.
8295 int zebra_vxlan_if_up(struct interface
*ifp
)
8298 struct zebra_if
*zif
= NULL
;
8299 struct zebra_l2info_vxlan
*vxl
= NULL
;
8300 zebra_vni_t
*zvni
= NULL
;
8301 zebra_l3vni_t
*zl3vni
= NULL
;
8303 /* Check if EVPN is enabled. */
8304 if (!is_evpn_enabled())
8309 vxl
= &zif
->l2info
.vxl
;
8312 zl3vni
= zl3vni_lookup(vni
);
8315 if (IS_ZEBRA_DEBUG_VXLAN
)
8316 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8319 /* we need to associate with SVI, if any, we can associate with
8320 * svi-if only after association with vxlan-intf is complete
8322 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8324 if (is_l3vni_oper_up(zl3vni
))
8325 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8327 /* Handle L2-VNI add */
8328 struct interface
*vlan_if
= NULL
;
8330 if (IS_ZEBRA_DEBUG_VXLAN
)
8331 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8334 /* Locate hash entry; it is expected to exist. */
8335 zvni
= zvni_lookup(vni
);
8338 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8339 ifp
->name
, ifp
->ifindex
, vni
);
8343 assert(zvni
->vxlan_if
== ifp
);
8344 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8345 zif
->brslave_info
.br_if
);
8347 zvni
->vrf_id
= vlan_if
->vrf_id
;
8348 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8350 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8353 /* If part of a bridge, inform BGP about this VNI. */
8354 /* Also, read and populate local MACs and neighbors. */
8355 if (zif
->brslave_info
.br_if
) {
8356 zvni_send_add_to_client(zvni
);
8357 zvni_read_mac_neigh(zvni
, ifp
);
8365 * Handle VxLAN interface delete. Locate and remove entry in hash table
8366 * and update BGP, if required.
8368 int zebra_vxlan_if_del(struct interface
*ifp
)
8371 struct zebra_if
*zif
= NULL
;
8372 struct zebra_l2info_vxlan
*vxl
= NULL
;
8373 zebra_vni_t
*zvni
= NULL
;
8374 zebra_l3vni_t
*zl3vni
= NULL
;
8376 /* Check if EVPN is enabled. */
8377 if (!is_evpn_enabled())
8382 vxl
= &zif
->l2info
.vxl
;
8385 zl3vni
= zl3vni_lookup(vni
);
8388 if (IS_ZEBRA_DEBUG_VXLAN
)
8389 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8392 /* process oper-down for l3-vni */
8393 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8395 /* remove the association with vxlan_if */
8396 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8397 zl3vni
->vxlan_if
= NULL
;
8400 /* process if-del for l2-vni*/
8401 if (IS_ZEBRA_DEBUG_VXLAN
)
8402 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8405 /* Locate hash entry; it is expected to exist. */
8406 zvni
= zvni_lookup(vni
);
8409 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8410 ifp
->name
, ifp
->ifindex
, vni
);
8414 /* remove from l3-vni list */
8415 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8417 listnode_delete(zl3vni
->l2vnis
, zvni
);
8419 /* Delete VNI from BGP. */
8420 zvni_send_del_to_client(zvni
->vni
);
8422 /* Free up all neighbors and MAC, if any. */
8423 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8424 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8426 /* Free up all remote VTEPs, if any. */
8427 zvni_vtep_del_all(zvni
, 0);
8429 /* Delete the hash entry. */
8430 if (zvni_del(zvni
)) {
8431 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8432 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8433 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8441 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8443 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8446 struct zebra_if
*zif
= NULL
;
8447 struct zebra_l2info_vxlan
*vxl
= NULL
;
8448 zebra_vni_t
*zvni
= NULL
;
8449 zebra_l3vni_t
*zl3vni
= NULL
;
8451 /* Check if EVPN is enabled. */
8452 if (!is_evpn_enabled())
8457 vxl
= &zif
->l2info
.vxl
;
8460 zl3vni
= zl3vni_lookup(vni
);
8463 if (IS_ZEBRA_DEBUG_VXLAN
)
8465 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8466 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8467 inet_ntoa(vxl
->vtep_ip
),
8468 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8470 /* Removed from bridge? Cleanup and return */
8471 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8472 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8473 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8477 /* access-vlan change - process oper down, associate with new
8478 * svi_if and then process oper up again
8480 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8481 if (if_is_operative(ifp
)) {
8482 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8483 zl3vni
->svi_if
= NULL
;
8484 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8485 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8486 if (is_l3vni_oper_up(zl3vni
))
8487 zebra_vxlan_process_l3vni_oper_up(
8493 * local-ip change - process oper down, associate with new
8494 * local-ip and then process oper up again
8496 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8497 if (if_is_operative(ifp
)) {
8498 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8499 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8500 if (is_l3vni_oper_up(zl3vni
))
8501 zebra_vxlan_process_l3vni_oper_up(
8506 /* Update local tunnel IP. */
8507 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8509 /* if we have a valid new master, process l3-vni oper up */
8510 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8511 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8512 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8516 /* Update VNI hash. */
8517 zvni
= zvni_lookup(vni
);
8520 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8521 ifp
->name
, ifp
->ifindex
, vni
);
8525 if (IS_ZEBRA_DEBUG_VXLAN
)
8527 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8528 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8529 inet_ntoa(vxl
->vtep_ip
),
8530 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8532 /* Removed from bridge? Cleanup and return */
8533 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8534 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8535 /* Delete from client, remove all remote VTEPs */
8536 /* Also, free up all MACs and neighbors. */
8537 zvni_send_del_to_client(zvni
->vni
);
8538 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8539 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8540 zvni_vtep_del_all(zvni
, 1);
8544 /* Handle other changes. */
8545 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8546 /* Remove all existing local neigh and MACs for this VNI
8547 * (including from BGP)
8549 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8550 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8553 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8554 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8555 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8557 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8558 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8559 zvni
->mcast_grp
= vxl
->mcast_grp
;
8561 zvni
->vxlan_if
= ifp
;
8563 /* Take further actions needed.
8564 * Note that if we are here, there is a change of interest.
8566 /* If down or not mapped to a bridge, we're done. */
8567 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8570 /* Inform BGP, if there is a change of interest. */
8572 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8573 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8574 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8575 zvni_send_add_to_client(zvni
);
8577 /* If there is a valid new master or a VLAN mapping change,
8578 * read and populate local MACs and neighbors.
8579 * Also, reinstall any remote MACs and neighbors
8580 * for this VNI (based on new VLAN).
8582 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8583 zvni_read_mac_neigh(zvni
, ifp
);
8584 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8585 struct mac_walk_ctx m_wctx
;
8586 struct neigh_walk_ctx n_wctx
;
8588 zvni_read_mac_neigh(zvni
, ifp
);
8590 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8592 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8595 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8597 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8606 * Handle VxLAN interface add.
8608 int zebra_vxlan_if_add(struct interface
*ifp
)
8611 struct zebra_if
*zif
= NULL
;
8612 struct zebra_l2info_vxlan
*vxl
= NULL
;
8613 zebra_vni_t
*zvni
= NULL
;
8614 zebra_l3vni_t
*zl3vni
= NULL
;
8616 /* Check if EVPN is enabled. */
8617 if (!is_evpn_enabled())
8622 vxl
= &zif
->l2info
.vxl
;
8625 zl3vni
= zl3vni_lookup(vni
);
8628 /* process if-add for l3-vni*/
8629 if (IS_ZEBRA_DEBUG_VXLAN
)
8631 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8632 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8633 inet_ntoa(vxl
->vtep_ip
),
8634 zif
->brslave_info
.bridge_ifindex
);
8636 /* associate with vxlan_if */
8637 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8638 zl3vni
->vxlan_if
= ifp
;
8640 /* Associate with SVI, if any. We can associate with svi-if only
8641 * after association with vxlan_if is complete */
8642 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8644 if (is_l3vni_oper_up(zl3vni
))
8645 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8648 /* process if-add for l2-vni */
8649 struct interface
*vlan_if
= NULL
;
8651 /* Create or update VNI hash. */
8652 zvni
= zvni_lookup(vni
);
8654 zvni
= zvni_add(vni
);
8657 EC_ZEBRA_VNI_ADD_FAILED
,
8658 "Failed to add VNI hash, IF %s(%u) VNI %u",
8659 ifp
->name
, ifp
->ifindex
, vni
);
8664 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8665 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8666 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8668 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8669 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8670 zvni
->mcast_grp
= vxl
->mcast_grp
;
8672 zvni
->vxlan_if
= ifp
;
8673 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8674 zif
->brslave_info
.br_if
);
8676 zvni
->vrf_id
= vlan_if
->vrf_id
;
8677 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8679 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8682 if (IS_ZEBRA_DEBUG_VXLAN
) {
8683 char addr_buf1
[INET_ADDRSTRLEN
];
8684 char addr_buf2
[INET_ADDRSTRLEN
];
8686 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8687 addr_buf1
, INET_ADDRSTRLEN
);
8688 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8689 addr_buf2
, INET_ADDRSTRLEN
);
8692 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8694 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8696 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8697 addr_buf1
, addr_buf2
,
8698 zif
->brslave_info
.bridge_ifindex
);
8701 /* If down or not mapped to a bridge, we're done. */
8702 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8706 zvni_send_add_to_client(zvni
);
8708 /* Read and populate local MACs and neighbors */
8709 zvni_read_mac_neigh(zvni
, ifp
);
8715 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8716 char *err
, int err_str_sz
, int filter
,
8719 zebra_l3vni_t
*zl3vni
= NULL
;
8720 struct zebra_vrf
*zvrf_evpn
= NULL
;
8722 zvrf_evpn
= zebra_vrf_get_evpn();
8726 if (IS_ZEBRA_DEBUG_VXLAN
)
8727 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8728 add
? "ADD" : "DEL");
8732 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8734 /* check if the vni is already present under zvrf */
8736 snprintf(err
, err_str_sz
,
8737 "VNI is already configured under the vrf");
8741 /* check if this VNI is already present in the system */
8742 zl3vni
= zl3vni_lookup(vni
);
8744 snprintf(err
, err_str_sz
,
8745 "VNI is already configured as L3-VNI");
8749 /* add the L3-VNI to the global table */
8750 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8752 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8756 /* associate the vrf with vni */
8759 /* set the filter in l3vni to denote if we are using l3vni only
8763 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8765 /* associate with vxlan-intf;
8766 * we need to associate with the vxlan-intf first
8768 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8770 /* associate with corresponding SVI interface, we can associate
8771 * with svi-if only after vxlan interface association is
8774 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8776 /* formulate l2vni list */
8777 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8780 if (is_l3vni_oper_up(zl3vni
))
8781 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8784 zl3vni
= zl3vni_lookup(vni
);
8786 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8790 if (zvrf
->l3vni
!= vni
) {
8791 snprintf(err
, err_str_sz
,
8792 "VNI %d doesn't exist in VRF: %s",
8793 vni
, zvrf
->vrf
->name
);
8797 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8798 snprintf(err
, ERR_STR_SZ
,
8799 "prefix-routes-only is not set for the vni");
8803 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8805 /* delete and uninstall all rmacs */
8806 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8809 /* delete and uninstall all next-hops */
8810 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8816 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8821 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8823 zebra_l3vni_t
*zl3vni
= NULL
;
8826 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8830 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8831 if (is_l3vni_oper_up(zl3vni
))
8832 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8836 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8838 zebra_l3vni_t
*zl3vni
= NULL
;
8841 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8845 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8846 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8850 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8852 zebra_l3vni_t
*zl3vni
= NULL
;
8856 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8862 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8868 * Handle message from client to specify the flooding mechanism for
8869 * BUM packets. The default is to do head-end (ingress) replication
8870 * and the other supported option is to disable it. This applies to
8871 * all BUM traffic and disabling it applies to both the transmit and
8872 * receive direction.
8874 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8877 enum vxlan_flood_control flood_ctrl
;
8879 if (!EVPN_ENABLED(zvrf
)) {
8880 zlog_err("EVPN flood control for non-EVPN VRF %u",
8886 STREAM_GETC(s
, flood_ctrl
);
8888 if (IS_ZEBRA_DEBUG_VXLAN
)
8889 zlog_debug("EVPN flood control %u, currently %u",
8890 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8892 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8895 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8897 /* Install or uninstall flood entries corresponding to
8900 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8908 * Handle message from client to enable/disable advertisement of svi macip
8911 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8916 zebra_vni_t
*zvni
= NULL
;
8917 struct interface
*ifp
= NULL
;
8919 if (!EVPN_ENABLED(zvrf
)) {
8920 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8926 STREAM_GETC(s
, advertise
);
8927 STREAM_GETL(s
, vni
);
8930 if (IS_ZEBRA_DEBUG_VXLAN
)
8931 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8932 advertise
? "enabled" : "disabled",
8933 advertise_gw_macip_enabled(NULL
)
8937 if (zvrf
->advertise_svi_macip
== advertise
)
8942 zvrf
->advertise_svi_macip
= advertise
;
8943 hash_iterate(zvrf
->vni_table
,
8944 zvni_gw_macip_add_for_vni_hash
, NULL
);
8946 hash_iterate(zvrf
->vni_table
,
8947 zvni_svi_macip_del_for_vni_hash
, NULL
);
8948 zvrf
->advertise_svi_macip
= advertise
;
8952 struct zebra_if
*zif
= NULL
;
8953 struct zebra_l2info_vxlan zl2_info
;
8954 struct interface
*vlan_if
= NULL
;
8956 zvni
= zvni_lookup(vni
);
8960 if (IS_ZEBRA_DEBUG_VXLAN
)
8962 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8963 advertise
? "enabled" : "disabled", vni
,
8964 advertise_svi_macip_enabled(zvni
)
8968 if (zvni
->advertise_svi_macip
== advertise
)
8971 ifp
= zvni
->vxlan_if
;
8977 /* If down or not mapped to a bridge, we're done. */
8978 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8981 zl2_info
= zif
->l2info
.vxl
;
8983 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8984 zif
->brslave_info
.br_if
);
8989 zvni
->advertise_svi_macip
= advertise
;
8990 /* Add primary SVI MAC-IP */
8991 zvni_add_macip_for_intf(vlan_if
, zvni
);
8993 /* Del primary MAC-IP */
8994 zvni_del_macip_for_intf(vlan_if
, zvni
);
8995 zvni
->advertise_svi_macip
= advertise
;
9004 * Handle message from client to enable/disable advertisement of g/w macip
9007 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9012 zebra_vni_t
*zvni
= NULL
;
9013 struct interface
*ifp
= NULL
;
9014 struct zebra_if
*zif
= NULL
;
9015 struct zebra_l2info_vxlan zl2_info
;
9016 struct interface
*vlan_if
= NULL
;
9018 if (!EVPN_ENABLED(zvrf
)) {
9019 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9025 STREAM_GETC(s
, advertise
);
9026 vni
= stream_get3(s
);
9028 zvni
= zvni_lookup(vni
);
9032 if (zvni
->advertise_subnet
== advertise
)
9035 if (IS_ZEBRA_DEBUG_VXLAN
)
9036 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9037 advertise
? "enabled" : "disabled", vni
,
9038 zvni
->advertise_subnet
? "enabled" : "disabled");
9041 zvni
->advertise_subnet
= advertise
;
9043 ifp
= zvni
->vxlan_if
;
9049 /* If down or not mapped to a bridge, we're done. */
9050 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9053 zl2_info
= zif
->l2info
.vxl
;
9056 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9060 if (zvni
->advertise_subnet
)
9061 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9063 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9070 * Handle message from client to enable/disable advertisement of g/w macip
9073 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9078 zebra_vni_t
*zvni
= NULL
;
9079 struct interface
*ifp
= NULL
;
9081 if (!EVPN_ENABLED(zvrf
)) {
9082 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9088 STREAM_GETC(s
, advertise
);
9089 STREAM_GETL(s
, vni
);
9092 if (IS_ZEBRA_DEBUG_VXLAN
)
9093 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9094 advertise
? "enabled" : "disabled",
9095 advertise_gw_macip_enabled(NULL
)
9099 if (zvrf
->advertise_gw_macip
== advertise
)
9102 zvrf
->advertise_gw_macip
= advertise
;
9104 if (advertise_gw_macip_enabled(zvni
))
9105 hash_iterate(zvrf
->vni_table
,
9106 zvni_gw_macip_add_for_vni_hash
, NULL
);
9108 hash_iterate(zvrf
->vni_table
,
9109 zvni_gw_macip_del_for_vni_hash
, NULL
);
9112 struct zebra_if
*zif
= NULL
;
9113 struct zebra_l2info_vxlan zl2_info
;
9114 struct interface
*vlan_if
= NULL
;
9115 struct interface
*vrr_if
= NULL
;
9117 zvni
= zvni_lookup(vni
);
9121 if (IS_ZEBRA_DEBUG_VXLAN
)
9123 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9124 advertise
? "enabled" : "disabled", vni
,
9125 advertise_gw_macip_enabled(zvni
) ? "enabled"
9128 if (zvni
->advertise_gw_macip
== advertise
)
9131 zvni
->advertise_gw_macip
= advertise
;
9133 ifp
= zvni
->vxlan_if
;
9139 /* If down or not mapped to a bridge, we're done. */
9140 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9143 zl2_info
= zif
->l2info
.vxl
;
9145 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9146 zif
->brslave_info
.br_if
);
9150 if (advertise_gw_macip_enabled(zvni
)) {
9151 /* Add primary SVI MAC-IP */
9152 zvni_add_macip_for_intf(vlan_if
, zvni
);
9154 /* Add VRR MAC-IP - if any*/
9155 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9157 zvni_add_macip_for_intf(vrr_if
, zvni
);
9159 /* Del primary MAC-IP */
9160 zvni_del_macip_for_intf(vlan_if
, zvni
);
9162 /* Del VRR MAC-IP - if any*/
9163 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9165 zvni_del_macip_for_intf(vrr_if
, zvni
);
9175 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9176 * When enabled, the VNI hash table will be built and MAC FDB table read;
9177 * when disabled, the entries should be deleted and remote VTEPs and MACs
9178 * uninstalled from the kernel.
9179 * This also informs the setting for BUM handling at the time this change
9180 * occurs; it is relevant only when specifying "learn".
9182 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9184 struct stream
*s
= NULL
;
9186 enum vxlan_flood_control flood_ctrl
;
9188 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9190 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9194 STREAM_GETC(s
, advertise
);
9195 STREAM_GETC(s
, flood_ctrl
);
9197 if (IS_ZEBRA_DEBUG_VXLAN
)
9198 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9199 zvrf_name(zvrf
), zvrf_id(zvrf
),
9200 advertise
? "enabled" : "disabled",
9201 is_evpn_enabled() ? "enabled" : "disabled",
9204 if (zvrf
->advertise_all_vni
== advertise
)
9207 zvrf
->advertise_all_vni
= advertise
;
9208 if (EVPN_ENABLED(zvrf
)) {
9209 zrouter
.evpn_vrf
= zvrf
;
9211 /* Note BUM handling */
9212 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9214 /* Build VNI hash table and inform BGP. */
9215 zvni_build_hash_table();
9217 /* Add all SVI (L3 GW) MACs to BGP*/
9218 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9221 /* Read the MAC FDB */
9222 macfdb_read(zvrf
->zns
);
9224 /* Read neighbors */
9225 neigh_read(zvrf
->zns
);
9227 /* Cleanup VTEPs for all VNIs - uninstall from
9228 * kernel and free entries.
9230 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9232 /* cleanup all l3vnis */
9233 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9235 /* Mark as "no EVPN VRF" */
9236 zrouter
.evpn_vrf
= NULL
;
9244 * Allocate VNI hash table for this VRF and do other initialization.
9245 * NOTE: Currently supported only for default VRF.
9247 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9251 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9252 "Zebra VRF VNI Table");
9253 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9254 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9257 /* Cleanup VNI info, but don't free the table. */
9258 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9262 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9263 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9266 /* Close all VNI handling */
9267 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9271 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9272 hash_free(zvrf
->vni_table
);
9275 /* init the l3vni table */
9276 void zebra_vxlan_init(void)
9278 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9279 "Zebra VRF L3 VNI table");
9280 zrouter
.evpn_vrf
= NULL
;
9283 /* free l3vni table */
9284 void zebra_vxlan_disable(void)
9286 hash_free(zrouter
.l3vni_table
);
9289 /* get the l3vni svi ifindex */
9290 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9292 zebra_l3vni_t
*zl3vni
= NULL
;
9294 zl3vni
= zl3vni_from_vrf(vrf_id
);
9295 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9298 return zl3vni
->svi_if
->ifindex
;
9301 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9303 struct zebra_vrf
*zvrf
= NULL
;
9304 zebra_neigh_t
*nbr
= NULL
;
9305 zebra_vni_t
*zvni
= NULL
;
9306 char buf1
[INET6_ADDRSTRLEN
];
9307 char buf2
[ETHER_ADDR_STRLEN
];
9309 nbr
= THREAD_ARG(t
);
9311 /* since this is asynchronous we need sanity checks*/
9312 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9316 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9320 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9324 if (IS_ZEBRA_DEBUG_VXLAN
)
9325 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9326 __PRETTY_FUNCTION__
,
9327 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9328 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9330 nbr
->dad_count
, zvni
->vni
);
9332 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9334 nbr
->detect_start_time
.tv_sec
= 0;
9335 nbr
->detect_start_time
.tv_usec
= 0;
9336 nbr
->dad_dup_detect_time
= 0;
9337 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9338 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9341 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9342 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9343 nbr
->flags
, nbr
->loc_seq
);
9344 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9345 zvni_neigh_install(zvni
, nbr
);
9351 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9353 struct zebra_vrf
*zvrf
= NULL
;
9354 zebra_mac_t
*mac
= NULL
;
9355 zebra_vni_t
*zvni
= NULL
;
9356 struct listnode
*node
= NULL
;
9357 zebra_neigh_t
*nbr
= NULL
;
9358 char buf
[ETHER_ADDR_STRLEN
];
9360 mac
= THREAD_ARG(t
);
9362 /* since this is asynchronous we need sanity checks*/
9363 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9367 zvni
= zvni_lookup(mac
->zvni
->vni
);
9371 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9375 if (IS_ZEBRA_DEBUG_VXLAN
)
9376 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9377 __PRETTY_FUNCTION__
,
9378 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9381 listcount(mac
->neigh_list
));
9383 /* Remove all IPs as duplicate associcated with this MAC */
9384 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9385 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9386 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9387 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9388 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9389 zvni_neigh_install(zvni
, nbr
);
9392 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9394 nbr
->detect_start_time
.tv_sec
= 0;
9395 nbr
->dad_dup_detect_time
= 0;
9398 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9400 mac
->detect_start_time
.tv_sec
= 0;
9401 mac
->detect_start_time
.tv_usec
= 0;
9402 mac
->dad_dup_detect_time
= 0;
9403 mac
->dad_mac_auto_recovery_timer
= NULL
;
9405 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9407 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9408 mac
->flags
, mac
->loc_seq
))
9411 /* Process all neighbors associated with this MAC. */
9412 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9414 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9415 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9417 /* Install the entry. */
9418 zvni_mac_install(zvni
, mac
);
9424 /************************** vxlan SG cache management ************************/
9425 /* Inform PIM about the mcast group */
9426 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9427 char *sg_str
, uint16_t cmd
)
9429 struct zserv
*client
= NULL
;
9430 struct stream
*s
= NULL
;
9432 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9436 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9438 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9439 stream_putl(s
, IPV4_MAX_BYTELEN
);
9440 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9441 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9443 /* Write packet size. */
9444 stream_putw_at(s
, 0, stream_get_endp(s
));
9446 if (IS_ZEBRA_DEBUG_VXLAN
)
9449 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9450 zebra_route_string(client
->proto
));
9452 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9453 client
->vxlan_sg_add_cnt
++;
9455 client
->vxlan_sg_del_cnt
++;
9457 return zserv_send_message(client
, s
);
9460 static unsigned int zebra_vxlan_sg_hash_key_make(void *p
)
9462 zebra_vxlan_sg_t
*vxlan_sg
= p
;
9464 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9465 vxlan_sg
->sg
.grp
.s_addr
, 0));
9468 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9470 const zebra_vxlan_sg_t
*sg1
= p1
;
9471 const zebra_vxlan_sg_t
*sg2
= p2
;
9473 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9474 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9477 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9478 struct prefix_sg
*sg
)
9480 zebra_vxlan_sg_t
*vxlan_sg
;
9482 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9484 vxlan_sg
->zvrf
= zvrf
;
9486 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9488 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9490 if (IS_ZEBRA_DEBUG_VXLAN
)
9491 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9496 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9497 struct prefix_sg
*sg
)
9499 zebra_vxlan_sg_t lookup
;
9502 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9505 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9506 struct prefix_sg
*sg
)
9508 zebra_vxlan_sg_t
*vxlan_sg
;
9509 zebra_vxlan_sg_t
*parent
= NULL
;
9512 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9516 /* create a *G entry for every BUM group implicitly -
9517 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9518 * 2. the XG entry is used by pimd to setup the
9519 * vxlan-termination-mroute
9521 if (sg
->src
.s_addr
) {
9522 memset(&sip
, 0, sizeof(sip
));
9523 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9528 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9531 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9535 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9540 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9543 struct zebra_vrf
*zvrf
;
9545 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9549 /* On SG entry deletion remove the reference to its parent XG
9552 if (vxlan_sg
->sg
.src
.s_addr
) {
9553 memset(&sip
, 0, sizeof(sip
));
9554 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9557 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9558 ZEBRA_VXLAN_SG_DEL
);
9560 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9562 if (IS_ZEBRA_DEBUG_VXLAN
)
9563 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9565 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9568 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9569 struct in_addr sip
, struct in_addr mcast_grp
)
9571 zebra_vxlan_sg_t
*vxlan_sg
;
9572 struct prefix_sg sg
;
9574 sg
.family
= AF_INET
;
9575 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9578 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9582 if (vxlan_sg
->ref_cnt
)
9583 --vxlan_sg
->ref_cnt
;
9585 if (!vxlan_sg
->ref_cnt
)
9586 zebra_vxlan_sg_del(vxlan_sg
);
9589 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9590 struct in_addr sip
, struct in_addr mcast_grp
)
9592 zebra_vxlan_sg_t
*vxlan_sg
;
9593 struct prefix_sg sg
;
9595 sg
.family
= AF_INET
;
9596 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9599 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9601 ++vxlan_sg
->ref_cnt
;
9606 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9607 struct in_addr mcast_grp
)
9609 struct zebra_vrf
*zvrf
;
9611 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9614 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9618 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9621 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9622 struct in_addr mcast_grp
)
9624 struct zebra_vrf
*zvrf
;
9626 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9629 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9632 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9635 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9637 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9639 zebra_vxlan_sg_del(vxlan_sg
);