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");
63 DEFINE_HOOK(zebra_rmac_update
, (zebra_mac_t
*rmac
, zebra_l3vni_t
*zl3vni
,
64 bool delete, const char *reason
), (rmac
, zl3vni
, delete, reason
))
68 #define VXLAN_FLOOD_STR_NO_INFO "-"
69 #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO
70 static const struct message zvtep_flood_str
[] = {
71 {VXLAN_FLOOD_DISABLED
, VXLAN_FLOOD_STR_NO_INFO
},
72 {VXLAN_FLOOD_PIM_SM
, "PIM-SM"},
73 {VXLAN_FLOOD_HEAD_END_REPL
, "HER"},
78 /* static function declarations */
79 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
81 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
82 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
83 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
84 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
86 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
88 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
90 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
91 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
92 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
);
93 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
94 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
96 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
97 struct ipaddr
*ip
, uint8_t flags
,
98 uint32_t seq
, int state
, uint16_t cmd
);
99 static unsigned int neigh_hash_keymake(const void *p
);
100 static void *zvni_neigh_alloc(void *p
);
101 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
102 struct ethaddr
*mac
);
103 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
104 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
105 struct in_addr
*r_vtep_ip
);
106 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
108 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
109 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
110 struct ethaddr
*macaddr
,
111 uint8_t flags
, uint32_t seq
);
112 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
113 struct ethaddr
*macaddr
,
114 uint8_t flags
, int state
);
115 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
116 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
117 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
118 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
119 struct interface
*br_if
);
120 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
122 /* l3-vni next-hop neigh related APIs */
123 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
125 static void *zl3vni_nh_alloc(void *p
);
126 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
127 struct ipaddr
*vtep_ip
,
128 struct ethaddr
*rmac
);
129 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
130 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
131 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
133 /* l3-vni rmac related APIs */
134 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
135 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
136 struct ethaddr
*rmac
);
137 static void *zl3vni_rmac_alloc(void *p
);
138 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
139 struct ethaddr
*rmac
);
140 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
141 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
142 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
144 /* l3-vni related APIs*/
145 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
146 static void *zl3vni_alloc(void *p
);
147 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
148 static int zl3vni_del(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(const 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(const 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(const 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 %u/%u\n",
844 -wctx
->addr_width
, buf2
, "local",
845 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
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 %u/%u\n",
880 -wctx
->addr_width
, buf2
, "remote", state_str
,
881 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
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 %s\n",
992 -wctx
.addr_width
, "IP", "Type",
993 "State", "MAC", "Remote VTEP", "Seq #'s");
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
);
1390 } else /* No vid? fill out the space */
1391 vty_out(vty
, " %-5s", "");
1392 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1393 if (json_mac_hdr
== NULL
) {
1396 json_object_int_add(json_mac
, "localSequence",
1398 json_object_int_add(json_mac
, "remoteSequence",
1400 json_object_int_add(json_mac
, "detectionCount",
1402 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1403 json_object_boolean_true_add(json_mac
,
1406 json_object_boolean_false_add(json_mac
,
1408 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1413 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1415 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1416 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1420 if (json_mac_hdr
== NULL
) {
1421 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1422 (wctx
->count
== 0)) {
1423 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1424 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n",
1425 "MAC", "Type", "Intf/Remote VTEP",
1428 vty_out(vty
, "%-17s %-6s %-21s %-5s %u/%u\n", buf1
,
1429 "remote", inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1430 "", mac
->loc_seq
, mac
->rem_seq
);
1432 json_object_string_add(json_mac
, "type", "remote");
1433 json_object_string_add(json_mac
, "remoteVtep",
1434 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1435 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1436 json_object_int_add(json_mac
, "localSequence",
1438 json_object_int_add(json_mac
, "remoteSequence",
1440 json_object_int_add(json_mac
, "detectionCount",
1442 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1443 json_object_boolean_true_add(json_mac
,
1446 json_object_boolean_false_add(json_mac
,
1455 /* Print Duplicate MAC */
1456 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1460 mac
= (zebra_mac_t
*)bucket
->data
;
1464 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1465 zvni_print_mac_hash(bucket
, ctxt
);
1469 * Print MAC hash entry in detail - called for display of all MACs.
1471 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1474 json_object
*json_mac_hdr
= NULL
;
1476 struct mac_walk_ctx
*wctx
= ctxt
;
1477 char buf1
[ETHER_ADDR_STRLEN
];
1480 json_mac_hdr
= wctx
->json
;
1481 mac
= (zebra_mac_t
*)bucket
->data
;
1486 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1488 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1491 /* Print Duplicate MAC in detail */
1492 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1497 mac
= (zebra_mac_t
*)bucket
->data
;
1501 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1502 zvni_print_mac_hash_detail(bucket
, ctxt
);
1506 * Print MACs for all VNI.
1508 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1511 json_object
*json
= NULL
, *json_vni
= NULL
;
1512 json_object
*json_mac
= NULL
;
1515 struct mac_walk_ctx
*wctx
= ctxt
;
1516 char vni_str
[VNI_STR_LEN
];
1518 vty
= (struct vty
*)wctx
->vty
;
1519 json
= (struct json_object
*)wctx
->json
;
1521 zvni
= (zebra_vni_t
*)bucket
->data
;
1524 /*We are iterating over a new VNI, set the count to 0*/
1527 num_macs
= num_valid_macs(zvni
);
1531 if (wctx
->print_dup
)
1532 num_macs
= num_dup_detected_macs(zvni
);
1535 json_vni
= json_object_new_object();
1536 json_mac
= json_object_new_object();
1537 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1540 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1542 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1543 zvni
->vni
, num_macs
);
1544 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC",
1545 "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
1547 json_object_int_add(json_vni
, "numMacs", num_macs
);
1552 json_object_int_add(json_vni
, "numMacs", num_macs
);
1553 json_object_object_add(json
, vni_str
, json_vni
);
1558 /* assign per-vni to wctx->json object to fill macs
1559 * under the vni. Re-assign primary json object to fill
1560 * next vni information.
1562 wctx
->json
= json_mac
;
1563 if (wctx
->print_dup
)
1564 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1566 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1570 json_object_object_add(json_vni
, "macs", json_mac
);
1571 json_object_object_add(json
, vni_str
, json_vni
);
1576 * Print MACs in detail for all VNI.
1578 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1582 json_object
*json
= NULL
, *json_vni
= NULL
;
1583 json_object
*json_mac
= NULL
;
1586 struct mac_walk_ctx
*wctx
= ctxt
;
1587 char vni_str
[VNI_STR_LEN
];
1589 vty
= (struct vty
*)wctx
->vty
;
1590 json
= (struct json_object
*)wctx
->json
;
1592 zvni
= (zebra_vni_t
*)bucket
->data
;
1595 vty_out(vty
, "{}\n");
1600 /*We are iterating over a new VNI, set the count to 0*/
1603 num_macs
= num_valid_macs(zvni
);
1607 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1611 json_vni
= json_object_new_object();
1612 json_mac
= json_object_new_object();
1613 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1616 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1618 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1619 zvni
->vni
, num_macs
);
1621 json_object_int_add(json_vni
, "numMacs", num_macs
);
1623 /* assign per-vni to wctx->json object to fill macs
1624 * under the vni. Re-assign primary json object to fill
1625 * next vni information.
1627 wctx
->json
= json_mac
;
1628 if (wctx
->print_dup
)
1629 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1632 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1636 json_object_object_add(json_vni
, "macs", json_mac
);
1637 json_object_object_add(json
, vni_str
, json_vni
);
1641 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1643 struct nh_walk_ctx
*wctx
= NULL
;
1644 struct vty
*vty
= NULL
;
1645 struct json_object
*json_vni
= NULL
;
1646 struct json_object
*json_nh
= NULL
;
1647 zebra_neigh_t
*n
= NULL
;
1648 char buf1
[ETHER_ADDR_STRLEN
];
1649 char buf2
[INET6_ADDRSTRLEN
];
1651 wctx
= (struct nh_walk_ctx
*)ctx
;
1653 json_vni
= wctx
->json
;
1655 json_nh
= json_object_new_object();
1656 n
= (zebra_neigh_t
*)bucket
->data
;
1659 vty_out(vty
, "%-15s %-17s\n",
1660 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1661 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1663 json_object_string_add(json_nh
, "nexthopIp",
1664 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1665 json_object_string_add(
1666 json_nh
, "routerMac",
1667 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1668 json_object_object_add(json_vni
,
1669 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1674 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1677 struct vty
*vty
= NULL
;
1678 json_object
*json
= NULL
;
1679 json_object
*json_vni
= NULL
;
1680 zebra_l3vni_t
*zl3vni
= NULL
;
1681 uint32_t num_nh
= 0;
1682 struct nh_walk_ctx wctx
;
1683 char vni_str
[VNI_STR_LEN
];
1685 vty
= (struct vty
*)args
[0];
1686 json
= (struct json_object
*)args
[1];
1688 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1690 num_nh
= hashcount(zl3vni
->nh_table
);
1695 json_vni
= json_object_new_object();
1696 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1700 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1701 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1703 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1705 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1707 wctx
.json
= json_vni
;
1708 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1710 json_object_object_add(json
, vni_str
, json_vni
);
1713 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1716 struct vty
*vty
= NULL
;
1717 json_object
*json
= NULL
;
1718 json_object
*json_vni
= NULL
;
1719 zebra_l3vni_t
*zl3vni
= NULL
;
1721 struct rmac_walk_ctx wctx
;
1722 char vni_str
[VNI_STR_LEN
];
1724 vty
= (struct vty
*)args
[0];
1725 json
= (struct json_object
*)args
[1];
1727 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1729 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1734 json_vni
= json_object_new_object();
1735 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1739 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1740 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1742 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1744 /* assign per-vni to wctx->json object to fill macs
1745 * under the vni. Re-assign primary json object to fill
1746 * next vni information.
1748 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1750 wctx
.json
= json_vni
;
1751 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1753 json_object_object_add(json
, vni_str
, json_vni
);
1756 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1758 zebra_mac_t
*zrmac
= NULL
;
1759 struct rmac_walk_ctx
*wctx
= NULL
;
1760 struct vty
*vty
= NULL
;
1761 struct json_object
*json
= NULL
;
1762 struct json_object
*json_rmac
= NULL
;
1763 char buf
[ETHER_ADDR_STRLEN
];
1765 wctx
= (struct rmac_walk_ctx
*)ctx
;
1769 json_rmac
= json_object_new_object();
1770 zrmac
= (zebra_mac_t
*)bucket
->data
;
1773 vty_out(vty
, "%-17s %-21s\n",
1774 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1775 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1777 json_object_string_add(
1778 json_rmac
, "routerMac",
1779 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1780 json_object_string_add(json_rmac
, "vtepIp",
1781 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1782 json_object_object_add(
1783 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1788 /* print a specific L3 VNI entry */
1789 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1791 char buf
[ETHER_ADDR_STRLEN
];
1792 struct vty
*vty
= NULL
;
1793 json_object
*json
= NULL
;
1794 zebra_vni_t
*zvni
= NULL
;
1795 json_object
*json_vni_list
= NULL
;
1796 struct listnode
*node
= NULL
, *nnode
= NULL
;
1802 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1803 vty_out(vty
, " Type: %s\n", "L3");
1804 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1805 vty_out(vty
, " Local Vtep Ip: %s\n",
1806 inet_ntoa(zl3vni
->local_vtep_ip
));
1807 vty_out(vty
, " Vxlan-Intf: %s\n",
1808 zl3vni_vxlan_if_name(zl3vni
));
1809 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1810 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1811 vty_out(vty
, " VNI Filter: %s\n",
1812 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1813 ? "prefix-routes-only"
1815 vty_out(vty
, " Router MAC: %s\n",
1816 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1817 vty_out(vty
, " L2 VNIs: ");
1818 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1819 vty_out(vty
, "%u ", zvni
->vni
);
1822 json_vni_list
= json_object_new_array();
1823 json_object_int_add(json
, "vni", zl3vni
->vni
);
1824 json_object_string_add(json
, "type", "L3");
1825 json_object_string_add(json
, "localVtepIp",
1826 inet_ntoa(zl3vni
->local_vtep_ip
));
1827 json_object_string_add(json
, "vxlanIntf",
1828 zl3vni_vxlan_if_name(zl3vni
));
1829 json_object_string_add(json
, "sviIntf",
1830 zl3vni_svi_if_name(zl3vni
));
1831 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1832 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1833 json_object_string_add(
1835 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1836 json_object_string_add(
1838 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1839 ? "prefix-routes-only"
1841 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1842 json_object_array_add(json_vni_list
,
1843 json_object_new_int(zvni
->vni
));
1845 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1850 * Print a specific VNI entry.
1852 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1855 zebra_vtep_t
*zvtep
;
1858 json_object
*json
= NULL
;
1859 json_object
*json_vtep_list
= NULL
;
1860 json_object
*json_ip_str
= NULL
;
1866 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1867 vty_out(vty
, " Type: %s\n", "L2");
1868 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1870 json_object_int_add(json
, "vni", zvni
->vni
);
1871 json_object_string_add(json
, "type", "L2");
1872 json_object_string_add(json
, "vrf",
1873 vrf_id_to_name(zvni
->vrf_id
));
1876 if (!zvni
->vxlan_if
) { // unexpected
1878 vty_out(vty
, " VxLAN interface: unknown\n");
1881 num_macs
= num_valid_macs(zvni
);
1882 num_neigh
= hashcount(zvni
->neigh_table
);
1884 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1885 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1886 vty_out(vty
, " Local VTEP IP: %s\n",
1887 inet_ntoa(zvni
->local_vtep_ip
));
1888 vty_out(vty
, " Mcast group: %s\n",
1889 inet_ntoa(zvni
->mcast_grp
));
1891 json_object_string_add(json
, "vxlanInterface",
1892 zvni
->vxlan_if
->name
);
1893 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1894 json_object_string_add(json
, "vtepIp",
1895 inet_ntoa(zvni
->local_vtep_ip
));
1896 json_object_string_add(json
, "mcastGroup",
1897 inet_ntoa(zvni
->mcast_grp
));
1898 json_object_string_add(json
, "advertiseGatewayMacip",
1899 zvni
->advertise_gw_macip
? "Yes" : "No");
1900 json_object_int_add(json
, "numMacs", num_macs
);
1901 json_object_int_add(json
, "numArpNd", num_neigh
);
1905 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1908 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1910 json_vtep_list
= json_object_new_array();
1911 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1912 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1913 zvtep
->flood_control
,
1914 VXLAN_FLOOD_STR_DEFAULT
);
1917 vty_out(vty
, " %s flood: %s\n",
1918 inet_ntoa(zvtep
->vtep_ip
),
1921 json_ip_str
= json_object_new_string(
1922 inet_ntoa(zvtep
->vtep_ip
));
1923 json_object_array_add(json_vtep_list
,
1928 json_object_object_add(json
, "numRemoteVteps",
1933 " Number of MACs (local and remote) known for this VNI: %u\n",
1936 " Number of ARPs (IPv4 and IPv6, local and remote) "
1937 "known for this VNI: %u\n",
1939 vty_out(vty
, " Advertise-gw-macip: %s\n",
1940 zvni
->advertise_gw_macip
? "Yes" : "No");
1944 /* print a L3 VNI hash entry */
1945 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1947 struct vty
*vty
= NULL
;
1948 json_object
*json
= NULL
;
1949 json_object
*json_vni
= NULL
;
1950 zebra_l3vni_t
*zl3vni
= NULL
;
1952 vty
= (struct vty
*)ctx
[0];
1953 json
= (json_object
*)ctx
[1];
1955 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1958 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1959 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1960 hashcount(zl3vni
->rmac_table
),
1961 hashcount(zl3vni
->nh_table
), "n/a",
1962 zl3vni_vrf_name(zl3vni
));
1964 char vni_str
[VNI_STR_LEN
];
1966 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1967 json_vni
= json_object_new_object();
1968 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1969 json_object_string_add(json_vni
, "vxlanIf",
1970 zl3vni_vxlan_if_name(zl3vni
));
1971 json_object_int_add(json_vni
, "numMacs",
1972 hashcount(zl3vni
->rmac_table
));
1973 json_object_int_add(json_vni
, "numArpNd",
1974 hashcount(zl3vni
->nh_table
));
1975 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1976 json_object_string_add(json_vni
, "type", "L3");
1977 json_object_string_add(json_vni
, "tenantVrf",
1978 zl3vni_vrf_name(zl3vni
));
1979 json_object_object_add(json
, vni_str
, json_vni
);
1983 /* Private Structure to pass callback data for hash iterator */
1984 struct zvni_evpn_show
{
1987 struct zebra_vrf
*zvrf
;
1990 /* print a L3 VNI hash entry in detail*/
1991 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1993 struct vty
*vty
= NULL
;
1994 zebra_l3vni_t
*zl3vni
= NULL
;
1995 json_object
*json
= NULL
;
1996 bool use_json
= false;
1997 struct zvni_evpn_show
*zes
= data
;
2005 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2007 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2013 * Print a VNI hash entry - called for display of all VNIs.
2015 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2019 zebra_vtep_t
*zvtep
;
2020 uint32_t num_vteps
= 0;
2021 uint32_t num_macs
= 0;
2022 uint32_t num_neigh
= 0;
2023 json_object
*json
= NULL
;
2024 json_object
*json_vni
= NULL
;
2025 json_object
*json_ip_str
= NULL
;
2026 json_object
*json_vtep_list
= NULL
;
2031 zvni
= (zebra_vni_t
*)bucket
->data
;
2033 zvtep
= zvni
->vteps
;
2036 zvtep
= zvtep
->next
;
2039 num_macs
= num_valid_macs(zvni
);
2040 num_neigh
= hashcount(zvni
->neigh_table
);
2042 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2044 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2045 num_macs
, num_neigh
, num_vteps
,
2046 vrf_id_to_name(zvni
->vrf_id
));
2048 char vni_str
[VNI_STR_LEN
];
2049 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2050 json_vni
= json_object_new_object();
2051 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2052 json_object_string_add(json_vni
, "type", "L2");
2053 json_object_string_add(json_vni
, "vxlanIf",
2054 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2056 json_object_int_add(json_vni
, "numMacs", num_macs
);
2057 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2058 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2059 json_object_string_add(json_vni
, "tenantVrf",
2060 vrf_id_to_name(zvni
->vrf_id
));
2062 json_vtep_list
= json_object_new_array();
2063 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2064 json_ip_str
= json_object_new_string(
2065 inet_ntoa(zvtep
->vtep_ip
));
2066 json_object_array_add(json_vtep_list
,
2069 json_object_object_add(json_vni
, "remoteVteps",
2072 json_object_object_add(json
, vni_str
, json_vni
);
2077 * Print a VNI hash entry in detail - called for display of all VNIs.
2079 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2083 json_object
*json
= NULL
;
2084 bool use_json
= false;
2085 struct zvni_evpn_show
*zes
= data
;
2093 zvni
= (zebra_vni_t
*)bucket
->data
;
2095 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2100 * Inform BGP about local MACIP.
2102 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2103 struct ipaddr
*ip
, uint8_t flags
,
2104 uint32_t seq
, int state
, uint16_t cmd
)
2106 char buf
[ETHER_ADDR_STRLEN
];
2107 char buf2
[INET6_ADDRSTRLEN
];
2109 struct zserv
*client
= NULL
;
2110 struct stream
*s
= NULL
;
2112 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2113 /* BGP may not be running. */
2117 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2119 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2120 stream_putl(s
, vni
);
2121 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2124 if (IS_IPADDR_V4(ip
))
2125 ipa_len
= IPV4_MAX_BYTELEN
;
2126 else if (IS_IPADDR_V6(ip
))
2127 ipa_len
= IPV6_MAX_BYTELEN
;
2129 stream_putl(s
, ipa_len
); /* IP address length */
2131 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2133 stream_putl(s
, 0); /* Just MAC. */
2135 if (cmd
== ZEBRA_MACIP_ADD
) {
2136 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2137 stream_putl(s
, seq
); /* sequence number */
2139 stream_putl(s
, state
); /* state - active/inactive */
2143 /* Write packet size. */
2144 stream_putw_at(s
, 0, stream_get_endp(s
));
2146 if (IS_ZEBRA_DEBUG_VXLAN
)
2148 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2149 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2150 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2151 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2152 zebra_route_string(client
->proto
));
2154 if (cmd
== ZEBRA_MACIP_ADD
)
2155 client
->macipadd_cnt
++;
2157 client
->macipdel_cnt
++;
2159 return zserv_send_message(client
, s
);
2163 * Make hash key for neighbors.
2165 static unsigned int neigh_hash_keymake(const void *p
)
2167 const zebra_neigh_t
*n
= p
;
2168 const struct ipaddr
*ip
= &n
->ip
;
2170 if (IS_IPADDR_V4(ip
))
2171 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2173 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2174 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2178 * Compare two neighbor hash structures.
2180 static bool neigh_cmp(const void *p1
, const void *p2
)
2182 const zebra_neigh_t
*n1
= p1
;
2183 const zebra_neigh_t
*n2
= p2
;
2185 if (n1
== NULL
&& n2
== NULL
)
2188 if (n1
== NULL
|| n2
== NULL
)
2191 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2194 static int neigh_list_cmp(void *p1
, void *p2
)
2196 const zebra_neigh_t
*n1
= p1
;
2197 const zebra_neigh_t
*n2
= p2
;
2199 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2203 * Callback to allocate neighbor hash entry.
2205 static void *zvni_neigh_alloc(void *p
)
2207 const zebra_neigh_t
*tmp_n
= p
;
2210 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2217 * Add neighbor entry.
2219 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2220 struct ethaddr
*mac
)
2222 zebra_neigh_t tmp_n
;
2223 zebra_neigh_t
*n
= NULL
;
2224 zebra_mac_t
*zmac
= NULL
;
2226 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2227 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2228 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2231 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2232 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2234 n
->dad_ip_auto_recovery_timer
= NULL
;
2236 /* Associate the neigh to mac */
2237 zmac
= zvni_mac_lookup(zvni
, mac
);
2239 listnode_add_sort(zmac
->neigh_list
, n
);
2245 * Delete neighbor entry.
2247 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2249 zebra_neigh_t
*tmp_n
;
2250 zebra_mac_t
*zmac
= NULL
;
2252 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2254 listnode_delete(zmac
->neigh_list
, n
);
2256 /* Cancel auto recovery */
2257 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2259 /* Free the VNI hash entry and allocated memory. */
2260 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2261 XFREE(MTYPE_NEIGH
, tmp_n
);
2267 * Free neighbor hash entry (callback)
2269 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2271 struct neigh_walk_ctx
*wctx
= arg
;
2272 zebra_neigh_t
*n
= bucket
->data
;
2274 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2275 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2276 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2277 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2278 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2279 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2280 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2281 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2282 &n
->emac
, 0, n
->state
);
2284 if (wctx
->uninstall
)
2285 zvni_neigh_uninstall(wctx
->zvni
, n
);
2287 zvni_neigh_del(wctx
->zvni
, n
);
2294 * Delete all neighbor entries from specific VTEP for a particular VNI.
2296 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2297 struct in_addr
*r_vtep_ip
)
2299 struct neigh_walk_ctx wctx
;
2301 if (!zvni
->neigh_table
)
2304 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2306 wctx
.uninstall
= uninstall
;
2307 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2308 wctx
.r_vtep_ip
= *r_vtep_ip
;
2310 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2314 * Delete all neighbor entries for this VNI.
2316 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2319 struct neigh_walk_ctx wctx
;
2321 if (!zvni
->neigh_table
)
2324 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2326 wctx
.uninstall
= uninstall
;
2327 wctx
.upd_client
= upd_client
;
2330 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2334 * Look up neighbor hash entry.
2336 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2341 memset(&tmp
, 0, sizeof(tmp
));
2342 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2343 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2349 * Process all neighbors associated with a MAC upon the MAC being learnt
2350 * locally or undergoing any other change (such as sequence number).
2352 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2356 zebra_neigh_t
*n
= NULL
;
2357 struct listnode
*node
= NULL
;
2358 struct zebra_vrf
*zvrf
= NULL
;
2359 char buf
[ETHER_ADDR_STRLEN
];
2361 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2363 if (IS_ZEBRA_DEBUG_VXLAN
)
2364 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2365 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2366 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2368 /* Walk all neighbors and mark any inactive local neighbors as
2369 * active and/or update sequence number upon a move, and inform BGP.
2370 * The action for remote neighbors is TBD.
2371 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2372 * accidentally end up deleting a just-learnt local neighbor.
2374 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2375 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2376 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2377 ZEBRA_NEIGH_SET_ACTIVE(n
);
2378 n
->loc_seq
= zmac
->loc_seq
;
2379 if (!(zvrf
->dup_addr_detect
&&
2380 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2381 ZEBRA_NEIGH_DUPLICATE
)))
2382 zvni_neigh_send_add_to_client(
2383 zvni
->vni
, &n
->ip
, &n
->emac
,
2384 n
->flags
, n
->loc_seq
);
2391 * Process all neighbors associated with a local MAC upon the MAC being
2394 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2397 zebra_neigh_t
*n
= NULL
;
2398 struct listnode
*node
= NULL
;
2399 char buf
[ETHER_ADDR_STRLEN
];
2401 if (IS_ZEBRA_DEBUG_VXLAN
)
2402 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2403 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2406 /* Walk all local neighbors and mark as inactive and inform
2408 * TBD: There is currently no handling for remote neighbors. We
2409 * don't expect them to exist, if they do, do we install the MAC
2410 * as a remote MAC and the neighbor as remote?
2412 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2413 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2414 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2415 ZEBRA_NEIGH_SET_INACTIVE(n
);
2417 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2418 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2425 * Process all neighbors associated with a MAC upon the MAC being remotely
2428 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2431 zebra_neigh_t
*n
= NULL
;
2432 struct listnode
*node
= NULL
;
2433 char buf
[ETHER_ADDR_STRLEN
];
2435 if (IS_ZEBRA_DEBUG_VXLAN
)
2436 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2437 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2440 /* Walk all local neighbors and mark as inactive and inform
2443 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2444 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2445 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2446 ZEBRA_NEIGH_SET_INACTIVE(n
);
2448 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2449 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2456 * Process all neighbors associated with a remote MAC upon the MAC being
2459 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2462 /* NOTE: Currently a NO-OP. */
2465 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2467 zebra_neigh_t
*nbr
= NULL
;
2468 struct listnode
*node
= NULL
;
2470 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2471 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2472 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2473 zvni_neigh_probe(zvni
, nbr
);
2478 * Inform BGP about local neighbor addition.
2480 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2481 struct ethaddr
*macaddr
,
2482 uint8_t neigh_flags
,
2487 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2488 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2489 /* Set router flag (R-bit) based on local neigh entry add */
2490 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2491 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2493 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2494 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2498 * Inform BGP about local neighbor deletion.
2500 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2501 struct ethaddr
*macaddr
, uint8_t flags
,
2504 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2505 0, state
, ZEBRA_MACIP_DEL
);
2509 * Install remote neighbor into the kernel.
2511 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2513 struct zebra_if
*zif
;
2514 struct zebra_l2info_vxlan
*vxl
;
2515 struct interface
*vlan_if
;
2521 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2524 zif
= zvni
->vxlan_if
->info
;
2527 vxl
= &zif
->l2info
.vxl
;
2529 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2533 flags
= NTF_EXT_LEARNED
;
2534 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2535 flags
|= NTF_ROUTER
;
2536 ZEBRA_NEIGH_SET_ACTIVE(n
);
2537 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2543 * Uninstall remote neighbor from the kernel.
2545 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2547 struct zebra_if
*zif
;
2548 struct zebra_l2info_vxlan
*vxl
;
2549 struct interface
*vlan_if
;
2551 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2554 if (!zvni
->vxlan_if
) {
2555 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2560 zif
= zvni
->vxlan_if
->info
;
2563 vxl
= &zif
->l2info
.vxl
;
2564 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2568 ZEBRA_NEIGH_SET_INACTIVE(n
);
2570 return kernel_del_neigh(vlan_if
, &n
->ip
);
2574 * Probe neighbor from the kernel.
2576 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2578 struct zebra_if
*zif
;
2579 struct zebra_l2info_vxlan
*vxl
;
2580 struct interface
*vlan_if
;
2582 zif
= zvni
->vxlan_if
->info
;
2585 vxl
= &zif
->l2info
.vxl
;
2587 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2592 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2600 * Install neighbor hash entry - called upon access VLAN change.
2602 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2605 struct neigh_walk_ctx
*wctx
= ctxt
;
2607 n
= (zebra_neigh_t
*)bucket
->data
;
2609 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2610 zvni_neigh_install(wctx
->zvni
, n
);
2613 /* Get the VRR interface for SVI if any */
2614 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2616 struct zebra_vrf
*zvrf
= NULL
;
2617 struct interface
*tmp_if
= NULL
;
2618 struct zebra_if
*zif
= NULL
;
2620 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2623 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2628 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2631 if (zif
->link
== ifp
)
2638 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2640 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2641 struct connected
*c
= NULL
;
2642 struct ethaddr macaddr
;
2644 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2646 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2649 memset(&ip
, 0, sizeof(struct ipaddr
));
2650 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2653 if (c
->address
->family
== AF_INET
) {
2654 ip
.ipa_type
= IPADDR_V4
;
2655 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2656 sizeof(struct in_addr
));
2657 } else if (c
->address
->family
== AF_INET6
) {
2658 ip
.ipa_type
= IPADDR_V6
;
2659 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2660 sizeof(struct in6_addr
));
2665 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2671 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2673 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2674 struct connected
*c
= NULL
;
2675 struct ethaddr macaddr
;
2677 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2679 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2682 memset(&ip
, 0, sizeof(struct ipaddr
));
2683 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2686 if (c
->address
->family
== AF_INET
) {
2687 ip
.ipa_type
= IPADDR_V4
;
2688 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2689 sizeof(struct in_addr
));
2690 } else if (c
->address
->family
== AF_INET6
) {
2691 ip
.ipa_type
= IPADDR_V6
;
2692 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2693 sizeof(struct in6_addr
));
2698 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2704 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2707 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2708 struct connected
*c
= NULL
;
2709 struct ethaddr macaddr
;
2711 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2713 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2716 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2718 /* skip link local address */
2719 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2724 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2725 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2727 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2728 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2734 * zvni_gw_macip_add_to_client
2736 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2737 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2739 char buf
[ETHER_ADDR_STRLEN
];
2740 char buf2
[INET6_ADDRSTRLEN
];
2741 zebra_neigh_t
*n
= NULL
;
2742 zebra_mac_t
*mac
= NULL
;
2743 struct zebra_if
*zif
= NULL
;
2744 struct zebra_l2info_vxlan
*vxl
= NULL
;
2746 zif
= zvni
->vxlan_if
->info
;
2750 vxl
= &zif
->l2info
.vxl
;
2752 mac
= zvni_mac_lookup(zvni
, macaddr
);
2754 mac
= zvni_mac_add(zvni
, macaddr
);
2756 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2757 "Failed to add MAC %s intf %s(%u) VID %u",
2758 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2759 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2764 /* Set "local" forwarding info. */
2765 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2766 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2767 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2768 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2769 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2770 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2772 n
= zvni_neigh_lookup(zvni
, ip
);
2774 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2777 EC_ZEBRA_MAC_ADD_FAILED
,
2778 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2779 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2780 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2781 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2786 /* Set "local" forwarding info. */
2787 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2788 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2789 ZEBRA_NEIGH_SET_ACTIVE(n
);
2790 /* Set Router flag (R-bit) */
2791 if (ip
->ipa_type
== IPADDR_V6
)
2792 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2793 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2794 n
->ifindex
= ifp
->ifindex
;
2796 /* Only advertise in BGP if the knob is enabled */
2797 if (!advertise_gw_macip_enabled(zvni
))
2800 if (IS_ZEBRA_DEBUG_VXLAN
)
2802 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2803 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2804 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2805 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2807 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2808 n
->flags
, n
->loc_seq
);
2814 * zvni_gw_macip_del_from_client
2816 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2819 char buf1
[ETHER_ADDR_STRLEN
];
2820 char buf2
[INET6_ADDRSTRLEN
];
2821 zebra_neigh_t
*n
= NULL
;
2822 zebra_mac_t
*mac
= NULL
;
2824 /* If the neigh entry is not present nothing to do*/
2825 n
= zvni_neigh_lookup(zvni
, ip
);
2829 /* mac entry should be present */
2830 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2832 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2833 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2834 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2838 /* If the entry is not local nothing to do*/
2839 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2842 /* only need to delete the entry from bgp if we sent it before */
2843 if (IS_ZEBRA_DEBUG_VXLAN
)
2845 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2846 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2847 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2848 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2850 /* Remove neighbor from BGP. */
2851 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2852 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2854 /* Delete this neighbor entry. */
2855 zvni_neigh_del(zvni
, n
);
2857 /* see if the mac needs to be deleted as well*/
2859 zvni_deref_ip2mac(zvni
, mac
);
2864 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2867 zebra_vni_t
*zvni
= NULL
;
2868 struct zebra_if
*zif
= NULL
;
2869 struct zebra_l2info_vxlan zl2_info
;
2870 struct interface
*vlan_if
= NULL
;
2871 struct interface
*vrr_if
= NULL
;
2872 struct interface
*ifp
;
2874 /* Add primary SVI MAC*/
2875 zvni
= (zebra_vni_t
*)bucket
->data
;
2877 ifp
= zvni
->vxlan_if
;
2882 /* If down or not mapped to a bridge, we're done. */
2883 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2886 zl2_info
= zif
->l2info
.vxl
;
2889 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2893 /* Del primary MAC-IP */
2894 zvni_del_macip_for_intf(vlan_if
, zvni
);
2896 /* Del VRR MAC-IP - if any*/
2897 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2899 zvni_del_macip_for_intf(vrr_if
, zvni
);
2904 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2907 zebra_vni_t
*zvni
= NULL
;
2908 struct zebra_if
*zif
= NULL
;
2909 struct zebra_l2info_vxlan zl2_info
;
2910 struct interface
*vlan_if
= NULL
;
2911 struct interface
*vrr_if
= NULL
;
2912 struct interface
*ifp
= NULL
;
2914 zvni
= (zebra_vni_t
*)bucket
->data
;
2916 ifp
= zvni
->vxlan_if
;
2921 /* If down or not mapped to a bridge, we're done. */
2922 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2924 zl2_info
= zif
->l2info
.vxl
;
2927 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2931 /* Add primary SVI MAC-IP */
2932 zvni_add_macip_for_intf(vlan_if
, zvni
);
2934 if (advertise_gw_macip_enabled(zvni
)) {
2935 /* Add VRR MAC-IP - if any*/
2936 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2938 zvni_add_macip_for_intf(vrr_if
, zvni
);
2944 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2947 zebra_vni_t
*zvni
= NULL
;
2948 struct zebra_if
*zif
= NULL
;
2949 struct zebra_l2info_vxlan zl2_info
;
2950 struct interface
*vlan_if
= NULL
;
2951 struct interface
*ifp
;
2953 /* Add primary SVI MAC*/
2954 zvni
= (zebra_vni_t
*)bucket
->data
;
2958 ifp
= zvni
->vxlan_if
;
2963 /* If down or not mapped to a bridge, we're done. */
2964 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2967 zl2_info
= zif
->l2info
.vxl
;
2969 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2970 zif
->brslave_info
.br_if
);
2974 /* Del primary MAC-IP */
2975 zvni_del_macip_for_intf(vlan_if
, zvni
);
2980 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2981 struct interface
*ifp
,
2983 struct ethaddr
*macaddr
,
2986 char buf
[ETHER_ADDR_STRLEN
];
2987 char buf2
[INET6_ADDRSTRLEN
];
2988 struct zebra_vrf
*zvrf
;
2989 zebra_neigh_t
*n
= NULL
;
2990 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2991 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2992 bool upd_mac_seq
= false;
2993 bool neigh_mac_change
= false;
2994 bool neigh_on_hold
= false;
2995 bool neigh_was_remote
= false;
2996 bool do_dad
= false;
2997 struct in_addr vtep_ip
= {.s_addr
= 0};
2999 /* Check if the MAC exists. */
3000 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3002 /* create a dummy MAC if the MAC is not already present */
3003 if (IS_ZEBRA_DEBUG_VXLAN
)
3005 "AUTO MAC %s created for neigh %s on VNI %u",
3006 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3007 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3009 zmac
= zvni_mac_add(zvni
, macaddr
);
3011 zlog_debug("Failed to add MAC %s VNI %u",
3012 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3017 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3018 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3019 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3021 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3023 * We don't change the MAC to local upon a neighbor
3024 * learn event, we wait for the explicit local MAC
3025 * learn. However, we have to compute its sequence
3026 * number in preparation for when it actually turns
3033 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3035 if (IS_ZEBRA_DEBUG_VXLAN
)
3036 zlog_debug("\tUnable to find vrf for: %d",
3037 zvni
->vxlan_if
->vrf_id
);
3041 /* Check if the neighbor exists. */
3042 n
= zvni_neigh_lookup(zvni
, ip
);
3044 /* New neighbor - create */
3045 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3048 EC_ZEBRA_MAC_ADD_FAILED
,
3049 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3050 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3051 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3052 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3055 /* Set "local" forwarding info. */
3056 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3057 n
->ifindex
= ifp
->ifindex
;
3059 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3063 /* Note any changes and see if of interest to BGP. */
3064 mac_different
= (memcmp(n
->emac
.octet
,
3065 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3066 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3067 ZEBRA_NEIGH_ROUTER_FLAG
);
3068 if (!mac_different
&& is_router
== cur_is_router
) {
3069 if (IS_ZEBRA_DEBUG_VXLAN
)
3071 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3072 n
->ifindex
= ifp
->ifindex
;
3076 if (!mac_different
) {
3077 bool is_neigh_freezed
= false;
3079 /* Only the router flag has changed. */
3082 ZEBRA_NEIGH_ROUTER_FLAG
);
3084 UNSET_FLAG(n
->flags
,
3085 ZEBRA_NEIGH_ROUTER_FLAG
);
3087 /* Neigh is in freeze state and freeze action
3088 * is enabled, do not send update to client.
3090 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3092 CHECK_FLAG(n
->flags
,
3093 ZEBRA_NEIGH_DUPLICATE
));
3095 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3097 return zvni_neigh_send_add_to_client(
3098 zvni
->vni
, ip
, macaddr
,
3099 n
->flags
, n
->loc_seq
);
3101 if (IS_ZEBRA_DEBUG_VXLAN
)
3103 "\tNeighbor active and frozen");
3108 /* The MAC has changed, need to issue a delete
3109 * first as this means a different MACIP route.
3110 * Also, need to do some unlinking/relinking.
3111 * We also need to update the MAC's sequence number
3112 * in different situations.
3114 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3115 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3116 &n
->emac
, 0, n
->state
);
3117 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3119 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3121 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3122 neigh_mac_change
= upd_mac_seq
= true;
3123 listnode_delete(old_zmac
->neigh_list
, n
);
3124 zvni_deref_ip2mac(zvni
, old_zmac
);
3127 /* Update the forwarding info. */
3128 n
->ifindex
= ifp
->ifindex
;
3129 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3131 /* Link to new MAC */
3132 listnode_add_sort(zmac
->neigh_list
, n
);
3133 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3135 * Neighbor has moved from remote to local. Its
3136 * MAC could have also changed as part of the move.
3138 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3140 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3142 old_mac_seq
= CHECK_FLAG(
3147 neigh_mac_change
= upd_mac_seq
= true;
3148 listnode_delete(old_zmac
->neigh_list
,
3150 zvni_deref_ip2mac(zvni
, old_zmac
);
3153 /* Link to new MAC */
3154 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3155 listnode_add_sort(zmac
->neigh_list
, n
);
3157 /* Based on Mobility event Scenario-B from the
3158 * draft, neigh's previous state was remote treat this
3161 neigh_was_remote
= true;
3162 vtep_ip
= n
->r_vtep_ip
;
3163 /* Mark appropriately */
3164 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3165 n
->r_vtep_ip
.s_addr
= 0;
3166 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3167 n
->ifindex
= ifp
->ifindex
;
3171 /* If MAC was previously remote, or the neighbor had a different
3172 * MAC earlier, recompute the sequence number.
3175 uint32_t seq1
, seq2
;
3177 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3178 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3179 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3180 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3181 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3184 /* Mark Router flag (R-bit) */
3186 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3188 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3190 /* Check old and/or new MAC detected as duplicate mark
3191 * the neigh as duplicate
3193 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3194 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3195 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3197 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3198 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3201 /* For IP Duplicate Address Detection (DAD) is trigger,
3202 * when the event is extended mobility based on scenario-B
3203 * from the draft, IP/Neigh's MAC binding changed and
3204 * neigh's previous state was remote.
3206 if (neigh_mac_change
&& neigh_was_remote
)
3209 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3210 &neigh_on_hold
, true);
3212 /* Before we program this in BGP, we need to check if MAC is locally
3213 * learnt. If not, force neighbor to be inactive and reset its seq.
3215 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3216 ZEBRA_NEIGH_SET_INACTIVE(n
);
3218 zmac
->loc_seq
= mac_new_seq
;
3222 /* If the MAC's sequence number has changed, inform the MAC and all
3223 * neighbors associated with the MAC to BGP, else just inform this
3226 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3227 if (IS_ZEBRA_DEBUG_VXLAN
)
3228 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3229 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3230 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3231 zmac
->loc_seq
= mac_new_seq
;
3232 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3233 zmac
->flags
, zmac
->loc_seq
))
3235 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3239 n
->loc_seq
= zmac
->loc_seq
;
3241 if (!neigh_on_hold
) {
3242 ZEBRA_NEIGH_SET_ACTIVE(n
);
3244 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3245 n
->flags
, n
->loc_seq
);
3247 if (IS_ZEBRA_DEBUG_VXLAN
)
3248 zlog_debug("\tNeighbor on hold not sending");
3253 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3254 struct interface
*ifp
,
3256 struct ethaddr
*macaddr
,
3259 char buf
[ETHER_ADDR_STRLEN
];
3260 char buf2
[INET6_ADDRSTRLEN
];
3261 zebra_neigh_t
*n
= NULL
;
3262 zebra_mac_t
*zmac
= NULL
;
3264 /* If the neighbor is unknown, there is no further action. */
3265 n
= zvni_neigh_lookup(zvni
, ip
);
3269 /* If a remote entry, see if it needs to be refreshed */
3270 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3272 if (state
& NUD_STALE
)
3273 zvni_neigh_install(zvni
, n
);
3276 /* We got a "remote" neighbor notification for an entry
3277 * we think is local. This can happen in a multihoming
3278 * scenario - but only if the MAC is already "remote".
3279 * Just mark our entry as "remote".
3281 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3282 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3284 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3285 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3286 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3291 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3292 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3293 ZEBRA_NEIGH_SET_ACTIVE(n
);
3294 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3301 * Make hash key for MAC.
3303 static unsigned int mac_hash_keymake(const void *p
)
3305 const zebra_mac_t
*pmac
= p
;
3306 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3308 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3312 * Compare two MAC addresses.
3314 static bool mac_cmp(const void *p1
, const void *p2
)
3316 const zebra_mac_t
*pmac1
= p1
;
3317 const zebra_mac_t
*pmac2
= p2
;
3319 if (pmac1
== NULL
&& pmac2
== NULL
)
3322 if (pmac1
== NULL
|| pmac2
== NULL
)
3325 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3330 * Callback to allocate MAC hash entry.
3332 static void *zvni_mac_alloc(void *p
)
3334 const zebra_mac_t
*tmp_mac
= p
;
3337 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3340 return ((void *)mac
);
3346 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3348 zebra_mac_t tmp_mac
;
3349 zebra_mac_t
*mac
= NULL
;
3351 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3352 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3353 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3357 mac
->dad_mac_auto_recovery_timer
= NULL
;
3359 mac
->neigh_list
= list_new();
3360 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3368 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3370 zebra_mac_t
*tmp_mac
;
3372 /* Cancel auto recovery */
3373 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3375 list_delete(&mac
->neigh_list
);
3377 /* Free the VNI hash entry and allocated memory. */
3378 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3379 XFREE(MTYPE_MAC
, tmp_mac
);
3385 * Free MAC hash entry (callback)
3387 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3389 struct mac_walk_ctx
*wctx
= arg
;
3390 zebra_mac_t
*mac
= bucket
->data
;
3392 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3393 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3394 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3395 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3396 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3397 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3398 &wctx
->r_vtep_ip
))) {
3399 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3400 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3404 if (wctx
->uninstall
)
3405 zvni_mac_uninstall(wctx
->zvni
, mac
);
3407 zvni_mac_del(wctx
->zvni
, mac
);
3414 * Delete all MAC entries from specific VTEP for a particular VNI.
3416 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3417 struct in_addr
*r_vtep_ip
)
3419 struct mac_walk_ctx wctx
;
3421 if (!zvni
->mac_table
)
3424 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3426 wctx
.uninstall
= uninstall
;
3427 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3428 wctx
.r_vtep_ip
= *r_vtep_ip
;
3430 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3434 * Delete all MAC entries for this VNI.
3436 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3439 struct mac_walk_ctx wctx
;
3441 if (!zvni
->mac_table
)
3444 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3446 wctx
.uninstall
= uninstall
;
3447 wctx
.upd_client
= upd_client
;
3450 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3454 * Look up MAC hash entry.
3456 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3461 memset(&tmp
, 0, sizeof(tmp
));
3462 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3463 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3469 * Inform BGP about local MAC addition.
3471 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3472 uint8_t mac_flags
, uint32_t seq
)
3476 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3477 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3478 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3479 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3481 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3482 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3486 * Inform BGP about local MAC deletion.
3488 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3490 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3491 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3495 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3496 * notifications, to see if they are of interest.
3498 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3499 struct interface
*br_if
, vlanid_t vid
)
3501 struct zebra_ns
*zns
;
3502 struct route_node
*rn
;
3503 struct interface
*tmp_if
= NULL
;
3504 struct zebra_if
*zif
;
3505 struct zebra_l2info_bridge
*br
;
3506 struct zebra_l2info_vxlan
*vxl
= NULL
;
3507 uint8_t bridge_vlan_aware
;
3511 /* Determine if bridge is VLAN-aware or not */
3514 br
= &zif
->l2info
.br
;
3515 bridge_vlan_aware
= br
->vlan_aware
;
3517 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3518 /* TODO: Optimize with a hash. */
3519 zns
= zebra_ns_lookup(NS_DEFAULT
);
3520 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3521 tmp_if
= (struct interface
*)rn
->info
;
3525 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3527 if (!if_is_operative(tmp_if
))
3529 vxl
= &zif
->l2info
.vxl
;
3531 if (zif
->brslave_info
.br_if
!= br_if
)
3534 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3543 zvni
= zvni_lookup(vxl
->vni
);
3548 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3549 * neighbor notifications, to see if they are of interest.
3551 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3552 struct interface
*br_if
)
3554 struct zebra_ns
*zns
;
3555 struct route_node
*rn
;
3556 struct interface
*tmp_if
= NULL
;
3557 struct zebra_if
*zif
;
3558 struct zebra_l2info_bridge
*br
;
3559 struct zebra_l2info_vxlan
*vxl
= NULL
;
3560 uint8_t bridge_vlan_aware
;
3568 /* Make sure the linked interface is a bridge. */
3569 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3572 /* Determine if bridge is VLAN-aware or not */
3575 br
= &zif
->l2info
.br
;
3576 bridge_vlan_aware
= br
->vlan_aware
;
3577 if (bridge_vlan_aware
) {
3578 struct zebra_l2info_vlan
*vl
;
3580 if (!IS_ZEBRA_IF_VLAN(ifp
))
3585 vl
= &zif
->l2info
.vl
;
3589 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3590 /* TODO: Optimize with a hash. */
3591 zns
= zebra_ns_lookup(NS_DEFAULT
);
3592 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3593 tmp_if
= (struct interface
*)rn
->info
;
3597 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3599 if (!if_is_operative(tmp_if
))
3601 vxl
= &zif
->l2info
.vxl
;
3603 if (zif
->brslave_info
.br_if
!= br_if
)
3606 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3615 zvni
= zvni_lookup(vxl
->vni
);
3619 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3621 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3622 * linked to the bridge
3623 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3626 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3628 struct zebra_ns
*zns
;
3629 struct route_node
*rn
;
3630 struct interface
*tmp_if
= NULL
;
3631 struct zebra_if
*zif
;
3632 struct zebra_l2info_bridge
*br
;
3633 struct zebra_l2info_vlan
*vl
;
3634 uint8_t bridge_vlan_aware
;
3637 /* Defensive check, caller expected to invoke only with valid bridge. */
3641 /* Determine if bridge is VLAN-aware or not */
3644 br
= &zif
->l2info
.br
;
3645 bridge_vlan_aware
= br
->vlan_aware
;
3647 /* Check oper status of the SVI. */
3648 if (!bridge_vlan_aware
)
3649 return if_is_operative(br_if
) ? br_if
: NULL
;
3651 /* Identify corresponding VLAN interface. */
3652 /* TODO: Optimize with a hash. */
3653 zns
= zebra_ns_lookup(NS_DEFAULT
);
3654 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3655 tmp_if
= (struct interface
*)rn
->info
;
3656 /* Check oper status of the SVI. */
3657 if (!tmp_if
|| !if_is_operative(tmp_if
))
3660 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3661 || zif
->link
!= br_if
)
3663 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3665 if (vl
->vid
== vid
) {
3671 return found
? tmp_if
: NULL
;
3675 * Install remote MAC into the kernel.
3677 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3679 struct zebra_if
*zif
;
3680 struct zebra_l2info_vxlan
*vxl
;
3683 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3686 zif
= zvni
->vxlan_if
->info
;
3689 vxl
= &zif
->l2info
.vxl
;
3691 sticky
= !!CHECK_FLAG(mac
->flags
,
3692 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3694 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3695 mac
->fwd_info
.r_vtep_ip
, sticky
);
3699 * Uninstall remote MAC from the kernel.
3701 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3703 struct zebra_if
*zif
;
3704 struct zebra_l2info_vxlan
*vxl
;
3705 struct in_addr vtep_ip
;
3706 struct interface
*ifp
;
3708 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3711 if (!zvni
->vxlan_if
) {
3712 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3717 zif
= zvni
->vxlan_if
->info
;
3720 vxl
= &zif
->l2info
.vxl
;
3722 ifp
= zvni
->vxlan_if
;
3723 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3725 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3729 * Install MAC hash entry - called upon access VLAN change.
3731 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3734 struct mac_walk_ctx
*wctx
= ctxt
;
3736 mac
= (zebra_mac_t
*)bucket
->data
;
3738 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3739 zvni_mac_install(wctx
->zvni
, mac
);
3743 * Count of remote neighbors referencing this MAC.
3745 static int remote_neigh_count(zebra_mac_t
*zmac
)
3747 zebra_neigh_t
*n
= NULL
;
3748 struct listnode
*node
= NULL
;
3751 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3752 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3760 * Decrement neighbor refcount of MAC; uninstall and free it if
3763 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3765 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3768 /* If all remote neighbors referencing a remote MAC go away,
3769 * we need to uninstall the MAC.
3771 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3772 remote_neigh_count(mac
) == 0) {
3773 zvni_mac_uninstall(zvni
, mac
);
3774 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3777 /* If no neighbors, delete the MAC. */
3778 if (list_isempty(mac
->neigh_list
))
3779 zvni_mac_del(zvni
, mac
);
3783 * Read and populate local MACs and neighbors corresponding to this VNI.
3785 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3787 struct zebra_ns
*zns
;
3788 struct zebra_if
*zif
;
3789 struct interface
*vlan_if
;
3790 struct zebra_l2info_vxlan
*vxl
;
3791 struct interface
*vrr_if
;
3794 vxl
= &zif
->l2info
.vxl
;
3795 zns
= zebra_ns_lookup(NS_DEFAULT
);
3797 if (IS_ZEBRA_DEBUG_VXLAN
)
3799 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3800 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3801 zif
->brslave_info
.bridge_ifindex
);
3803 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3804 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3807 /* Add SVI MAC-IP */
3808 zvni_add_macip_for_intf(vlan_if
, zvni
);
3810 /* Add VRR MAC-IP - if any*/
3811 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3813 zvni_add_macip_for_intf(vrr_if
, zvni
);
3815 neigh_read_for_vlan(zns
, vlan_if
);
3820 * Hash function for VNI.
3822 static unsigned int vni_hash_keymake(const void *p
)
3824 const zebra_vni_t
*zvni
= p
;
3826 return (jhash_1word(zvni
->vni
, 0));
3830 * Compare 2 VNI hash entries.
3832 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3834 const zebra_vni_t
*zvni1
= p1
;
3835 const zebra_vni_t
*zvni2
= p2
;
3837 return (zvni1
->vni
== zvni2
->vni
);
3840 static int vni_list_cmp(void *p1
, void *p2
)
3842 const zebra_vni_t
*zvni1
= p1
;
3843 const zebra_vni_t
*zvni2
= p2
;
3845 if (zvni1
->vni
== zvni2
->vni
)
3847 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3851 * Callback to allocate VNI hash entry.
3853 static void *zvni_alloc(void *p
)
3855 const zebra_vni_t
*tmp_vni
= p
;
3858 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3859 zvni
->vni
= tmp_vni
->vni
;
3860 return ((void *)zvni
);
3864 * Look up VNI hash entry.
3866 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3868 struct zebra_vrf
*zvrf
;
3869 zebra_vni_t tmp_vni
;
3870 zebra_vni_t
*zvni
= NULL
;
3872 zvrf
= zebra_vrf_get_evpn();
3874 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3876 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3882 * Add VNI hash entry.
3884 static zebra_vni_t
*zvni_add(vni_t vni
)
3886 struct zebra_vrf
*zvrf
;
3887 zebra_vni_t tmp_zvni
;
3888 zebra_vni_t
*zvni
= NULL
;
3890 zvrf
= zebra_vrf_get_evpn();
3892 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3894 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3897 /* Create hash table for MAC */
3899 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3901 /* Create hash table for neighbors */
3902 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3903 "Zebra VNI Neighbor Table");
3909 * Delete VNI hash entry.
3911 static int zvni_del(zebra_vni_t
*zvni
)
3913 struct zebra_vrf
*zvrf
;
3914 zebra_vni_t
*tmp_zvni
;
3916 zvrf
= zebra_vrf_get_evpn();
3919 zvni
->vxlan_if
= NULL
;
3921 /* Remove references to the BUM mcast grp */
3922 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3924 /* Free the neighbor hash table. */
3925 hash_free(zvni
->neigh_table
);
3926 zvni
->neigh_table
= NULL
;
3928 /* Free the MAC hash table. */
3929 hash_free(zvni
->mac_table
);
3930 zvni
->mac_table
= NULL
;
3932 /* Free the VNI hash entry and allocated memory. */
3933 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3934 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3940 * Inform BGP about local VNI addition.
3942 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3944 struct zserv
*client
;
3947 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3948 /* BGP may not be running. */
3952 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3954 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3955 stream_putl(s
, zvni
->vni
);
3956 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3957 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3958 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3960 /* Write packet size. */
3961 stream_putw_at(s
, 0, stream_get_endp(s
));
3963 if (IS_ZEBRA_DEBUG_VXLAN
)
3964 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3965 inet_ntoa(zvni
->local_vtep_ip
),
3966 vrf_id_to_name(zvni
->vrf_id
),
3967 zebra_route_string(client
->proto
));
3969 client
->vniadd_cnt
++;
3970 return zserv_send_message(client
, s
);
3974 * Inform BGP about local VNI deletion.
3976 static int zvni_send_del_to_client(vni_t vni
)
3978 struct zserv
*client
;
3981 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3982 /* BGP may not be running. */
3986 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3989 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3990 stream_putl(s
, vni
);
3992 /* Write packet size. */
3993 stream_putw_at(s
, 0, stream_get_endp(s
));
3995 if (IS_ZEBRA_DEBUG_VXLAN
)
3996 zlog_debug("Send VNI_DEL %u to %s", vni
,
3997 zebra_route_string(client
->proto
));
3999 client
->vnidel_cnt
++;
4000 return zserv_send_message(client
, s
);
4004 * Build the VNI hash table by going over the VxLAN interfaces. This
4005 * is called when EVPN (advertise-all-vni) is enabled.
4007 static void zvni_build_hash_table(void)
4009 struct zebra_ns
*zns
;
4010 struct route_node
*rn
;
4011 struct interface
*ifp
;
4013 /* Walk VxLAN interfaces and create VNI hash. */
4014 zns
= zebra_ns_lookup(NS_DEFAULT
);
4015 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4017 zebra_vni_t
*zvni
= NULL
;
4018 zebra_l3vni_t
*zl3vni
= NULL
;
4019 struct zebra_if
*zif
;
4020 struct zebra_l2info_vxlan
*vxl
;
4022 ifp
= (struct interface
*)rn
->info
;
4026 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4029 vxl
= &zif
->l2info
.vxl
;
4032 /* L3-VNI and L2-VNI are handled seperately */
4033 zl3vni
= zl3vni_lookup(vni
);
4036 if (IS_ZEBRA_DEBUG_VXLAN
)
4038 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4039 ifp
->name
, ifp
->ifindex
, vni
);
4041 /* associate with vxlan_if */
4042 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4043 zl3vni
->vxlan_if
= ifp
;
4046 * we need to associate with SVI.
4047 * we can associate with svi-if only after association
4048 * with vxlan-intf is complete
4050 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4052 if (is_l3vni_oper_up(zl3vni
))
4053 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4056 struct interface
*vlan_if
= NULL
;
4058 if (IS_ZEBRA_DEBUG_VXLAN
)
4060 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4061 ifp
->name
, ifp
->ifindex
, vni
,
4062 inet_ntoa(vxl
->vtep_ip
));
4064 /* VNI hash entry is not expected to exist. */
4065 zvni
= zvni_lookup(vni
);
4068 "VNI hash already present for IF %s(%u) L2-VNI %u",
4069 ifp
->name
, ifp
->ifindex
, vni
);
4073 zvni
= zvni_add(vni
);
4076 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4077 ifp
->name
, ifp
->ifindex
, vni
);
4081 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
4082 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
4083 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
4085 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4087 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4088 zvni
->mcast_grp
= vxl
->mcast_grp
;
4090 zvni
->vxlan_if
= ifp
;
4091 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4092 zif
->brslave_info
.br_if
);
4094 zvni
->vrf_id
= vlan_if
->vrf_id
;
4095 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4097 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4101 /* Inform BGP if intf is up and mapped to bridge. */
4102 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4103 zvni_send_add_to_client(zvni
);
4109 * See if remote VTEP matches with prefix.
4111 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4113 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4117 * Locate remote VTEP in VNI hash table.
4119 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4121 zebra_vtep_t
*zvtep
;
4126 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4127 if (zvni_vtep_match(vtep_ip
, zvtep
))
4135 * Add remote VTEP to VNI hash table.
4137 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4141 zebra_vtep_t
*zvtep
;
4143 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4145 zvtep
->vtep_ip
= *vtep_ip
;
4146 zvtep
->flood_control
= flood_control
;
4149 zvni
->vteps
->prev
= zvtep
;
4150 zvtep
->next
= zvni
->vteps
;
4151 zvni
->vteps
= zvtep
;
4157 * Remove remote VTEP from VNI hash table.
4159 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4162 zvtep
->next
->prev
= zvtep
->prev
;
4164 zvtep
->prev
->next
= zvtep
->next
;
4166 zvni
->vteps
= zvtep
->next
;
4168 zvtep
->prev
= zvtep
->next
= NULL
;
4169 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4175 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4176 * uninstall from kernel if asked to.
4178 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4180 zebra_vtep_t
*zvtep
, *zvtep_next
;
4185 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4186 zvtep_next
= zvtep
->next
;
4188 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4189 zvni_vtep_del(zvni
, zvtep
);
4196 * Install remote VTEP into the kernel if the remote VTEP has asked
4197 * for head-end-replication.
4199 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4201 if (is_vxlan_flooding_head_end() &&
4202 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4203 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4209 * Uninstall remote VTEP from the kernel.
4211 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4213 if (!zvni
->vxlan_if
) {
4214 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4219 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4223 * Install or uninstall flood entries in the kernel corresponding to
4224 * remote VTEPs. This is invoked upon change to BUM handling.
4226 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4230 zebra_vtep_t
*zvtep
;
4232 zvni
= (zebra_vni_t
*)bucket
->data
;
4236 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4237 if (is_vxlan_flooding_head_end())
4238 zvni_vtep_install(zvni
, zvtep
);
4240 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4245 * Cleanup VNI/VTEP and update kernel
4247 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4249 zebra_vni_t
*zvni
= NULL
;
4250 zebra_l3vni_t
*zl3vni
= NULL
;
4251 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4253 zvni
= (zebra_vni_t
*)bucket
->data
;
4255 /* remove from l3-vni list */
4257 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4259 listnode_delete(zl3vni
->l2vnis
, zvni
);
4261 /* Free up all neighbors and MACs, if any. */
4262 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4263 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4265 /* Free up all remote VTEPs, if any. */
4266 zvni_vtep_del_all(zvni
, 1);
4268 /* Delete the hash entry. */
4273 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4275 zebra_l3vni_t
*zl3vni
= NULL
;
4277 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4279 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4282 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4283 struct prefix
*host
)
4285 struct host_rb_entry lookup
;
4286 struct host_rb_entry
*hle
;
4288 memset(&lookup
, 0, sizeof(lookup
));
4289 memcpy(&lookup
.p
, host
, sizeof(*host
));
4291 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4295 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4296 memcpy(hle
, &lookup
, sizeof(lookup
));
4298 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4301 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4303 struct host_rb_entry lookup
;
4304 struct host_rb_entry
*hle
;
4306 memset(&lookup
, 0, sizeof(lookup
));
4307 memcpy(&lookup
.p
, host
, sizeof(*host
));
4309 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4311 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4312 XFREE(MTYPE_HOST_PREFIX
, hle
);
4319 * Look up MAC hash entry.
4321 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4322 struct ethaddr
*rmac
)
4327 memset(&tmp
, 0, sizeof(tmp
));
4328 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4329 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4335 * Callback to allocate RMAC hash entry.
4337 static void *zl3vni_rmac_alloc(void *p
)
4339 const zebra_mac_t
*tmp_rmac
= p
;
4342 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4345 return ((void *)zrmac
);
4349 * Add RMAC entry to l3-vni
4351 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4353 zebra_mac_t tmp_rmac
;
4354 zebra_mac_t
*zrmac
= NULL
;
4356 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4357 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4358 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4361 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4363 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4364 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4372 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4374 zebra_mac_t
*tmp_rmac
;
4375 struct host_rb_entry
*hle
;
4377 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4378 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4380 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4381 XFREE(MTYPE_HOST_PREFIX
, hle
);
4384 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4385 XFREE(MTYPE_MAC
, tmp_rmac
);
4391 * Install remote RMAC into the kernel.
4393 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4395 struct zebra_if
*zif
= NULL
;
4396 struct zebra_l2info_vxlan
*vxl
= NULL
;
4398 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4399 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4402 zif
= zl3vni
->vxlan_if
->info
;
4406 vxl
= &zif
->l2info
.vxl
;
4408 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4409 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4413 * Uninstall remote RMAC from the kernel.
4415 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4417 char buf
[ETHER_ADDR_STRLEN
];
4418 struct zebra_if
*zif
= NULL
;
4419 struct zebra_l2info_vxlan
*vxl
= NULL
;
4421 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4422 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4425 if (!zl3vni
->vxlan_if
) {
4427 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4428 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4429 zl3vni
->vni
, zl3vni
);
4433 zif
= zl3vni
->vxlan_if
->info
;
4437 vxl
= &zif
->l2info
.vxl
;
4439 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4440 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4443 /* handle rmac add */
4444 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4445 struct ipaddr
*vtep_ip
,
4446 struct prefix
*host_prefix
)
4448 char buf
[ETHER_ADDR_STRLEN
];
4449 char buf1
[INET6_ADDRSTRLEN
];
4450 zebra_mac_t
*zrmac
= NULL
;
4452 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4455 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4458 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4459 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4461 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4464 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4465 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4467 /* Send RMAC for FPM processing */
4468 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
4471 /* install rmac in kernel */
4472 zl3vni_rmac_install(zl3vni
, zrmac
);
4475 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4481 /* handle rmac delete */
4482 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4483 struct prefix
*host_prefix
)
4485 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4487 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4488 /* uninstall from kernel */
4489 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4491 /* Send RMAC for FPM processing */
4492 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
4495 /* del the rmac entry */
4496 zl3vni_rmac_del(zl3vni
, zrmac
);
4501 * Look up nh hash entry on a l3-vni.
4503 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4508 memset(&tmp
, 0, sizeof(tmp
));
4509 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4510 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4517 * Callback to allocate NH hash entry on L3-VNI.
4519 static void *zl3vni_nh_alloc(void *p
)
4521 const zebra_neigh_t
*tmp_n
= p
;
4524 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4531 * Add neighbor entry.
4533 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4534 struct ethaddr
*mac
)
4536 zebra_neigh_t tmp_n
;
4537 zebra_neigh_t
*n
= NULL
;
4539 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4540 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4541 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4544 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4546 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4547 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4548 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4554 * Delete neighbor entry.
4556 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4558 zebra_neigh_t
*tmp_n
;
4559 struct host_rb_entry
*hle
;
4561 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4562 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4564 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4565 XFREE(MTYPE_HOST_PREFIX
, hle
);
4568 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4569 XFREE(MTYPE_NEIGH
, tmp_n
);
4575 * Install remote nh as neigh into the kernel.
4577 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4584 if (!is_l3vni_oper_up(zl3vni
))
4587 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4588 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4591 flags
= NTF_EXT_LEARNED
;
4592 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4593 flags
|= NTF_ROUTER
;
4594 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4600 * Uninstall remote nh from the kernel.
4602 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4604 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4605 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4608 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4611 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4614 /* add remote vtep as a neigh entry */
4615 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4616 struct ethaddr
*rmac
,
4617 struct prefix
*host_prefix
)
4619 char buf
[ETHER_ADDR_STRLEN
];
4620 char buf1
[INET6_ADDRSTRLEN
];
4621 zebra_neigh_t
*nh
= NULL
;
4623 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4625 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4629 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4630 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4631 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4636 /* install the nh neigh in kernel */
4637 zl3vni_nh_install(zl3vni
, nh
);
4640 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4645 /* handle nh neigh delete */
4646 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4647 struct prefix
*host_prefix
)
4649 rb_delete_host(&nh
->host_rb
, host_prefix
);
4651 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4652 /* uninstall from kernel */
4653 zl3vni_nh_uninstall(zl3vni
, nh
);
4655 /* delete the nh entry */
4656 zl3vni_nh_del(zl3vni
, nh
);
4660 /* handle neigh update from kernel - the only thing of interest is to
4661 * readd stale entries.
4663 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4667 zebra_neigh_t
*n
= NULL
;
4669 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4673 /* all next hop neigh are remote and installed by frr.
4674 * If the kernel has aged this entry, re-install.
4676 if (state
& NUD_STALE
)
4677 zl3vni_nh_install(zl3vni
, n
);
4682 /* handle neigh delete from kernel */
4683 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4685 zebra_neigh_t
*n
= NULL
;
4687 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4691 /* all next hop neigh are remote and installed by frr.
4692 * If we get an age out notification for these neigh entries, we have to
4695 zl3vni_nh_install(zl3vni
, n
);
4701 * Hash function for L3 VNI.
4703 static unsigned int l3vni_hash_keymake(const void *p
)
4705 const zebra_l3vni_t
*zl3vni
= p
;
4707 return jhash_1word(zl3vni
->vni
, 0);
4711 * Compare 2 L3 VNI hash entries.
4713 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4715 const zebra_l3vni_t
*zl3vni1
= p1
;
4716 const zebra_l3vni_t
*zl3vni2
= p2
;
4718 return (zl3vni1
->vni
== zl3vni2
->vni
);
4722 * Callback to allocate L3 VNI hash entry.
4724 static void *zl3vni_alloc(void *p
)
4726 zebra_l3vni_t
*zl3vni
= NULL
;
4727 const zebra_l3vni_t
*tmp_l3vni
= p
;
4729 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4730 zl3vni
->vni
= tmp_l3vni
->vni
;
4731 return ((void *)zl3vni
);
4735 * Look up L3 VNI hash entry.
4737 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4739 zebra_l3vni_t tmp_l3vni
;
4740 zebra_l3vni_t
*zl3vni
= NULL
;
4742 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4743 tmp_l3vni
.vni
= vni
;
4744 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4750 * Add L3 VNI hash entry.
4752 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4754 zebra_l3vni_t tmp_zl3vni
;
4755 zebra_l3vni_t
*zl3vni
= NULL
;
4757 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4758 tmp_zl3vni
.vni
= vni
;
4760 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4763 zl3vni
->vrf_id
= vrf_id
;
4764 zl3vni
->svi_if
= NULL
;
4765 zl3vni
->vxlan_if
= NULL
;
4766 zl3vni
->l2vnis
= list_new();
4767 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4769 /* Create hash table for remote RMAC */
4770 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4771 "Zebra L3-VNI RMAC-Table");
4773 /* Create hash table for neighbors */
4774 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4775 "Zebra L3-VNI next-hop table");
4781 * Delete L3 VNI hash entry.
4783 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4785 zebra_l3vni_t
*tmp_zl3vni
;
4787 /* free the list of l2vnis */
4788 list_delete(&zl3vni
->l2vnis
);
4789 zl3vni
->l2vnis
= NULL
;
4791 /* Free the rmac table */
4792 hash_free(zl3vni
->rmac_table
);
4793 zl3vni
->rmac_table
= NULL
;
4795 /* Free the nh table */
4796 hash_free(zl3vni
->nh_table
);
4797 zl3vni
->nh_table
= NULL
;
4799 /* Free the VNI hash entry and allocated memory. */
4800 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4801 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4806 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4808 struct zebra_ns
*zns
= NULL
;
4809 struct route_node
*rn
= NULL
;
4810 struct interface
*ifp
= NULL
;
4812 /* loop through all vxlan-interface */
4813 zns
= zebra_ns_lookup(NS_DEFAULT
);
4814 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4816 struct zebra_if
*zif
= NULL
;
4817 struct zebra_l2info_vxlan
*vxl
= NULL
;
4819 ifp
= (struct interface
*)rn
->info
;
4824 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4827 vxl
= &zif
->l2info
.vxl
;
4828 if (vxl
->vni
== zl3vni
->vni
) {
4829 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4837 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4839 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4840 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4845 if (!zl3vni
->vxlan_if
)
4848 zif
= zl3vni
->vxlan_if
->info
;
4852 vxl
= &zif
->l2info
.vxl
;
4854 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4857 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4859 struct zebra_vrf
*zvrf
= NULL
;
4861 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4865 return zl3vni_lookup(zvrf
->l3vni
);
4869 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4870 * neighbor notifications, to see if they are of interest.
4872 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4873 struct interface
*br_if
)
4877 uint8_t bridge_vlan_aware
= 0;
4878 zebra_l3vni_t
*zl3vni
= NULL
;
4879 struct zebra_ns
*zns
= NULL
;
4880 struct route_node
*rn
= NULL
;
4881 struct zebra_if
*zif
= NULL
;
4882 struct interface
*tmp_if
= NULL
;
4883 struct zebra_l2info_bridge
*br
= NULL
;
4884 struct zebra_l2info_vxlan
*vxl
= NULL
;
4889 /* Make sure the linked interface is a bridge. */
4890 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4893 /* Determine if bridge is VLAN-aware or not */
4896 br
= &zif
->l2info
.br
;
4897 bridge_vlan_aware
= br
->vlan_aware
;
4898 if (bridge_vlan_aware
) {
4899 struct zebra_l2info_vlan
*vl
;
4901 if (!IS_ZEBRA_IF_VLAN(ifp
))
4906 vl
= &zif
->l2info
.vl
;
4910 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4911 /* TODO: Optimize with a hash. */
4912 zns
= zebra_ns_lookup(NS_DEFAULT
);
4913 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4914 tmp_if
= (struct interface
*)rn
->info
;
4918 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4920 if (!if_is_operative(tmp_if
))
4922 vxl
= &zif
->l2info
.vxl
;
4924 if (zif
->brslave_info
.br_if
!= br_if
)
4927 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4936 zl3vni
= zl3vni_lookup(vxl
->vni
);
4941 * Inform BGP about l3-vni.
4943 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4945 struct stream
*s
= NULL
;
4946 struct zserv
*client
= NULL
;
4947 struct ethaddr rmac
;
4948 char buf
[ETHER_ADDR_STRLEN
];
4950 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4951 /* BGP may not be running. */
4956 memset(&rmac
, 0, sizeof(struct ethaddr
));
4957 zl3vni_get_rmac(zl3vni
, &rmac
);
4959 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4961 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4962 stream_putl(s
, zl3vni
->vni
);
4963 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4964 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4965 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4966 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4968 /* Write packet size. */
4969 stream_putw_at(s
, 0, stream_get_endp(s
));
4971 if (IS_ZEBRA_DEBUG_VXLAN
)
4973 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4974 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4975 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4976 inet_ntoa(zl3vni
->local_vtep_ip
),
4977 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4978 ? "prefix-routes-only"
4980 zebra_route_string(client
->proto
));
4982 client
->l3vniadd_cnt
++;
4983 return zserv_send_message(client
, s
);
4987 * Inform BGP about local l3-VNI deletion.
4989 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4991 struct stream
*s
= NULL
;
4992 struct zserv
*client
= NULL
;
4994 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4995 /* BGP may not be running. */
4999 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5001 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5002 stream_putl(s
, zl3vni
->vni
);
5004 /* Write packet size. */
5005 stream_putw_at(s
, 0, stream_get_endp(s
));
5007 if (IS_ZEBRA_DEBUG_VXLAN
)
5008 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5009 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5010 zebra_route_string(client
->proto
));
5012 client
->l3vnidel_cnt
++;
5013 return zserv_send_message(client
, s
);
5016 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5021 /* send l3vni add to BGP */
5022 zl3vni_send_add_to_client(zl3vni
);
5025 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5030 /* send l3-vni del to BGP*/
5031 zl3vni_send_del_to_client(zl3vni
);
5034 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5036 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5037 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5039 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5040 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5044 * handle transition of vni from l2 to l3 and vice versa
5046 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5049 zebra_vni_t
*zvni
= NULL
;
5051 /* There is a possibility that VNI notification was already received
5052 * from kernel and we programmed it as L2-VNI
5053 * In such a case we need to delete this L2-VNI first, so
5054 * that it can be reprogrammed as L3-VNI in the system. It is also
5055 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5056 * interface is still present in kernel. In this case to keep it
5057 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5060 /* Locate hash entry */
5061 zvni
= zvni_lookup(vni
);
5065 if (IS_ZEBRA_DEBUG_VXLAN
)
5066 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5068 /* Delete VNI from BGP. */
5069 zvni_send_del_to_client(zvni
->vni
);
5071 /* Free up all neighbors and MAC, if any. */
5072 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5073 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5075 /* Free up all remote VTEPs, if any. */
5076 zvni_vtep_del_all(zvni
, 0);
5078 /* Delete the hash entry. */
5079 if (zvni_del(zvni
)) {
5080 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5081 "Failed to del VNI hash %p, VNI %u", zvni
,
5086 /* TODO_MITESH: This needs to be thought through. We don't have
5087 * enough information at this point to reprogram the vni as
5088 * l2-vni. One way is to store the required info in l3-vni and
5089 * used it solely for this purpose
5096 /* delete and uninstall rmac hash entry */
5097 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5099 zebra_mac_t
*zrmac
= NULL
;
5100 zebra_l3vni_t
*zl3vni
= NULL
;
5102 zrmac
= (zebra_mac_t
*)bucket
->data
;
5103 zl3vni
= (zebra_l3vni_t
*)ctx
;
5104 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5106 /* Send RMAC for FPM processing */
5107 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5109 zl3vni_rmac_del(zl3vni
, zrmac
);
5112 /* delete and uninstall nh hash entry */
5113 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5115 zebra_neigh_t
*n
= NULL
;
5116 zebra_l3vni_t
*zl3vni
= NULL
;
5118 n
= (zebra_neigh_t
*)bucket
->data
;
5119 zl3vni
= (zebra_l3vni_t
*)ctx
;
5120 zl3vni_nh_uninstall(zl3vni
, n
);
5121 zl3vni_nh_del(zl3vni
, n
);
5124 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5127 struct zserv
*client
= NULL
;
5128 struct stream
*s
= NULL
;
5129 char buf
[PREFIX_STRLEN
];
5131 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5132 /* BGP may not be running. */
5136 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5138 zclient_create_header(s
, cmd
, vrf_id
);
5139 stream_put(s
, p
, sizeof(struct prefix
));
5141 /* Write packet size. */
5142 stream_putw_at(s
, 0, stream_get_endp(s
));
5144 if (IS_ZEBRA_DEBUG_VXLAN
)
5145 zlog_debug("Send ip prefix %s %s on vrf %s",
5146 prefix2str(p
, buf
, sizeof(buf
)),
5147 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5148 vrf_id_to_name(vrf_id
));
5150 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5151 client
->prefixadd_cnt
++;
5153 client
->prefixdel_cnt
++;
5155 return zserv_send_message(client
, s
);
5158 /* re-add remote rmac if needed */
5159 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5160 struct ethaddr
*rmac
)
5162 char buf
[ETHER_ADDR_STRLEN
];
5163 zebra_mac_t
*zrmac
= NULL
;
5165 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5169 if (IS_ZEBRA_DEBUG_VXLAN
)
5170 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5171 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5173 zl3vni_rmac_install(zl3vni
, zrmac
);
5177 /* Process a remote MACIP add from BGP. */
5178 static void process_remote_macip_add(vni_t vni
,
5179 struct ethaddr
*macaddr
,
5181 struct ipaddr
*ipaddr
,
5184 struct in_addr vtep_ip
)
5187 zebra_vtep_t
*zvtep
;
5188 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5189 zebra_neigh_t
*n
= NULL
;
5190 int update_mac
= 0, update_neigh
= 0;
5191 char buf
[ETHER_ADDR_STRLEN
];
5192 char buf1
[INET6_ADDRSTRLEN
];
5193 struct interface
*ifp
= NULL
;
5194 struct zebra_if
*zif
= NULL
;
5195 struct zebra_vrf
*zvrf
;
5200 bool do_dad
= false;
5201 bool is_dup_detect
= false;
5203 /* Locate VNI hash entry - expected to exist. */
5204 zvni
= zvni_lookup(vni
);
5206 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5210 ifp
= zvni
->vxlan_if
;
5214 !if_is_operative(ifp
) ||
5216 !zif
->brslave_info
.br_if
) {
5217 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5222 /* The remote VTEP specified should normally exist, but it is
5223 * possible that when peering comes up, peer may advertise MACIP
5224 * routes before advertising type-3 routes.
5226 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5228 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5231 EC_ZEBRA_VTEP_ADD_FAILED
,
5232 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5237 zvni_vtep_install(zvni
, zvtep
);
5240 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5241 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5242 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5244 mac
= zvni_mac_lookup(zvni
, macaddr
);
5246 /* Ignore if the mac is already present as a gateway mac */
5248 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5249 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5250 if (IS_ZEBRA_DEBUG_VXLAN
)
5251 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5253 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5254 ipa_len
? " IP " : "",
5256 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5260 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5264 /* check if the remote MAC is unknown or has a change.
5265 * If so, that needs to be updated first. Note that client could
5266 * install MAC and MACIP separately or just install the latter.
5269 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5270 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5271 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5272 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5273 || seq
!= mac
->rem_seq
)
5278 mac
= zvni_mac_add(zvni
, macaddr
);
5281 "Failed to add MAC %s VNI %u Remote VTEP %s",
5282 prefix_mac2str(macaddr
, buf
,
5284 vni
, inet_ntoa(vtep_ip
));
5288 /* Is this MAC created for a MACIP? */
5290 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5292 const char *mac_type
;
5294 /* When host moves but changes its (MAC,IP)
5295 * binding, BGP may install a MACIP entry that
5296 * corresponds to "older" location of the host
5297 * in transient situations (because {IP1,M1}
5298 * is a different route from {IP1,M2}). Check
5299 * the sequence number and ignore this update
5302 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5303 tmp_seq
= mac
->loc_seq
;
5306 tmp_seq
= mac
->rem_seq
;
5307 mac_type
= "remote";
5309 if (seq
< tmp_seq
) {
5310 if (IS_ZEBRA_DEBUG_VXLAN
)
5311 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5313 prefix_mac2str(macaddr
,
5315 ipa_len
? " IP " : "",
5318 buf1
, sizeof(buf1
)) : "",
5325 /* Check MAC's curent state is local (this is the case
5326 * where MAC has moved from L->R) and check previous
5327 * detection started via local learning.
5328 * RFC-7432: A PE/VTEP that detects a MAC mobility
5329 * event via local learning starts an M-second timer.
5331 * VTEP-IP or seq. change alone is not considered
5332 * for dup. detection.
5334 * MAC is already marked duplicate set dad, then
5335 * is_dup_detect will be set to not install the entry.
5337 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5339 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5342 /* Remove local MAC from BGP. */
5343 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5344 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5346 /* Set "auto" and "remote" forwarding info. */
5347 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5348 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5349 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5350 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5353 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5355 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5358 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5360 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5362 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5363 mac
->fwd_info
.r_vtep_ip
,
5364 do_dad
, &is_dup_detect
,
5367 if (!is_dup_detect
) {
5368 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5369 /* Install the entry. */
5370 zvni_mac_install(zvni
, mac
);
5374 /* Update seq number. */
5377 /* If there is no IP, return after clearing AUTO flag of MAC. */
5379 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5386 /* Check if the remote neighbor itself is unknown or has a
5387 * change. If so, create or update and then install the entry.
5389 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5391 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5392 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5393 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5394 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5395 || seq
!= n
->rem_seq
)
5400 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5403 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5404 ipaddr2str(ipaddr
, buf1
,
5406 prefix_mac2str(macaddr
, buf
,
5408 vni
, inet_ntoa(vtep_ip
));
5415 /* When host moves but changes its (MAC,IP)
5416 * binding, BGP may install a MACIP entry that
5417 * corresponds to "older" location of the host
5418 * in transient situations (because {IP1,M1}
5419 * is a different route from {IP1,M2}). Check
5420 * the sequence number and ignore this update
5423 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5424 tmp_seq
= n
->loc_seq
;
5427 tmp_seq
= n
->rem_seq
;
5430 if (seq
< tmp_seq
) {
5431 if (IS_ZEBRA_DEBUG_VXLAN
)
5432 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5434 prefix_mac2str(macaddr
,
5437 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5442 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5443 /* MAC change, send a delete for old
5444 * neigh if learnt locally.
5446 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5447 IS_ZEBRA_NEIGH_ACTIVE(n
))
5448 zvni_neigh_send_del_to_client(
5450 &n
->emac
, 0, n
->state
);
5452 /* update neigh list for macs */
5453 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5455 listnode_delete(old_mac
->neigh_list
, n
);
5456 zvni_deref_ip2mac(zvni
, old_mac
);
5458 listnode_add_sort(mac
->neigh_list
, n
);
5459 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5461 /* Check Neigh's curent state is local
5462 * (this is the case where neigh/host has moved
5463 * from L->R) and check previous detction
5464 * started via local learning.
5466 * RFC-7432: A PE/VTEP that detects a MAC
5467 * mobilit event via local learning starts
5468 * an M-second timer.
5469 * VTEP-IP or seq. change along is not
5470 * considered for dup. detection.
5472 * Mobilty event scenario-B IP-MAC binding
5475 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5482 /* Set "remote" forwarding info. */
5483 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5484 n
->r_vtep_ip
= vtep_ip
;
5485 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5487 /* Set router flag (R-bit) to this Neighbor entry */
5488 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5489 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5491 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5493 /* Check old or new MAC detected as duplicate,
5494 * inherit duplicate flag to this neigh.
5496 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5498 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5499 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5501 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5502 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5505 /* Check duplicate address detection for IP */
5506 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5511 /* Install the entry. */
5513 zvni_neigh_install(zvni
, n
);
5516 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5518 /* Update seq number. */
5522 /* Process a remote MACIP delete from BGP. */
5523 static void process_remote_macip_del(vni_t vni
,
5524 struct ethaddr
*macaddr
,
5526 struct ipaddr
*ipaddr
,
5527 struct in_addr vtep_ip
)
5530 zebra_mac_t
*mac
= NULL
;
5531 zebra_neigh_t
*n
= NULL
;
5532 struct interface
*ifp
= NULL
;
5533 struct zebra_if
*zif
= NULL
;
5534 struct zebra_ns
*zns
;
5535 struct zebra_l2info_vxlan
*vxl
;
5536 struct zebra_vrf
*zvrf
;
5537 char buf
[ETHER_ADDR_STRLEN
];
5538 char buf1
[INET6_ADDRSTRLEN
];
5540 /* Locate VNI hash entry - expected to exist. */
5541 zvni
= zvni_lookup(vni
);
5543 if (IS_ZEBRA_DEBUG_VXLAN
)
5544 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5548 ifp
= zvni
->vxlan_if
;
5552 !if_is_operative(ifp
) ||
5554 !zif
->brslave_info
.br_if
) {
5555 if (IS_ZEBRA_DEBUG_VXLAN
)
5556 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5560 zns
= zebra_ns_lookup(NS_DEFAULT
);
5561 vxl
= &zif
->l2info
.vxl
;
5563 /* The remote VTEP specified is normally expected to exist, but
5564 * it is possible that the peer may delete the VTEP before deleting
5565 * any MACs referring to the VTEP, in which case the handler (see
5566 * remote_vtep_del) would have already deleted the MACs.
5568 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5571 mac
= zvni_mac_lookup(zvni
, macaddr
);
5573 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5576 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5577 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5578 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5582 /* If the remote mac or neighbor doesn't exist there is nothing
5583 * more to do. Otherwise, uninstall the entry and then remove it.
5588 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5590 /* Ignore the delete if this mac is a gateway mac-ip */
5591 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5592 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5594 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5596 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5597 ipa_len
? " IP " : "",
5599 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5603 /* Uninstall remote neighbor or MAC. */
5605 if (zvrf
->dad_freeze
&&
5606 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5607 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5608 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5609 struct interface
*vlan_if
;
5611 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5612 zif
->brslave_info
.br_if
);
5613 if (IS_ZEBRA_DEBUG_VXLAN
)
5614 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5615 __PRETTY_FUNCTION__
,
5616 ipaddr2str(ipaddr
, buf1
,
5617 sizeof(buf1
)), n
->flags
,
5619 neigh_read_specific_ip(ipaddr
, vlan_if
);
5622 /* When the MAC changes for an IP, it is possible the
5623 * client may update the new MAC before trying to delete the
5624 * "old" neighbor (as these are two different MACIP routes).
5625 * Do the delete only if the MAC matches.
5627 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5628 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5629 zvni_neigh_uninstall(zvni
, n
);
5630 zvni_neigh_del(zvni
, n
);
5631 zvni_deref_ip2mac(zvni
, mac
);
5634 /* DAD: when MAC is freeze state as remote learn event,
5635 * remote mac-ip delete event is received will result in freeze
5636 * entry removal, first fetch kernel for the same entry present
5637 * as LOCAL and reachable, avoid deleting this entry instead
5638 * use kerenel local entry to update during unfreeze time.
5640 if (zvrf
->dad_freeze
&&
5641 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5642 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5643 if (IS_ZEBRA_DEBUG_VXLAN
)
5644 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5645 __PRETTY_FUNCTION__
,
5646 prefix_mac2str(macaddr
, buf
,
5649 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5650 macaddr
, vxl
->access_vlan
);
5653 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5654 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5656 * the remote sequence number in the auto mac entry
5657 * needs to be reset to 0 as the mac entry may have
5658 * been removed on all VTEPs (including
5659 * the originating one)
5663 /* If all remote neighbors referencing a remote MAC
5664 * go away, we need to uninstall the MAC.
5666 if (remote_neigh_count(mac
) == 0) {
5667 zvni_mac_uninstall(zvni
, mac
);
5668 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5670 if (list_isempty(mac
->neigh_list
))
5671 zvni_mac_del(zvni
, mac
);
5673 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5679 /* Public functions */
5681 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5683 zebra_l3vni_t
*zl3vni
= NULL
;
5685 zl3vni
= zl3vni_lookup(vni
);
5689 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5692 /* handle evpn route in vrf table */
5693 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5694 struct ipaddr
*vtep_ip
,
5695 struct prefix
*host_prefix
)
5697 zebra_l3vni_t
*zl3vni
= NULL
;
5698 struct ipaddr ipv4_vtep
;
5700 zl3vni
= zl3vni_from_vrf(vrf_id
);
5701 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5705 * add the next hop neighbor -
5706 * neigh to be installed is the ipv6 nexthop neigh
5708 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5711 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5712 * address. Rmac is programmed against the ipv4 vtep because we only
5713 * support ipv4 tunnels in the h/w right now
5715 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5716 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5717 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5718 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5719 &(ipv4_vtep
.ipaddr_v4
));
5721 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5722 sizeof(struct in_addr
));
5725 * add the rmac - remote rmac to be installed is against the ipv4
5728 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5731 /* handle evpn vrf route delete */
5732 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5733 struct ipaddr
*vtep_ip
,
5734 struct prefix
*host_prefix
)
5736 zebra_l3vni_t
*zl3vni
= NULL
;
5737 zebra_neigh_t
*nh
= NULL
;
5738 zebra_mac_t
*zrmac
= NULL
;
5740 zl3vni
= zl3vni_from_vrf(vrf_id
);
5744 /* find the next hop entry and rmac entry */
5745 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5748 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5750 /* delete the next hop entry */
5751 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5753 /* delete the rmac entry */
5755 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5759 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5760 struct ethaddr
*rmac
, bool use_json
)
5762 zebra_l3vni_t
*zl3vni
= NULL
;
5763 zebra_mac_t
*zrmac
= NULL
;
5764 json_object
*json
= NULL
;
5766 if (!is_evpn_enabled()) {
5768 vty_out(vty
, "{}\n");
5773 json
= json_object_new_object();
5775 zl3vni
= zl3vni_lookup(l3vni
);
5778 vty_out(vty
, "{}\n");
5780 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5784 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5787 vty_out(vty
, "{}\n");
5790 "%% Requested RMAC doesn't exist in L3-VNI %u",
5795 zl3vni_print_rmac(zrmac
, vty
, json
);
5798 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5799 json
, JSON_C_TO_STRING_PRETTY
));
5800 json_object_free(json
);
5804 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5806 zebra_l3vni_t
*zl3vni
;
5808 struct rmac_walk_ctx wctx
;
5809 json_object
*json
= NULL
;
5811 if (!is_evpn_enabled())
5814 zl3vni
= zl3vni_lookup(l3vni
);
5817 vty_out(vty
, "{}\n");
5819 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5822 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5827 json
= json_object_new_object();
5829 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5833 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5835 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5837 json_object_int_add(json
, "numRmacs", num_rmacs
);
5839 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5842 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5843 json
, JSON_C_TO_STRING_PRETTY
));
5844 json_object_free(json
);
5848 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5850 json_object
*json
= NULL
;
5853 if (!is_evpn_enabled()) {
5855 vty_out(vty
, "{}\n");
5860 json
= json_object_new_object();
5864 hash_iterate(zrouter
.l3vni_table
,
5865 (void (*)(struct hash_bucket
*,
5866 void *))zl3vni_print_rmac_hash_all_vni
,
5870 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5871 json
, JSON_C_TO_STRING_PRETTY
));
5872 json_object_free(json
);
5876 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5877 struct ipaddr
*ip
, bool use_json
)
5879 zebra_l3vni_t
*zl3vni
= NULL
;
5880 zebra_neigh_t
*n
= NULL
;
5881 json_object
*json
= NULL
;
5883 if (!is_evpn_enabled()) {
5885 vty_out(vty
, "{}\n");
5890 json
= json_object_new_object();
5892 zl3vni
= zl3vni_lookup(l3vni
);
5895 vty_out(vty
, "{}\n");
5897 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5901 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5904 vty_out(vty
, "{}\n");
5907 "%% Requested next-hop not present for L3-VNI %u",
5912 zl3vni_print_nh(n
, vty
, json
);
5915 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5916 json
, JSON_C_TO_STRING_PRETTY
));
5917 json_object_free(json
);
5921 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5924 struct nh_walk_ctx wctx
;
5925 json_object
*json
= NULL
;
5926 zebra_l3vni_t
*zl3vni
= NULL
;
5928 if (!is_evpn_enabled())
5931 zl3vni
= zl3vni_lookup(l3vni
);
5934 vty_out(vty
, "{}\n");
5936 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5940 num_nh
= hashcount(zl3vni
->nh_table
);
5945 json
= json_object_new_object();
5950 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5952 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5954 json_object_int_add(json
, "numNextHops", num_nh
);
5956 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5959 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5960 json
, JSON_C_TO_STRING_PRETTY
));
5961 json_object_free(json
);
5965 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5967 json_object
*json
= NULL
;
5970 if (!is_evpn_enabled()) {
5972 vty_out(vty
, "{}\n");
5977 json
= json_object_new_object();
5981 hash_iterate(zrouter
.l3vni_table
,
5982 (void (*)(struct hash_bucket
*,
5983 void *))zl3vni_print_nh_hash_all_vni
,
5987 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5988 json
, JSON_C_TO_STRING_PRETTY
));
5989 json_object_free(json
);
5994 * Display L3 VNI information (VTY command handler).
5996 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5999 json_object
*json
= NULL
;
6000 zebra_l3vni_t
*zl3vni
= NULL
;
6002 if (!is_evpn_enabled()) {
6004 vty_out(vty
, "{}\n");
6008 zl3vni
= zl3vni_lookup(vni
);
6011 vty_out(vty
, "{}\n");
6013 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6018 json
= json_object_new_object();
6022 zl3vni_print(zl3vni
, (void *)args
);
6025 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6026 json
, JSON_C_TO_STRING_PRETTY
));
6027 json_object_free(json
);
6031 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6032 json_object
*json_vrfs
)
6034 char buf
[ETHER_ADDR_STRLEN
];
6035 zebra_l3vni_t
*zl3vni
= NULL
;
6037 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6042 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6043 zvrf_name(zvrf
), zl3vni
->vni
,
6044 zl3vni_vxlan_if_name(zl3vni
),
6045 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6046 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6048 json_object
*json_vrf
= NULL
;
6050 json_vrf
= json_object_new_object();
6051 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6052 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6053 json_object_string_add(json_vrf
, "vxlanIntf",
6054 zl3vni_vxlan_if_name(zl3vni
));
6055 json_object_string_add(json_vrf
, "sviIntf",
6056 zl3vni_svi_if_name(zl3vni
));
6057 json_object_string_add(json_vrf
, "state",
6058 zl3vni_state2str(zl3vni
));
6059 json_object_string_add(
6060 json_vrf
, "routerMac",
6061 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6062 json_object_array_add(json_vrfs
, json_vrf
);
6067 * Display Neighbors for a VNI (VTY command handler).
6069 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6070 vni_t vni
, bool use_json
)
6074 struct neigh_walk_ctx wctx
;
6075 json_object
*json
= NULL
;
6077 if (!is_evpn_enabled())
6079 zvni
= zvni_lookup(vni
);
6082 vty_out(vty
, "{}\n");
6084 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6087 num_neigh
= hashcount(zvni
->neigh_table
);
6092 json
= json_object_new_object();
6094 /* Since we have IPv6 addresses to deal with which can vary widely in
6095 * size, we try to be a bit more elegant in display by first computing
6096 * the maximum width.
6098 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6101 wctx
.addr_width
= 15;
6103 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6107 "Number of ARPs (local and remote) known for this VNI: %u\n",
6109 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6110 -wctx
.addr_width
, "IP", "Type",
6111 "State", "MAC", "Remote VTEP");
6113 json_object_int_add(json
, "numArpNd", num_neigh
);
6115 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6117 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6118 json
, JSON_C_TO_STRING_PRETTY
));
6119 json_object_free(json
);
6124 * Display neighbors across all VNIs (VTY command handler).
6126 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6127 bool print_dup
, bool use_json
)
6129 json_object
*json
= NULL
;
6132 if (!is_evpn_enabled())
6136 json
= json_object_new_object();
6140 args
[2] = (void *)(ptrdiff_t)print_dup
;
6142 hash_iterate(zvrf
->vni_table
,
6143 (void (*)(struct hash_bucket
*,
6144 void *))zvni_print_neigh_hash_all_vni
,
6147 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6148 json
, JSON_C_TO_STRING_PRETTY
));
6149 json_object_free(json
);
6154 * Display neighbors across all VNIs in detail(VTY command handler).
6156 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6157 struct zebra_vrf
*zvrf
,
6158 bool print_dup
, bool use_json
)
6160 json_object
*json
= NULL
;
6163 if (!is_evpn_enabled())
6167 json
= json_object_new_object();
6171 args
[2] = (void *)(ptrdiff_t)print_dup
;
6173 hash_iterate(zvrf
->vni_table
,
6174 (void (*)(struct hash_bucket
*,
6175 void *))zvni_print_neigh_hash_all_vni_detail
,
6178 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6179 json
, JSON_C_TO_STRING_PRETTY
));
6180 json_object_free(json
);
6185 * Display specific neighbor for a VNI, if present (VTY command handler).
6187 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6188 struct zebra_vrf
*zvrf
, vni_t vni
,
6189 struct ipaddr
*ip
, bool use_json
)
6193 json_object
*json
= NULL
;
6195 if (!is_evpn_enabled())
6197 zvni
= zvni_lookup(vni
);
6200 vty_out(vty
, "{}\n");
6202 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6205 n
= zvni_neigh_lookup(zvni
, ip
);
6209 "%% Requested neighbor does not exist in VNI %u\n",
6214 json
= json_object_new_object();
6216 zvni_print_neigh(n
, vty
, json
);
6219 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6220 json
, JSON_C_TO_STRING_PRETTY
));
6221 json_object_free(json
);
6226 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6227 * By definition, these are remote neighbors.
6229 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6230 vni_t vni
, struct in_addr vtep_ip
,
6235 struct neigh_walk_ctx wctx
;
6236 json_object
*json
= NULL
;
6238 if (!is_evpn_enabled())
6240 zvni
= zvni_lookup(vni
);
6243 vty_out(vty
, "{}\n");
6245 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6248 num_neigh
= hashcount(zvni
->neigh_table
);
6252 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6255 wctx
.addr_width
= 15;
6256 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6257 wctx
.r_vtep_ip
= vtep_ip
;
6259 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6260 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6263 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6264 json
, JSON_C_TO_STRING_PRETTY
));
6265 json_object_free(json
);
6270 * Display Duplicate detected Neighbors for a VNI
6271 * (VTY command handler).
6273 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6274 struct zebra_vrf
*zvrf
,
6280 struct neigh_walk_ctx wctx
;
6281 json_object
*json
= NULL
;
6283 if (!is_evpn_enabled())
6286 zvni
= zvni_lookup(vni
);
6288 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6292 num_neigh
= hashcount(zvni
->neigh_table
);
6296 num_neigh
= num_dup_detected_neighs(zvni
);
6301 json
= json_object_new_object();
6303 /* Since we have IPv6 addresses to deal with which can vary widely in
6304 * size, we try to be a bit more elegant in display by first computing
6305 * the maximum width.
6307 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6310 wctx
.addr_width
= 15;
6312 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6316 "Number of ARPs (local and remote) known for this VNI: %u\n",
6318 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6319 -wctx
.addr_width
, "IP", "Type",
6320 "State", "MAC", "Remote VTEP");
6322 json_object_int_add(json
, "numArpNd", num_neigh
);
6324 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6327 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6328 json
, JSON_C_TO_STRING_PRETTY
));
6329 json_object_free(json
);
6334 * Display MACs for a VNI (VTY command handler).
6336 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6337 vni_t vni
, bool use_json
)
6341 struct mac_walk_ctx wctx
;
6342 json_object
*json
= NULL
;
6343 json_object
*json_mac
= NULL
;
6345 if (!is_evpn_enabled())
6347 zvni
= zvni_lookup(vni
);
6350 vty_out(vty
, "{}\n");
6352 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6355 num_macs
= num_valid_macs(zvni
);
6360 json
= json_object_new_object();
6361 json_mac
= json_object_new_object();
6364 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6367 wctx
.json
= json_mac
;
6371 "Number of MACs (local and remote) known for this VNI: %u\n",
6373 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6374 "Intf/Remote VTEP", "VLAN");
6376 json_object_int_add(json
, "numMacs", num_macs
);
6378 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6381 json_object_object_add(json
, "macs", json_mac
);
6382 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6383 json
, JSON_C_TO_STRING_PRETTY
));
6384 json_object_free(json
);
6389 * Display MACs for all VNIs (VTY command handler).
6391 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6392 bool print_dup
, bool use_json
)
6394 struct mac_walk_ctx wctx
;
6395 json_object
*json
= NULL
;
6397 if (!is_evpn_enabled()) {
6399 vty_out(vty
, "{}\n");
6403 json
= json_object_new_object();
6405 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6408 wctx
.print_dup
= print_dup
;
6409 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6412 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6413 json
, JSON_C_TO_STRING_PRETTY
));
6414 json_object_free(json
);
6419 * Display MACs in detail for all VNIs (VTY command handler).
6421 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6422 struct zebra_vrf
*zvrf
,
6423 bool print_dup
, bool use_json
)
6425 struct mac_walk_ctx wctx
;
6426 json_object
*json
= NULL
;
6428 if (!is_evpn_enabled()) {
6430 vty_out(vty
, "{}\n");
6434 json
= json_object_new_object();
6436 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6439 wctx
.print_dup
= print_dup
;
6440 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6444 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6445 json
, JSON_C_TO_STRING_PRETTY
));
6446 json_object_free(json
);
6451 * Display MACs for all VNIs (VTY command handler).
6453 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6454 struct zebra_vrf
*zvrf
,
6455 struct in_addr vtep_ip
, bool use_json
)
6457 struct mac_walk_ctx wctx
;
6458 json_object
*json
= NULL
;
6460 if (!is_evpn_enabled())
6464 json
= json_object_new_object();
6466 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6468 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6469 wctx
.r_vtep_ip
= vtep_ip
;
6471 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6474 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6475 json
, JSON_C_TO_STRING_PRETTY
));
6476 json_object_free(json
);
6481 * Display specific MAC for a VNI, if present (VTY command handler).
6483 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6484 vni_t vni
, struct ethaddr
*macaddr
,
6489 json_object
*json
= NULL
;
6491 if (!is_evpn_enabled())
6494 zvni
= zvni_lookup(vni
);
6497 vty_out(vty
, "{}\n");
6499 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6502 mac
= zvni_mac_lookup(zvni
, macaddr
);
6505 vty_out(vty
, "{}\n");
6508 "%% Requested MAC does not exist in VNI %u\n",
6514 json
= json_object_new_object();
6516 zvni_print_mac(mac
, vty
, json
);
6518 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6519 json
, JSON_C_TO_STRING_PRETTY
));
6520 json_object_free(json
);
6524 /* Print Duplicate MACs per VNI */
6525 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6526 struct zebra_vrf
*zvrf
,
6527 vni_t vni
, bool use_json
)
6530 struct mac_walk_ctx wctx
;
6532 json_object
*json
= NULL
;
6533 json_object
*json_mac
= NULL
;
6535 if (!is_evpn_enabled())
6538 zvni
= zvni_lookup(vni
);
6540 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6544 num_macs
= num_valid_macs(zvni
);
6548 num_macs
= num_dup_detected_macs(zvni
);
6553 json
= json_object_new_object();
6554 json_mac
= json_object_new_object();
6557 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6560 wctx
.json
= json_mac
;
6564 "Number of MACs (local and remote) known for this VNI: %u\n",
6566 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6567 "Intf/Remote VTEP", "VLAN");
6569 json_object_int_add(json
, "numMacs", num_macs
);
6571 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6574 json_object_object_add(json
, "macs", json_mac
);
6575 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6576 json
, JSON_C_TO_STRING_PRETTY
));
6577 json_object_free(json
);
6582 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6583 struct zebra_vrf
*zvrf
,
6584 vni_t vni
, struct ethaddr
*macaddr
)
6588 struct listnode
*node
= NULL
;
6589 zebra_neigh_t
*nbr
= NULL
;
6591 if (!is_evpn_enabled())
6594 zvni
= zvni_lookup(vni
);
6596 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6600 mac
= zvni_mac_lookup(zvni
, macaddr
);
6602 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6607 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6608 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6612 /* Remove all IPs as duplicate associcated with this MAC */
6613 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6614 /* For local neigh mark inactive so MACIP update is generated
6615 * to BGP. This is a scenario where MAC update received
6616 * and detected as duplicate which marked neigh as duplicate.
6617 * Later local neigh update did not get a chance to relay
6618 * to BGP. Similarly remote macip update, neigh needs to be
6619 * installed locally.
6621 if (zvrf
->dad_freeze
&&
6622 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6623 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6624 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6625 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6626 zvni_neigh_install(zvni
, nbr
);
6629 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6631 nbr
->detect_start_time
.tv_sec
= 0;
6632 nbr
->dad_dup_detect_time
= 0;
6635 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6637 mac
->detect_start_time
.tv_sec
= 0;
6638 mac
->detect_start_time
.tv_usec
= 0;
6639 mac
->dad_dup_detect_time
= 0;
6640 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6642 /* warn-only action return */
6643 if (!zvrf
->dad_freeze
)
6646 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6647 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6649 if (zvni_mac_send_add_to_client(zvni
->vni
,
6655 /* Process all neighbors associated with this MAC. */
6656 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6658 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6659 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6661 /* Install the entry. */
6662 zvni_mac_install(zvni
, mac
);
6668 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6669 struct zebra_vrf
*zvrf
,
6670 vni_t vni
, struct ipaddr
*ip
)
6675 char buf
[INET6_ADDRSTRLEN
];
6676 char buf2
[ETHER_ADDR_STRLEN
];
6678 if (!is_evpn_enabled())
6681 zvni
= zvni_lookup(vni
);
6683 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6687 nbr
= zvni_neigh_lookup(zvni
, ip
);
6690 "%% Requested host IP does not exist in VNI %u\n",
6695 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6697 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6699 "%% Requsted host IP %s is not duplicate detected\n",
6704 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6706 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6708 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6709 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6710 return CMD_WARNING_CONFIG_FAILED
;
6713 if (IS_ZEBRA_DEBUG_VXLAN
)
6714 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6715 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6718 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6720 nbr
->detect_start_time
.tv_sec
= 0;
6721 nbr
->detect_start_time
.tv_usec
= 0;
6722 nbr
->dad_dup_detect_time
= 0;
6723 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6725 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6726 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6728 nbr
->flags
, nbr
->loc_seq
);
6729 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6730 zvni_neigh_install(zvni
, nbr
);
6736 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6738 struct mac_walk_ctx
*wctx
= ctxt
;
6741 struct listnode
*node
= NULL
;
6742 zebra_neigh_t
*nbr
= NULL
;
6744 mac
= (zebra_mac_t
*)bucket
->data
;
6750 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6753 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6755 mac
->detect_start_time
.tv_sec
= 0;
6756 mac
->detect_start_time
.tv_usec
= 0;
6757 mac
->dad_dup_detect_time
= 0;
6758 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6760 /* Remove all IPs as duplicate associcated with this MAC */
6761 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6762 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6764 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6766 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6768 nbr
->detect_start_time
.tv_sec
= 0;
6769 nbr
->dad_dup_detect_time
= 0;
6772 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6773 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6775 if (zvni_mac_send_add_to_client(zvni
->vni
,
6777 mac
->flags
, mac
->loc_seq
))
6780 /* Process all neighbors associated with this MAC. */
6781 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6783 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6784 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6786 /* Install the entry. */
6787 zvni_mac_install(zvni
, mac
);
6791 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6793 struct neigh_walk_ctx
*wctx
= ctxt
;
6796 char buf
[INET6_ADDRSTRLEN
];
6798 nbr
= (zebra_neigh_t
*)bucket
->data
;
6804 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6807 if (IS_ZEBRA_DEBUG_VXLAN
) {
6808 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6810 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6811 __PRETTY_FUNCTION__
, buf
,
6812 nbr
->flags
, nbr
->loc_seq
);
6815 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6817 nbr
->detect_start_time
.tv_sec
= 0;
6818 nbr
->detect_start_time
.tv_usec
= 0;
6819 nbr
->dad_dup_detect_time
= 0;
6820 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6822 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6823 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6825 nbr
->flags
, nbr
->loc_seq
);
6826 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6827 zvni_neigh_install(zvni
, nbr
);
6831 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6836 struct zebra_vrf
*zvrf
;
6837 struct mac_walk_ctx m_wctx
;
6838 struct neigh_walk_ctx n_wctx
;
6840 zvni
= (zebra_vni_t
*)bucket
->data
;
6844 vty
= (struct vty
*)args
[0];
6845 zvrf
= (struct zebra_vrf
*)args
[1];
6847 if (hashcount(zvni
->neigh_table
)) {
6848 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6852 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6856 if (num_valid_macs(zvni
)) {
6857 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6861 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6866 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6867 struct zebra_vrf
*zvrf
)
6871 if (!is_evpn_enabled())
6877 hash_iterate(zvrf
->vni_table
,
6878 (void (*)(struct hash_bucket
*, void *))
6879 zvni_clear_dup_detect_hash_vni_all
, args
);
6884 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6885 struct zebra_vrf
*zvrf
,
6889 struct mac_walk_ctx m_wctx
;
6890 struct neigh_walk_ctx n_wctx
;
6892 if (!is_evpn_enabled())
6895 zvni
= zvni_lookup(vni
);
6897 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6901 if (hashcount(zvni
->neigh_table
)) {
6902 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6906 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6910 if (num_valid_macs(zvni
)) {
6911 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6915 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6922 * Display MACs for a VNI from specific VTEP (VTY command handler).
6924 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6925 vni_t vni
, struct in_addr vtep_ip
,
6930 struct mac_walk_ctx wctx
;
6931 json_object
*json
= NULL
;
6932 json_object
*json_mac
= NULL
;
6934 if (!is_evpn_enabled())
6936 zvni
= zvni_lookup(vni
);
6939 vty_out(vty
, "{}\n");
6941 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6944 num_macs
= num_valid_macs(zvni
);
6949 json
= json_object_new_object();
6950 json_mac
= json_object_new_object();
6953 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6956 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6957 wctx
.r_vtep_ip
= vtep_ip
;
6958 wctx
.json
= json_mac
;
6959 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6962 json_object_int_add(json
, "numMacs", wctx
.count
);
6964 json_object_object_add(json
, "macs", json_mac
);
6965 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6966 json
, JSON_C_TO_STRING_PRETTY
));
6967 json_object_free(json
);
6973 * Display VNI information (VTY command handler).
6975 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6978 json_object
*json
= NULL
;
6980 zebra_l3vni_t
*zl3vni
= NULL
;
6981 zebra_vni_t
*zvni
= NULL
;
6983 if (!is_evpn_enabled())
6987 json
= json_object_new_object();
6991 zl3vni
= zl3vni_lookup(vni
);
6993 zl3vni_print(zl3vni
, (void *)args
);
6995 zvni
= zvni_lookup(vni
);
6998 vty_out(vty
, "{}\n");
7000 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7004 zvni_print(zvni
, (void *)args
);
7008 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7009 json
, JSON_C_TO_STRING_PRETTY
));
7010 json_object_free(json
);
7014 /* Display all global details for EVPN */
7015 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7020 json_object
*json
= NULL
;
7021 struct zebra_vrf
*zvrf
= NULL
;
7023 if (!is_evpn_enabled())
7026 zvrf
= zebra_vrf_get_evpn();
7030 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7031 num_l2vnis
= hashcount(zvrf
->vni_table
);
7032 num_vnis
= num_l2vnis
+ num_l3vnis
;
7035 json
= json_object_new_object();
7036 json_object_string_add(json
, "advertiseGatewayMacip",
7037 zvrf
->advertise_gw_macip
? "Yes" : "No");
7038 json_object_int_add(json
, "numVnis", num_vnis
);
7039 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7040 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7041 if (zvrf
->dup_addr_detect
)
7042 json_object_boolean_true_add(json
,
7043 "isDuplicateAddrDetection");
7045 json_object_boolean_false_add(json
,
7046 "isDuplicateAddrDetection");
7047 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7048 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7049 json_object_int_add(json
, "detectionFreezeTime",
7050 zvrf
->dad_freeze_time
);
7053 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7054 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7055 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7056 zvrf
->advertise_gw_macip
? "Yes" : "No");
7057 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7058 zvrf
->advertise_svi_macip
? "Yes" : "No");
7059 vty_out(vty
, "Duplicate address detection: %s\n",
7060 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7061 vty_out(vty
, " Detection max-moves %u, time %d\n",
7062 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7063 if (zvrf
->dad_freeze
) {
7064 if (zvrf
->dad_freeze_time
)
7065 vty_out(vty
, " Detection freeze %u\n",
7066 zvrf
->dad_freeze_time
);
7068 vty_out(vty
, " Detection freeze %s\n",
7074 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7075 json
, JSON_C_TO_STRING_PRETTY
));
7076 json_object_free(json
);
7081 * Display VNI hash table (VTY command handler).
7083 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7086 json_object
*json
= NULL
;
7089 if (!is_evpn_enabled())
7093 json
= json_object_new_object();
7095 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7096 "Type", "VxLAN IF", "# MACs", "# ARPs",
7097 "# Remote VTEPs", "Tenant VRF");
7102 /* Display all L2-VNIs */
7103 hash_iterate(zvrf
->vni_table
,
7104 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7107 /* Display all L3-VNIs */
7108 hash_iterate(zrouter
.l3vni_table
,
7109 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7113 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7114 json
, JSON_C_TO_STRING_PRETTY
));
7115 json_object_free(json
);
7119 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7123 uint32_t max_moves
= 0;
7124 uint32_t freeze_time
= 0;
7125 bool dup_addr_detect
= false;
7126 bool freeze
= false;
7129 STREAM_GETL(s
, dup_addr_detect
);
7130 STREAM_GETL(s
, time
);
7131 STREAM_GETL(s
, max_moves
);
7132 STREAM_GETL(s
, freeze
);
7133 STREAM_GETL(s
, freeze_time
);
7135 /* DAD previous state was enabled, and new state is disable,
7136 * clear all duplicate detected addresses.
7138 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7139 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7141 zvrf
->dup_addr_detect
= dup_addr_detect
;
7142 zvrf
->dad_time
= time
;
7143 zvrf
->dad_max_moves
= max_moves
;
7144 zvrf
->dad_freeze
= freeze
;
7145 zvrf
->dad_freeze_time
= freeze_time
;
7147 if (IS_ZEBRA_DEBUG_VXLAN
)
7149 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7150 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7151 zvrf
->dup_addr_detect
? "enable" : "disable",
7152 zvrf
->dad_max_moves
,
7154 zvrf
->dad_freeze
? "enable" : "disable",
7155 zvrf
->dad_freeze_time
);
7162 * Display VNI hash table in detail(VTY command handler).
7164 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7167 json_object
*json
= NULL
;
7168 struct zebra_ns
*zns
= NULL
;
7169 struct zvni_evpn_show zes
;
7171 if (!is_evpn_enabled())
7174 zns
= zebra_ns_lookup(NS_DEFAULT
);
7180 json
= json_object_new_object();
7186 /* Display all L2-VNIs */
7189 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7192 /* Display all L3-VNIs */
7193 hash_iterate(zrouter
.l3vni_table
,
7194 (void (*)(struct hash_bucket
*,
7195 void *))zl3vni_print_hash_detail
,
7199 vty_out(vty
, "%s\n",
7200 json_object_to_json_string_ext(
7201 json
, JSON_C_TO_STRING_PRETTY
));
7202 json_object_free(json
);
7207 * Handle neighbor delete notification from the kernel (on a VLAN device
7208 * / L3 interface). This may result in either the neighbor getting deleted
7209 * from our database or being re-added to the kernel (if it is a valid
7212 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7213 struct interface
*link_if
,
7216 char buf
[INET6_ADDRSTRLEN
];
7217 char buf2
[ETHER_ADDR_STRLEN
];
7218 zebra_neigh_t
*n
= NULL
;
7219 zebra_vni_t
*zvni
= NULL
;
7220 zebra_mac_t
*zmac
= NULL
;
7221 zebra_l3vni_t
*zl3vni
= NULL
;
7222 struct zebra_vrf
*zvrf
;
7224 /* check if this is a remote neigh entry corresponding to remote
7227 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7229 return zl3vni_local_nh_del(zl3vni
, ip
);
7231 /* We are only interested in neighbors on an SVI that resides on top
7232 * of a VxLAN bridge.
7234 zvni
= zvni_from_svi(ifp
, link_if
);
7238 if (!zvni
->vxlan_if
) {
7240 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7245 if (IS_ZEBRA_DEBUG_VXLAN
)
7246 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7247 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7248 ifp
->ifindex
, zvni
->vni
);
7250 /* If entry doesn't exist, nothing to do. */
7251 n
= zvni_neigh_lookup(zvni
, ip
);
7255 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7257 if (IS_ZEBRA_DEBUG_VXLAN
)
7259 "Trying to del a neigh %s without a mac %s on VNI %u",
7260 ipaddr2str(ip
, buf
, sizeof(buf
)),
7261 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7267 /* If it is a remote entry, the kernel has aged this out or someone has
7268 * deleted it, it needs to be re-installed as Quagga is the owner.
7270 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7271 zvni_neigh_install(zvni
, n
);
7275 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7277 zlog_debug("%s: VNI %u vrf lookup failed.",
7278 __PRETTY_FUNCTION__
, zvni
->vni
);
7282 /* In case of feeze action, if local neigh is in duplicate state,
7283 * Mark the Neigh as inactive before sending delete request to BGPd,
7284 * If BGPd has remote entry, it will re-install
7286 if (zvrf
->dad_freeze
&&
7287 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7288 ZEBRA_NEIGH_SET_INACTIVE(n
);
7290 /* Remove neighbor from BGP. */
7291 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7293 /* Delete this neighbor entry. */
7294 zvni_neigh_del(zvni
, n
);
7296 /* see if the AUTO mac needs to be deleted */
7297 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7298 && !listcount(zmac
->neigh_list
))
7299 zvni_mac_del(zvni
, zmac
);
7305 * Handle neighbor add or update notification from the kernel (on a VLAN
7306 * device / L3 interface). This is typically for a local neighbor but can
7307 * also be for a remote neighbor (e.g., ageout notification). It could
7308 * also be a "move" scenario.
7310 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7311 struct interface
*link_if
,
7313 struct ethaddr
*macaddr
,
7318 char buf
[ETHER_ADDR_STRLEN
];
7319 char buf2
[INET6_ADDRSTRLEN
];
7320 zebra_vni_t
*zvni
= NULL
;
7321 zebra_l3vni_t
*zl3vni
= NULL
;
7323 /* check if this is a remote neigh entry corresponding to remote
7326 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7328 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7330 /* We are only interested in neighbors on an SVI that resides on top
7331 * of a VxLAN bridge.
7333 zvni
= zvni_from_svi(ifp
, link_if
);
7337 if (IS_ZEBRA_DEBUG_VXLAN
)
7339 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7340 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7341 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7342 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7343 is_router
? "router " : "",
7346 /* Is this about a local neighbor or a remote one? */
7348 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7351 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7356 * Handle message from client to delete a remote MACIP for a VNI.
7358 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7362 struct ethaddr macaddr
;
7364 struct in_addr vtep_ip
;
7365 uint16_t l
= 0, ipa_len
;
7366 char buf
[ETHER_ADDR_STRLEN
];
7367 char buf1
[INET6_ADDRSTRLEN
];
7369 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7370 memset(&ip
, 0, sizeof(struct ipaddr
));
7371 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7375 while (l
< hdr
->length
) {
7376 /* Obtain each remote MACIP and process. */
7377 /* Message contains VNI, followed by MAC followed by IP (if any)
7378 * followed by remote VTEP IP.
7380 memset(&ip
, 0, sizeof(ip
));
7381 STREAM_GETL(s
, vni
);
7382 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7383 STREAM_GETL(s
, ipa_len
);
7385 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7387 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7389 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7390 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7391 l
+= IPV4_MAX_BYTELEN
;
7393 if (IS_ZEBRA_DEBUG_VXLAN
)
7395 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7397 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7398 ipa_len
? " IP " : "",
7400 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7402 zebra_route_string(client
->proto
));
7404 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7412 * Handle message from client to add a remote MACIP for a VNI. This
7413 * could be just the add of a MAC address or the add of a neighbor
7416 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7420 struct ethaddr macaddr
;
7422 struct in_addr vtep_ip
;
7423 uint16_t l
= 0, ipa_len
;
7426 char buf
[ETHER_ADDR_STRLEN
];
7427 char buf1
[INET6_ADDRSTRLEN
];
7429 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7430 memset(&ip
, 0, sizeof(struct ipaddr
));
7431 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7433 if (!EVPN_ENABLED(zvrf
)) {
7434 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7440 while (l
< hdr
->length
) {
7441 /* Obtain each remote MACIP and process. */
7442 /* Message contains VNI, followed by MAC followed by IP (if any)
7443 * followed by remote VTEP IP.
7445 memset(&ip
, 0, sizeof(ip
));
7446 STREAM_GETL(s
, vni
);
7447 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7448 STREAM_GETL(s
, ipa_len
);
7450 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7452 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7454 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7455 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7456 l
+= IPV4_MAX_BYTELEN
;
7458 /* Get flags - sticky mac and/or gateway mac */
7459 STREAM_GETC(s
, flags
);
7461 STREAM_GETL(s
, seq
);
7464 if (IS_ZEBRA_DEBUG_VXLAN
)
7466 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7468 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7469 ipa_len
? " IP " : "",
7471 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7472 flags
, seq
, inet_ntoa(vtep_ip
),
7473 zebra_route_string(client
->proto
));
7475 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7476 flags
, seq
, vtep_ip
);
7484 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7485 * us, this must involve a multihoming scenario. Treat this as implicit delete
7486 * of any prior local MAC.
7488 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7489 struct interface
*br_if
,
7490 struct ethaddr
*macaddr
, vlanid_t vid
)
7492 struct zebra_if
*zif
;
7493 struct zebra_l2info_vxlan
*vxl
;
7497 char buf
[ETHER_ADDR_STRLEN
];
7501 vxl
= &zif
->l2info
.vxl
;
7504 /* Check if EVPN is enabled. */
7505 if (!is_evpn_enabled())
7508 /* Locate hash entry; it is expected to exist. */
7509 zvni
= zvni_lookup(vni
);
7513 /* If entry doesn't exist, nothing to do. */
7514 mac
= zvni_mac_lookup(zvni
, macaddr
);
7518 /* Is it a local entry? */
7519 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7522 if (IS_ZEBRA_DEBUG_VXLAN
)
7524 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7525 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7526 ifp
->ifindex
, vni
, mac
->flags
);
7528 /* Remove MAC from BGP. */
7529 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7532 * If there are no neigh associated with the mac delete the mac
7533 * else mark it as AUTO for forward reference
7535 if (!listcount(mac
->neigh_list
)) {
7536 zvni_mac_del(zvni
, mac
);
7538 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7539 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7540 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7547 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7548 * This can happen because the remote MAC entries are also added as "dynamic",
7549 * so the kernel can ageout the entry.
7551 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7552 struct interface
*br_if
,
7553 struct ethaddr
*macaddr
, vlanid_t vid
)
7555 struct zebra_if
*zif
= NULL
;
7556 struct zebra_l2info_vxlan
*vxl
= NULL
;
7558 zebra_vni_t
*zvni
= NULL
;
7559 zebra_l3vni_t
*zl3vni
= NULL
;
7560 zebra_mac_t
*mac
= NULL
;
7561 char buf
[ETHER_ADDR_STRLEN
];
7565 vxl
= &zif
->l2info
.vxl
;
7568 /* Check if EVPN is enabled. */
7569 if (!is_evpn_enabled())
7572 /* check if this is a remote RMAC and readd simillar to remote macs */
7573 zl3vni
= zl3vni_lookup(vni
);
7575 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7577 /* Locate hash entry; it is expected to exist. */
7578 zvni
= zvni_lookup(vni
);
7582 /* If entry doesn't exist, nothing to do. */
7583 mac
= zvni_mac_lookup(zvni
, macaddr
);
7587 /* Is it a remote entry? */
7588 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7591 if (IS_ZEBRA_DEBUG_VXLAN
)
7592 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7593 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7596 zvni_mac_install(zvni
, mac
);
7601 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7603 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7604 struct ethaddr
*macaddr
, vlanid_t vid
)
7608 char buf
[ETHER_ADDR_STRLEN
];
7610 /* We are interested in MACs only on ports or (port, VLAN) that
7613 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7616 if (!zvni
->vxlan_if
) {
7618 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7623 /* If entry doesn't exist, nothing to do. */
7624 mac
= zvni_mac_lookup(zvni
, macaddr
);
7628 /* Is it a local entry? */
7629 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7632 if (IS_ZEBRA_DEBUG_VXLAN
)
7633 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7634 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7635 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7637 /* Update all the neigh entries associated with this mac */
7638 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7640 /* Remove MAC from BGP. */
7641 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7644 * If there are no neigh associated with the mac delete the mac
7645 * else mark it as AUTO for forward reference
7647 if (!listcount(mac
->neigh_list
)) {
7648 zvni_mac_del(zvni
, mac
);
7650 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7651 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7652 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7659 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7661 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7662 struct interface
*br_if
,
7663 struct ethaddr
*macaddr
, vlanid_t vid
,
7668 struct zebra_vrf
*zvrf
;
7669 char buf
[ETHER_ADDR_STRLEN
];
7670 bool mac_sticky
= false;
7671 bool inform_client
= false;
7672 bool upd_neigh
= false;
7673 bool is_dup_detect
= false;
7674 struct in_addr vtep_ip
= {.s_addr
= 0};
7676 /* We are interested in MACs only on ports or (port, VLAN) that
7679 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7681 if (IS_ZEBRA_DEBUG_VXLAN
)
7683 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7684 sticky
? "sticky " : "",
7685 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7686 ifp
->name
, ifp
->ifindex
, vid
);
7690 if (!zvni
->vxlan_if
) {
7691 if (IS_ZEBRA_DEBUG_VXLAN
)
7693 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7698 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7700 if (IS_ZEBRA_DEBUG_VXLAN
)
7701 zlog_debug("\tNo Vrf found for vrf_id: %d",
7702 zvni
->vxlan_if
->vrf_id
);
7706 /* Check if we need to create or update or it is a NO-OP. */
7707 mac
= zvni_mac_lookup(zvni
, macaddr
);
7709 if (IS_ZEBRA_DEBUG_VXLAN
)
7711 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7712 sticky
? "sticky " : "",
7713 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7714 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7716 mac
= zvni_mac_add(zvni
, macaddr
);
7719 EC_ZEBRA_MAC_ADD_FAILED
,
7720 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7721 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7722 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7725 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7726 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7727 mac
->fwd_info
.local
.vid
= vid
;
7729 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7730 inform_client
= true;
7733 if (IS_ZEBRA_DEBUG_VXLAN
)
7735 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7736 sticky
? "sticky " : "",
7737 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7738 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7741 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7742 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7746 * Update any changes and if changes are relevant to
7749 if (mac_sticky
== sticky
7750 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7751 && mac
->fwd_info
.local
.vid
== vid
) {
7752 if (IS_ZEBRA_DEBUG_VXLAN
)
7754 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7755 "entry exists and has not changed ",
7756 sticky
? "sticky " : "",
7757 prefix_mac2str(macaddr
, buf
,
7759 ifp
->name
, ifp
->ifindex
, vid
,
7763 if (mac_sticky
!= sticky
) {
7765 SET_FLAG(mac
->flags
,
7768 UNSET_FLAG(mac
->flags
,
7770 inform_client
= true;
7773 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7774 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7775 mac
->fwd_info
.local
.vid
= vid
;
7777 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7778 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7779 bool do_dad
= false;
7782 * MAC has either moved or was "internally" created due
7783 * to a neighbor learn and is now actually learnt. If
7784 * it was learnt as a remote sticky MAC, this is an
7787 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7789 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7790 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7791 prefix_mac2str(macaddr
, buf
,
7793 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7798 /* If an actual move, compute MAC's seq number */
7799 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7800 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7802 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7803 /* Trigger DAD for remote MAC */
7807 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7808 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7809 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7810 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7811 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7812 mac
->fwd_info
.local
.vid
= vid
;
7814 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7816 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7818 * We have to inform BGP of this MAC as well as process
7821 inform_client
= true;
7824 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7828 if (is_dup_detect
) {
7829 inform_client
= false;
7835 /* Inform BGP if required. */
7836 if (inform_client
) {
7837 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7838 mac
->flags
, mac
->loc_seq
))
7842 /* Process all neighbors associated with this MAC, if required. */
7844 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7850 * Handle message from client to delete a remote VTEP for a VNI.
7852 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7855 unsigned short l
= 0;
7857 struct in_addr vtep_ip
;
7859 zebra_vtep_t
*zvtep
;
7860 struct interface
*ifp
;
7861 struct zebra_if
*zif
;
7863 if (!is_evpn_enabled()) {
7865 "%s: EVPN is not enabled yet we have received a vtep del command",
7866 __PRETTY_FUNCTION__
);
7870 if (!EVPN_ENABLED(zvrf
)) {
7871 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7878 while (l
< hdr
->length
) {
7879 int flood_control
__attribute__((unused
));
7881 /* Obtain each remote VTEP and process. */
7882 STREAM_GETL(s
, vni
);
7884 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7885 l
+= IPV4_MAX_BYTELEN
;
7887 /* Flood control is intentionally ignored right now */
7888 STREAM_GETL(s
, flood_control
);
7891 if (IS_ZEBRA_DEBUG_VXLAN
)
7892 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7893 inet_ntoa(vtep_ip
), vni
,
7894 zebra_route_string(client
->proto
));
7896 /* Locate VNI hash entry - expected to exist. */
7897 zvni
= zvni_lookup(vni
);
7899 if (IS_ZEBRA_DEBUG_VXLAN
)
7901 "Failed to locate VNI hash upon remote VTEP DEL, "
7907 ifp
= zvni
->vxlan_if
;
7910 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7916 /* If down or not mapped to a bridge, we're done. */
7917 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7920 /* If the remote VTEP does not exist, there's nothing more to
7922 * Otherwise, uninstall any remote MACs pointing to this VTEP
7924 * then, the VTEP entry itself and remove it.
7926 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7930 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7931 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7932 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7933 zvni_vtep_del(zvni
, zvtep
);
7941 * Handle message from client to add a remote VTEP for a VNI.
7943 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7946 unsigned short l
= 0;
7948 struct in_addr vtep_ip
;
7950 struct interface
*ifp
;
7951 struct zebra_if
*zif
;
7953 zebra_vtep_t
*zvtep
;
7955 if (!is_evpn_enabled()) {
7957 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7958 __PRETTY_FUNCTION__
);
7962 if (!EVPN_ENABLED(zvrf
)) {
7963 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7970 while (l
< hdr
->length
) {
7971 /* Obtain each remote VTEP and process. */
7972 STREAM_GETL(s
, vni
);
7974 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7975 STREAM_GETL(s
, flood_control
);
7976 l
+= IPV4_MAX_BYTELEN
+ 4;
7978 if (IS_ZEBRA_DEBUG_VXLAN
)
7979 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
7980 inet_ntoa(vtep_ip
), vni
, flood_control
,
7981 zebra_route_string(client
->proto
));
7983 /* Locate VNI hash entry - expected to exist. */
7984 zvni
= zvni_lookup(vni
);
7987 EC_ZEBRA_VTEP_ADD_FAILED
,
7988 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7993 ifp
= zvni
->vxlan_if
;
7996 EC_ZEBRA_VTEP_ADD_FAILED
,
7997 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8004 /* If down or not mapped to a bridge, we're done. */
8005 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8008 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8010 /* If the remote VTEP already exists check if
8011 * the flood mode has changed
8013 if (zvtep
->flood_control
!= flood_control
) {
8014 if (zvtep
->flood_control
8015 == VXLAN_FLOOD_DISABLED
)
8016 /* old mode was head-end-replication but
8017 * is no longer; get rid of the HER fdb
8018 * entry installed before
8020 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8021 zvtep
->flood_control
= flood_control
;
8022 zvni_vtep_install(zvni
, zvtep
);
8025 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8027 zvni_vtep_install(zvni
, zvtep
);
8029 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8030 "Failed to add remote VTEP, VNI %u zvni %p",
8040 * Add/Del gateway macip to evpn
8042 * 1. SVI interface on a vlan aware bridge
8043 * 2. SVI interface on a vlan unaware bridge
8044 * 3. vrr interface (MACVLAN) associated to a SVI
8045 * We advertise macip routes for an interface if it is associated to VxLan vlan
8047 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8051 struct ethaddr macaddr
;
8052 zebra_vni_t
*zvni
= NULL
;
8054 memset(&ip
, 0, sizeof(struct ipaddr
));
8055 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8057 /* Check if EVPN is enabled. */
8058 if (!is_evpn_enabled())
8061 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8062 struct interface
*svi_if
=
8063 NULL
; /* SVI corresponding to the MACVLAN */
8064 struct zebra_if
*ifp_zif
=
8065 NULL
; /* Zebra daemon specific info for MACVLAN */
8066 struct zebra_if
*svi_if_zif
=
8067 NULL
; /* Zebra daemon specific info for SVI*/
8069 ifp_zif
= ifp
->info
;
8074 * for a MACVLAN interface the link represents the svi_if
8076 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8077 ifp_zif
->link_ifindex
);
8079 zlog_debug("MACVLAN %s(%u) without link information",
8080 ifp
->name
, ifp
->ifindex
);
8084 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8086 * If it is a vlan aware bridge then the link gives the
8087 * bridge information
8089 struct interface
*svi_if_link
= NULL
;
8091 svi_if_zif
= svi_if
->info
;
8093 svi_if_link
= if_lookup_by_index_per_ns(
8094 zebra_ns_lookup(NS_DEFAULT
),
8095 svi_if_zif
->link_ifindex
);
8096 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8098 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8100 * If it is a vlan unaware bridge then svi is the bridge
8103 zvni
= zvni_from_svi(svi_if
, svi_if
);
8105 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8106 struct zebra_if
*svi_if_zif
=
8107 NULL
; /* Zebra daemon specific info for SVI */
8108 struct interface
*svi_if_link
=
8109 NULL
; /* link info for the SVI = bridge info */
8111 svi_if_zif
= ifp
->info
;
8113 svi_if_link
= if_lookup_by_index_per_ns(
8114 zebra_ns_lookup(NS_DEFAULT
),
8115 svi_if_zif
->link_ifindex
);
8117 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8119 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8120 zvni
= zvni_from_svi(ifp
, ifp
);
8126 if (!zvni
->vxlan_if
) {
8127 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8133 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8135 if (p
->family
== AF_INET
) {
8136 ip
.ipa_type
= IPADDR_V4
;
8137 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8138 sizeof(struct in_addr
));
8139 } else if (p
->family
== AF_INET6
) {
8140 ip
.ipa_type
= IPADDR_V6
;
8141 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8142 sizeof(struct in6_addr
));
8147 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8149 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8155 * Handle SVI interface going down.
8156 * SVI can be associated to either L3-VNI or L2-VNI.
8157 * For L2-VNI: At this point, this is a NOP since
8158 * the kernel deletes the neighbor entries on this SVI (if any).
8159 * We only need to update the vrf corresponding to zvni.
8160 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8163 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8165 zebra_l3vni_t
*zl3vni
= NULL
;
8167 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8170 /* process l3-vni down */
8171 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8173 /* remove association with svi-if */
8174 zl3vni
->svi_if
= NULL
;
8176 zebra_vni_t
*zvni
= NULL
;
8178 /* since we dont have svi corresponding to zvni, we associate it
8179 * to default vrf. Note: the corresponding neigh entries on the
8180 * SVI would have already been deleted */
8181 zvni
= zvni_from_svi(ifp
, link_if
);
8183 zvni
->vrf_id
= VRF_DEFAULT
;
8185 /* update the tenant vrf in BGP */
8186 zvni_send_add_to_client(zvni
);
8193 * Handle SVI interface coming up.
8194 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8196 * For L2-VNI: we need to install any remote neighbors entried (used for
8198 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8200 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8202 zebra_vni_t
*zvni
= NULL
;
8203 zebra_l3vni_t
*zl3vni
= NULL
;
8205 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8208 /* associate with svi */
8209 zl3vni
->svi_if
= ifp
;
8211 /* process oper-up */
8212 if (is_l3vni_oper_up(zl3vni
))
8213 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8216 /* process SVI up for l2-vni */
8217 struct neigh_walk_ctx n_wctx
;
8219 zvni
= zvni_from_svi(ifp
, link_if
);
8223 if (!zvni
->vxlan_if
) {
8225 "VNI %u hash %p doesn't have intf upon SVI up",
8230 if (IS_ZEBRA_DEBUG_VXLAN
)
8232 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8233 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8234 vrf_id_to_name(ifp
->vrf_id
));
8236 /* update the vrf information for l2-vni and inform bgp */
8237 zvni
->vrf_id
= ifp
->vrf_id
;
8238 zvni_send_add_to_client(zvni
);
8240 /* Install any remote neighbors for this VNI. */
8241 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8243 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8251 * Handle VxLAN interface down
8253 int zebra_vxlan_if_down(struct interface
*ifp
)
8256 struct zebra_if
*zif
= NULL
;
8257 struct zebra_l2info_vxlan
*vxl
= NULL
;
8258 zebra_l3vni_t
*zl3vni
= NULL
;
8261 /* Check if EVPN is enabled. */
8262 if (!is_evpn_enabled())
8267 vxl
= &zif
->l2info
.vxl
;
8270 zl3vni
= zl3vni_lookup(vni
);
8272 /* process-if-down for l3-vni */
8273 if (IS_ZEBRA_DEBUG_VXLAN
)
8274 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8277 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8279 /* process if-down for l2-vni */
8280 if (IS_ZEBRA_DEBUG_VXLAN
)
8281 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8284 /* Locate hash entry; it is expected to exist. */
8285 zvni
= zvni_lookup(vni
);
8288 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8289 ifp
->name
, ifp
->ifindex
, vni
);
8293 assert(zvni
->vxlan_if
== ifp
);
8295 /* Delete this VNI from BGP. */
8296 zvni_send_del_to_client(zvni
->vni
);
8298 /* Free up all neighbors and MACs, if any. */
8299 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8300 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8302 /* Free up all remote VTEPs, if any. */
8303 zvni_vtep_del_all(zvni
, 1);
8309 * Handle VxLAN interface up - update BGP if required.
8311 int zebra_vxlan_if_up(struct interface
*ifp
)
8314 struct zebra_if
*zif
= NULL
;
8315 struct zebra_l2info_vxlan
*vxl
= NULL
;
8316 zebra_vni_t
*zvni
= NULL
;
8317 zebra_l3vni_t
*zl3vni
= NULL
;
8319 /* Check if EVPN is enabled. */
8320 if (!is_evpn_enabled())
8325 vxl
= &zif
->l2info
.vxl
;
8328 zl3vni
= zl3vni_lookup(vni
);
8331 if (IS_ZEBRA_DEBUG_VXLAN
)
8332 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8335 /* we need to associate with SVI, if any, we can associate with
8336 * svi-if only after association with vxlan-intf is complete
8338 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8340 if (is_l3vni_oper_up(zl3vni
))
8341 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8343 /* Handle L2-VNI add */
8344 struct interface
*vlan_if
= NULL
;
8346 if (IS_ZEBRA_DEBUG_VXLAN
)
8347 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8350 /* Locate hash entry; it is expected to exist. */
8351 zvni
= zvni_lookup(vni
);
8354 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8355 ifp
->name
, ifp
->ifindex
, vni
);
8359 assert(zvni
->vxlan_if
== ifp
);
8360 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8361 zif
->brslave_info
.br_if
);
8363 zvni
->vrf_id
= vlan_if
->vrf_id
;
8364 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8366 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8369 /* If part of a bridge, inform BGP about this VNI. */
8370 /* Also, read and populate local MACs and neighbors. */
8371 if (zif
->brslave_info
.br_if
) {
8372 zvni_send_add_to_client(zvni
);
8373 zvni_read_mac_neigh(zvni
, ifp
);
8381 * Handle VxLAN interface delete. Locate and remove entry in hash table
8382 * and update BGP, if required.
8384 int zebra_vxlan_if_del(struct interface
*ifp
)
8387 struct zebra_if
*zif
= NULL
;
8388 struct zebra_l2info_vxlan
*vxl
= NULL
;
8389 zebra_vni_t
*zvni
= NULL
;
8390 zebra_l3vni_t
*zl3vni
= NULL
;
8392 /* Check if EVPN is enabled. */
8393 if (!is_evpn_enabled())
8398 vxl
= &zif
->l2info
.vxl
;
8401 zl3vni
= zl3vni_lookup(vni
);
8404 if (IS_ZEBRA_DEBUG_VXLAN
)
8405 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8408 /* process oper-down for l3-vni */
8409 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8411 /* remove the association with vxlan_if */
8412 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8413 zl3vni
->vxlan_if
= NULL
;
8416 /* process if-del for l2-vni*/
8417 if (IS_ZEBRA_DEBUG_VXLAN
)
8418 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8421 /* Locate hash entry; it is expected to exist. */
8422 zvni
= zvni_lookup(vni
);
8425 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8426 ifp
->name
, ifp
->ifindex
, vni
);
8430 /* remove from l3-vni list */
8431 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8433 listnode_delete(zl3vni
->l2vnis
, zvni
);
8435 /* Delete VNI from BGP. */
8436 zvni_send_del_to_client(zvni
->vni
);
8438 /* Free up all neighbors and MAC, if any. */
8439 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8440 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8442 /* Free up all remote VTEPs, if any. */
8443 zvni_vtep_del_all(zvni
, 0);
8445 /* Delete the hash entry. */
8446 if (zvni_del(zvni
)) {
8447 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8448 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8449 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8457 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8459 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8462 struct zebra_if
*zif
= NULL
;
8463 struct zebra_l2info_vxlan
*vxl
= NULL
;
8464 zebra_vni_t
*zvni
= NULL
;
8465 zebra_l3vni_t
*zl3vni
= NULL
;
8467 /* Check if EVPN is enabled. */
8468 if (!is_evpn_enabled())
8473 vxl
= &zif
->l2info
.vxl
;
8476 zl3vni
= zl3vni_lookup(vni
);
8479 if (IS_ZEBRA_DEBUG_VXLAN
)
8481 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8482 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8483 inet_ntoa(vxl
->vtep_ip
),
8484 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8486 /* Removed from bridge? Cleanup and return */
8487 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8488 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8489 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8493 /* access-vlan change - process oper down, associate with new
8494 * svi_if and then process oper up again
8496 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8497 if (if_is_operative(ifp
)) {
8498 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8499 zl3vni
->svi_if
= NULL
;
8500 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8501 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8502 if (is_l3vni_oper_up(zl3vni
))
8503 zebra_vxlan_process_l3vni_oper_up(
8509 * local-ip change - process oper down, associate with new
8510 * local-ip and then process oper up again
8512 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8513 if (if_is_operative(ifp
)) {
8514 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8515 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8516 if (is_l3vni_oper_up(zl3vni
))
8517 zebra_vxlan_process_l3vni_oper_up(
8522 /* Update local tunnel IP. */
8523 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8525 /* if we have a valid new master, process l3-vni oper up */
8526 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8527 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8528 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8532 /* Update VNI hash. */
8533 zvni
= zvni_lookup(vni
);
8536 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8537 ifp
->name
, ifp
->ifindex
, vni
);
8541 if (IS_ZEBRA_DEBUG_VXLAN
)
8543 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8544 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8545 inet_ntoa(vxl
->vtep_ip
),
8546 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8548 /* Removed from bridge? Cleanup and return */
8549 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8550 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8551 /* Delete from client, remove all remote VTEPs */
8552 /* Also, free up all MACs and neighbors. */
8553 zvni_send_del_to_client(zvni
->vni
);
8554 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8555 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8556 zvni_vtep_del_all(zvni
, 1);
8560 /* Handle other changes. */
8561 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8562 /* Remove all existing local neigh and MACs for this VNI
8563 * (including from BGP)
8565 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8566 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8569 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8570 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8571 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8573 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8574 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8575 zvni
->mcast_grp
= vxl
->mcast_grp
;
8577 zvni
->vxlan_if
= ifp
;
8579 /* Take further actions needed.
8580 * Note that if we are here, there is a change of interest.
8582 /* If down or not mapped to a bridge, we're done. */
8583 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8586 /* Inform BGP, if there is a change of interest. */
8588 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8589 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8590 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8591 zvni_send_add_to_client(zvni
);
8593 /* If there is a valid new master or a VLAN mapping change,
8594 * read and populate local MACs and neighbors.
8595 * Also, reinstall any remote MACs and neighbors
8596 * for this VNI (based on new VLAN).
8598 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8599 zvni_read_mac_neigh(zvni
, ifp
);
8600 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8601 struct mac_walk_ctx m_wctx
;
8602 struct neigh_walk_ctx n_wctx
;
8604 zvni_read_mac_neigh(zvni
, ifp
);
8606 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8608 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8611 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8613 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8622 * Handle VxLAN interface add.
8624 int zebra_vxlan_if_add(struct interface
*ifp
)
8627 struct zebra_if
*zif
= NULL
;
8628 struct zebra_l2info_vxlan
*vxl
= NULL
;
8629 zebra_vni_t
*zvni
= NULL
;
8630 zebra_l3vni_t
*zl3vni
= NULL
;
8632 /* Check if EVPN is enabled. */
8633 if (!is_evpn_enabled())
8638 vxl
= &zif
->l2info
.vxl
;
8641 zl3vni
= zl3vni_lookup(vni
);
8644 /* process if-add for l3-vni*/
8645 if (IS_ZEBRA_DEBUG_VXLAN
)
8647 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8648 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8649 inet_ntoa(vxl
->vtep_ip
),
8650 zif
->brslave_info
.bridge_ifindex
);
8652 /* associate with vxlan_if */
8653 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8654 zl3vni
->vxlan_if
= ifp
;
8656 /* Associate with SVI, if any. We can associate with svi-if only
8657 * after association with vxlan_if is complete */
8658 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8660 if (is_l3vni_oper_up(zl3vni
))
8661 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8664 /* process if-add for l2-vni */
8665 struct interface
*vlan_if
= NULL
;
8667 /* Create or update VNI hash. */
8668 zvni
= zvni_lookup(vni
);
8670 zvni
= zvni_add(vni
);
8673 EC_ZEBRA_VNI_ADD_FAILED
,
8674 "Failed to add VNI hash, IF %s(%u) VNI %u",
8675 ifp
->name
, ifp
->ifindex
, vni
);
8680 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8681 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8682 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8684 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8685 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8686 zvni
->mcast_grp
= vxl
->mcast_grp
;
8688 zvni
->vxlan_if
= ifp
;
8689 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8690 zif
->brslave_info
.br_if
);
8692 zvni
->vrf_id
= vlan_if
->vrf_id
;
8693 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8695 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8698 if (IS_ZEBRA_DEBUG_VXLAN
) {
8699 char addr_buf1
[INET_ADDRSTRLEN
];
8700 char addr_buf2
[INET_ADDRSTRLEN
];
8702 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8703 addr_buf1
, INET_ADDRSTRLEN
);
8704 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8705 addr_buf2
, INET_ADDRSTRLEN
);
8708 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8710 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8712 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8713 addr_buf1
, addr_buf2
,
8714 zif
->brslave_info
.bridge_ifindex
);
8717 /* If down or not mapped to a bridge, we're done. */
8718 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8722 zvni_send_add_to_client(zvni
);
8724 /* Read and populate local MACs and neighbors */
8725 zvni_read_mac_neigh(zvni
, ifp
);
8731 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8732 char *err
, int err_str_sz
, int filter
,
8735 zebra_l3vni_t
*zl3vni
= NULL
;
8736 struct zebra_vrf
*zvrf_evpn
= NULL
;
8738 zvrf_evpn
= zebra_vrf_get_evpn();
8742 if (IS_ZEBRA_DEBUG_VXLAN
)
8743 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8744 add
? "ADD" : "DEL");
8748 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8750 /* check if the vni is already present under zvrf */
8752 snprintf(err
, err_str_sz
,
8753 "VNI is already configured under the vrf");
8757 /* check if this VNI is already present in the system */
8758 zl3vni
= zl3vni_lookup(vni
);
8760 snprintf(err
, err_str_sz
,
8761 "VNI is already configured as L3-VNI");
8765 /* add the L3-VNI to the global table */
8766 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8768 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8772 /* associate the vrf with vni */
8775 /* set the filter in l3vni to denote if we are using l3vni only
8779 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8781 /* associate with vxlan-intf;
8782 * we need to associate with the vxlan-intf first
8784 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8786 /* associate with corresponding SVI interface, we can associate
8787 * with svi-if only after vxlan interface association is
8790 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8792 /* formulate l2vni list */
8793 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8796 if (is_l3vni_oper_up(zl3vni
))
8797 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8800 zl3vni
= zl3vni_lookup(vni
);
8802 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8806 if (zvrf
->l3vni
!= vni
) {
8807 snprintf(err
, err_str_sz
,
8808 "VNI %d doesn't exist in VRF: %s",
8809 vni
, zvrf
->vrf
->name
);
8813 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8814 snprintf(err
, ERR_STR_SZ
,
8815 "prefix-routes-only is not set for the vni");
8819 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8821 /* delete and uninstall all rmacs */
8822 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8825 /* delete and uninstall all next-hops */
8826 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8832 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8837 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8839 zebra_l3vni_t
*zl3vni
= NULL
;
8842 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8846 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8847 if (is_l3vni_oper_up(zl3vni
))
8848 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8852 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8854 zebra_l3vni_t
*zl3vni
= NULL
;
8857 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8861 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8862 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8866 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8868 zebra_l3vni_t
*zl3vni
= NULL
;
8872 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8878 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8884 * Handle message from client to specify the flooding mechanism for
8885 * BUM packets. The default is to do head-end (ingress) replication
8886 * and the other supported option is to disable it. This applies to
8887 * all BUM traffic and disabling it applies to both the transmit and
8888 * receive direction.
8890 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8893 enum vxlan_flood_control flood_ctrl
;
8895 if (!EVPN_ENABLED(zvrf
)) {
8896 zlog_err("EVPN flood control for non-EVPN VRF %u",
8902 STREAM_GETC(s
, flood_ctrl
);
8904 if (IS_ZEBRA_DEBUG_VXLAN
)
8905 zlog_debug("EVPN flood control %u, currently %u",
8906 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8908 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8911 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8913 /* Install or uninstall flood entries corresponding to
8916 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8924 * Handle message from client to enable/disable advertisement of svi macip
8927 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8932 zebra_vni_t
*zvni
= NULL
;
8933 struct interface
*ifp
= NULL
;
8935 if (!EVPN_ENABLED(zvrf
)) {
8936 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8942 STREAM_GETC(s
, advertise
);
8943 STREAM_GETL(s
, vni
);
8946 if (IS_ZEBRA_DEBUG_VXLAN
)
8947 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8948 advertise
? "enabled" : "disabled",
8949 advertise_gw_macip_enabled(NULL
)
8953 if (zvrf
->advertise_svi_macip
== advertise
)
8958 zvrf
->advertise_svi_macip
= advertise
;
8959 hash_iterate(zvrf
->vni_table
,
8960 zvni_gw_macip_add_for_vni_hash
, NULL
);
8962 hash_iterate(zvrf
->vni_table
,
8963 zvni_svi_macip_del_for_vni_hash
, NULL
);
8964 zvrf
->advertise_svi_macip
= advertise
;
8968 struct zebra_if
*zif
= NULL
;
8969 struct zebra_l2info_vxlan zl2_info
;
8970 struct interface
*vlan_if
= NULL
;
8972 zvni
= zvni_lookup(vni
);
8976 if (IS_ZEBRA_DEBUG_VXLAN
)
8978 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8979 advertise
? "enabled" : "disabled", vni
,
8980 advertise_svi_macip_enabled(zvni
)
8984 if (zvni
->advertise_svi_macip
== advertise
)
8987 ifp
= zvni
->vxlan_if
;
8993 /* If down or not mapped to a bridge, we're done. */
8994 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8997 zl2_info
= zif
->l2info
.vxl
;
8999 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9000 zif
->brslave_info
.br_if
);
9005 zvni
->advertise_svi_macip
= advertise
;
9006 /* Add primary SVI MAC-IP */
9007 zvni_add_macip_for_intf(vlan_if
, zvni
);
9009 /* Del primary MAC-IP */
9010 zvni_del_macip_for_intf(vlan_if
, zvni
);
9011 zvni
->advertise_svi_macip
= advertise
;
9020 * Handle message from client to enable/disable advertisement of g/w macip
9023 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9028 zebra_vni_t
*zvni
= NULL
;
9029 struct interface
*ifp
= NULL
;
9030 struct zebra_if
*zif
= NULL
;
9031 struct zebra_l2info_vxlan zl2_info
;
9032 struct interface
*vlan_if
= NULL
;
9034 if (!EVPN_ENABLED(zvrf
)) {
9035 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9041 STREAM_GETC(s
, advertise
);
9042 vni
= stream_get3(s
);
9044 zvni
= zvni_lookup(vni
);
9048 if (zvni
->advertise_subnet
== advertise
)
9051 if (IS_ZEBRA_DEBUG_VXLAN
)
9052 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9053 advertise
? "enabled" : "disabled", vni
,
9054 zvni
->advertise_subnet
? "enabled" : "disabled");
9057 zvni
->advertise_subnet
= advertise
;
9059 ifp
= zvni
->vxlan_if
;
9065 /* If down or not mapped to a bridge, we're done. */
9066 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9069 zl2_info
= zif
->l2info
.vxl
;
9072 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9076 if (zvni
->advertise_subnet
)
9077 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9079 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9086 * Handle message from client to enable/disable advertisement of g/w macip
9089 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9094 zebra_vni_t
*zvni
= NULL
;
9095 struct interface
*ifp
= NULL
;
9097 if (!EVPN_ENABLED(zvrf
)) {
9098 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9104 STREAM_GETC(s
, advertise
);
9105 STREAM_GETL(s
, vni
);
9108 if (IS_ZEBRA_DEBUG_VXLAN
)
9109 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9110 advertise
? "enabled" : "disabled",
9111 advertise_gw_macip_enabled(NULL
)
9115 if (zvrf
->advertise_gw_macip
== advertise
)
9118 zvrf
->advertise_gw_macip
= advertise
;
9120 if (advertise_gw_macip_enabled(zvni
))
9121 hash_iterate(zvrf
->vni_table
,
9122 zvni_gw_macip_add_for_vni_hash
, NULL
);
9124 hash_iterate(zvrf
->vni_table
,
9125 zvni_gw_macip_del_for_vni_hash
, NULL
);
9128 struct zebra_if
*zif
= NULL
;
9129 struct zebra_l2info_vxlan zl2_info
;
9130 struct interface
*vlan_if
= NULL
;
9131 struct interface
*vrr_if
= NULL
;
9133 zvni
= zvni_lookup(vni
);
9137 if (IS_ZEBRA_DEBUG_VXLAN
)
9139 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9140 advertise
? "enabled" : "disabled", vni
,
9141 advertise_gw_macip_enabled(zvni
) ? "enabled"
9144 if (zvni
->advertise_gw_macip
== advertise
)
9147 zvni
->advertise_gw_macip
= advertise
;
9149 ifp
= zvni
->vxlan_if
;
9155 /* If down or not mapped to a bridge, we're done. */
9156 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9159 zl2_info
= zif
->l2info
.vxl
;
9161 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9162 zif
->brslave_info
.br_if
);
9166 if (advertise_gw_macip_enabled(zvni
)) {
9167 /* Add primary SVI MAC-IP */
9168 zvni_add_macip_for_intf(vlan_if
, zvni
);
9170 /* Add VRR MAC-IP - if any*/
9171 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9173 zvni_add_macip_for_intf(vrr_if
, zvni
);
9175 /* Del primary MAC-IP */
9176 zvni_del_macip_for_intf(vlan_if
, zvni
);
9178 /* Del VRR MAC-IP - if any*/
9179 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9181 zvni_del_macip_for_intf(vrr_if
, zvni
);
9191 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9192 * When enabled, the VNI hash table will be built and MAC FDB table read;
9193 * when disabled, the entries should be deleted and remote VTEPs and MACs
9194 * uninstalled from the kernel.
9195 * This also informs the setting for BUM handling at the time this change
9196 * occurs; it is relevant only when specifying "learn".
9198 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9200 struct stream
*s
= NULL
;
9202 enum vxlan_flood_control flood_ctrl
;
9204 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9206 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9210 STREAM_GETC(s
, advertise
);
9211 STREAM_GETC(s
, flood_ctrl
);
9213 if (IS_ZEBRA_DEBUG_VXLAN
)
9214 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9215 zvrf_name(zvrf
), zvrf_id(zvrf
),
9216 advertise
? "enabled" : "disabled",
9217 is_evpn_enabled() ? "enabled" : "disabled",
9220 if (zvrf
->advertise_all_vni
== advertise
)
9223 zvrf
->advertise_all_vni
= advertise
;
9224 if (EVPN_ENABLED(zvrf
)) {
9225 zrouter
.evpn_vrf
= zvrf
;
9227 /* Note BUM handling */
9228 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9230 /* Build VNI hash table and inform BGP. */
9231 zvni_build_hash_table();
9233 /* Add all SVI (L3 GW) MACs to BGP*/
9234 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9237 /* Read the MAC FDB */
9238 macfdb_read(zvrf
->zns
);
9240 /* Read neighbors */
9241 neigh_read(zvrf
->zns
);
9243 /* Cleanup VTEPs for all VNIs - uninstall from
9244 * kernel and free entries.
9246 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9248 /* cleanup all l3vnis */
9249 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9251 /* Mark as "no EVPN VRF" */
9252 zrouter
.evpn_vrf
= NULL
;
9260 * Allocate VNI hash table for this VRF and do other initialization.
9261 * NOTE: Currently supported only for default VRF.
9263 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9267 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9268 "Zebra VRF VNI Table");
9269 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9270 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9273 /* Cleanup VNI info, but don't free the table. */
9274 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9278 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9279 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9282 /* Close all VNI handling */
9283 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9287 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9288 hash_free(zvrf
->vni_table
);
9291 /* init the l3vni table */
9292 void zebra_vxlan_init(void)
9294 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9295 "Zebra VRF L3 VNI table");
9296 zrouter
.evpn_vrf
= NULL
;
9299 /* free l3vni table */
9300 void zebra_vxlan_disable(void)
9302 hash_free(zrouter
.l3vni_table
);
9305 /* get the l3vni svi ifindex */
9306 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9308 zebra_l3vni_t
*zl3vni
= NULL
;
9310 zl3vni
= zl3vni_from_vrf(vrf_id
);
9311 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9314 return zl3vni
->svi_if
->ifindex
;
9317 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9319 struct zebra_vrf
*zvrf
= NULL
;
9320 zebra_neigh_t
*nbr
= NULL
;
9321 zebra_vni_t
*zvni
= NULL
;
9322 char buf1
[INET6_ADDRSTRLEN
];
9323 char buf2
[ETHER_ADDR_STRLEN
];
9325 nbr
= THREAD_ARG(t
);
9327 /* since this is asynchronous we need sanity checks*/
9328 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9332 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9336 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9340 if (IS_ZEBRA_DEBUG_VXLAN
)
9341 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9342 __PRETTY_FUNCTION__
,
9343 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9344 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9346 nbr
->dad_count
, zvni
->vni
);
9348 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9350 nbr
->detect_start_time
.tv_sec
= 0;
9351 nbr
->detect_start_time
.tv_usec
= 0;
9352 nbr
->dad_dup_detect_time
= 0;
9353 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9354 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9357 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9358 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9359 nbr
->flags
, nbr
->loc_seq
);
9360 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9361 zvni_neigh_install(zvni
, nbr
);
9367 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9369 struct zebra_vrf
*zvrf
= NULL
;
9370 zebra_mac_t
*mac
= NULL
;
9371 zebra_vni_t
*zvni
= NULL
;
9372 struct listnode
*node
= NULL
;
9373 zebra_neigh_t
*nbr
= NULL
;
9374 char buf
[ETHER_ADDR_STRLEN
];
9376 mac
= THREAD_ARG(t
);
9378 /* since this is asynchronous we need sanity checks*/
9379 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9383 zvni
= zvni_lookup(mac
->zvni
->vni
);
9387 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9391 if (IS_ZEBRA_DEBUG_VXLAN
)
9392 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9393 __PRETTY_FUNCTION__
,
9394 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9397 listcount(mac
->neigh_list
));
9399 /* Remove all IPs as duplicate associcated with this MAC */
9400 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9401 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9402 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9403 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9404 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9405 zvni_neigh_install(zvni
, nbr
);
9408 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9410 nbr
->detect_start_time
.tv_sec
= 0;
9411 nbr
->dad_dup_detect_time
= 0;
9414 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9416 mac
->detect_start_time
.tv_sec
= 0;
9417 mac
->detect_start_time
.tv_usec
= 0;
9418 mac
->dad_dup_detect_time
= 0;
9419 mac
->dad_mac_auto_recovery_timer
= NULL
;
9421 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9423 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9424 mac
->flags
, mac
->loc_seq
))
9427 /* Process all neighbors associated with this MAC. */
9428 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9430 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9431 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9433 /* Install the entry. */
9434 zvni_mac_install(zvni
, mac
);
9440 /************************** vxlan SG cache management ************************/
9441 /* Inform PIM about the mcast group */
9442 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9443 char *sg_str
, uint16_t cmd
)
9445 struct zserv
*client
= NULL
;
9446 struct stream
*s
= NULL
;
9448 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9452 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9454 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9455 stream_putl(s
, IPV4_MAX_BYTELEN
);
9456 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9457 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9459 /* Write packet size. */
9460 stream_putw_at(s
, 0, stream_get_endp(s
));
9462 if (IS_ZEBRA_DEBUG_VXLAN
)
9465 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9466 zebra_route_string(client
->proto
));
9468 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9469 client
->vxlan_sg_add_cnt
++;
9471 client
->vxlan_sg_del_cnt
++;
9473 return zserv_send_message(client
, s
);
9476 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9478 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9480 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9481 vxlan_sg
->sg
.grp
.s_addr
, 0));
9484 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9486 const zebra_vxlan_sg_t
*sg1
= p1
;
9487 const zebra_vxlan_sg_t
*sg2
= p2
;
9489 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9490 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9493 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9494 struct prefix_sg
*sg
)
9496 zebra_vxlan_sg_t
*vxlan_sg
;
9498 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9500 vxlan_sg
->zvrf
= zvrf
;
9502 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9504 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9506 if (IS_ZEBRA_DEBUG_VXLAN
)
9507 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9512 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9513 struct prefix_sg
*sg
)
9515 zebra_vxlan_sg_t lookup
;
9518 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9521 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9522 struct prefix_sg
*sg
)
9524 zebra_vxlan_sg_t
*vxlan_sg
;
9525 zebra_vxlan_sg_t
*parent
= NULL
;
9528 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9532 /* create a *G entry for every BUM group implicitly -
9533 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9534 * 2. the XG entry is used by pimd to setup the
9535 * vxlan-termination-mroute
9537 if (sg
->src
.s_addr
) {
9538 memset(&sip
, 0, sizeof(sip
));
9539 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9544 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9547 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9551 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9556 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9559 struct zebra_vrf
*zvrf
;
9561 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9565 /* On SG entry deletion remove the reference to its parent XG
9568 if (vxlan_sg
->sg
.src
.s_addr
) {
9569 memset(&sip
, 0, sizeof(sip
));
9570 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9573 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9574 ZEBRA_VXLAN_SG_DEL
);
9576 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9578 if (IS_ZEBRA_DEBUG_VXLAN
)
9579 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9581 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9584 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9585 struct in_addr sip
, struct in_addr mcast_grp
)
9587 zebra_vxlan_sg_t
*vxlan_sg
;
9588 struct prefix_sg sg
;
9590 sg
.family
= AF_INET
;
9591 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9594 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9598 if (vxlan_sg
->ref_cnt
)
9599 --vxlan_sg
->ref_cnt
;
9601 if (!vxlan_sg
->ref_cnt
)
9602 zebra_vxlan_sg_del(vxlan_sg
);
9605 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9606 struct in_addr sip
, struct in_addr mcast_grp
)
9608 zebra_vxlan_sg_t
*vxlan_sg
;
9609 struct prefix_sg sg
;
9611 sg
.family
= AF_INET
;
9612 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9615 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9617 ++vxlan_sg
->ref_cnt
;
9622 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9623 struct in_addr mcast_grp
)
9625 struct zebra_vrf
*zvrf
;
9627 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9630 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9634 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9637 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9638 struct in_addr mcast_grp
)
9640 struct zebra_vrf
*zvrf
;
9642 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9645 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9648 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9651 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9653 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9655 zebra_vxlan_sg_del(vxlan_sg
);