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
);
121 static struct interface
*zvni_map_to_macvlan(struct interface
*br_if
,
122 struct interface
*svi_if
);
124 /* l3-vni next-hop neigh related APIs */
125 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
127 static void *zl3vni_nh_alloc(void *p
);
128 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
129 struct ipaddr
*vtep_ip
,
130 struct ethaddr
*rmac
);
131 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
132 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
133 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
135 /* l3-vni rmac related APIs */
136 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
137 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
138 struct ethaddr
*rmac
);
139 static void *zl3vni_rmac_alloc(void *p
);
140 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
141 struct ethaddr
*rmac
);
142 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
143 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
144 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
146 /* l3-vni related APIs*/
147 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
148 static void *zl3vni_alloc(void *p
);
149 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
150 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
151 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
152 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
154 static unsigned int mac_hash_keymake(const void *p
);
155 static bool mac_cmp(const void *p1
, const void *p2
);
156 static void *zvni_mac_alloc(void *p
);
157 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
158 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
159 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
160 struct in_addr
*r_vtep_ip
);
161 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
163 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
164 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
165 uint8_t flags
, uint32_t seq
);
166 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
167 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
168 struct interface
*br_if
, vlanid_t vid
);
169 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
170 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
171 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
173 static unsigned int vni_hash_keymake(const void *p
);
174 static void *zvni_alloc(void *p
);
175 static zebra_vni_t
*zvni_lookup(vni_t vni
);
176 static zebra_vni_t
*zvni_add(vni_t vni
);
177 static int zvni_del(zebra_vni_t
*zvni
);
178 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
179 static int zvni_send_del_to_client(vni_t vni
);
180 static void zvni_build_hash_table(void);
181 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
182 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
183 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
185 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
186 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
187 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
188 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
189 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
190 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
191 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
192 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
193 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
195 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
196 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
197 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
198 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
199 zebra_mac_t
*old_zmac
,
200 zebra_mac_t
*new_zmac
,
202 static int remote_neigh_count(zebra_mac_t
*zmac
);
203 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
204 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
205 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
206 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
208 struct in_addr vtep_ip
,
212 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
214 struct in_addr vtep_ip
,
218 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
219 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
220 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
221 struct in_addr sip
, struct in_addr mcast_grp
);
222 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
223 struct in_addr sip
, struct in_addr mcast_grp
);
224 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
225 struct in_addr mcast_grp
);
226 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
227 struct in_addr mcast_grp
);
228 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
);
230 static void zvni_send_mac_to_client(zebra_vni_t
*zvn
);
231 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
);
233 /* Private functions */
234 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
235 const struct host_rb_entry
*hle2
)
237 if (hle1
->p
.family
< hle2
->p
.family
)
240 if (hle1
->p
.family
> hle2
->p
.family
)
243 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
246 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
249 if (hle1
->p
.family
== AF_INET
) {
250 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
253 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
257 } else if (hle1
->p
.family
== AF_INET6
) {
258 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
261 zlog_debug("%s: Unexpected family type: %d",
262 __PRETTY_FUNCTION__
, hle1
->p
.family
);
266 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
268 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
270 struct host_rb_entry
*hle
;
273 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
280 * Return number of valid MACs in a VNI's MAC hash table - all
281 * remote MACs and non-internal (auto) local MACs count.
283 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
286 uint32_t num_macs
= 0;
288 struct hash_bucket
*hb
;
291 hash
= zvni
->mac_table
;
294 for (i
= 0; i
< hash
->size
; i
++) {
295 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
296 mac
= (zebra_mac_t
*)hb
->data
;
297 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
298 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
299 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
307 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
310 uint32_t num_macs
= 0;
312 struct hash_bucket
*hb
;
315 hash
= zvni
->mac_table
;
318 for (i
= 0; i
< hash
->size
; i
++) {
319 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
320 mac
= (zebra_mac_t
*)hb
->data
;
321 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
329 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
332 uint32_t num_neighs
= 0;
334 struct hash_bucket
*hb
;
337 hash
= zvni
->neigh_table
;
340 for (i
= 0; i
< hash
->size
; i
++) {
341 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
342 nbr
= (zebra_neigh_t
*)hb
->data
;
343 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
351 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
353 struct zebra_vrf
*zvrf
;
355 zvrf
= zebra_vrf_get_evpn();
356 if (zvrf
&& zvrf
->advertise_gw_macip
)
359 if (zvni
&& zvni
->advertise_gw_macip
)
365 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
367 struct zebra_vrf
*zvrf
;
369 zvrf
= zebra_vrf_get_evpn();
370 if (zvrf
&& zvrf
->advertise_svi_macip
)
373 if (zvni
&& zvni
->advertise_svi_macip
)
379 /* As part Duplicate Address Detection (DAD) for IP mobility
380 * MAC binding changes, ensure to inherit duplicate flag
383 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
384 zebra_mac_t
*old_zmac
,
385 zebra_mac_t
*new_zmac
,
388 bool is_old_mac_dup
= false;
389 bool is_new_mac_dup
= false;
391 if (!zvrf
->dup_addr_detect
)
393 /* Check old or new MAC is detected as duplicate
394 * mark this neigh as duplicate
397 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
398 ZEBRA_MAC_DUPLICATE
);
400 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
401 ZEBRA_MAC_DUPLICATE
);
402 /* Old and/or new MAC can be in duplicate state,
403 * based on that IP/Neigh Inherits the flag.
404 * If New MAC is marked duplicate, inherit to the IP.
405 * If old MAC is duplicate but new MAC is not, clear
406 * duplicate flag for IP and reset detection params
407 * and let IP DAD retrigger.
409 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
410 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
411 /* Capture Duplicate detection time */
412 nbr
->dad_dup_detect_time
= monotime(NULL
);
413 /* Mark neigh inactive */
414 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
417 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
418 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
420 nbr
->detect_start_time
.tv_sec
= 0;
421 nbr
->detect_start_time
.tv_usec
= 0;
426 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
428 struct in_addr vtep_ip
,
434 struct listnode
*node
= NULL
;
435 struct timeval elapsed
= {0, 0};
436 char buf
[ETHER_ADDR_STRLEN
];
437 char buf1
[INET6_ADDRSTRLEN
];
438 bool reset_params
= false;
440 if (!(zvrf
->dup_addr_detect
&& do_dad
))
443 /* MAC is detected as duplicate,
444 * Local MAC event -> hold on advertising to BGP.
445 * Remote MAC event -> hold on installing it.
447 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
448 if (IS_ZEBRA_DEBUG_VXLAN
)
450 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
452 prefix_mac2str(&mac
->macaddr
, buf
,
454 mac
->flags
, mac
->dad_count
,
455 zvrf
->dad_freeze_time
);
457 /* For duplicate MAC do not update
458 * client but update neigh due to
461 if (zvrf
->dad_freeze
)
462 *is_dup_detect
= true;
467 /* Check if detection time (M-secs) expired.
468 * Reset learn count and detection start time.
470 monotime_since(&mac
->detect_start_time
, &elapsed
);
471 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
472 if (is_local
&& !reset_params
) {
473 /* RFC-7432: A PE/VTEP that detects a MAC mobility
474 * event via LOCAL learning starts an M-second timer.
476 * NOTE: This is the START of the probe with count is
477 * 0 during LOCAL learn event.
478 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
480 reset_params
= !mac
->dad_count
;
484 if (IS_ZEBRA_DEBUG_VXLAN
)
486 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
487 , __PRETTY_FUNCTION__
,
488 prefix_mac2str(&mac
->macaddr
, buf
,
490 mac
->flags
, mac
->dad_count
);
493 /* Start dup. addr detection (DAD) start time,
494 * ONLY during LOCAL learn.
497 monotime(&mac
->detect_start_time
);
499 } else if (!is_local
) {
500 /* For REMOTE MAC, increment detection count
501 * ONLY while in probe window, once window passed,
502 * next local learn event should trigger DAD.
507 /* For LOCAL MAC learn event, once count is reset above via either
508 * initial/start detection time or passed the probe time, the count
509 * needs to be incremented.
514 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
515 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
516 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
518 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
519 is_local
? "local update, last" :
520 "remote update, from", inet_ntoa(vtep_ip
));
522 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
524 /* Capture Duplicate detection time */
525 mac
->dad_dup_detect_time
= monotime(NULL
);
527 /* Mark all IPs/Neighs as duplicate
528 * associcated with this MAC
530 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
532 /* Ony Mark IPs which are Local */
533 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
536 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
538 nbr
->dad_dup_detect_time
= monotime(NULL
);
540 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
541 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
543 prefix_mac2str(&mac
->macaddr
,
545 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
546 is_local
? "local" : "remote");
549 /* Start auto recovery timer for this MAC */
550 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
551 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
552 if (IS_ZEBRA_DEBUG_VXLAN
)
554 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
555 , __PRETTY_FUNCTION__
,
556 prefix_mac2str(&mac
->macaddr
, buf
,
558 mac
->flags
, zvrf
->dad_freeze_time
);
560 thread_add_timer(zrouter
.master
,
561 zebra_vxlan_dad_mac_auto_recovery_exp
,
562 mac
, zvrf
->dad_freeze_time
,
563 &mac
->dad_mac_auto_recovery_timer
);
566 /* In case of local update, do not inform to client (BGPd),
567 * upd_neigh for neigh sequence change.
569 if (zvrf
->dad_freeze
)
570 *is_dup_detect
= true;
574 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
576 struct in_addr vtep_ip
,
582 struct timeval elapsed
= {0, 0};
583 char buf
[ETHER_ADDR_STRLEN
];
584 char buf1
[INET6_ADDRSTRLEN
];
585 bool reset_params
= false;
587 if (!zvrf
->dup_addr_detect
)
590 /* IP is detected as duplicate or inherit dup
591 * state, hold on to install as remote entry
592 * only if freeze is enabled.
594 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
595 if (IS_ZEBRA_DEBUG_VXLAN
)
597 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
599 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
600 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
601 nbr
->flags
, nbr
->dad_count
,
602 zvrf
->dad_freeze_time
);
604 if (zvrf
->dad_freeze
)
605 *is_dup_detect
= true;
607 /* warn-only action, neigh will be installed.
608 * freeze action, it wil not be installed.
616 /* Check if detection time (M-secs) expired.
617 * Reset learn count and detection start time.
618 * During remote mac add, count should already be 1
619 * via local learning.
621 monotime_since(&nbr
->detect_start_time
, &elapsed
);
622 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
624 if (is_local
&& !reset_params
) {
625 /* RFC-7432: A PE/VTEP that detects a MAC mobility
626 * event via LOCAL learning starts an M-second timer.
628 * NOTE: This is the START of the probe with count is
629 * 0 during LOCAL learn event.
631 reset_params
= !nbr
->dad_count
;
635 if (IS_ZEBRA_DEBUG_VXLAN
)
637 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
639 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
640 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
641 nbr
->flags
, nbr
->dad_count
);
642 /* Reset learn count but do not start detection
643 * during REMOTE learn event.
646 /* Start dup. addr detection (DAD) start time,
647 * ONLY during LOCAL learn.
650 monotime(&nbr
->detect_start_time
);
652 } else if (!is_local
) {
653 /* For REMOTE IP/Neigh, increment detection count
654 * ONLY while in probe window, once window passed,
655 * next local learn event should trigger DAD.
660 /* For LOCAL IP/Neigh learn event, once count is reset above via either
661 * initial/start detection time or passed the probe time, the count
662 * needs to be incremented.
667 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
668 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
669 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
671 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
672 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
673 is_local
? "local update, last" :
674 "remote update, from",
677 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
679 /* Capture Duplicate detection time */
680 nbr
->dad_dup_detect_time
= monotime(NULL
);
682 /* Start auto recovery timer for this IP */
683 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
684 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
685 if (IS_ZEBRA_DEBUG_VXLAN
)
687 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
689 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
690 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
691 nbr
->flags
, zvrf
->dad_freeze_time
);
693 thread_add_timer(zrouter
.master
,
694 zebra_vxlan_dad_ip_auto_recovery_exp
,
695 nbr
, zvrf
->dad_freeze_time
,
696 &nbr
->dad_ip_auto_recovery_timer
);
698 if (zvrf
->dad_freeze
)
699 *is_dup_detect
= true;
704 * Helper function to determine maximum width of neighbor IP address for
705 * display - just because we're dealing with IPv6 addresses that can
708 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
711 char buf
[INET6_ADDRSTRLEN
];
712 struct neigh_walk_ctx
*wctx
= ctxt
;
715 n
= (zebra_neigh_t
*)bucket
->data
;
717 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
719 if (width
> wctx
->addr_width
)
720 wctx
->addr_width
= width
;
725 * Print a specific neighbor entry.
727 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
730 char buf1
[ETHER_ADDR_STRLEN
];
731 char buf2
[INET6_ADDRSTRLEN
];
732 const char *type_str
;
733 const char *state_str
;
734 bool flags_present
= false;
735 struct zebra_vrf
*zvrf
= NULL
;
736 struct timeval detect_start_time
= {0, 0};
737 char timebuf
[MONOTIME_STRLEN
];
739 zvrf
= zebra_vrf_get_evpn();
743 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
744 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
745 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
747 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
748 vty
= (struct vty
*)ctxt
;
750 vty_out(vty
, "IP: %s\n",
751 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
752 vty_out(vty
, " Type: %s\n", type_str
);
753 vty_out(vty
, " State: %s\n", state_str
);
754 vty_out(vty
, " MAC: %s\n",
755 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
757 json_object_string_add(json
, "ip", buf2
);
758 json_object_string_add(json
, "type", type_str
);
759 json_object_string_add(json
, "state", state_str
);
760 json_object_string_add(json
, "mac", buf1
);
762 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
764 vty_out(vty
, " Remote VTEP: %s\n",
765 inet_ntoa(n
->r_vtep_ip
));
767 json_object_string_add(json
, "remoteVtep",
768 inet_ntoa(n
->r_vtep_ip
));
770 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
772 vty_out(vty
, " Flags: Default-gateway");
773 flags_present
= true;
775 json_object_boolean_true_add(json
, "defaultGateway");
777 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
780 flags_present
? " ,Router" : " Flags: Router");
781 flags_present
= true;
787 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
788 n
->loc_seq
, n
->rem_seq
);
790 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
791 vty_out(vty
, " Duplicate, detected at %s",
792 time_to_string(n
->dad_dup_detect_time
,
794 } else if (n
->dad_count
) {
795 monotime_since(&n
->detect_start_time
,
797 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
798 time_to_string(n
->detect_start_time
.tv_sec
,
801 " Duplicate detection started at %s, detection count %u\n",
802 timebuf
, n
->dad_count
);
806 json_object_int_add(json
, "localSequence", n
->loc_seq
);
807 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
808 json_object_int_add(json
, "detectionCount",
810 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
811 json_object_boolean_true_add(json
, "isDuplicate");
813 json_object_boolean_false_add(json
, "isDuplicate");
820 * Print neighbor hash entry - called for display of all neighbors.
822 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
825 json_object
*json_vni
= NULL
, *json_row
= NULL
;
827 char buf1
[ETHER_ADDR_STRLEN
];
828 char buf2
[INET6_ADDRSTRLEN
];
829 struct neigh_walk_ctx
*wctx
= ctxt
;
830 const char *state_str
;
833 json_vni
= wctx
->json
;
834 n
= (zebra_neigh_t
*)bucket
->data
;
837 json_row
= json_object_new_object();
839 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
840 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
841 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
842 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
843 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
846 if (json_vni
== NULL
) {
847 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
848 -wctx
->addr_width
, buf2
, "local",
849 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
851 json_object_string_add(json_row
, "type", "local");
852 json_object_string_add(json_row
, "state", state_str
);
853 json_object_string_add(json_row
, "mac", buf1
);
854 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
855 json_object_boolean_true_add(
856 json_row
, "defaultGateway");
857 json_object_int_add(json_row
, "localSequence",
859 json_object_int_add(json_row
, "remoteSequence",
861 json_object_int_add(json_row
, "detectionCount",
863 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
864 json_object_boolean_true_add(json_row
,
867 json_object_boolean_false_add(json_row
,
871 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
872 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
873 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
876 if (json_vni
== NULL
) {
877 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
879 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
880 -wctx
->addr_width
, "Neighbor", "Type",
881 "State", "MAC", "Remote VTEP",
883 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
884 -wctx
->addr_width
, buf2
, "remote", state_str
,
885 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
887 json_object_string_add(json_row
, "type", "remote");
888 json_object_string_add(json_row
, "state", state_str
);
889 json_object_string_add(json_row
, "mac", buf1
);
890 json_object_string_add(json_row
, "remoteVtep",
891 inet_ntoa(n
->r_vtep_ip
));
892 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
893 json_object_boolean_true_add(json_row
,
895 json_object_int_add(json_row
, "localSequence",
897 json_object_int_add(json_row
, "remoteSequence",
899 json_object_int_add(json_row
, "detectionCount",
901 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
902 json_object_boolean_true_add(json_row
,
905 json_object_boolean_false_add(json_row
,
912 json_object_object_add(json_vni
, buf2
, json_row
);
916 * Print neighbor hash entry in detail - called for display of all neighbors.
918 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
921 json_object
*json_vni
= NULL
, *json_row
= NULL
;
923 char buf
[INET6_ADDRSTRLEN
];
924 struct neigh_walk_ctx
*wctx
= ctxt
;
927 json_vni
= wctx
->json
;
928 n
= (zebra_neigh_t
*)bucket
->data
;
932 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
934 json_row
= json_object_new_object();
936 zvni_print_neigh(n
, vty
, json_row
);
939 json_object_object_add(json_vni
, buf
, json_row
);
943 * Print neighbors for all VNI.
945 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
949 json_object
*json
= NULL
, *json_vni
= NULL
;
952 struct neigh_walk_ctx wctx
;
953 char vni_str
[VNI_STR_LEN
];
956 vty
= (struct vty
*)args
[0];
957 json
= (json_object
*)args
[1];
958 print_dup
= (uint32_t)(uintptr_t)args
[2];
960 zvni
= (zebra_vni_t
*)bucket
->data
;
962 num_neigh
= hashcount(zvni
->neigh_table
);
965 num_neigh
= num_dup_detected_neighs(zvni
);
969 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
970 zvni
->vni
, num_neigh
);
972 json_vni
= json_object_new_object();
973 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
974 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
979 json_object_object_add(json
, vni_str
, json_vni
);
983 /* Since we have IPv6 addresses to deal with which can vary widely in
984 * size, we try to be a bit more elegant in display by first computing
987 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
990 wctx
.addr_width
= 15;
991 wctx
.json
= json_vni
;
992 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
995 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
996 -wctx
.addr_width
, "IP", "Type",
997 "State", "MAC", "Remote VTEP", "Seq #'s");
1000 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
1003 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1006 json_object_object_add(json
, vni_str
, json_vni
);
1009 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1013 nbr
= (zebra_neigh_t
*)bucket
->data
;
1017 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1018 zvni_print_neigh_hash(bucket
, ctxt
);
1021 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1026 nbr
= (zebra_neigh_t
*)bucket
->data
;
1030 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1031 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1035 * Print neighbors for all VNIs in detail.
1037 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1041 json_object
*json
= NULL
, *json_vni
= NULL
;
1044 struct neigh_walk_ctx wctx
;
1045 char vni_str
[VNI_STR_LEN
];
1048 vty
= (struct vty
*)args
[0];
1049 json
= (json_object
*)args
[1];
1050 print_dup
= (uint32_t)(uintptr_t)args
[2];
1052 zvni
= (zebra_vni_t
*)bucket
->data
;
1055 vty_out(vty
, "{}\n");
1058 num_neigh
= hashcount(zvni
->neigh_table
);
1060 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1065 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1066 zvni
->vni
, num_neigh
);
1068 json_vni
= json_object_new_object();
1069 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1070 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1074 json_object_object_add(json
, vni_str
, json_vni
);
1078 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1081 wctx
.addr_width
= 15;
1082 wctx
.json
= json_vni
;
1085 hash_iterate(zvni
->neigh_table
,
1086 zvni_print_dad_neigh_hash_detail
, &wctx
);
1088 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1092 json_object_object_add(json
, vni_str
, json_vni
);
1095 /* print a specific next hop for an l3vni */
1096 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1099 char buf1
[ETHER_ADDR_STRLEN
];
1100 char buf2
[INET6_ADDRSTRLEN
];
1101 json_object
*json_hosts
= NULL
;
1102 struct host_rb_entry
*hle
;
1105 vty_out(vty
, "Ip: %s\n",
1106 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1107 vty_out(vty
, " RMAC: %s\n",
1108 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1109 vty_out(vty
, " Refcount: %d\n",
1110 rb_host_count(&n
->host_rb
));
1111 vty_out(vty
, " Prefixes:\n");
1112 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1113 vty_out(vty
, " %s\n",
1114 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1116 json_hosts
= json_object_new_array();
1117 json_object_string_add(
1118 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1119 json_object_string_add(
1121 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1122 json_object_int_add(json
, "refCount",
1123 rb_host_count(&n
->host_rb
));
1124 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1125 json_object_array_add(json_hosts
,
1126 json_object_new_string(prefix2str(
1127 &hle
->p
, buf2
, sizeof(buf2
))));
1128 json_object_object_add(json
, "prefixList", json_hosts
);
1132 /* Print a specific RMAC entry */
1133 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1136 char buf1
[ETHER_ADDR_STRLEN
];
1137 char buf2
[PREFIX_STRLEN
];
1138 json_object
*json_hosts
= NULL
;
1139 struct host_rb_entry
*hle
;
1142 vty_out(vty
, "MAC: %s\n",
1143 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1144 vty_out(vty
, " Remote VTEP: %s\n",
1145 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1146 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1147 vty_out(vty
, " Prefixes:\n");
1148 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1149 vty_out(vty
, " %s\n",
1150 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1152 json_hosts
= json_object_new_array();
1153 json_object_string_add(
1155 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1156 json_object_string_add(json
, "vtepIp",
1157 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1158 json_object_int_add(json
, "refCount",
1159 rb_host_count(&zrmac
->host_rb
));
1160 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1161 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1162 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1163 json_object_array_add(
1165 json_object_new_string(prefix2str(
1166 &hle
->p
, buf2
, sizeof(buf2
))));
1167 json_object_object_add(json
, "prefixList", json_hosts
);
1172 * Print a specific MAC entry.
1174 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1177 zebra_neigh_t
*n
= NULL
;
1178 struct listnode
*node
= NULL
;
1179 char buf1
[ETHER_ADDR_STRLEN
];
1180 char buf2
[INET6_ADDRSTRLEN
];
1181 struct zebra_vrf
*zvrf
;
1182 struct timeval detect_start_time
= {0, 0};
1183 char timebuf
[MONOTIME_STRLEN
];
1185 zvrf
= zebra_vrf_get_evpn();
1189 vty
= (struct vty
*)ctxt
;
1190 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1193 json_object
*json_mac
= json_object_new_object();
1195 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1196 struct zebra_ns
*zns
;
1197 struct interface
*ifp
;
1200 ifindex
= mac
->fwd_info
.local
.ifindex
;
1201 zns
= zebra_ns_lookup(NS_DEFAULT
);
1202 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1205 json_object_string_add(json_mac
, "type", "local");
1206 json_object_string_add(json_mac
, "intf", ifp
->name
);
1207 json_object_int_add(json_mac
, "ifindex", ifindex
);
1208 if (mac
->fwd_info
.local
.vid
)
1209 json_object_int_add(json_mac
, "vlan",
1210 mac
->fwd_info
.local
.vid
);
1211 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1212 json_object_string_add(json_mac
, "type", "remote");
1213 json_object_string_add(
1214 json_mac
, "remoteVtep",
1215 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1216 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1217 json_object_string_add(json_mac
, "type", "auto");
1219 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1220 json_object_boolean_true_add(json_mac
, "stickyMac");
1222 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1223 json_object_boolean_true_add(json_mac
,
1226 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1227 json_object_boolean_true_add(json_mac
,
1228 "remoteGatewayMac");
1230 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1231 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1233 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1234 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1235 json_object_boolean_true_add(json_mac
, "isDuplicate");
1237 json_object_boolean_false_add(json_mac
, "isDuplicate");
1239 /* print all the associated neigh */
1240 if (!listcount(mac
->neigh_list
))
1241 json_object_string_add(json_mac
, "neighbors", "none");
1243 json_object
*json_active_nbrs
= json_object_new_array();
1244 json_object
*json_inactive_nbrs
=
1245 json_object_new_array();
1246 json_object
*json_nbrs
= json_object_new_object();
1248 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1249 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1250 json_object_array_add(
1252 json_object_new_string(
1257 json_object_array_add(
1259 json_object_new_string(
1265 json_object_object_add(json_nbrs
, "active",
1267 json_object_object_add(json_nbrs
, "inactive",
1268 json_inactive_nbrs
);
1269 json_object_object_add(json_mac
, "neighbors",
1273 json_object_object_add(json
, buf1
, json_mac
);
1275 vty_out(vty
, "MAC: %s\n", buf1
);
1277 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1278 struct zebra_ns
*zns
;
1279 struct interface
*ifp
;
1282 ifindex
= mac
->fwd_info
.local
.ifindex
;
1283 zns
= zebra_ns_lookup(NS_DEFAULT
);
1284 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1287 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1288 if (mac
->fwd_info
.local
.vid
)
1289 vty_out(vty
, " VLAN: %u",
1290 mac
->fwd_info
.local
.vid
);
1291 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1292 vty_out(vty
, " Remote VTEP: %s",
1293 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1294 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1295 vty_out(vty
, " Auto Mac ");
1298 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1299 vty_out(vty
, " Sticky Mac ");
1301 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1302 vty_out(vty
, " Default-gateway Mac ");
1304 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1305 vty_out(vty
, " Remote-gateway Mac ");
1308 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1312 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1313 vty_out(vty
, " Duplicate, detected at %s",
1314 time_to_string(mac
->dad_dup_detect_time
,
1316 } else if (mac
->dad_count
) {
1317 monotime_since(&mac
->detect_start_time
,
1318 &detect_start_time
);
1319 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1320 time_to_string(mac
->detect_start_time
.tv_sec
,
1323 " Duplicate detection started at %s, detection count %u\n",
1324 timebuf
, mac
->dad_count
);
1328 /* print all the associated neigh */
1329 vty_out(vty
, " Neighbors:\n");
1330 if (!listcount(mac
->neigh_list
))
1331 vty_out(vty
, " No Neighbors\n");
1333 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1334 vty_out(vty
, " %s %s\n",
1335 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1336 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1347 * Print MAC hash entry - called for display of all MACs.
1349 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1352 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1354 char buf1
[ETHER_ADDR_STRLEN
];
1355 struct mac_walk_ctx
*wctx
= ctxt
;
1358 json_mac_hdr
= wctx
->json
;
1359 mac
= (zebra_mac_t
*)bucket
->data
;
1361 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1364 json_mac
= json_object_new_object();
1366 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1367 struct zebra_ns
*zns
;
1369 struct interface
*ifp
;
1372 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1375 zns
= zebra_ns_lookup(NS_DEFAULT
);
1376 ifindex
= mac
->fwd_info
.local
.ifindex
;
1377 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1378 if (!ifp
) // unexpected
1380 vid
= mac
->fwd_info
.local
.vid
;
1381 if (json_mac_hdr
== NULL
)
1382 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1385 json_object_string_add(json_mac
, "type", "local");
1386 json_object_string_add(json_mac
, "intf", ifp
->name
);
1389 if (json_mac_hdr
== NULL
)
1390 vty_out(vty
, " %-5u", vid
);
1392 json_object_int_add(json_mac
, "vlan", vid
);
1393 } else /* No vid? fill out the space */
1394 if (json_mac_hdr
== NULL
)
1395 vty_out(vty
, " %-5s", "");
1396 if (json_mac_hdr
== NULL
) {
1397 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1400 json_object_int_add(json_mac
, "localSequence",
1402 json_object_int_add(json_mac
, "remoteSequence",
1404 json_object_int_add(json_mac
, "detectionCount",
1406 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1407 json_object_boolean_true_add(json_mac
,
1410 json_object_boolean_false_add(json_mac
,
1412 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1417 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1419 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1420 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1424 if (json_mac_hdr
== NULL
) {
1425 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1426 (wctx
->count
== 0)) {
1427 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1428 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n",
1429 "MAC", "Type", "Intf/Remote VTEP",
1432 vty_out(vty
, "%-17s %-6s %-21s %-5s %u/%u\n", buf1
,
1433 "remote", inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1434 "", mac
->loc_seq
, mac
->rem_seq
);
1436 json_object_string_add(json_mac
, "type", "remote");
1437 json_object_string_add(json_mac
, "remoteVtep",
1438 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1439 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1440 json_object_int_add(json_mac
, "localSequence",
1442 json_object_int_add(json_mac
, "remoteSequence",
1444 json_object_int_add(json_mac
, "detectionCount",
1446 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1447 json_object_boolean_true_add(json_mac
,
1450 json_object_boolean_false_add(json_mac
,
1459 /* Print Duplicate MAC */
1460 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1464 mac
= (zebra_mac_t
*)bucket
->data
;
1468 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1469 zvni_print_mac_hash(bucket
, ctxt
);
1473 * Print MAC hash entry in detail - called for display of all MACs.
1475 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1478 json_object
*json_mac_hdr
= NULL
;
1480 struct mac_walk_ctx
*wctx
= ctxt
;
1481 char buf1
[ETHER_ADDR_STRLEN
];
1484 json_mac_hdr
= wctx
->json
;
1485 mac
= (zebra_mac_t
*)bucket
->data
;
1490 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1492 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1495 /* Print Duplicate MAC in detail */
1496 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1501 mac
= (zebra_mac_t
*)bucket
->data
;
1505 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1506 zvni_print_mac_hash_detail(bucket
, ctxt
);
1510 * Print MACs for all VNI.
1512 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1515 json_object
*json
= NULL
, *json_vni
= NULL
;
1516 json_object
*json_mac
= NULL
;
1519 struct mac_walk_ctx
*wctx
= ctxt
;
1520 char vni_str
[VNI_STR_LEN
];
1522 vty
= (struct vty
*)wctx
->vty
;
1523 json
= (struct json_object
*)wctx
->json
;
1525 zvni
= (zebra_vni_t
*)bucket
->data
;
1528 /*We are iterating over a new VNI, set the count to 0*/
1531 num_macs
= num_valid_macs(zvni
);
1535 if (wctx
->print_dup
)
1536 num_macs
= num_dup_detected_macs(zvni
);
1539 json_vni
= json_object_new_object();
1540 json_mac
= json_object_new_object();
1541 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1544 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1546 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1547 zvni
->vni
, num_macs
);
1548 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC",
1549 "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
1551 json_object_int_add(json_vni
, "numMacs", num_macs
);
1556 json_object_int_add(json_vni
, "numMacs", num_macs
);
1557 json_object_object_add(json
, vni_str
, json_vni
);
1562 /* assign per-vni to wctx->json object to fill macs
1563 * under the vni. Re-assign primary json object to fill
1564 * next vni information.
1566 wctx
->json
= json_mac
;
1567 if (wctx
->print_dup
)
1568 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1570 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1574 json_object_object_add(json_vni
, "macs", json_mac
);
1575 json_object_object_add(json
, vni_str
, json_vni
);
1580 * Print MACs in detail for all VNI.
1582 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1586 json_object
*json
= NULL
, *json_vni
= NULL
;
1587 json_object
*json_mac
= NULL
;
1590 struct mac_walk_ctx
*wctx
= ctxt
;
1591 char vni_str
[VNI_STR_LEN
];
1593 vty
= (struct vty
*)wctx
->vty
;
1594 json
= (struct json_object
*)wctx
->json
;
1596 zvni
= (zebra_vni_t
*)bucket
->data
;
1599 vty_out(vty
, "{}\n");
1604 /*We are iterating over a new VNI, set the count to 0*/
1607 num_macs
= num_valid_macs(zvni
);
1611 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1615 json_vni
= json_object_new_object();
1616 json_mac
= json_object_new_object();
1617 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1620 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1622 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1623 zvni
->vni
, num_macs
);
1625 json_object_int_add(json_vni
, "numMacs", num_macs
);
1627 /* assign per-vni to wctx->json object to fill macs
1628 * under the vni. Re-assign primary json object to fill
1629 * next vni information.
1631 wctx
->json
= json_mac
;
1632 if (wctx
->print_dup
)
1633 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1636 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1640 json_object_object_add(json_vni
, "macs", json_mac
);
1641 json_object_object_add(json
, vni_str
, json_vni
);
1645 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1647 struct nh_walk_ctx
*wctx
= NULL
;
1648 struct vty
*vty
= NULL
;
1649 struct json_object
*json_vni
= NULL
;
1650 struct json_object
*json_nh
= NULL
;
1651 zebra_neigh_t
*n
= NULL
;
1652 char buf1
[ETHER_ADDR_STRLEN
];
1653 char buf2
[INET6_ADDRSTRLEN
];
1655 wctx
= (struct nh_walk_ctx
*)ctx
;
1657 json_vni
= wctx
->json
;
1659 json_nh
= json_object_new_object();
1660 n
= (zebra_neigh_t
*)bucket
->data
;
1663 vty_out(vty
, "%-15s %-17s\n",
1664 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1665 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1667 json_object_string_add(json_nh
, "nexthopIp",
1668 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1669 json_object_string_add(
1670 json_nh
, "routerMac",
1671 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1672 json_object_object_add(json_vni
,
1673 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1678 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1681 struct vty
*vty
= NULL
;
1682 json_object
*json
= NULL
;
1683 json_object
*json_vni
= NULL
;
1684 zebra_l3vni_t
*zl3vni
= NULL
;
1685 uint32_t num_nh
= 0;
1686 struct nh_walk_ctx wctx
;
1687 char vni_str
[VNI_STR_LEN
];
1689 vty
= (struct vty
*)args
[0];
1690 json
= (struct json_object
*)args
[1];
1692 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1694 num_nh
= hashcount(zl3vni
->nh_table
);
1699 json_vni
= json_object_new_object();
1700 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1704 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1705 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1707 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1709 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1711 wctx
.json
= json_vni
;
1712 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1714 json_object_object_add(json
, vni_str
, json_vni
);
1717 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1720 struct vty
*vty
= NULL
;
1721 json_object
*json
= NULL
;
1722 json_object
*json_vni
= NULL
;
1723 zebra_l3vni_t
*zl3vni
= NULL
;
1725 struct rmac_walk_ctx wctx
;
1726 char vni_str
[VNI_STR_LEN
];
1728 vty
= (struct vty
*)args
[0];
1729 json
= (struct json_object
*)args
[1];
1731 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1733 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1738 json_vni
= json_object_new_object();
1739 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1743 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1744 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1746 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1748 /* assign per-vni to wctx->json object to fill macs
1749 * under the vni. Re-assign primary json object to fill
1750 * next vni information.
1752 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1754 wctx
.json
= json_vni
;
1755 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1757 json_object_object_add(json
, vni_str
, json_vni
);
1760 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1762 zebra_mac_t
*zrmac
= NULL
;
1763 struct rmac_walk_ctx
*wctx
= NULL
;
1764 struct vty
*vty
= NULL
;
1765 struct json_object
*json
= NULL
;
1766 struct json_object
*json_rmac
= NULL
;
1767 char buf
[ETHER_ADDR_STRLEN
];
1769 wctx
= (struct rmac_walk_ctx
*)ctx
;
1773 json_rmac
= json_object_new_object();
1774 zrmac
= (zebra_mac_t
*)bucket
->data
;
1777 vty_out(vty
, "%-17s %-21s\n",
1778 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1779 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1781 json_object_string_add(
1782 json_rmac
, "routerMac",
1783 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1784 json_object_string_add(json_rmac
, "vtepIp",
1785 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1786 json_object_object_add(
1787 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1792 /* print a specific L3 VNI entry */
1793 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1795 char buf
[ETHER_ADDR_STRLEN
];
1796 struct vty
*vty
= NULL
;
1797 json_object
*json
= NULL
;
1798 zebra_vni_t
*zvni
= NULL
;
1799 json_object
*json_vni_list
= NULL
;
1800 struct listnode
*node
= NULL
, *nnode
= NULL
;
1806 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1807 vty_out(vty
, " Type: %s\n", "L3");
1808 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1809 vty_out(vty
, " Local Vtep Ip: %s\n",
1810 inet_ntoa(zl3vni
->local_vtep_ip
));
1811 vty_out(vty
, " Vxlan-Intf: %s\n",
1812 zl3vni_vxlan_if_name(zl3vni
));
1813 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1814 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1815 vty_out(vty
, " VNI Filter: %s\n",
1816 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1817 ? "prefix-routes-only"
1819 vty_out(vty
, " System MAC: %s\n",
1820 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
1821 vty_out(vty
, " Router MAC: %s\n",
1822 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1823 vty_out(vty
, " L2 VNIs: ");
1824 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1825 vty_out(vty
, "%u ", zvni
->vni
);
1828 json_vni_list
= json_object_new_array();
1829 json_object_int_add(json
, "vni", zl3vni
->vni
);
1830 json_object_string_add(json
, "type", "L3");
1831 json_object_string_add(json
, "localVtepIp",
1832 inet_ntoa(zl3vni
->local_vtep_ip
));
1833 json_object_string_add(json
, "vxlanIntf",
1834 zl3vni_vxlan_if_name(zl3vni
));
1835 json_object_string_add(json
, "sviIntf",
1836 zl3vni_svi_if_name(zl3vni
));
1837 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1838 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1839 json_object_string_add(
1841 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
1842 json_object_string_add(
1844 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1845 json_object_string_add(
1847 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1848 ? "prefix-routes-only"
1850 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1851 json_object_array_add(json_vni_list
,
1852 json_object_new_int(zvni
->vni
));
1854 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1859 * Print a specific VNI entry.
1861 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1864 zebra_vtep_t
*zvtep
;
1867 json_object
*json
= NULL
;
1868 json_object
*json_vtep_list
= NULL
;
1869 json_object
*json_ip_str
= NULL
;
1875 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1876 vty_out(vty
, " Type: %s\n", "L2");
1877 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1879 json_object_int_add(json
, "vni", zvni
->vni
);
1880 json_object_string_add(json
, "type", "L2");
1881 json_object_string_add(json
, "vrf",
1882 vrf_id_to_name(zvni
->vrf_id
));
1885 if (!zvni
->vxlan_if
) { // unexpected
1887 vty_out(vty
, " VxLAN interface: unknown\n");
1890 num_macs
= num_valid_macs(zvni
);
1891 num_neigh
= hashcount(zvni
->neigh_table
);
1893 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1894 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1895 vty_out(vty
, " Local VTEP IP: %s\n",
1896 inet_ntoa(zvni
->local_vtep_ip
));
1897 vty_out(vty
, " Mcast group: %s\n",
1898 inet_ntoa(zvni
->mcast_grp
));
1900 json_object_string_add(json
, "vxlanInterface",
1901 zvni
->vxlan_if
->name
);
1902 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1903 json_object_string_add(json
, "vtepIp",
1904 inet_ntoa(zvni
->local_vtep_ip
));
1905 json_object_string_add(json
, "mcastGroup",
1906 inet_ntoa(zvni
->mcast_grp
));
1907 json_object_string_add(json
, "advertiseGatewayMacip",
1908 zvni
->advertise_gw_macip
? "Yes" : "No");
1909 json_object_int_add(json
, "numMacs", num_macs
);
1910 json_object_int_add(json
, "numArpNd", num_neigh
);
1914 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1917 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1919 json_vtep_list
= json_object_new_array();
1920 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1921 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1922 zvtep
->flood_control
,
1923 VXLAN_FLOOD_STR_DEFAULT
);
1926 vty_out(vty
, " %s flood: %s\n",
1927 inet_ntoa(zvtep
->vtep_ip
),
1930 json_ip_str
= json_object_new_string(
1931 inet_ntoa(zvtep
->vtep_ip
));
1932 json_object_array_add(json_vtep_list
,
1937 json_object_object_add(json
, "numRemoteVteps",
1942 " Number of MACs (local and remote) known for this VNI: %u\n",
1945 " Number of ARPs (IPv4 and IPv6, local and remote) "
1946 "known for this VNI: %u\n",
1948 vty_out(vty
, " Advertise-gw-macip: %s\n",
1949 zvni
->advertise_gw_macip
? "Yes" : "No");
1953 /* print a L3 VNI hash entry */
1954 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1956 struct vty
*vty
= NULL
;
1957 json_object
*json
= NULL
;
1958 json_object
*json_vni
= NULL
;
1959 zebra_l3vni_t
*zl3vni
= NULL
;
1961 vty
= (struct vty
*)ctx
[0];
1962 json
= (json_object
*)ctx
[1];
1964 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1967 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1968 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1969 hashcount(zl3vni
->rmac_table
),
1970 hashcount(zl3vni
->nh_table
), "n/a",
1971 zl3vni_vrf_name(zl3vni
));
1973 char vni_str
[VNI_STR_LEN
];
1975 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1976 json_vni
= json_object_new_object();
1977 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1978 json_object_string_add(json_vni
, "vxlanIf",
1979 zl3vni_vxlan_if_name(zl3vni
));
1980 json_object_int_add(json_vni
, "numMacs",
1981 hashcount(zl3vni
->rmac_table
));
1982 json_object_int_add(json_vni
, "numArpNd",
1983 hashcount(zl3vni
->nh_table
));
1984 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1985 json_object_string_add(json_vni
, "type", "L3");
1986 json_object_string_add(json_vni
, "tenantVrf",
1987 zl3vni_vrf_name(zl3vni
));
1988 json_object_object_add(json
, vni_str
, json_vni
);
1992 /* Private Structure to pass callback data for hash iterator */
1993 struct zvni_evpn_show
{
1996 struct zebra_vrf
*zvrf
;
2000 /* print a L3 VNI hash entry in detail*/
2001 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2003 struct vty
*vty
= NULL
;
2004 zebra_l3vni_t
*zl3vni
= NULL
;
2005 json_object
*json_array
= NULL
;
2006 bool use_json
= false;
2007 struct zvni_evpn_show
*zes
= data
;
2010 json_array
= zes
->json
;
2011 use_json
= zes
->use_json
;
2013 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2015 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
,
2016 use_json
, json_array
);
2024 * Print a VNI hash entry - called for display of all VNIs.
2026 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2030 zebra_vtep_t
*zvtep
;
2031 uint32_t num_vteps
= 0;
2032 uint32_t num_macs
= 0;
2033 uint32_t num_neigh
= 0;
2034 json_object
*json
= NULL
;
2035 json_object
*json_vni
= NULL
;
2036 json_object
*json_ip_str
= NULL
;
2037 json_object
*json_vtep_list
= NULL
;
2042 zvni
= (zebra_vni_t
*)bucket
->data
;
2044 zvtep
= zvni
->vteps
;
2047 zvtep
= zvtep
->next
;
2050 num_macs
= num_valid_macs(zvni
);
2051 num_neigh
= hashcount(zvni
->neigh_table
);
2053 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2055 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2056 num_macs
, num_neigh
, num_vteps
,
2057 vrf_id_to_name(zvni
->vrf_id
));
2059 char vni_str
[VNI_STR_LEN
];
2060 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2061 json_vni
= json_object_new_object();
2062 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2063 json_object_string_add(json_vni
, "type", "L2");
2064 json_object_string_add(json_vni
, "vxlanIf",
2065 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2067 json_object_int_add(json_vni
, "numMacs", num_macs
);
2068 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2069 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2070 json_object_string_add(json_vni
, "tenantVrf",
2071 vrf_id_to_name(zvni
->vrf_id
));
2073 json_vtep_list
= json_object_new_array();
2074 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2075 json_ip_str
= json_object_new_string(
2076 inet_ntoa(zvtep
->vtep_ip
));
2077 json_object_array_add(json_vtep_list
,
2080 json_object_object_add(json_vni
, "remoteVteps",
2083 json_object_object_add(json
, vni_str
, json_vni
);
2088 * Print a VNI hash entry in detail - called for display of all VNIs.
2090 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2094 json_object
*json_array
= NULL
;
2095 bool use_json
= false;
2096 struct zvni_evpn_show
*zes
= data
;
2099 json_array
= zes
->json
;
2100 use_json
= zes
->use_json
;
2102 zvni
= (zebra_vni_t
*)bucket
->data
;
2104 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
, json_array
);
2111 * Inform BGP about local MACIP.
2113 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2114 struct ipaddr
*ip
, uint8_t flags
,
2115 uint32_t seq
, int state
, uint16_t cmd
)
2117 char buf
[ETHER_ADDR_STRLEN
];
2118 char buf2
[INET6_ADDRSTRLEN
];
2120 struct zserv
*client
= NULL
;
2121 struct stream
*s
= NULL
;
2123 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2124 /* BGP may not be running. */
2128 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2130 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2131 stream_putl(s
, vni
);
2132 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2135 if (IS_IPADDR_V4(ip
))
2136 ipa_len
= IPV4_MAX_BYTELEN
;
2137 else if (IS_IPADDR_V6(ip
))
2138 ipa_len
= IPV6_MAX_BYTELEN
;
2140 stream_putl(s
, ipa_len
); /* IP address length */
2142 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2144 stream_putl(s
, 0); /* Just MAC. */
2146 if (cmd
== ZEBRA_MACIP_ADD
) {
2147 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2148 stream_putl(s
, seq
); /* sequence number */
2150 stream_putl(s
, state
); /* state - active/inactive */
2154 /* Write packet size. */
2155 stream_putw_at(s
, 0, stream_get_endp(s
));
2157 if (IS_ZEBRA_DEBUG_VXLAN
)
2159 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2160 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2161 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2162 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2163 zebra_route_string(client
->proto
));
2165 if (cmd
== ZEBRA_MACIP_ADD
)
2166 client
->macipadd_cnt
++;
2168 client
->macipdel_cnt
++;
2170 return zserv_send_message(client
, s
);
2174 * Make hash key for neighbors.
2176 static unsigned int neigh_hash_keymake(const void *p
)
2178 const zebra_neigh_t
*n
= p
;
2179 const struct ipaddr
*ip
= &n
->ip
;
2181 if (IS_IPADDR_V4(ip
))
2182 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2184 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2185 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2189 * Compare two neighbor hash structures.
2191 static bool neigh_cmp(const void *p1
, const void *p2
)
2193 const zebra_neigh_t
*n1
= p1
;
2194 const zebra_neigh_t
*n2
= p2
;
2196 if (n1
== NULL
&& n2
== NULL
)
2199 if (n1
== NULL
|| n2
== NULL
)
2202 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2205 static int neigh_list_cmp(void *p1
, void *p2
)
2207 const zebra_neigh_t
*n1
= p1
;
2208 const zebra_neigh_t
*n2
= p2
;
2210 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2214 * Callback to allocate neighbor hash entry.
2216 static void *zvni_neigh_alloc(void *p
)
2218 const zebra_neigh_t
*tmp_n
= p
;
2221 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2228 * Add neighbor entry.
2230 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2231 struct ethaddr
*mac
)
2233 zebra_neigh_t tmp_n
;
2234 zebra_neigh_t
*n
= NULL
;
2235 zebra_mac_t
*zmac
= NULL
;
2237 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2238 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2239 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2242 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2243 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2245 n
->dad_ip_auto_recovery_timer
= NULL
;
2247 /* Associate the neigh to mac */
2248 zmac
= zvni_mac_lookup(zvni
, mac
);
2250 listnode_add_sort(zmac
->neigh_list
, n
);
2256 * Delete neighbor entry.
2258 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2260 zebra_neigh_t
*tmp_n
;
2261 zebra_mac_t
*zmac
= NULL
;
2263 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2265 listnode_delete(zmac
->neigh_list
, n
);
2267 /* Cancel auto recovery */
2268 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2270 /* Free the VNI hash entry and allocated memory. */
2271 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2272 XFREE(MTYPE_NEIGH
, tmp_n
);
2278 * Free neighbor hash entry (callback)
2280 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2282 struct neigh_walk_ctx
*wctx
= arg
;
2283 zebra_neigh_t
*n
= bucket
->data
;
2285 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2286 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2287 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2288 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2289 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2290 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2291 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2292 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2293 &n
->emac
, 0, n
->state
);
2295 if (wctx
->uninstall
)
2296 zvni_neigh_uninstall(wctx
->zvni
, n
);
2298 zvni_neigh_del(wctx
->zvni
, n
);
2305 * Delete all neighbor entries from specific VTEP for a particular VNI.
2307 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2308 struct in_addr
*r_vtep_ip
)
2310 struct neigh_walk_ctx wctx
;
2312 if (!zvni
->neigh_table
)
2315 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2317 wctx
.uninstall
= uninstall
;
2318 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2319 wctx
.r_vtep_ip
= *r_vtep_ip
;
2321 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2325 * Delete all neighbor entries for this VNI.
2327 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2330 struct neigh_walk_ctx wctx
;
2332 if (!zvni
->neigh_table
)
2335 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2337 wctx
.uninstall
= uninstall
;
2338 wctx
.upd_client
= upd_client
;
2341 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2345 * Look up neighbor hash entry.
2347 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2352 memset(&tmp
, 0, sizeof(tmp
));
2353 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2354 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2360 * Process all neighbors associated with a MAC upon the MAC being learnt
2361 * locally or undergoing any other change (such as sequence number).
2363 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2367 zebra_neigh_t
*n
= NULL
;
2368 struct listnode
*node
= NULL
;
2369 struct zebra_vrf
*zvrf
= NULL
;
2370 char buf
[ETHER_ADDR_STRLEN
];
2372 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2374 if (IS_ZEBRA_DEBUG_VXLAN
)
2375 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2376 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2377 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2379 /* Walk all neighbors and mark any inactive local neighbors as
2380 * active and/or update sequence number upon a move, and inform BGP.
2381 * The action for remote neighbors is TBD.
2382 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2383 * accidentally end up deleting a just-learnt local neighbor.
2385 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2386 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2387 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2388 ZEBRA_NEIGH_SET_ACTIVE(n
);
2389 n
->loc_seq
= zmac
->loc_seq
;
2390 if (!(zvrf
->dup_addr_detect
&&
2391 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2392 ZEBRA_NEIGH_DUPLICATE
)))
2393 zvni_neigh_send_add_to_client(
2394 zvni
->vni
, &n
->ip
, &n
->emac
,
2395 n
->flags
, n
->loc_seq
);
2402 * Process all neighbors associated with a local MAC upon the MAC being
2405 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2408 zebra_neigh_t
*n
= NULL
;
2409 struct listnode
*node
= NULL
;
2410 char buf
[ETHER_ADDR_STRLEN
];
2412 if (IS_ZEBRA_DEBUG_VXLAN
)
2413 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2414 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2417 /* Walk all local neighbors and mark as inactive and inform
2419 * TBD: There is currently no handling for remote neighbors. We
2420 * don't expect them to exist, if they do, do we install the MAC
2421 * as a remote MAC and the neighbor as remote?
2423 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2424 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2425 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2426 ZEBRA_NEIGH_SET_INACTIVE(n
);
2428 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2429 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2436 * Process all neighbors associated with a MAC upon the MAC being remotely
2439 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2442 zebra_neigh_t
*n
= NULL
;
2443 struct listnode
*node
= NULL
;
2444 char buf
[ETHER_ADDR_STRLEN
];
2446 if (IS_ZEBRA_DEBUG_VXLAN
)
2447 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2448 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2451 /* Walk all local neighbors and mark as inactive and inform
2454 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2455 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2456 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2457 ZEBRA_NEIGH_SET_INACTIVE(n
);
2459 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2460 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2467 * Process all neighbors associated with a remote MAC upon the MAC being
2470 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2473 /* NOTE: Currently a NO-OP. */
2476 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2478 zebra_neigh_t
*nbr
= NULL
;
2479 struct listnode
*node
= NULL
;
2481 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2482 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2483 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2484 zvni_neigh_probe(zvni
, nbr
);
2489 * Inform BGP about local neighbor addition.
2491 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2492 struct ethaddr
*macaddr
,
2493 uint8_t neigh_flags
,
2498 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2499 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2500 /* Set router flag (R-bit) based on local neigh entry add */
2501 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2502 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2503 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_SVI_IP
))
2504 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_SVI_IP
);
2506 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2507 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2511 * Inform BGP about local neighbor deletion.
2513 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2514 struct ethaddr
*macaddr
, uint8_t flags
,
2517 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2518 0, state
, ZEBRA_MACIP_DEL
);
2522 * Install remote neighbor into the kernel.
2524 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2526 struct zebra_if
*zif
;
2527 struct zebra_l2info_vxlan
*vxl
;
2528 struct interface
*vlan_if
;
2532 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2535 zif
= zvni
->vxlan_if
->info
;
2538 vxl
= &zif
->l2info
.vxl
;
2540 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2544 flags
= DPLANE_NTF_EXT_LEARNED
;
2545 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2546 flags
|= DPLANE_NTF_ROUTER
;
2547 ZEBRA_NEIGH_SET_ACTIVE(n
);
2549 dplane_neigh_add(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2555 * Uninstall remote neighbor from the kernel.
2557 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2559 struct zebra_if
*zif
;
2560 struct zebra_l2info_vxlan
*vxl
;
2561 struct interface
*vlan_if
;
2563 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2566 if (!zvni
->vxlan_if
) {
2567 if (IS_ZEBRA_DEBUG_VXLAN
)
2568 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2573 zif
= zvni
->vxlan_if
->info
;
2576 vxl
= &zif
->l2info
.vxl
;
2577 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2581 ZEBRA_NEIGH_SET_INACTIVE(n
);
2584 dplane_neigh_delete(vlan_if
, &n
->ip
);
2590 * Probe neighbor from the kernel.
2592 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2594 struct zebra_if
*zif
;
2595 struct zebra_l2info_vxlan
*vxl
;
2596 struct interface
*vlan_if
;
2598 zif
= zvni
->vxlan_if
->info
;
2601 vxl
= &zif
->l2info
.vxl
;
2603 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2607 dplane_neigh_update(vlan_if
, &n
->ip
, &n
->emac
);
2613 * Install neighbor hash entry - called upon access VLAN change.
2615 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2618 struct neigh_walk_ctx
*wctx
= ctxt
;
2620 n
= (zebra_neigh_t
*)bucket
->data
;
2622 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2623 zvni_neigh_install(wctx
->zvni
, n
);
2626 /* Get the VRR interface for SVI if any */
2627 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2629 struct zebra_vrf
*zvrf
= NULL
;
2630 struct interface
*tmp_if
= NULL
;
2631 struct zebra_if
*zif
= NULL
;
2633 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2636 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2641 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2644 if (zif
->link
== ifp
)
2651 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2653 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2654 struct connected
*c
= NULL
;
2655 struct ethaddr macaddr
;
2657 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2659 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2662 memset(&ip
, 0, sizeof(struct ipaddr
));
2663 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2666 if (c
->address
->family
== AF_INET
) {
2667 ip
.ipa_type
= IPADDR_V4
;
2668 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2669 sizeof(struct in_addr
));
2670 } else if (c
->address
->family
== AF_INET6
) {
2671 ip
.ipa_type
= IPADDR_V6
;
2672 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2673 sizeof(struct in6_addr
));
2678 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2684 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2686 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2687 struct connected
*c
= NULL
;
2688 struct ethaddr macaddr
;
2690 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2692 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2695 memset(&ip
, 0, sizeof(struct ipaddr
));
2696 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2699 if (c
->address
->family
== AF_INET
) {
2700 ip
.ipa_type
= IPADDR_V4
;
2701 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2702 sizeof(struct in_addr
));
2703 } else if (c
->address
->family
== AF_INET6
) {
2704 ip
.ipa_type
= IPADDR_V6
;
2705 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2706 sizeof(struct in6_addr
));
2711 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2717 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2720 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2721 struct connected
*c
= NULL
;
2722 struct ethaddr macaddr
;
2724 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2726 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2729 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2731 /* skip link local address */
2732 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2737 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2738 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2740 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2741 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2747 * zvni_gw_macip_add_to_client
2749 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2750 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2752 char buf
[ETHER_ADDR_STRLEN
];
2753 char buf2
[INET6_ADDRSTRLEN
];
2754 zebra_neigh_t
*n
= NULL
;
2755 zebra_mac_t
*mac
= NULL
;
2756 struct zebra_if
*zif
= NULL
;
2757 struct zebra_l2info_vxlan
*vxl
= NULL
;
2759 zif
= zvni
->vxlan_if
->info
;
2763 vxl
= &zif
->l2info
.vxl
;
2765 mac
= zvni_mac_lookup(zvni
, macaddr
);
2767 mac
= zvni_mac_add(zvni
, macaddr
);
2769 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2770 "Failed to add MAC %s intf %s(%u) VID %u",
2771 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2772 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2777 /* Set "local" forwarding info. */
2778 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2779 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2780 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2781 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2782 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2783 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2785 n
= zvni_neigh_lookup(zvni
, ip
);
2787 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2790 EC_ZEBRA_MAC_ADD_FAILED
,
2791 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2792 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2793 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2794 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2799 /* Set "local" forwarding info. */
2800 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2801 ZEBRA_NEIGH_SET_ACTIVE(n
);
2802 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2803 n
->ifindex
= ifp
->ifindex
;
2805 /* Only advertise in BGP if the knob is enabled */
2806 if (advertise_gw_macip_enabled(zvni
)) {
2808 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2809 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2810 /* Set Router flag (R-bit) */
2811 if (ip
->ipa_type
== IPADDR_V6
)
2812 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2814 if (IS_ZEBRA_DEBUG_VXLAN
)
2816 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2817 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2818 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2819 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2821 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2822 n
->flags
, n
->loc_seq
);
2823 } else if (advertise_svi_macip_enabled(zvni
)) {
2825 SET_FLAG(n
->flags
, ZEBRA_NEIGH_SVI_IP
);
2826 if (IS_ZEBRA_DEBUG_VXLAN
)
2828 "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
2829 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2830 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2831 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2833 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2834 n
->flags
, n
->loc_seq
);
2841 * zvni_gw_macip_del_from_client
2843 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2846 char buf1
[ETHER_ADDR_STRLEN
];
2847 char buf2
[INET6_ADDRSTRLEN
];
2848 zebra_neigh_t
*n
= NULL
;
2849 zebra_mac_t
*mac
= NULL
;
2851 /* If the neigh entry is not present nothing to do*/
2852 n
= zvni_neigh_lookup(zvni
, ip
);
2856 /* mac entry should be present */
2857 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2859 if (IS_ZEBRA_DEBUG_VXLAN
)
2860 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2861 prefix_mac2str(&n
->emac
,
2862 buf1
, sizeof(buf1
)),
2863 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2868 /* If the entry is not local nothing to do*/
2869 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2872 /* only need to delete the entry from bgp if we sent it before */
2873 if (IS_ZEBRA_DEBUG_VXLAN
)
2875 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2876 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2877 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2878 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2880 /* Remove neighbor from BGP. */
2881 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2882 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2884 /* Delete this neighbor entry. */
2885 zvni_neigh_del(zvni
, n
);
2887 /* see if the mac needs to be deleted as well*/
2889 zvni_deref_ip2mac(zvni
, mac
);
2894 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2897 zebra_vni_t
*zvni
= NULL
;
2898 struct zebra_if
*zif
= NULL
;
2899 struct zebra_l2info_vxlan zl2_info
;
2900 struct interface
*vlan_if
= NULL
;
2901 struct interface
*vrr_if
= NULL
;
2902 struct interface
*ifp
;
2904 /* Add primary SVI MAC*/
2905 zvni
= (zebra_vni_t
*)bucket
->data
;
2907 /* Global (Zvrf) advertise-default-gw is disabled,
2908 * but zvni advertise-default-gw is enabled
2910 if (zvni
->advertise_gw_macip
) {
2911 if (IS_ZEBRA_DEBUG_VXLAN
)
2912 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
2917 ifp
= zvni
->vxlan_if
;
2922 /* If down or not mapped to a bridge, we're done. */
2923 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2926 zl2_info
= zif
->l2info
.vxl
;
2929 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2933 /* Del primary MAC-IP */
2934 zvni_del_macip_for_intf(vlan_if
, zvni
);
2936 /* Del VRR MAC-IP - if any*/
2937 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2939 zvni_del_macip_for_intf(vrr_if
, zvni
);
2944 static void zvni_gw_macip_add_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
*vrr_if
= NULL
;
2952 struct interface
*ifp
= NULL
;
2954 zvni
= (zebra_vni_t
*)bucket
->data
;
2956 ifp
= zvni
->vxlan_if
;
2961 /* If down or not mapped to a bridge, we're done. */
2962 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2964 zl2_info
= zif
->l2info
.vxl
;
2967 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2971 /* Add primary SVI MAC-IP */
2972 zvni_add_macip_for_intf(vlan_if
, zvni
);
2974 if (advertise_gw_macip_enabled(zvni
)) {
2975 /* Add VRR MAC-IP - if any*/
2976 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2978 zvni_add_macip_for_intf(vrr_if
, zvni
);
2984 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2987 zebra_vni_t
*zvni
= NULL
;
2988 struct zebra_if
*zif
= NULL
;
2989 struct zebra_l2info_vxlan zl2_info
;
2990 struct interface
*vlan_if
= NULL
;
2991 struct interface
*ifp
;
2993 /* Add primary SVI MAC*/
2994 zvni
= (zebra_vni_t
*)bucket
->data
;
2998 /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
3001 if (zvni
->advertise_svi_macip
) {
3002 if (IS_ZEBRA_DEBUG_VXLAN
)
3003 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
3008 ifp
= zvni
->vxlan_if
;
3013 /* If down or not mapped to a bridge, we're done. */
3014 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3017 zl2_info
= zif
->l2info
.vxl
;
3019 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
3020 zif
->brslave_info
.br_if
);
3024 /* Del primary MAC-IP */
3025 zvni_del_macip_for_intf(vlan_if
, zvni
);
3030 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
3031 struct interface
*ifp
,
3033 struct ethaddr
*macaddr
,
3036 char buf
[ETHER_ADDR_STRLEN
];
3037 char buf2
[INET6_ADDRSTRLEN
];
3038 struct zebra_vrf
*zvrf
;
3039 zebra_neigh_t
*n
= NULL
;
3040 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3041 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3042 bool upd_mac_seq
= false;
3043 bool neigh_mac_change
= false;
3044 bool neigh_on_hold
= false;
3045 bool neigh_was_remote
= false;
3046 bool do_dad
= false;
3047 struct in_addr vtep_ip
= {.s_addr
= 0};
3049 /* Check if the MAC exists. */
3050 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3052 /* create a dummy MAC if the MAC is not already present */
3053 if (IS_ZEBRA_DEBUG_VXLAN
)
3055 "AUTO MAC %s created for neigh %s on VNI %u",
3056 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3057 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3059 zmac
= zvni_mac_add(zvni
, macaddr
);
3061 zlog_debug("Failed to add MAC %s VNI %u",
3062 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3067 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3068 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3069 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3071 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3073 * We don't change the MAC to local upon a neighbor
3074 * learn event, we wait for the explicit local MAC
3075 * learn. However, we have to compute its sequence
3076 * number in preparation for when it actually turns
3083 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3085 if (IS_ZEBRA_DEBUG_VXLAN
)
3086 zlog_debug("\tUnable to find vrf for: %d",
3087 zvni
->vxlan_if
->vrf_id
);
3091 /* Check if the neighbor exists. */
3092 n
= zvni_neigh_lookup(zvni
, ip
);
3094 /* New neighbor - create */
3095 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3098 EC_ZEBRA_MAC_ADD_FAILED
,
3099 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3100 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3101 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3102 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3105 /* Set "local" forwarding info. */
3106 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3107 n
->ifindex
= ifp
->ifindex
;
3109 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3113 /* Note any changes and see if of interest to BGP. */
3114 mac_different
= (memcmp(n
->emac
.octet
,
3115 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3116 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3117 ZEBRA_NEIGH_ROUTER_FLAG
);
3118 if (!mac_different
&& is_router
== cur_is_router
) {
3119 if (IS_ZEBRA_DEBUG_VXLAN
)
3121 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3122 n
->ifindex
= ifp
->ifindex
;
3126 if (!mac_different
) {
3127 bool is_neigh_freezed
= false;
3129 /* Only the router flag has changed. */
3132 ZEBRA_NEIGH_ROUTER_FLAG
);
3134 UNSET_FLAG(n
->flags
,
3135 ZEBRA_NEIGH_ROUTER_FLAG
);
3137 /* Neigh is in freeze state and freeze action
3138 * is enabled, do not send update to client.
3140 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3142 CHECK_FLAG(n
->flags
,
3143 ZEBRA_NEIGH_DUPLICATE
));
3145 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3147 return zvni_neigh_send_add_to_client(
3148 zvni
->vni
, ip
, macaddr
,
3149 n
->flags
, n
->loc_seq
);
3151 if (IS_ZEBRA_DEBUG_VXLAN
)
3153 "\tNeighbor active and frozen");
3158 /* The MAC has changed, need to issue a delete
3159 * first as this means a different MACIP route.
3160 * Also, need to do some unlinking/relinking.
3161 * We also need to update the MAC's sequence number
3162 * in different situations.
3164 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3165 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3166 &n
->emac
, 0, n
->state
);
3167 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3169 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3171 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3172 neigh_mac_change
= upd_mac_seq
= true;
3173 listnode_delete(old_zmac
->neigh_list
, n
);
3174 zvni_deref_ip2mac(zvni
, old_zmac
);
3177 /* Update the forwarding info. */
3178 n
->ifindex
= ifp
->ifindex
;
3179 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3181 /* Link to new MAC */
3182 listnode_add_sort(zmac
->neigh_list
, n
);
3183 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3185 * Neighbor has moved from remote to local. Its
3186 * MAC could have also changed as part of the move.
3188 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3190 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3192 old_mac_seq
= CHECK_FLAG(
3197 neigh_mac_change
= upd_mac_seq
= true;
3198 listnode_delete(old_zmac
->neigh_list
,
3200 zvni_deref_ip2mac(zvni
, old_zmac
);
3203 /* Link to new MAC */
3204 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3205 listnode_add_sort(zmac
->neigh_list
, n
);
3207 /* Based on Mobility event Scenario-B from the
3208 * draft, neigh's previous state was remote treat this
3211 neigh_was_remote
= true;
3212 vtep_ip
= n
->r_vtep_ip
;
3213 /* Mark appropriately */
3214 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3215 n
->r_vtep_ip
.s_addr
= 0;
3216 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3217 n
->ifindex
= ifp
->ifindex
;
3221 /* If MAC was previously remote, or the neighbor had a different
3222 * MAC earlier, recompute the sequence number.
3225 uint32_t seq1
, seq2
;
3227 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3228 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3229 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3230 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3231 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3234 /* Mark Router flag (R-bit) */
3236 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3238 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3240 /* Check old and/or new MAC detected as duplicate mark
3241 * the neigh as duplicate
3243 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3244 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3245 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3247 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3248 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3251 /* For IP Duplicate Address Detection (DAD) is trigger,
3252 * when the event is extended mobility based on scenario-B
3253 * from the draft, IP/Neigh's MAC binding changed and
3254 * neigh's previous state was remote.
3256 if (neigh_mac_change
&& neigh_was_remote
)
3259 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3260 &neigh_on_hold
, true);
3262 /* Before we program this in BGP, we need to check if MAC is locally
3263 * learnt. If not, force neighbor to be inactive and reset its seq.
3265 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3266 ZEBRA_NEIGH_SET_INACTIVE(n
);
3268 zmac
->loc_seq
= mac_new_seq
;
3272 /* If the MAC's sequence number has changed, inform the MAC and all
3273 * neighbors associated with the MAC to BGP, else just inform this
3276 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3277 if (IS_ZEBRA_DEBUG_VXLAN
)
3278 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3279 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3280 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3281 zmac
->loc_seq
= mac_new_seq
;
3282 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3283 zmac
->flags
, zmac
->loc_seq
))
3285 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3289 n
->loc_seq
= zmac
->loc_seq
;
3291 if (!neigh_on_hold
) {
3292 ZEBRA_NEIGH_SET_ACTIVE(n
);
3294 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3295 n
->flags
, n
->loc_seq
);
3297 if (IS_ZEBRA_DEBUG_VXLAN
)
3298 zlog_debug("\tNeighbor on hold not sending");
3303 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3304 struct interface
*ifp
,
3306 struct ethaddr
*macaddr
,
3309 char buf
[ETHER_ADDR_STRLEN
];
3310 char buf2
[INET6_ADDRSTRLEN
];
3311 zebra_neigh_t
*n
= NULL
;
3312 zebra_mac_t
*zmac
= NULL
;
3314 /* If the neighbor is unknown, there is no further action. */
3315 n
= zvni_neigh_lookup(zvni
, ip
);
3319 /* If a remote entry, see if it needs to be refreshed */
3320 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3322 if (state
& NUD_STALE
)
3323 zvni_neigh_install(zvni
, n
);
3326 /* We got a "remote" neighbor notification for an entry
3327 * we think is local. This can happen in a multihoming
3328 * scenario - but only if the MAC is already "remote".
3329 * Just mark our entry as "remote".
3331 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3332 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3334 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3335 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3336 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3341 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3342 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3343 ZEBRA_NEIGH_SET_ACTIVE(n
);
3344 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3351 * Make hash key for MAC.
3353 static unsigned int mac_hash_keymake(const void *p
)
3355 const zebra_mac_t
*pmac
= p
;
3356 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3358 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3362 * Compare two MAC addresses.
3364 static bool mac_cmp(const void *p1
, const void *p2
)
3366 const zebra_mac_t
*pmac1
= p1
;
3367 const zebra_mac_t
*pmac2
= p2
;
3369 if (pmac1
== NULL
&& pmac2
== NULL
)
3372 if (pmac1
== NULL
|| pmac2
== NULL
)
3375 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3380 * Callback to allocate MAC hash entry.
3382 static void *zvni_mac_alloc(void *p
)
3384 const zebra_mac_t
*tmp_mac
= p
;
3387 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3390 return ((void *)mac
);
3396 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3398 zebra_mac_t tmp_mac
;
3399 zebra_mac_t
*mac
= NULL
;
3401 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3402 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3403 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3407 mac
->dad_mac_auto_recovery_timer
= NULL
;
3409 mac
->neigh_list
= list_new();
3410 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3418 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3420 zebra_mac_t
*tmp_mac
;
3422 /* Cancel auto recovery */
3423 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3425 list_delete(&mac
->neigh_list
);
3427 /* Free the VNI hash entry and allocated memory. */
3428 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3429 XFREE(MTYPE_MAC
, tmp_mac
);
3434 static bool zvni_check_mac_del_from_db(struct mac_walk_ctx
*wctx
,
3437 if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3438 (mac
->flags
& ZEBRA_MAC_LOCAL
))
3440 else if ((wctx
->flags
& DEL_REMOTE_MAC
) &&
3441 (mac
->flags
& ZEBRA_MAC_REMOTE
))
3443 else if ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
) &&
3444 (mac
->flags
& ZEBRA_MAC_REMOTE
) &&
3445 IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &wctx
->r_vtep_ip
))
3447 else if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3448 (mac
->flags
& ZEBRA_MAC_AUTO
) &&
3449 !listcount(mac
->neigh_list
)) {
3450 if (IS_ZEBRA_DEBUG_VXLAN
) {
3451 char buf
[ETHER_ADDR_STRLEN
];
3453 zlog_debug("%s: Del MAC %s flags 0x%x",
3454 __PRETTY_FUNCTION__
,
3455 prefix_mac2str(&mac
->macaddr
,
3459 wctx
->uninstall
= 0;
3468 * Free MAC hash entry (callback)
3470 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3472 struct mac_walk_ctx
*wctx
= arg
;
3473 zebra_mac_t
*mac
= bucket
->data
;
3475 if (zvni_check_mac_del_from_db(wctx
, mac
)) {
3476 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3477 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3480 if (wctx
->uninstall
)
3481 zvni_mac_uninstall(wctx
->zvni
, mac
);
3483 zvni_mac_del(wctx
->zvni
, mac
);
3490 * Delete all MAC entries from specific VTEP for a particular VNI.
3492 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3493 struct in_addr
*r_vtep_ip
)
3495 struct mac_walk_ctx wctx
;
3497 if (!zvni
->mac_table
)
3500 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3502 wctx
.uninstall
= uninstall
;
3503 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3504 wctx
.r_vtep_ip
= *r_vtep_ip
;
3506 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3510 * Delete all MAC entries for this VNI.
3512 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3515 struct mac_walk_ctx wctx
;
3517 if (!zvni
->mac_table
)
3520 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3522 wctx
.uninstall
= uninstall
;
3523 wctx
.upd_client
= upd_client
;
3526 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3530 * Look up MAC hash entry.
3532 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3537 memset(&tmp
, 0, sizeof(tmp
));
3538 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3539 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3545 * Inform BGP about local MAC addition.
3547 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3548 uint8_t mac_flags
, uint32_t seq
)
3552 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3553 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3554 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3555 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3557 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3558 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3562 * Inform BGP about local MAC deletion.
3564 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3566 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3567 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3571 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3572 * notifications, to see if they are of interest.
3574 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3575 struct interface
*br_if
, vlanid_t vid
)
3577 struct zebra_ns
*zns
;
3578 struct route_node
*rn
;
3579 struct interface
*tmp_if
= NULL
;
3580 struct zebra_if
*zif
;
3581 struct zebra_l2info_bridge
*br
;
3582 struct zebra_l2info_vxlan
*vxl
= NULL
;
3583 uint8_t bridge_vlan_aware
;
3587 /* Determine if bridge is VLAN-aware or not */
3590 br
= &zif
->l2info
.br
;
3591 bridge_vlan_aware
= br
->vlan_aware
;
3593 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3594 /* TODO: Optimize with a hash. */
3595 zns
= zebra_ns_lookup(NS_DEFAULT
);
3596 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3597 tmp_if
= (struct interface
*)rn
->info
;
3601 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3603 if (!if_is_operative(tmp_if
))
3605 vxl
= &zif
->l2info
.vxl
;
3607 if (zif
->brslave_info
.br_if
!= br_if
)
3610 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3619 zvni
= zvni_lookup(vxl
->vni
);
3624 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3625 * neighbor notifications, to see if they are of interest.
3627 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3628 struct interface
*br_if
)
3630 struct zebra_ns
*zns
;
3631 struct route_node
*rn
;
3632 struct interface
*tmp_if
= NULL
;
3633 struct zebra_if
*zif
;
3634 struct zebra_l2info_bridge
*br
;
3635 struct zebra_l2info_vxlan
*vxl
= NULL
;
3636 uint8_t bridge_vlan_aware
;
3644 /* Make sure the linked interface is a bridge. */
3645 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3648 /* Determine if bridge is VLAN-aware or not */
3651 br
= &zif
->l2info
.br
;
3652 bridge_vlan_aware
= br
->vlan_aware
;
3653 if (bridge_vlan_aware
) {
3654 struct zebra_l2info_vlan
*vl
;
3656 if (!IS_ZEBRA_IF_VLAN(ifp
))
3661 vl
= &zif
->l2info
.vl
;
3665 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3666 /* TODO: Optimize with a hash. */
3667 zns
= zebra_ns_lookup(NS_DEFAULT
);
3668 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3669 tmp_if
= (struct interface
*)rn
->info
;
3673 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3675 if (!if_is_operative(tmp_if
))
3677 vxl
= &zif
->l2info
.vxl
;
3679 if (zif
->brslave_info
.br_if
!= br_if
)
3682 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3691 zvni
= zvni_lookup(vxl
->vni
);
3695 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3697 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3698 * linked to the bridge
3699 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
3702 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3704 struct zebra_ns
*zns
;
3705 struct route_node
*rn
;
3706 struct interface
*tmp_if
= NULL
;
3707 struct zebra_if
*zif
;
3708 struct zebra_l2info_bridge
*br
;
3709 struct zebra_l2info_vlan
*vl
;
3710 uint8_t bridge_vlan_aware
;
3713 /* Defensive check, caller expected to invoke only with valid bridge. */
3717 /* Determine if bridge is VLAN-aware or not */
3720 br
= &zif
->l2info
.br
;
3721 bridge_vlan_aware
= br
->vlan_aware
;
3723 /* Check oper status of the SVI. */
3724 if (!bridge_vlan_aware
)
3725 return if_is_operative(br_if
) ? br_if
: NULL
;
3727 /* Identify corresponding VLAN interface. */
3728 /* TODO: Optimize with a hash. */
3729 zns
= zebra_ns_lookup(NS_DEFAULT
);
3730 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3731 tmp_if
= (struct interface
*)rn
->info
;
3732 /* Check oper status of the SVI. */
3733 if (!tmp_if
|| !if_is_operative(tmp_if
))
3736 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3737 || zif
->link
!= br_if
)
3739 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3741 if (vl
->vid
== vid
) {
3747 return found
? tmp_if
: NULL
;
3750 /* Map to MAC-VLAN interface corresponding to specified SVI interface.
3752 static struct interface
*zvni_map_to_macvlan(struct interface
*br_if
,
3753 struct interface
*svi_if
)
3755 struct zebra_ns
*zns
;
3756 struct route_node
*rn
;
3757 struct interface
*tmp_if
= NULL
;
3758 struct zebra_if
*zif
;
3761 /* Defensive check, caller expected to invoke only with valid bridge. */
3766 zlog_debug("svi_if is not passed.");
3770 /* Determine if bridge is VLAN-aware or not */
3774 /* Identify corresponding VLAN interface. */
3775 zns
= zebra_ns_lookup(NS_DEFAULT
);
3776 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3777 tmp_if
= (struct interface
*)rn
->info
;
3778 /* Check oper status of the SVI. */
3779 if (!tmp_if
|| !if_is_operative(tmp_if
))
3783 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_MACVLAN
)
3786 if (zif
->link
== svi_if
) {
3792 return found
? tmp_if
: NULL
;
3797 * Install remote MAC into the forwarding plane.
3799 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3801 const struct zebra_if
*zif
, *br_zif
;
3802 const struct zebra_l2info_vxlan
*vxl
;
3804 enum zebra_dplane_result res
;
3805 const struct interface
*br_ifp
;
3808 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3811 zif
= zvni
->vxlan_if
->info
;
3815 br_ifp
= zif
->brslave_info
.br_if
;
3819 vxl
= &zif
->l2info
.vxl
;
3821 sticky
= !!CHECK_FLAG(mac
->flags
,
3822 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3824 br_zif
= (const struct zebra_if
*)(br_ifp
->info
);
3826 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3827 vid
= vxl
->access_vlan
;
3831 res
= dplane_mac_add(zvni
->vxlan_if
, br_ifp
, vid
,
3832 &mac
->macaddr
, mac
->fwd_info
.r_vtep_ip
, sticky
);
3833 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3840 * Uninstall remote MAC from the forwarding plane.
3842 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3844 const struct zebra_if
*zif
, *br_zif
;
3845 const struct zebra_l2info_vxlan
*vxl
;
3846 struct in_addr vtep_ip
;
3847 const struct interface
*ifp
, *br_ifp
;
3849 enum zebra_dplane_result res
;
3851 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3854 if (!zvni
->vxlan_if
) {
3855 if (IS_ZEBRA_DEBUG_VXLAN
)
3856 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3861 zif
= zvni
->vxlan_if
->info
;
3865 br_ifp
= zif
->brslave_info
.br_if
;
3869 vxl
= &zif
->l2info
.vxl
;
3871 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
3873 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3874 vid
= vxl
->access_vlan
;
3878 ifp
= zvni
->vxlan_if
;
3879 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3881 res
= dplane_mac_del(ifp
, br_ifp
, vid
, &mac
->macaddr
, vtep_ip
);
3882 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3889 * Install MAC hash entry - called upon access VLAN change.
3891 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3894 struct mac_walk_ctx
*wctx
= ctxt
;
3896 mac
= (zebra_mac_t
*)bucket
->data
;
3898 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3899 zvni_mac_install(wctx
->zvni
, mac
);
3903 * Count of remote neighbors referencing this MAC.
3905 static int remote_neigh_count(zebra_mac_t
*zmac
)
3907 zebra_neigh_t
*n
= NULL
;
3908 struct listnode
*node
= NULL
;
3911 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3912 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3920 * Decrement neighbor refcount of MAC; uninstall and free it if
3923 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3925 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3928 /* If all remote neighbors referencing a remote MAC go away,
3929 * we need to uninstall the MAC.
3931 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3932 remote_neigh_count(mac
) == 0) {
3933 zvni_mac_uninstall(zvni
, mac
);
3934 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3937 /* If no neighbors, delete the MAC. */
3938 if (list_isempty(mac
->neigh_list
))
3939 zvni_mac_del(zvni
, mac
);
3943 * Read and populate local MACs and neighbors corresponding to this VNI.
3945 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3947 struct zebra_ns
*zns
;
3948 struct zebra_if
*zif
;
3949 struct interface
*vlan_if
;
3950 struct zebra_l2info_vxlan
*vxl
;
3951 struct interface
*vrr_if
;
3954 vxl
= &zif
->l2info
.vxl
;
3955 zns
= zebra_ns_lookup(NS_DEFAULT
);
3957 if (IS_ZEBRA_DEBUG_VXLAN
)
3959 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3960 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3961 zif
->brslave_info
.bridge_ifindex
);
3963 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3964 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3967 /* Add SVI MAC-IP */
3968 zvni_add_macip_for_intf(vlan_if
, zvni
);
3970 /* Add VRR MAC-IP - if any*/
3971 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3973 zvni_add_macip_for_intf(vrr_if
, zvni
);
3975 neigh_read_for_vlan(zns
, vlan_if
);
3980 * Hash function for VNI.
3982 static unsigned int vni_hash_keymake(const void *p
)
3984 const zebra_vni_t
*zvni
= p
;
3986 return (jhash_1word(zvni
->vni
, 0));
3990 * Compare 2 VNI hash entries.
3992 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3994 const zebra_vni_t
*zvni1
= p1
;
3995 const zebra_vni_t
*zvni2
= p2
;
3997 return (zvni1
->vni
== zvni2
->vni
);
4000 static int vni_list_cmp(void *p1
, void *p2
)
4002 const zebra_vni_t
*zvni1
= p1
;
4003 const zebra_vni_t
*zvni2
= p2
;
4005 if (zvni1
->vni
== zvni2
->vni
)
4007 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
4011 * Callback to allocate VNI hash entry.
4013 static void *zvni_alloc(void *p
)
4015 const zebra_vni_t
*tmp_vni
= p
;
4018 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
4019 zvni
->vni
= tmp_vni
->vni
;
4020 return ((void *)zvni
);
4024 * Look up VNI hash entry.
4026 static zebra_vni_t
*zvni_lookup(vni_t vni
)
4028 struct zebra_vrf
*zvrf
;
4029 zebra_vni_t tmp_vni
;
4030 zebra_vni_t
*zvni
= NULL
;
4032 zvrf
= zebra_vrf_get_evpn();
4034 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
4036 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
4042 * Add VNI hash entry.
4044 static zebra_vni_t
*zvni_add(vni_t vni
)
4046 struct zebra_vrf
*zvrf
;
4047 zebra_vni_t tmp_zvni
;
4048 zebra_vni_t
*zvni
= NULL
;
4050 zvrf
= zebra_vrf_get_evpn();
4052 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
4054 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
4057 /* Create hash table for MAC */
4059 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
4061 /* Create hash table for neighbors */
4062 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4063 "Zebra VNI Neighbor Table");
4069 * Delete VNI hash entry.
4071 static int zvni_del(zebra_vni_t
*zvni
)
4073 struct zebra_vrf
*zvrf
;
4074 zebra_vni_t
*tmp_zvni
;
4076 zvrf
= zebra_vrf_get_evpn();
4079 zvni
->vxlan_if
= NULL
;
4081 /* Remove references to the BUM mcast grp */
4082 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
4084 /* Free the neighbor hash table. */
4085 hash_free(zvni
->neigh_table
);
4086 zvni
->neigh_table
= NULL
;
4088 /* Free the MAC hash table. */
4089 hash_free(zvni
->mac_table
);
4090 zvni
->mac_table
= NULL
;
4092 /* Free the VNI hash entry and allocated memory. */
4093 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
4094 XFREE(MTYPE_ZVNI
, tmp_zvni
);
4100 * Inform BGP about local VNI addition.
4102 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
4104 struct zserv
*client
;
4107 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4108 /* BGP may not be running. */
4112 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4114 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
4115 stream_putl(s
, zvni
->vni
);
4116 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
4117 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
4118 stream_put_in_addr(s
, &zvni
->mcast_grp
);
4120 /* Write packet size. */
4121 stream_putw_at(s
, 0, stream_get_endp(s
));
4123 if (IS_ZEBRA_DEBUG_VXLAN
)
4124 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
4125 inet_ntoa(zvni
->local_vtep_ip
),
4126 vrf_id_to_name(zvni
->vrf_id
),
4127 zebra_route_string(client
->proto
));
4129 client
->vniadd_cnt
++;
4130 return zserv_send_message(client
, s
);
4134 * Inform BGP about local VNI deletion.
4136 static int zvni_send_del_to_client(vni_t vni
)
4138 struct zserv
*client
;
4141 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4142 /* BGP may not be running. */
4146 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4149 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4150 stream_putl(s
, vni
);
4152 /* Write packet size. */
4153 stream_putw_at(s
, 0, stream_get_endp(s
));
4155 if (IS_ZEBRA_DEBUG_VXLAN
)
4156 zlog_debug("Send VNI_DEL %u to %s", vni
,
4157 zebra_route_string(client
->proto
));
4159 client
->vnidel_cnt
++;
4160 return zserv_send_message(client
, s
);
4164 * Build the VNI hash table by going over the VxLAN interfaces. This
4165 * is called when EVPN (advertise-all-vni) is enabled.
4167 static void zvni_build_hash_table(void)
4169 struct zebra_ns
*zns
;
4170 struct route_node
*rn
;
4171 struct interface
*ifp
;
4173 /* Walk VxLAN interfaces and create VNI hash. */
4174 zns
= zebra_ns_lookup(NS_DEFAULT
);
4175 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4177 zebra_vni_t
*zvni
= NULL
;
4178 zebra_l3vni_t
*zl3vni
= NULL
;
4179 struct zebra_if
*zif
;
4180 struct zebra_l2info_vxlan
*vxl
;
4182 ifp
= (struct interface
*)rn
->info
;
4186 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4189 vxl
= &zif
->l2info
.vxl
;
4192 /* L3-VNI and L2-VNI are handled seperately */
4193 zl3vni
= zl3vni_lookup(vni
);
4196 if (IS_ZEBRA_DEBUG_VXLAN
)
4198 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4199 ifp
->name
, ifp
->ifindex
, vni
);
4201 /* associate with vxlan_if */
4202 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4203 zl3vni
->vxlan_if
= ifp
;
4206 * we need to associate with SVI.
4207 * we can associate with svi-if only after association
4208 * with vxlan-intf is complete
4210 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4212 /* Associate l3vni to mac-vlan and extract VRR MAC */
4213 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4215 if (IS_ZEBRA_DEBUG_VXLAN
)
4216 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
4217 vni
, zl3vni
->svi_if
? zl3vni
->svi_if
->name
4219 zl3vni
->mac_vlan_if
?
4220 zl3vni
->mac_vlan_if
->name
: "NIL");
4222 if (is_l3vni_oper_up(zl3vni
))
4223 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4226 struct interface
*vlan_if
= NULL
;
4228 if (IS_ZEBRA_DEBUG_VXLAN
)
4230 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4231 ifp
->name
, ifp
->ifindex
, vni
,
4232 inet_ntoa(vxl
->vtep_ip
));
4234 /* VNI hash entry is expected to exist, if the BGP process is killed */
4235 zvni
= zvni_lookup(vni
);
4238 "VNI hash already present for IF %s(%u) L2-VNI %u",
4239 ifp
->name
, ifp
->ifindex
, vni
);
4242 * Inform BGP if intf is up and mapped to
4245 if (if_is_operative(ifp
) &&
4246 zif
->brslave_info
.br_if
)
4247 zvni_send_add_to_client(zvni
);
4249 /* Send Local MAC-entries to client */
4250 zvni_send_mac_to_client(zvni
);
4252 /* Send Loval Neighbor entries to client */
4253 zvni_send_neigh_to_client(zvni
);
4255 zvni
= zvni_add(vni
);
4258 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4259 ifp
->name
, ifp
->ifindex
, vni
);
4263 if (zvni
->local_vtep_ip
.s_addr
!=
4264 vxl
->vtep_ip
.s_addr
||
4265 zvni
->mcast_grp
.s_addr
!=
4266 vxl
->mcast_grp
.s_addr
) {
4267 zebra_vxlan_sg_deref(
4268 zvni
->local_vtep_ip
,
4270 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4272 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4273 zvni
->mcast_grp
= vxl
->mcast_grp
;
4275 zvni
->vxlan_if
= ifp
;
4276 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4277 zif
->brslave_info
.br_if
);
4279 zvni
->vrf_id
= vlan_if
->vrf_id
;
4280 zl3vni
= zl3vni_from_vrf(
4284 zl3vni
->l2vnis
, zvni
);
4288 * Inform BGP if intf is up and mapped to
4291 if (if_is_operative(ifp
) &&
4292 zif
->brslave_info
.br_if
)
4293 zvni_send_add_to_client(zvni
);
4300 * See if remote VTEP matches with prefix.
4302 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4304 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4308 * Locate remote VTEP in VNI hash table.
4310 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4312 zebra_vtep_t
*zvtep
;
4317 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4318 if (zvni_vtep_match(vtep_ip
, zvtep
))
4326 * Add remote VTEP to VNI hash table.
4328 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4332 zebra_vtep_t
*zvtep
;
4334 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4336 zvtep
->vtep_ip
= *vtep_ip
;
4337 zvtep
->flood_control
= flood_control
;
4340 zvni
->vteps
->prev
= zvtep
;
4341 zvtep
->next
= zvni
->vteps
;
4342 zvni
->vteps
= zvtep
;
4348 * Remove remote VTEP from VNI hash table.
4350 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4353 zvtep
->next
->prev
= zvtep
->prev
;
4355 zvtep
->prev
->next
= zvtep
->next
;
4357 zvni
->vteps
= zvtep
->next
;
4359 zvtep
->prev
= zvtep
->next
= NULL
;
4360 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4366 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4367 * uninstall from kernel if asked to.
4369 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4371 zebra_vtep_t
*zvtep
, *zvtep_next
;
4376 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4377 zvtep_next
= zvtep
->next
;
4379 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4380 zvni_vtep_del(zvni
, zvtep
);
4387 * Install remote VTEP into the kernel if the remote VTEP has asked
4388 * for head-end-replication.
4390 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4392 if (is_vxlan_flooding_head_end() &&
4393 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
)) {
4394 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4395 dplane_vtep_add(zvni
->vxlan_if
,
4396 &zvtep
->vtep_ip
, zvni
->vni
))
4404 * Uninstall remote VTEP from the kernel.
4406 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4408 if (!zvni
->vxlan_if
) {
4409 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4414 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4415 dplane_vtep_delete(zvni
->vxlan_if
, vtep_ip
, zvni
->vni
))
4422 * Install or uninstall flood entries in the kernel corresponding to
4423 * remote VTEPs. This is invoked upon change to BUM handling.
4425 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4429 zebra_vtep_t
*zvtep
;
4431 zvni
= (zebra_vni_t
*)bucket
->data
;
4435 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4436 if (is_vxlan_flooding_head_end())
4437 zvni_vtep_install(zvni
, zvtep
);
4439 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4444 * Cleanup VNI/VTEP and update kernel
4446 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4448 zebra_vni_t
*zvni
= NULL
;
4449 zebra_l3vni_t
*zl3vni
= NULL
;
4450 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4452 zvni
= (zebra_vni_t
*)bucket
->data
;
4454 /* remove from l3-vni list */
4456 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4458 listnode_delete(zl3vni
->l2vnis
, zvni
);
4460 /* Free up all neighbors and MACs, if any. */
4461 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4462 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4464 /* Free up all remote VTEPs, if any. */
4465 zvni_vtep_del_all(zvni
, 1);
4467 /* Delete the hash entry. */
4472 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4474 zebra_l3vni_t
*zl3vni
= NULL
;
4476 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4478 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4481 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4482 struct prefix
*host
)
4484 struct host_rb_entry lookup
;
4485 struct host_rb_entry
*hle
;
4487 memset(&lookup
, 0, sizeof(lookup
));
4488 memcpy(&lookup
.p
, host
, sizeof(*host
));
4490 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4494 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4495 memcpy(hle
, &lookup
, sizeof(lookup
));
4497 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4500 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4502 struct host_rb_entry lookup
;
4503 struct host_rb_entry
*hle
;
4505 memset(&lookup
, 0, sizeof(lookup
));
4506 memcpy(&lookup
.p
, host
, sizeof(*host
));
4508 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4510 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4511 XFREE(MTYPE_HOST_PREFIX
, hle
);
4518 * Look up MAC hash entry.
4520 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4521 struct ethaddr
*rmac
)
4526 memset(&tmp
, 0, sizeof(tmp
));
4527 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4528 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4534 * Callback to allocate RMAC hash entry.
4536 static void *zl3vni_rmac_alloc(void *p
)
4538 const zebra_mac_t
*tmp_rmac
= p
;
4541 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4544 return ((void *)zrmac
);
4548 * Add RMAC entry to l3-vni
4550 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4552 zebra_mac_t tmp_rmac
;
4553 zebra_mac_t
*zrmac
= NULL
;
4555 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4556 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4557 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4560 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4562 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4563 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4571 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4573 zebra_mac_t
*tmp_rmac
;
4574 struct host_rb_entry
*hle
;
4576 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4577 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4579 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4580 XFREE(MTYPE_HOST_PREFIX
, hle
);
4583 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4584 XFREE(MTYPE_MAC
, tmp_rmac
);
4590 * Install remote RMAC into the forwarding plane.
4592 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4594 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
4595 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4596 const struct interface
*br_ifp
;
4597 enum zebra_dplane_result res
;
4600 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4601 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4604 zif
= zl3vni
->vxlan_if
->info
;
4608 br_ifp
= zif
->brslave_info
.br_if
;
4612 vxl
= &zif
->l2info
.vxl
;
4614 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4616 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4617 vid
= vxl
->access_vlan
;
4621 res
= dplane_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
,
4622 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4623 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4630 * Uninstall remote RMAC from the forwarding plane.
4632 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4634 char buf
[ETHER_ADDR_STRLEN
];
4635 const struct zebra_if
*zif
= NULL
, *br_zif
;
4636 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4637 const struct interface
*br_ifp
;
4639 enum zebra_dplane_result res
;
4641 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4642 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4645 if (!zl3vni
->vxlan_if
) {
4646 if (IS_ZEBRA_DEBUG_VXLAN
)
4648 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4649 prefix_mac2str(&zrmac
->macaddr
,
4651 zl3vni
->vni
, zl3vni
);
4655 zif
= zl3vni
->vxlan_if
->info
;
4659 br_ifp
= zif
->brslave_info
.br_if
;
4663 vxl
= &zif
->l2info
.vxl
;
4665 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4666 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4667 vid
= vxl
->access_vlan
;
4671 res
= dplane_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
,
4672 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4673 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4679 /* handle rmac add */
4680 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4681 struct ipaddr
*vtep_ip
,
4682 struct prefix
*host_prefix
)
4684 char buf
[ETHER_ADDR_STRLEN
];
4685 char buf1
[INET6_ADDRSTRLEN
];
4686 char buf2
[PREFIX_STRLEN
];
4687 zebra_mac_t
*zrmac
= NULL
;
4689 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4692 /* Create the RMAC entry, or update its vtep, if necessary. */
4693 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4696 "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s",
4697 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4699 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4700 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4703 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4704 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4706 /* Send RMAC for FPM processing */
4707 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
4710 /* install rmac in kernel */
4711 zl3vni_rmac_install(zl3vni
, zrmac
);
4712 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
4713 &vtep_ip
->ipaddr_v4
)) {
4714 if (IS_ZEBRA_DEBUG_VXLAN
)
4716 "L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s",
4718 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
),
4719 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4720 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4721 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4723 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4725 /* install rmac in kernel */
4726 zl3vni_rmac_install(zl3vni
, zrmac
);
4729 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4735 /* handle rmac delete */
4736 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4737 struct prefix
*host_prefix
)
4739 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4741 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4742 /* uninstall from kernel */
4743 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4745 /* Send RMAC for FPM processing */
4746 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
4749 /* del the rmac entry */
4750 zl3vni_rmac_del(zl3vni
, zrmac
);
4755 * Look up nh hash entry on a l3-vni.
4757 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4762 memset(&tmp
, 0, sizeof(tmp
));
4763 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4764 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4771 * Callback to allocate NH hash entry on L3-VNI.
4773 static void *zl3vni_nh_alloc(void *p
)
4775 const zebra_neigh_t
*tmp_n
= p
;
4778 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4785 * Add neighbor entry.
4787 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4788 struct ethaddr
*mac
)
4790 zebra_neigh_t tmp_n
;
4791 zebra_neigh_t
*n
= NULL
;
4793 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4794 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4795 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4798 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4800 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4801 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4802 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4808 * Delete neighbor entry.
4810 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4812 zebra_neigh_t
*tmp_n
;
4813 struct host_rb_entry
*hle
;
4815 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4816 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4818 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4819 XFREE(MTYPE_HOST_PREFIX
, hle
);
4822 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4823 XFREE(MTYPE_NEIGH
, tmp_n
);
4829 * Install remote nh as neigh into the kernel.
4831 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4836 if (!is_l3vni_oper_up(zl3vni
))
4839 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4840 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4843 flags
= DPLANE_NTF_EXT_LEARNED
;
4844 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4845 flags
|= DPLANE_NTF_ROUTER
;
4847 dplane_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4853 * Uninstall remote nh from the kernel.
4855 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4857 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4858 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4861 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4864 dplane_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
4869 /* add remote vtep as a neigh entry */
4870 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4871 struct ethaddr
*rmac
,
4872 struct prefix
*host_prefix
)
4874 char buf
[ETHER_ADDR_STRLEN
];
4875 char buf1
[ETHER_ADDR_STRLEN
];
4876 char buf2
[INET6_ADDRSTRLEN
];
4877 char buf3
[PREFIX_STRLEN
];
4878 zebra_neigh_t
*nh
= NULL
;
4880 /* Create the next hop entry, or update its mac, if necessary. */
4881 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4883 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4886 "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)",
4887 ipaddr2str(vtep_ip
, buf1
, sizeof(buf2
)),
4888 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4890 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4894 /* install the nh neigh in kernel */
4895 zl3vni_nh_install(zl3vni
, nh
);
4896 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
4897 if (IS_ZEBRA_DEBUG_VXLAN
)
4898 zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s",
4900 prefix_mac2str(&nh
->emac
, buf
, sizeof(buf
)),
4901 prefix_mac2str(rmac
, buf1
, sizeof(buf1
)),
4902 ipaddr2str(vtep_ip
, buf2
, sizeof(buf2
)),
4903 prefix2str(host_prefix
, buf3
, sizeof(buf3
)));
4905 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
4906 /* install (update) the nh neigh in kernel */
4907 zl3vni_nh_install(zl3vni
, nh
);
4910 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4915 /* handle nh neigh delete */
4916 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4917 struct prefix
*host_prefix
)
4919 rb_delete_host(&nh
->host_rb
, host_prefix
);
4921 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4922 /* uninstall from kernel */
4923 zl3vni_nh_uninstall(zl3vni
, nh
);
4925 /* delete the nh entry */
4926 zl3vni_nh_del(zl3vni
, nh
);
4930 /* handle neigh update from kernel - the only thing of interest is to
4931 * readd stale entries.
4933 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4937 zebra_neigh_t
*n
= NULL
;
4939 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4943 /* all next hop neigh are remote and installed by frr.
4944 * If the kernel has aged this entry, re-install.
4946 if (state
& NUD_STALE
)
4947 zl3vni_nh_install(zl3vni
, n
);
4952 /* handle neigh delete from kernel */
4953 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4955 zebra_neigh_t
*n
= NULL
;
4957 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4961 /* all next hop neigh are remote and installed by frr.
4962 * If we get an age out notification for these neigh entries, we have to
4965 zl3vni_nh_install(zl3vni
, n
);
4971 * Hash function for L3 VNI.
4973 static unsigned int l3vni_hash_keymake(const void *p
)
4975 const zebra_l3vni_t
*zl3vni
= p
;
4977 return jhash_1word(zl3vni
->vni
, 0);
4981 * Compare 2 L3 VNI hash entries.
4983 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4985 const zebra_l3vni_t
*zl3vni1
= p1
;
4986 const zebra_l3vni_t
*zl3vni2
= p2
;
4988 return (zl3vni1
->vni
== zl3vni2
->vni
);
4992 * Callback to allocate L3 VNI hash entry.
4994 static void *zl3vni_alloc(void *p
)
4996 zebra_l3vni_t
*zl3vni
= NULL
;
4997 const zebra_l3vni_t
*tmp_l3vni
= p
;
4999 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
5000 zl3vni
->vni
= tmp_l3vni
->vni
;
5001 return ((void *)zl3vni
);
5005 * Look up L3 VNI hash entry.
5007 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
5009 zebra_l3vni_t tmp_l3vni
;
5010 zebra_l3vni_t
*zl3vni
= NULL
;
5012 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
5013 tmp_l3vni
.vni
= vni
;
5014 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
5020 * Add L3 VNI hash entry.
5022 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
5024 zebra_l3vni_t tmp_zl3vni
;
5025 zebra_l3vni_t
*zl3vni
= NULL
;
5027 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
5028 tmp_zl3vni
.vni
= vni
;
5030 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
5033 zl3vni
->vrf_id
= vrf_id
;
5034 zl3vni
->svi_if
= NULL
;
5035 zl3vni
->vxlan_if
= NULL
;
5036 zl3vni
->l2vnis
= list_new();
5037 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
5039 /* Create hash table for remote RMAC */
5040 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
5041 "Zebra L3-VNI RMAC-Table");
5043 /* Create hash table for neighbors */
5044 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
5045 "Zebra L3-VNI next-hop table");
5051 * Delete L3 VNI hash entry.
5053 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
5055 zebra_l3vni_t
*tmp_zl3vni
;
5057 /* free the list of l2vnis */
5058 list_delete(&zl3vni
->l2vnis
);
5059 zl3vni
->l2vnis
= NULL
;
5061 /* Free the rmac table */
5062 hash_free(zl3vni
->rmac_table
);
5063 zl3vni
->rmac_table
= NULL
;
5065 /* Free the nh table */
5066 hash_free(zl3vni
->nh_table
);
5067 zl3vni
->nh_table
= NULL
;
5069 /* Free the VNI hash entry and allocated memory. */
5070 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
5071 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
5076 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
5078 struct zebra_ns
*zns
= NULL
;
5079 struct route_node
*rn
= NULL
;
5080 struct interface
*ifp
= NULL
;
5082 /* loop through all vxlan-interface */
5083 zns
= zebra_ns_lookup(NS_DEFAULT
);
5084 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5086 struct zebra_if
*zif
= NULL
;
5087 struct zebra_l2info_vxlan
*vxl
= NULL
;
5089 ifp
= (struct interface
*)rn
->info
;
5094 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5097 vxl
= &zif
->l2info
.vxl
;
5098 if (vxl
->vni
== zl3vni
->vni
) {
5099 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
5107 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
5109 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5110 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
5115 if (!zl3vni
->vxlan_if
)
5118 zif
= zl3vni
->vxlan_if
->info
;
5122 vxl
= &zif
->l2info
.vxl
;
5124 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
5127 struct interface
*zl3vni_map_to_mac_vlan_if(zebra_l3vni_t
*zl3vni
)
5129 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5134 if (!zl3vni
->vxlan_if
)
5137 zif
= zl3vni
->vxlan_if
->info
;
5141 return zvni_map_to_macvlan(zif
->brslave_info
.br_if
, zl3vni
->svi_if
);
5145 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
5147 struct zebra_vrf
*zvrf
= NULL
;
5149 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
5153 return zl3vni_lookup(zvrf
->l3vni
);
5157 * Map SVI and associated bridge to a VNI. This is invoked upon getting
5158 * neighbor notifications, to see if they are of interest.
5160 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
5161 struct interface
*br_if
)
5165 uint8_t bridge_vlan_aware
= 0;
5166 zebra_l3vni_t
*zl3vni
= NULL
;
5167 struct zebra_ns
*zns
= NULL
;
5168 struct route_node
*rn
= NULL
;
5169 struct zebra_if
*zif
= NULL
;
5170 struct interface
*tmp_if
= NULL
;
5171 struct zebra_l2info_bridge
*br
= NULL
;
5172 struct zebra_l2info_vxlan
*vxl
= NULL
;
5177 /* Make sure the linked interface is a bridge. */
5178 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
5181 /* Determine if bridge is VLAN-aware or not */
5184 br
= &zif
->l2info
.br
;
5185 bridge_vlan_aware
= br
->vlan_aware
;
5186 if (bridge_vlan_aware
) {
5187 struct zebra_l2info_vlan
*vl
;
5189 if (!IS_ZEBRA_IF_VLAN(ifp
))
5194 vl
= &zif
->l2info
.vl
;
5198 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
5199 /* TODO: Optimize with a hash. */
5200 zns
= zebra_ns_lookup(NS_DEFAULT
);
5201 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5202 tmp_if
= (struct interface
*)rn
->info
;
5206 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5208 if (!if_is_operative(tmp_if
))
5210 vxl
= &zif
->l2info
.vxl
;
5212 if (zif
->brslave_info
.br_if
!= br_if
)
5215 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
5224 zl3vni
= zl3vni_lookup(vxl
->vni
);
5228 static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t
*zl3vni
,
5229 struct ethaddr
*rmac
)
5234 if (!is_l3vni_oper_up(zl3vni
))
5237 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
5238 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
5242 * Inform BGP about l3-vni.
5244 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
5246 struct stream
*s
= NULL
;
5247 struct zserv
*client
= NULL
;
5248 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
5249 struct zebra_vrf
*zvrf
;
5250 char buf
[ETHER_ADDR_STRLEN
];
5251 char buf1
[ETHER_ADDR_STRLEN
];
5252 bool is_anycast_mac
= true;
5254 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5255 /* BGP may not be running. */
5259 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
5262 /* get the svi and vrr rmac values */
5263 memset(&svi_rmac
, 0, sizeof(struct ethaddr
));
5264 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
5265 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
5267 /* In absence of vrr mac use svi mac as anycast MAC value */
5268 if (is_zero_mac(&vrr_rmac
)) {
5269 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
5270 is_anycast_mac
= false;
5273 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5275 /* The message is used for both vni add and/or update like
5276 * vrr mac is added for l3vni SVI.
5278 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
5279 stream_putl(s
, zl3vni
->vni
);
5280 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
5281 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
5282 stream_put(s
, &zl3vni
->filter
, sizeof(int));
5283 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
5284 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
5285 stream_putl(s
, is_anycast_mac
);
5287 /* Write packet size. */
5288 stream_putw_at(s
, 0, stream_get_endp(s
));
5290 if (IS_ZEBRA_DEBUG_VXLAN
)
5292 "Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %s filter %s to %s",
5293 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5294 prefix_mac2str(&svi_rmac
, buf
, sizeof(buf
)),
5295 prefix_mac2str(&vrr_rmac
, buf1
, sizeof(buf1
)),
5296 inet_ntoa(zl3vni
->local_vtep_ip
),
5297 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5298 ? "prefix-routes-only"
5300 zebra_route_string(client
->proto
));
5302 client
->l3vniadd_cnt
++;
5303 return zserv_send_message(client
, s
);
5307 * Inform BGP about local l3-VNI deletion.
5309 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5311 struct stream
*s
= NULL
;
5312 struct zserv
*client
= NULL
;
5314 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5315 /* BGP may not be running. */
5319 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5321 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5322 stream_putl(s
, zl3vni
->vni
);
5324 /* Write packet size. */
5325 stream_putw_at(s
, 0, stream_get_endp(s
));
5327 if (IS_ZEBRA_DEBUG_VXLAN
)
5328 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5329 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5330 zebra_route_string(client
->proto
));
5332 client
->l3vnidel_cnt
++;
5333 return zserv_send_message(client
, s
);
5336 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5341 /* send l3vni add to BGP */
5342 zl3vni_send_add_to_client(zl3vni
);
5345 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5350 /* send l3-vni del to BGP*/
5351 zl3vni_send_del_to_client(zl3vni
);
5354 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5356 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5357 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5359 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5360 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5364 * handle transition of vni from l2 to l3 and vice versa
5366 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5369 zebra_vni_t
*zvni
= NULL
;
5371 /* There is a possibility that VNI notification was already received
5372 * from kernel and we programmed it as L2-VNI
5373 * In such a case we need to delete this L2-VNI first, so
5374 * that it can be reprogrammed as L3-VNI in the system. It is also
5375 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5376 * interface is still present in kernel. In this case to keep it
5377 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5380 /* Locate hash entry */
5381 zvni
= zvni_lookup(vni
);
5385 if (IS_ZEBRA_DEBUG_VXLAN
)
5386 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5388 /* Delete VNI from BGP. */
5389 zvni_send_del_to_client(zvni
->vni
);
5391 /* Free up all neighbors and MAC, if any. */
5392 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5393 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5395 /* Free up all remote VTEPs, if any. */
5396 zvni_vtep_del_all(zvni
, 0);
5398 /* Delete the hash entry. */
5399 if (zvni_del(zvni
)) {
5400 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5401 "Failed to del VNI hash %p, VNI %u", zvni
,
5406 /* TODO_MITESH: This needs to be thought through. We don't have
5407 * enough information at this point to reprogram the vni as
5408 * l2-vni. One way is to store the required info in l3-vni and
5409 * used it solely for this purpose
5416 /* delete and uninstall rmac hash entry */
5417 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5419 zebra_mac_t
*zrmac
= NULL
;
5420 zebra_l3vni_t
*zl3vni
= NULL
;
5422 zrmac
= (zebra_mac_t
*)bucket
->data
;
5423 zl3vni
= (zebra_l3vni_t
*)ctx
;
5424 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5426 /* Send RMAC for FPM processing */
5427 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5429 zl3vni_rmac_del(zl3vni
, zrmac
);
5432 /* delete and uninstall nh hash entry */
5433 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5435 zebra_neigh_t
*n
= NULL
;
5436 zebra_l3vni_t
*zl3vni
= NULL
;
5438 n
= (zebra_neigh_t
*)bucket
->data
;
5439 zl3vni
= (zebra_l3vni_t
*)ctx
;
5440 zl3vni_nh_uninstall(zl3vni
, n
);
5441 zl3vni_nh_del(zl3vni
, n
);
5444 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5447 struct zserv
*client
= NULL
;
5448 struct stream
*s
= NULL
;
5449 char buf
[PREFIX_STRLEN
];
5451 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5452 /* BGP may not be running. */
5456 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5458 zclient_create_header(s
, cmd
, vrf_id
);
5459 stream_put(s
, p
, sizeof(struct prefix
));
5461 /* Write packet size. */
5462 stream_putw_at(s
, 0, stream_get_endp(s
));
5464 if (IS_ZEBRA_DEBUG_VXLAN
)
5465 zlog_debug("Send ip prefix %s %s on vrf %s",
5466 prefix2str(p
, buf
, sizeof(buf
)),
5467 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5468 vrf_id_to_name(vrf_id
));
5470 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5471 client
->prefixadd_cnt
++;
5473 client
->prefixdel_cnt
++;
5475 return zserv_send_message(client
, s
);
5478 /* re-add remote rmac if needed */
5479 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5480 struct ethaddr
*rmac
)
5482 char buf
[ETHER_ADDR_STRLEN
];
5483 zebra_mac_t
*zrmac
= NULL
;
5485 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5489 if (IS_ZEBRA_DEBUG_VXLAN
)
5490 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5491 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5493 zl3vni_rmac_install(zl3vni
, zrmac
);
5497 /* Process a remote MACIP add from BGP. */
5498 static void process_remote_macip_add(vni_t vni
,
5499 struct ethaddr
*macaddr
,
5501 struct ipaddr
*ipaddr
,
5504 struct in_addr vtep_ip
)
5507 zebra_vtep_t
*zvtep
;
5508 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5509 zebra_neigh_t
*n
= NULL
;
5510 int update_mac
= 0, update_neigh
= 0;
5511 char buf
[ETHER_ADDR_STRLEN
];
5512 char buf1
[INET6_ADDRSTRLEN
];
5513 struct interface
*ifp
= NULL
;
5514 struct zebra_if
*zif
= NULL
;
5515 struct zebra_vrf
*zvrf
;
5520 bool do_dad
= false;
5521 bool is_dup_detect
= false;
5523 /* Locate VNI hash entry - expected to exist. */
5524 zvni
= zvni_lookup(vni
);
5526 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5530 ifp
= zvni
->vxlan_if
;
5534 !if_is_operative(ifp
) ||
5536 !zif
->brslave_info
.br_if
) {
5537 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5542 /* The remote VTEP specified should normally exist, but it is
5543 * possible that when peering comes up, peer may advertise MACIP
5544 * routes before advertising type-3 routes.
5546 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5548 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5551 EC_ZEBRA_VTEP_ADD_FAILED
,
5552 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5557 zvni_vtep_install(zvni
, zvtep
);
5560 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5561 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5562 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5564 mac
= zvni_mac_lookup(zvni
, macaddr
);
5566 /* Ignore if the mac is already present as a gateway mac */
5568 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5569 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5570 if (IS_ZEBRA_DEBUG_VXLAN
)
5571 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5573 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5574 ipa_len
? " IP " : "",
5576 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5580 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5584 /* check if the remote MAC is unknown or has a change.
5585 * If so, that needs to be updated first. Note that client could
5586 * install MAC and MACIP separately or just install the latter.
5589 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5590 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5591 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5592 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5593 || seq
!= mac
->rem_seq
)
5598 mac
= zvni_mac_add(zvni
, macaddr
);
5601 "Failed to add MAC %s VNI %u Remote VTEP %s",
5602 prefix_mac2str(macaddr
, buf
,
5604 vni
, inet_ntoa(vtep_ip
));
5608 /* Is this MAC created for a MACIP? */
5610 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5612 /* When host moves but changes its (MAC,IP)
5613 * binding, BGP may install a MACIP entry that
5614 * corresponds to "older" location of the host
5615 * in transient situations (because {IP1,M1}
5616 * is a different route from {IP1,M2}). Check
5617 * the sequence number and ignore this update
5620 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5621 tmp_seq
= mac
->loc_seq
;
5623 tmp_seq
= mac
->rem_seq
;
5625 if (seq
< tmp_seq
) {
5626 if (IS_ZEBRA_DEBUG_VXLAN
)
5627 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
5629 prefix_mac2str(macaddr
,
5631 ipa_len
? " IP " : "",
5634 buf1
, sizeof(buf1
)) : "",
5635 tmp_seq
, mac
->flags
);
5640 /* Check MAC's curent state is local (this is the case
5641 * where MAC has moved from L->R) and check previous
5642 * detection started via local learning.
5643 * RFC-7432: A PE/VTEP that detects a MAC mobility
5644 * event via local learning starts an M-second timer.
5646 * VTEP-IP or seq. change alone is not considered
5647 * for dup. detection.
5649 * MAC is already marked duplicate set dad, then
5650 * is_dup_detect will be set to not install the entry.
5652 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5654 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5657 /* Remove local MAC from BGP. */
5658 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5659 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5661 /* Set "auto" and "remote" forwarding info. */
5662 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5663 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5664 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5665 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5668 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5670 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5673 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5675 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5677 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5678 mac
->fwd_info
.r_vtep_ip
,
5679 do_dad
, &is_dup_detect
,
5682 if (!is_dup_detect
) {
5683 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5684 /* Install the entry. */
5685 zvni_mac_install(zvni
, mac
);
5689 /* Update seq number. */
5692 /* If there is no IP, return after clearing AUTO flag of MAC. */
5694 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5701 /* Check if the remote neighbor itself is unknown or has a
5702 * change. If so, create or update and then install the entry.
5704 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5706 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5707 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5708 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5709 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5710 || seq
!= n
->rem_seq
)
5715 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5718 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5719 ipaddr2str(ipaddr
, buf1
,
5721 prefix_mac2str(macaddr
, buf
,
5723 vni
, inet_ntoa(vtep_ip
));
5730 /* When host moves but changes its (MAC,IP)
5731 * binding, BGP may install a MACIP entry that
5732 * corresponds to "older" location of the host
5733 * in transient situations (because {IP1,M1}
5734 * is a different route from {IP1,M2}). Check
5735 * the sequence number and ignore this update
5738 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5739 tmp_seq
= n
->loc_seq
;
5742 tmp_seq
= n
->rem_seq
;
5745 if (seq
< tmp_seq
) {
5746 if (IS_ZEBRA_DEBUG_VXLAN
)
5747 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5749 prefix_mac2str(macaddr
,
5752 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5757 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5758 /* MAC change, send a delete for old
5759 * neigh if learnt locally.
5761 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5762 IS_ZEBRA_NEIGH_ACTIVE(n
))
5763 zvni_neigh_send_del_to_client(
5765 &n
->emac
, 0, n
->state
);
5767 /* update neigh list for macs */
5768 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5770 listnode_delete(old_mac
->neigh_list
, n
);
5771 zvni_deref_ip2mac(zvni
, old_mac
);
5773 listnode_add_sort(mac
->neigh_list
, n
);
5774 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5776 /* Check Neigh's curent state is local
5777 * (this is the case where neigh/host has moved
5778 * from L->R) and check previous detction
5779 * started via local learning.
5781 * RFC-7432: A PE/VTEP that detects a MAC
5782 * mobilit event via local learning starts
5783 * an M-second timer.
5784 * VTEP-IP or seq. change along is not
5785 * considered for dup. detection.
5787 * Mobilty event scenario-B IP-MAC binding
5790 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5797 /* Set "remote" forwarding info. */
5798 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5799 n
->r_vtep_ip
= vtep_ip
;
5800 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5802 /* Set router flag (R-bit) to this Neighbor entry */
5803 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5804 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5806 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5808 /* Check old or new MAC detected as duplicate,
5809 * inherit duplicate flag to this neigh.
5811 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5813 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5814 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5816 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5817 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5820 /* Check duplicate address detection for IP */
5821 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5826 /* Install the entry. */
5828 zvni_neigh_install(zvni
, n
);
5831 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5833 /* Update seq number. */
5837 /* Process a remote MACIP delete from BGP. */
5838 static void process_remote_macip_del(vni_t vni
,
5839 struct ethaddr
*macaddr
,
5841 struct ipaddr
*ipaddr
,
5842 struct in_addr vtep_ip
)
5845 zebra_mac_t
*mac
= NULL
;
5846 zebra_neigh_t
*n
= NULL
;
5847 struct interface
*ifp
= NULL
;
5848 struct zebra_if
*zif
= NULL
;
5849 struct zebra_ns
*zns
;
5850 struct zebra_l2info_vxlan
*vxl
;
5851 struct zebra_vrf
*zvrf
;
5852 char buf
[ETHER_ADDR_STRLEN
];
5853 char buf1
[INET6_ADDRSTRLEN
];
5855 /* Locate VNI hash entry - expected to exist. */
5856 zvni
= zvni_lookup(vni
);
5858 if (IS_ZEBRA_DEBUG_VXLAN
)
5859 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5863 ifp
= zvni
->vxlan_if
;
5867 !if_is_operative(ifp
) ||
5869 !zif
->brslave_info
.br_if
) {
5870 if (IS_ZEBRA_DEBUG_VXLAN
)
5871 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5875 zns
= zebra_ns_lookup(NS_DEFAULT
);
5876 vxl
= &zif
->l2info
.vxl
;
5878 /* The remote VTEP specified is normally expected to exist, but
5879 * it is possible that the peer may delete the VTEP before deleting
5880 * any MACs referring to the VTEP, in which case the handler (see
5881 * remote_vtep_del) would have already deleted the MACs.
5883 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5886 mac
= zvni_mac_lookup(zvni
, macaddr
);
5888 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5891 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5892 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5893 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5897 /* If the remote mac or neighbor doesn't exist there is nothing
5898 * more to do. Otherwise, uninstall the entry and then remove it.
5903 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5905 /* Ignore the delete if this mac is a gateway mac-ip */
5906 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5907 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5909 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5911 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5912 ipa_len
? " IP " : "",
5914 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5918 /* Uninstall remote neighbor or MAC. */
5920 if (zvrf
->dad_freeze
&&
5921 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5922 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5923 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5924 struct interface
*vlan_if
;
5926 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5927 zif
->brslave_info
.br_if
);
5928 if (IS_ZEBRA_DEBUG_VXLAN
)
5930 "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5931 __PRETTY_FUNCTION__
,
5932 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5934 vlan_if
? vlan_if
->name
: "Unknown");
5936 neigh_read_specific_ip(ipaddr
, vlan_if
);
5939 /* When the MAC changes for an IP, it is possible the
5940 * client may update the new MAC before trying to delete the
5941 * "old" neighbor (as these are two different MACIP routes).
5942 * Do the delete only if the MAC matches.
5944 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5945 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5946 zvni_neigh_uninstall(zvni
, n
);
5947 zvni_neigh_del(zvni
, n
);
5948 zvni_deref_ip2mac(zvni
, mac
);
5951 /* DAD: when MAC is freeze state as remote learn event,
5952 * remote mac-ip delete event is received will result in freeze
5953 * entry removal, first fetch kernel for the same entry present
5954 * as LOCAL and reachable, avoid deleting this entry instead
5955 * use kerenel local entry to update during unfreeze time.
5957 if (zvrf
->dad_freeze
&&
5958 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5959 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5960 if (IS_ZEBRA_DEBUG_VXLAN
)
5961 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5962 __PRETTY_FUNCTION__
,
5963 prefix_mac2str(macaddr
, buf
,
5966 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5967 macaddr
, vxl
->access_vlan
);
5970 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5971 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5973 * the remote sequence number in the auto mac entry
5974 * needs to be reset to 0 as the mac entry may have
5975 * been removed on all VTEPs (including
5976 * the originating one)
5980 /* If all remote neighbors referencing a remote MAC
5981 * go away, we need to uninstall the MAC.
5983 if (remote_neigh_count(mac
) == 0) {
5984 zvni_mac_uninstall(zvni
, mac
);
5985 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5987 if (list_isempty(mac
->neigh_list
))
5988 zvni_mac_del(zvni
, mac
);
5990 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5996 /* Public functions */
5998 int is_l3vni_for_prefix_routes_only(vni_t vni
)
6000 zebra_l3vni_t
*zl3vni
= NULL
;
6002 zl3vni
= zl3vni_lookup(vni
);
6006 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
6009 /* handle evpn route in vrf table */
6010 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
6011 struct ipaddr
*vtep_ip
,
6012 struct prefix
*host_prefix
)
6014 zebra_l3vni_t
*zl3vni
= NULL
;
6015 struct ipaddr ipv4_vtep
;
6017 zl3vni
= zl3vni_from_vrf(vrf_id
);
6018 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6022 * add the next hop neighbor -
6023 * neigh to be installed is the ipv6 nexthop neigh
6025 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
6028 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
6029 * address. Rmac is programmed against the ipv4 vtep because we only
6030 * support ipv4 tunnels in the h/w right now
6032 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
6033 ipv4_vtep
.ipa_type
= IPADDR_V4
;
6034 if (vtep_ip
->ipa_type
== IPADDR_V6
)
6035 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
6036 &(ipv4_vtep
.ipaddr_v4
));
6038 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
6039 sizeof(struct in_addr
));
6042 * add the rmac - remote rmac to be installed is against the ipv4
6045 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
6048 /* handle evpn vrf route delete */
6049 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
6050 struct ipaddr
*vtep_ip
,
6051 struct prefix
*host_prefix
)
6053 zebra_l3vni_t
*zl3vni
= NULL
;
6054 zebra_neigh_t
*nh
= NULL
;
6055 zebra_mac_t
*zrmac
= NULL
;
6057 zl3vni
= zl3vni_from_vrf(vrf_id
);
6061 /* find the next hop entry and rmac entry */
6062 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
6065 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
6067 /* delete the next hop entry */
6068 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
6070 /* delete the rmac entry */
6072 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
6076 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
6077 struct ethaddr
*rmac
, bool use_json
)
6079 zebra_l3vni_t
*zl3vni
= NULL
;
6080 zebra_mac_t
*zrmac
= NULL
;
6081 json_object
*json
= NULL
;
6083 if (!is_evpn_enabled()) {
6085 vty_out(vty
, "{}\n");
6090 json
= json_object_new_object();
6092 zl3vni
= zl3vni_lookup(l3vni
);
6095 vty_out(vty
, "{}\n");
6097 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
6101 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
6104 vty_out(vty
, "{}\n");
6107 "%% Requested RMAC doesn't exist in L3-VNI %u",
6112 zl3vni_print_rmac(zrmac
, vty
, json
);
6115 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6116 json
, JSON_C_TO_STRING_PRETTY
));
6117 json_object_free(json
);
6121 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6123 zebra_l3vni_t
*zl3vni
;
6125 struct rmac_walk_ctx wctx
;
6126 json_object
*json
= NULL
;
6128 if (!is_evpn_enabled())
6131 zl3vni
= zl3vni_lookup(l3vni
);
6134 vty_out(vty
, "{}\n");
6136 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6139 num_rmacs
= hashcount(zl3vni
->rmac_table
);
6144 json
= json_object_new_object();
6146 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
6150 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
6152 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
6154 json_object_int_add(json
, "numRmacs", num_rmacs
);
6156 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
6159 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6160 json
, JSON_C_TO_STRING_PRETTY
));
6161 json_object_free(json
);
6165 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
6167 json_object
*json
= NULL
;
6170 if (!is_evpn_enabled()) {
6172 vty_out(vty
, "{}\n");
6177 json
= json_object_new_object();
6181 hash_iterate(zrouter
.l3vni_table
,
6182 (void (*)(struct hash_bucket
*,
6183 void *))zl3vni_print_rmac_hash_all_vni
,
6187 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6188 json
, JSON_C_TO_STRING_PRETTY
));
6189 json_object_free(json
);
6193 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
6194 struct ipaddr
*ip
, bool use_json
)
6196 zebra_l3vni_t
*zl3vni
= NULL
;
6197 zebra_neigh_t
*n
= NULL
;
6198 json_object
*json
= NULL
;
6200 if (!is_evpn_enabled()) {
6202 vty_out(vty
, "{}\n");
6207 json
= json_object_new_object();
6209 zl3vni
= zl3vni_lookup(l3vni
);
6212 vty_out(vty
, "{}\n");
6214 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6218 n
= zl3vni_nh_lookup(zl3vni
, ip
);
6221 vty_out(vty
, "{}\n");
6224 "%% Requested next-hop not present for L3-VNI %u",
6229 zl3vni_print_nh(n
, vty
, json
);
6232 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6233 json
, JSON_C_TO_STRING_PRETTY
));
6234 json_object_free(json
);
6238 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6241 struct nh_walk_ctx wctx
;
6242 json_object
*json
= NULL
;
6243 zebra_l3vni_t
*zl3vni
= NULL
;
6245 if (!is_evpn_enabled())
6248 zl3vni
= zl3vni_lookup(l3vni
);
6251 vty_out(vty
, "{}\n");
6253 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6257 num_nh
= hashcount(zl3vni
->nh_table
);
6262 json
= json_object_new_object();
6267 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
6269 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
6271 json_object_int_add(json
, "numNextHops", num_nh
);
6273 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
6276 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6277 json
, JSON_C_TO_STRING_PRETTY
));
6278 json_object_free(json
);
6282 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
6284 json_object
*json
= NULL
;
6287 if (!is_evpn_enabled()) {
6289 vty_out(vty
, "{}\n");
6294 json
= json_object_new_object();
6298 hash_iterate(zrouter
.l3vni_table
,
6299 (void (*)(struct hash_bucket
*,
6300 void *))zl3vni_print_nh_hash_all_vni
,
6304 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6305 json
, JSON_C_TO_STRING_PRETTY
));
6306 json_object_free(json
);
6311 * Display L3 VNI information (VTY command handler).
6313 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
6316 json_object
*json
= NULL
;
6317 zebra_l3vni_t
*zl3vni
= NULL
;
6319 if (!is_evpn_enabled()) {
6321 vty_out(vty
, "{}\n");
6325 zl3vni
= zl3vni_lookup(vni
);
6328 vty_out(vty
, "{}\n");
6330 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6335 json
= json_object_new_object();
6339 zl3vni_print(zl3vni
, (void *)args
);
6342 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6343 json
, JSON_C_TO_STRING_PRETTY
));
6344 json_object_free(json
);
6348 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6349 json_object
*json_vrfs
)
6351 char buf
[ETHER_ADDR_STRLEN
];
6352 zebra_l3vni_t
*zl3vni
= NULL
;
6354 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6359 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6360 zvrf_name(zvrf
), zl3vni
->vni
,
6361 zl3vni_vxlan_if_name(zl3vni
),
6362 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6363 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6365 json_object
*json_vrf
= NULL
;
6367 json_vrf
= json_object_new_object();
6368 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6369 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6370 json_object_string_add(json_vrf
, "vxlanIntf",
6371 zl3vni_vxlan_if_name(zl3vni
));
6372 json_object_string_add(json_vrf
, "sviIntf",
6373 zl3vni_svi_if_name(zl3vni
));
6374 json_object_string_add(json_vrf
, "state",
6375 zl3vni_state2str(zl3vni
));
6376 json_object_string_add(
6377 json_vrf
, "routerMac",
6378 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6379 json_object_array_add(json_vrfs
, json_vrf
);
6384 * Display Neighbors for a VNI (VTY command handler).
6386 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6387 vni_t vni
, bool use_json
)
6391 struct neigh_walk_ctx wctx
;
6392 json_object
*json
= NULL
;
6394 if (!is_evpn_enabled())
6396 zvni
= zvni_lookup(vni
);
6399 vty_out(vty
, "{}\n");
6401 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6404 num_neigh
= hashcount(zvni
->neigh_table
);
6409 json
= json_object_new_object();
6411 /* Since we have IPv6 addresses to deal with which can vary widely in
6412 * size, we try to be a bit more elegant in display by first computing
6413 * the maximum width.
6415 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6418 wctx
.addr_width
= 15;
6420 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6424 "Number of ARPs (local and remote) known for this VNI: %u\n",
6426 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx
.addr_width
,
6427 "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s");
6429 json_object_int_add(json
, "numArpNd", num_neigh
);
6431 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6433 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6434 json
, JSON_C_TO_STRING_PRETTY
));
6435 json_object_free(json
);
6440 * Display neighbors across all VNIs (VTY command handler).
6442 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6443 bool print_dup
, bool use_json
)
6445 json_object
*json
= NULL
;
6448 if (!is_evpn_enabled())
6452 json
= json_object_new_object();
6456 args
[2] = (void *)(ptrdiff_t)print_dup
;
6458 hash_iterate(zvrf
->vni_table
,
6459 (void (*)(struct hash_bucket
*,
6460 void *))zvni_print_neigh_hash_all_vni
,
6463 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6464 json
, JSON_C_TO_STRING_PRETTY
));
6465 json_object_free(json
);
6470 * Display neighbors across all VNIs in detail(VTY command handler).
6472 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6473 struct zebra_vrf
*zvrf
,
6474 bool print_dup
, bool use_json
)
6476 json_object
*json
= NULL
;
6479 if (!is_evpn_enabled())
6483 json
= json_object_new_object();
6487 args
[2] = (void *)(ptrdiff_t)print_dup
;
6489 hash_iterate(zvrf
->vni_table
,
6490 (void (*)(struct hash_bucket
*,
6491 void *))zvni_print_neigh_hash_all_vni_detail
,
6494 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6495 json
, JSON_C_TO_STRING_PRETTY
));
6496 json_object_free(json
);
6501 * Display specific neighbor for a VNI, if present (VTY command handler).
6503 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6504 struct zebra_vrf
*zvrf
, vni_t vni
,
6505 struct ipaddr
*ip
, bool use_json
)
6509 json_object
*json
= NULL
;
6511 if (!is_evpn_enabled())
6513 zvni
= zvni_lookup(vni
);
6516 vty_out(vty
, "{}\n");
6518 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6521 n
= zvni_neigh_lookup(zvni
, ip
);
6525 "%% Requested neighbor does not exist in VNI %u\n",
6530 json
= json_object_new_object();
6532 zvni_print_neigh(n
, vty
, json
);
6535 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6536 json
, JSON_C_TO_STRING_PRETTY
));
6537 json_object_free(json
);
6542 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6543 * By definition, these are remote neighbors.
6545 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6546 vni_t vni
, struct in_addr vtep_ip
,
6551 struct neigh_walk_ctx wctx
;
6552 json_object
*json
= NULL
;
6554 if (!is_evpn_enabled())
6556 zvni
= zvni_lookup(vni
);
6559 vty_out(vty
, "{}\n");
6561 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6564 num_neigh
= hashcount(zvni
->neigh_table
);
6568 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6571 wctx
.addr_width
= 15;
6572 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6573 wctx
.r_vtep_ip
= vtep_ip
;
6575 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6576 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6579 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6580 json
, JSON_C_TO_STRING_PRETTY
));
6581 json_object_free(json
);
6586 * Display Duplicate detected Neighbors for a VNI
6587 * (VTY command handler).
6589 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6590 struct zebra_vrf
*zvrf
,
6596 struct neigh_walk_ctx wctx
;
6597 json_object
*json
= NULL
;
6599 if (!is_evpn_enabled())
6602 zvni
= zvni_lookup(vni
);
6604 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6608 num_neigh
= hashcount(zvni
->neigh_table
);
6612 num_neigh
= num_dup_detected_neighs(zvni
);
6617 json
= json_object_new_object();
6619 /* Since we have IPv6 addresses to deal with which can vary widely in
6620 * size, we try to be a bit more elegant in display by first computing
6621 * the maximum width.
6623 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6626 wctx
.addr_width
= 15;
6628 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6632 "Number of ARPs (local and remote) known for this VNI: %u\n",
6634 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6635 -wctx
.addr_width
, "IP", "Type",
6636 "State", "MAC", "Remote VTEP");
6638 json_object_int_add(json
, "numArpNd", num_neigh
);
6640 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6643 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6644 json
, JSON_C_TO_STRING_PRETTY
));
6645 json_object_free(json
);
6650 * Display MACs for a VNI (VTY command handler).
6652 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6653 vni_t vni
, bool use_json
)
6657 struct mac_walk_ctx wctx
;
6658 json_object
*json
= NULL
;
6659 json_object
*json_mac
= NULL
;
6661 if (!is_evpn_enabled())
6663 zvni
= zvni_lookup(vni
);
6666 vty_out(vty
, "{}\n");
6668 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6671 num_macs
= num_valid_macs(zvni
);
6676 json
= json_object_new_object();
6677 json_mac
= json_object_new_object();
6680 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6683 wctx
.json
= json_mac
;
6687 "Number of MACs (local and remote) known for this VNI: %u\n",
6689 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type",
6690 "Intf/Remote VTEP", "VLAN", "Seq #'s");
6692 json_object_int_add(json
, "numMacs", num_macs
);
6694 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6697 json_object_object_add(json
, "macs", json_mac
);
6698 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6699 json
, JSON_C_TO_STRING_PRETTY
));
6700 json_object_free(json
);
6705 * Display MACs for all VNIs (VTY command handler).
6707 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6708 bool print_dup
, bool use_json
)
6710 struct mac_walk_ctx wctx
;
6711 json_object
*json
= NULL
;
6713 if (!is_evpn_enabled()) {
6715 vty_out(vty
, "{}\n");
6719 json
= json_object_new_object();
6721 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6724 wctx
.print_dup
= print_dup
;
6725 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6728 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6729 json
, JSON_C_TO_STRING_PRETTY
));
6730 json_object_free(json
);
6735 * Display MACs in detail for all VNIs (VTY command handler).
6737 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6738 struct zebra_vrf
*zvrf
,
6739 bool print_dup
, bool use_json
)
6741 struct mac_walk_ctx wctx
;
6742 json_object
*json
= NULL
;
6744 if (!is_evpn_enabled()) {
6746 vty_out(vty
, "{}\n");
6750 json
= json_object_new_object();
6752 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6755 wctx
.print_dup
= print_dup
;
6756 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6760 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6761 json
, JSON_C_TO_STRING_PRETTY
));
6762 json_object_free(json
);
6767 * Display MACs for all VNIs (VTY command handler).
6769 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6770 struct zebra_vrf
*zvrf
,
6771 struct in_addr vtep_ip
, bool use_json
)
6773 struct mac_walk_ctx wctx
;
6774 json_object
*json
= NULL
;
6776 if (!is_evpn_enabled())
6780 json
= json_object_new_object();
6782 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6784 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6785 wctx
.r_vtep_ip
= vtep_ip
;
6787 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6790 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6791 json
, JSON_C_TO_STRING_PRETTY
));
6792 json_object_free(json
);
6797 * Display specific MAC for a VNI, if present (VTY command handler).
6799 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6800 vni_t vni
, struct ethaddr
*macaddr
,
6805 json_object
*json
= NULL
;
6807 if (!is_evpn_enabled())
6810 zvni
= zvni_lookup(vni
);
6813 vty_out(vty
, "{}\n");
6815 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6818 mac
= zvni_mac_lookup(zvni
, macaddr
);
6821 vty_out(vty
, "{}\n");
6824 "%% Requested MAC does not exist in VNI %u\n",
6830 json
= json_object_new_object();
6832 zvni_print_mac(mac
, vty
, json
);
6834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6835 json
, JSON_C_TO_STRING_PRETTY
));
6836 json_object_free(json
);
6840 /* Print Duplicate MACs per VNI */
6841 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6842 struct zebra_vrf
*zvrf
,
6843 vni_t vni
, bool use_json
)
6846 struct mac_walk_ctx wctx
;
6848 json_object
*json
= NULL
;
6849 json_object
*json_mac
= NULL
;
6851 if (!is_evpn_enabled())
6854 zvni
= zvni_lookup(vni
);
6856 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6860 num_macs
= num_valid_macs(zvni
);
6864 num_macs
= num_dup_detected_macs(zvni
);
6869 json
= json_object_new_object();
6870 json_mac
= json_object_new_object();
6873 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6876 wctx
.json
= json_mac
;
6880 "Number of MACs (local and remote) known for this VNI: %u\n",
6882 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6883 "Intf/Remote VTEP", "VLAN");
6885 json_object_int_add(json
, "numMacs", num_macs
);
6887 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6890 json_object_object_add(json
, "macs", json_mac
);
6891 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6892 json
, JSON_C_TO_STRING_PRETTY
));
6893 json_object_free(json
);
6898 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6899 struct zebra_vrf
*zvrf
,
6900 vni_t vni
, struct ethaddr
*macaddr
)
6904 struct listnode
*node
= NULL
;
6905 zebra_neigh_t
*nbr
= NULL
;
6907 if (!is_evpn_enabled())
6910 zvni
= zvni_lookup(vni
);
6912 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6916 mac
= zvni_mac_lookup(zvni
, macaddr
);
6918 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6923 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6924 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6928 /* Remove all IPs as duplicate associcated with this MAC */
6929 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6930 /* For local neigh mark inactive so MACIP update is generated
6931 * to BGP. This is a scenario where MAC update received
6932 * and detected as duplicate which marked neigh as duplicate.
6933 * Later local neigh update did not get a chance to relay
6934 * to BGP. Similarly remote macip update, neigh needs to be
6935 * installed locally.
6937 if (zvrf
->dad_freeze
&&
6938 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6939 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6940 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6941 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6942 zvni_neigh_install(zvni
, nbr
);
6945 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6947 nbr
->detect_start_time
.tv_sec
= 0;
6948 nbr
->dad_dup_detect_time
= 0;
6951 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6953 mac
->detect_start_time
.tv_sec
= 0;
6954 mac
->detect_start_time
.tv_usec
= 0;
6955 mac
->dad_dup_detect_time
= 0;
6956 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6958 /* warn-only action return */
6959 if (!zvrf
->dad_freeze
)
6962 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6963 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6965 if (zvni_mac_send_add_to_client(zvni
->vni
,
6971 /* Process all neighbors associated with this MAC. */
6972 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6974 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6975 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6977 /* Install the entry. */
6978 zvni_mac_install(zvni
, mac
);
6984 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6985 struct zebra_vrf
*zvrf
,
6986 vni_t vni
, struct ipaddr
*ip
)
6991 char buf
[INET6_ADDRSTRLEN
];
6992 char buf2
[ETHER_ADDR_STRLEN
];
6994 if (!is_evpn_enabled())
6997 zvni
= zvni_lookup(vni
);
6999 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7003 nbr
= zvni_neigh_lookup(zvni
, ip
);
7006 "%% Requested host IP does not exist in VNI %u\n",
7011 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
7013 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
7015 "%% Requested host IP %s is not duplicate detected\n",
7020 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
7022 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
7024 "%% Requested IP's associated MAC %s is still in duplicate state\n",
7025 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
7026 return CMD_WARNING_CONFIG_FAILED
;
7029 if (IS_ZEBRA_DEBUG_VXLAN
)
7030 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
7031 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
7034 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7036 nbr
->detect_start_time
.tv_sec
= 0;
7037 nbr
->detect_start_time
.tv_usec
= 0;
7038 nbr
->dad_dup_detect_time
= 0;
7039 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
7041 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7042 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
7044 nbr
->flags
, nbr
->loc_seq
);
7045 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7046 zvni_neigh_install(zvni
, nbr
);
7052 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
7054 struct mac_walk_ctx
*wctx
= ctxt
;
7057 struct listnode
*node
= NULL
;
7058 zebra_neigh_t
*nbr
= NULL
;
7060 mac
= (zebra_mac_t
*)bucket
->data
;
7066 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
7069 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
7071 mac
->detect_start_time
.tv_sec
= 0;
7072 mac
->detect_start_time
.tv_usec
= 0;
7073 mac
->dad_dup_detect_time
= 0;
7074 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
7076 /* Remove all IPs as duplicate associcated with this MAC */
7077 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
7078 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
7080 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
7082 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7084 nbr
->detect_start_time
.tv_sec
= 0;
7085 nbr
->dad_dup_detect_time
= 0;
7088 /* Local: Notify Peer VTEPs, Remote: Install the entry */
7089 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7091 if (zvni_mac_send_add_to_client(zvni
->vni
,
7093 mac
->flags
, mac
->loc_seq
))
7096 /* Process all neighbors associated with this MAC. */
7097 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7099 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7100 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
7102 /* Install the entry. */
7103 zvni_mac_install(zvni
, mac
);
7107 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
7109 struct neigh_walk_ctx
*wctx
= ctxt
;
7112 char buf
[INET6_ADDRSTRLEN
];
7114 nbr
= (zebra_neigh_t
*)bucket
->data
;
7120 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7123 if (IS_ZEBRA_DEBUG_VXLAN
) {
7124 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
7126 "%s: clear neigh %s dup state, flags 0x%x seq %u",
7127 __PRETTY_FUNCTION__
, buf
,
7128 nbr
->flags
, nbr
->loc_seq
);
7131 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7133 nbr
->detect_start_time
.tv_sec
= 0;
7134 nbr
->detect_start_time
.tv_usec
= 0;
7135 nbr
->dad_dup_detect_time
= 0;
7136 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
7138 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7139 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
7141 nbr
->flags
, nbr
->loc_seq
);
7142 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7143 zvni_neigh_install(zvni
, nbr
);
7147 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
7152 struct zebra_vrf
*zvrf
;
7153 struct mac_walk_ctx m_wctx
;
7154 struct neigh_walk_ctx n_wctx
;
7156 zvni
= (zebra_vni_t
*)bucket
->data
;
7160 vty
= (struct vty
*)args
[0];
7161 zvrf
= (struct zebra_vrf
*)args
[1];
7163 if (hashcount(zvni
->neigh_table
)) {
7164 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7168 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7172 if (num_valid_macs(zvni
)) {
7173 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7177 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7182 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
7183 struct zebra_vrf
*zvrf
)
7187 if (!is_evpn_enabled())
7193 hash_iterate(zvrf
->vni_table
,
7194 (void (*)(struct hash_bucket
*, void *))
7195 zvni_clear_dup_detect_hash_vni_all
, args
);
7200 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
7201 struct zebra_vrf
*zvrf
,
7205 struct mac_walk_ctx m_wctx
;
7206 struct neigh_walk_ctx n_wctx
;
7208 if (!is_evpn_enabled())
7211 zvni
= zvni_lookup(vni
);
7213 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7217 if (hashcount(zvni
->neigh_table
)) {
7218 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7222 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7226 if (num_valid_macs(zvni
)) {
7227 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7231 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7238 * Display MACs for a VNI from specific VTEP (VTY command handler).
7240 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7241 vni_t vni
, struct in_addr vtep_ip
,
7246 struct mac_walk_ctx wctx
;
7247 json_object
*json
= NULL
;
7248 json_object
*json_mac
= NULL
;
7250 if (!is_evpn_enabled())
7252 zvni
= zvni_lookup(vni
);
7255 vty_out(vty
, "{}\n");
7257 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7260 num_macs
= num_valid_macs(zvni
);
7265 json
= json_object_new_object();
7266 json_mac
= json_object_new_object();
7269 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
7272 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
7273 wctx
.r_vtep_ip
= vtep_ip
;
7274 wctx
.json
= json_mac
;
7275 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
7278 json_object_int_add(json
, "numMacs", wctx
.count
);
7280 json_object_object_add(json
, "macs", json_mac
);
7281 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7282 json
, JSON_C_TO_STRING_PRETTY
));
7283 json_object_free(json
);
7289 * Display VNI information (VTY command handler).
7291 * use_json flag indicates that output should be in JSON format.
7292 * json_array is non NULL when JSON output needs to be aggregated (by the
7293 * caller) and then printed, otherwise, JSON evpn vni info is printed
7296 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
7297 bool use_json
, json_object
*json_array
)
7299 json_object
*json
= NULL
;
7301 zebra_l3vni_t
*zl3vni
= NULL
;
7302 zebra_vni_t
*zvni
= NULL
;
7304 if (!is_evpn_enabled())
7308 json
= json_object_new_object();
7313 zl3vni
= zl3vni_lookup(vni
);
7315 zl3vni_print(zl3vni
, (void *)args
);
7317 zvni
= zvni_lookup(vni
);
7319 zvni_print(zvni
, (void *)args
);
7321 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7326 * Each "json" object contains info about 1 VNI.
7327 * When "json_array" is non-null, we aggreggate the json output
7328 * into json_array and print it as a JSON array.
7331 json_object_array_add(json_array
, json
);
7333 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7334 json
, JSON_C_TO_STRING_PRETTY
));
7335 json_object_free(json
);
7340 /* Display all global details for EVPN */
7341 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7346 json_object
*json
= NULL
;
7347 struct zebra_vrf
*zvrf
= NULL
;
7349 if (!is_evpn_enabled())
7352 zvrf
= zebra_vrf_get_evpn();
7356 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7357 num_l2vnis
= hashcount(zvrf
->vni_table
);
7358 num_vnis
= num_l2vnis
+ num_l3vnis
;
7361 json
= json_object_new_object();
7362 json_object_string_add(json
, "advertiseGatewayMacip",
7363 zvrf
->advertise_gw_macip
? "Yes" : "No");
7364 json_object_int_add(json
, "numVnis", num_vnis
);
7365 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7366 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7367 if (zvrf
->dup_addr_detect
)
7368 json_object_boolean_true_add(json
,
7369 "isDuplicateAddrDetection");
7371 json_object_boolean_false_add(json
,
7372 "isDuplicateAddrDetection");
7373 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7374 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7375 json_object_int_add(json
, "detectionFreezeTime",
7376 zvrf
->dad_freeze_time
);
7379 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7380 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7381 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7382 zvrf
->advertise_gw_macip
? "Yes" : "No");
7383 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7384 zvrf
->advertise_svi_macip
? "Yes" : "No");
7385 vty_out(vty
, "Duplicate address detection: %s\n",
7386 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7387 vty_out(vty
, " Detection max-moves %u, time %d\n",
7388 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7389 if (zvrf
->dad_freeze
) {
7390 if (zvrf
->dad_freeze_time
)
7391 vty_out(vty
, " Detection freeze %u\n",
7392 zvrf
->dad_freeze_time
);
7394 vty_out(vty
, " Detection freeze %s\n",
7400 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7401 json
, JSON_C_TO_STRING_PRETTY
));
7402 json_object_free(json
);
7407 * Display VNI hash table (VTY command handler).
7409 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7412 json_object
*json
= NULL
;
7415 if (!is_evpn_enabled())
7419 json
= json_object_new_object();
7421 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7422 "Type", "VxLAN IF", "# MACs", "# ARPs",
7423 "# Remote VTEPs", "Tenant VRF");
7428 /* Display all L2-VNIs */
7429 hash_iterate(zvrf
->vni_table
,
7430 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7433 /* Display all L3-VNIs */
7434 hash_iterate(zrouter
.l3vni_table
,
7435 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7439 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7440 json
, JSON_C_TO_STRING_PRETTY
));
7441 json_object_free(json
);
7445 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7449 uint32_t max_moves
= 0;
7450 uint32_t freeze_time
= 0;
7451 bool dup_addr_detect
= false;
7452 bool freeze
= false;
7455 STREAM_GETL(s
, dup_addr_detect
);
7456 STREAM_GETL(s
, time
);
7457 STREAM_GETL(s
, max_moves
);
7458 STREAM_GETL(s
, freeze
);
7459 STREAM_GETL(s
, freeze_time
);
7461 /* DAD previous state was enabled, and new state is disable,
7462 * clear all duplicate detected addresses.
7464 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7465 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7467 zvrf
->dup_addr_detect
= dup_addr_detect
;
7468 zvrf
->dad_time
= time
;
7469 zvrf
->dad_max_moves
= max_moves
;
7470 zvrf
->dad_freeze
= freeze
;
7471 zvrf
->dad_freeze_time
= freeze_time
;
7473 if (IS_ZEBRA_DEBUG_VXLAN
)
7475 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7476 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7477 zvrf
->dup_addr_detect
? "enable" : "disable",
7478 zvrf
->dad_max_moves
,
7480 zvrf
->dad_freeze
? "enable" : "disable",
7481 zvrf
->dad_freeze_time
);
7488 * Display VNI hash table in detail(VTY command handler).
7490 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7493 json_object
*json_array
= NULL
;
7494 struct zebra_ns
*zns
= NULL
;
7495 struct zvni_evpn_show zes
;
7497 if (!is_evpn_enabled())
7500 zns
= zebra_ns_lookup(NS_DEFAULT
);
7505 json_array
= json_object_new_array();
7508 zes
.json
= json_array
;
7510 zes
.use_json
= use_json
;
7512 /* Display all L2-VNIs */
7515 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7518 /* Display all L3-VNIs */
7519 hash_iterate(zrouter
.l3vni_table
,
7520 (void (*)(struct hash_bucket
*,
7521 void *))zl3vni_print_hash_detail
,
7525 vty_out(vty
, "%s\n",
7526 json_object_to_json_string_ext(
7527 json_array
, JSON_C_TO_STRING_PRETTY
));
7528 json_object_free(json_array
);
7533 * Handle neighbor delete notification from the kernel (on a VLAN device
7534 * / L3 interface). This may result in either the neighbor getting deleted
7535 * from our database or being re-added to the kernel (if it is a valid
7538 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7539 struct interface
*link_if
,
7542 char buf
[INET6_ADDRSTRLEN
];
7543 char buf2
[ETHER_ADDR_STRLEN
];
7544 zebra_neigh_t
*n
= NULL
;
7545 zebra_vni_t
*zvni
= NULL
;
7546 zebra_mac_t
*zmac
= NULL
;
7547 zebra_l3vni_t
*zl3vni
= NULL
;
7548 struct zebra_vrf
*zvrf
;
7550 /* check if this is a remote neigh entry corresponding to remote
7553 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7555 return zl3vni_local_nh_del(zl3vni
, ip
);
7557 /* We are only interested in neighbors on an SVI that resides on top
7558 * of a VxLAN bridge.
7560 zvni
= zvni_from_svi(ifp
, link_if
);
7562 if (IS_ZEBRA_DEBUG_VXLAN
)
7563 zlog_debug("%s: Del neighbor %s VNI is not present for interface %s",
7564 __PRETTY_FUNCTION__
,
7565 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
);
7569 if (!zvni
->vxlan_if
) {
7571 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7576 if (IS_ZEBRA_DEBUG_VXLAN
)
7577 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7578 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7579 ifp
->ifindex
, zvni
->vni
);
7581 /* If entry doesn't exist, nothing to do. */
7582 n
= zvni_neigh_lookup(zvni
, ip
);
7586 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7588 if (IS_ZEBRA_DEBUG_VXLAN
)
7590 "Trying to del a neigh %s without a mac %s on VNI %u",
7591 ipaddr2str(ip
, buf
, sizeof(buf
)),
7592 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7598 /* If it is a remote entry, the kernel has aged this out or someone has
7599 * deleted it, it needs to be re-installed as Quagga is the owner.
7601 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7602 zvni_neigh_install(zvni
, n
);
7606 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7608 zlog_debug("%s: VNI %u vrf lookup failed.",
7609 __PRETTY_FUNCTION__
, zvni
->vni
);
7613 /* In case of feeze action, if local neigh is in duplicate state,
7614 * Mark the Neigh as inactive before sending delete request to BGPd,
7615 * If BGPd has remote entry, it will re-install
7617 if (zvrf
->dad_freeze
&&
7618 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7619 ZEBRA_NEIGH_SET_INACTIVE(n
);
7621 /* Remove neighbor from BGP. */
7622 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7624 /* Delete this neighbor entry. */
7625 zvni_neigh_del(zvni
, n
);
7627 /* see if the AUTO mac needs to be deleted */
7628 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7629 && !listcount(zmac
->neigh_list
))
7630 zvni_mac_del(zvni
, zmac
);
7636 * Handle neighbor add or update notification from the kernel (on a VLAN
7637 * device / L3 interface). This is typically for a local neighbor but can
7638 * also be for a remote neighbor (e.g., ageout notification). It could
7639 * also be a "move" scenario.
7641 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7642 struct interface
*link_if
,
7644 struct ethaddr
*macaddr
,
7649 char buf
[ETHER_ADDR_STRLEN
];
7650 char buf2
[INET6_ADDRSTRLEN
];
7651 zebra_vni_t
*zvni
= NULL
;
7652 zebra_l3vni_t
*zl3vni
= NULL
;
7654 /* check if this is a remote neigh entry corresponding to remote
7657 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7659 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7661 /* We are only interested in neighbors on an SVI that resides on top
7662 * of a VxLAN bridge.
7664 zvni
= zvni_from_svi(ifp
, link_if
);
7668 if (IS_ZEBRA_DEBUG_VXLAN
)
7670 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7671 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7672 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7673 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7674 is_router
? "router " : "",
7677 /* Is this about a local neighbor or a remote one? */
7679 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7682 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7686 zebra_vxlan_remote_macip_helper(bool add
, struct stream
*s
, vni_t
*vni
,
7687 struct ethaddr
*macaddr
, uint16_t *ipa_len
,
7688 struct ipaddr
*ip
, struct in_addr
*vtep_ip
,
7689 uint8_t *flags
, uint32_t *seq
)
7694 * Obtain each remote MACIP and process.
7695 * Message contains VNI, followed by MAC followed by IP (if any)
7696 * followed by remote VTEP IP.
7698 memset(ip
, 0, sizeof(*ip
));
7699 STREAM_GETL(s
, *vni
);
7700 STREAM_GET(macaddr
->octet
, s
, ETH_ALEN
);
7701 STREAM_GETL(s
, *ipa_len
);
7704 if (*ipa_len
== IPV4_MAX_BYTELEN
)
7705 ip
->ipa_type
= IPADDR_V4
;
7706 else if (*ipa_len
== IPV6_MAX_BYTELEN
)
7707 ip
->ipa_type
= IPADDR_V6
;
7709 if (IS_ZEBRA_DEBUG_VXLAN
)
7711 "ipa_len *must* be %d or %d bytes in length not %d",
7712 IPV4_MAX_BYTELEN
, IPV6_MAX_BYTELEN
,
7714 goto stream_failure
;
7717 STREAM_GET(&ip
->ip
.addr
, s
, *ipa_len
);
7719 l
+= 4 + ETH_ALEN
+ 4 + *ipa_len
;
7720 STREAM_GET(&vtep_ip
->s_addr
, s
, IPV4_MAX_BYTELEN
);
7721 l
+= IPV4_MAX_BYTELEN
;
7724 STREAM_GETC(s
, *flags
);
7725 STREAM_GETL(s
, *seq
);
7736 * Handle message from client to delete a remote MACIP for a VNI.
7738 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7742 struct ethaddr macaddr
;
7744 struct in_addr vtep_ip
;
7745 uint16_t l
= 0, ipa_len
;
7746 char buf
[ETHER_ADDR_STRLEN
];
7747 char buf1
[INET6_ADDRSTRLEN
];
7749 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7750 memset(&ip
, 0, sizeof(struct ipaddr
));
7751 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7755 while (l
< hdr
->length
) {
7756 int res_length
= zebra_vxlan_remote_macip_helper(
7757 false, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
, NULL
,
7760 if (res_length
== -1)
7761 goto stream_failure
;
7764 if (IS_ZEBRA_DEBUG_VXLAN
)
7766 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7768 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7769 ipa_len
? " IP " : "",
7771 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7773 zebra_route_string(client
->proto
));
7775 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7783 * Handle message from client to add a remote MACIP for a VNI. This
7784 * could be just the add of a MAC address or the add of a neighbor
7787 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7791 struct ethaddr macaddr
;
7793 struct in_addr vtep_ip
;
7794 uint16_t l
= 0, ipa_len
;
7797 char buf
[ETHER_ADDR_STRLEN
];
7798 char buf1
[INET6_ADDRSTRLEN
];
7800 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7801 memset(&ip
, 0, sizeof(struct ipaddr
));
7802 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7804 if (!EVPN_ENABLED(zvrf
)) {
7805 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7811 while (l
< hdr
->length
) {
7812 int res_length
= zebra_vxlan_remote_macip_helper(
7813 true, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
,
7816 if (res_length
== -1)
7817 goto stream_failure
;
7820 if (IS_ZEBRA_DEBUG_VXLAN
)
7822 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7824 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7825 ipa_len
? " IP " : "",
7827 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7828 flags
, seq
, inet_ntoa(vtep_ip
),
7829 zebra_route_string(client
->proto
));
7831 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7832 flags
, seq
, vtep_ip
);
7840 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7841 * us, this must involve a multihoming scenario. Treat this as implicit delete
7842 * of any prior local MAC.
7844 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7845 struct interface
*br_if
,
7846 struct ethaddr
*macaddr
, vlanid_t vid
)
7848 struct zebra_if
*zif
;
7849 struct zebra_l2info_vxlan
*vxl
;
7853 char buf
[ETHER_ADDR_STRLEN
];
7857 vxl
= &zif
->l2info
.vxl
;
7860 /* Check if EVPN is enabled. */
7861 if (!is_evpn_enabled())
7864 /* Locate hash entry; it is expected to exist. */
7865 zvni
= zvni_lookup(vni
);
7869 /* If entry doesn't exist, nothing to do. */
7870 mac
= zvni_mac_lookup(zvni
, macaddr
);
7874 /* Is it a local entry? */
7875 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7878 if (IS_ZEBRA_DEBUG_VXLAN
)
7880 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7881 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7882 ifp
->ifindex
, vni
, mac
->flags
);
7884 /* Remove MAC from BGP. */
7885 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7888 * If there are no neigh associated with the mac delete the mac
7889 * else mark it as AUTO for forward reference
7891 if (!listcount(mac
->neigh_list
)) {
7892 zvni_mac_del(zvni
, mac
);
7894 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7895 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7896 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7903 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7904 * This can happen because the remote MAC entries are also added as "dynamic",
7905 * so the kernel can ageout the entry.
7907 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7908 struct interface
*br_if
,
7909 struct ethaddr
*macaddr
, vlanid_t vid
)
7911 struct zebra_if
*zif
= NULL
;
7912 struct zebra_l2info_vxlan
*vxl
= NULL
;
7914 zebra_vni_t
*zvni
= NULL
;
7915 zebra_l3vni_t
*zl3vni
= NULL
;
7916 zebra_mac_t
*mac
= NULL
;
7917 char buf
[ETHER_ADDR_STRLEN
];
7921 vxl
= &zif
->l2info
.vxl
;
7924 /* Check if EVPN is enabled. */
7925 if (!is_evpn_enabled())
7928 /* check if this is a remote RMAC and readd simillar to remote macs */
7929 zl3vni
= zl3vni_lookup(vni
);
7931 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7933 /* Locate hash entry; it is expected to exist. */
7934 zvni
= zvni_lookup(vni
);
7938 /* If entry doesn't exist, nothing to do. */
7939 mac
= zvni_mac_lookup(zvni
, macaddr
);
7943 /* Is it a remote entry? */
7944 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7947 if (IS_ZEBRA_DEBUG_VXLAN
)
7948 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7949 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7952 zvni_mac_install(zvni
, mac
);
7957 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7959 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7960 struct ethaddr
*macaddr
, vlanid_t vid
)
7964 char buf
[ETHER_ADDR_STRLEN
];
7966 /* We are interested in MACs only on ports or (port, VLAN) that
7969 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7972 if (!zvni
->vxlan_if
) {
7974 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7979 /* If entry doesn't exist, nothing to do. */
7980 mac
= zvni_mac_lookup(zvni
, macaddr
);
7984 /* Is it a local entry? */
7985 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7988 if (IS_ZEBRA_DEBUG_VXLAN
)
7989 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
7990 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7991 ifp
->ifindex
, vid
, zvni
->vni
, mac
->loc_seq
,
7992 mac
->flags
, listcount(mac
->neigh_list
));
7994 /* Update all the neigh entries associated with this mac */
7995 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7997 /* Remove MAC from BGP. */
7998 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
8001 * If there are no neigh associated with the mac delete the mac
8002 * else mark it as AUTO for forward reference
8004 if (!listcount(mac
->neigh_list
)) {
8005 zvni_mac_del(zvni
, mac
);
8007 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
8008 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8009 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
8016 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
8018 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
8019 struct interface
*br_if
,
8020 struct ethaddr
*macaddr
, vlanid_t vid
,
8025 struct zebra_vrf
*zvrf
;
8026 char buf
[ETHER_ADDR_STRLEN
];
8027 bool mac_sticky
= false;
8028 bool inform_client
= false;
8029 bool upd_neigh
= false;
8030 bool is_dup_detect
= false;
8031 struct in_addr vtep_ip
= {.s_addr
= 0};
8033 /* We are interested in MACs only on ports or (port, VLAN) that
8036 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
8038 if (IS_ZEBRA_DEBUG_VXLAN
)
8040 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
8041 sticky
? "sticky " : "",
8042 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8043 ifp
->name
, ifp
->ifindex
, vid
);
8047 if (!zvni
->vxlan_if
) {
8048 if (IS_ZEBRA_DEBUG_VXLAN
)
8050 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
8055 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
8057 if (IS_ZEBRA_DEBUG_VXLAN
)
8058 zlog_debug("\tNo Vrf found for vrf_id: %d",
8059 zvni
->vxlan_if
->vrf_id
);
8063 /* Check if we need to create or update or it is a NO-OP. */
8064 mac
= zvni_mac_lookup(zvni
, macaddr
);
8066 if (IS_ZEBRA_DEBUG_VXLAN
)
8068 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
8069 sticky
? "sticky " : "",
8070 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8071 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
8073 mac
= zvni_mac_add(zvni
, macaddr
);
8076 EC_ZEBRA_MAC_ADD_FAILED
,
8077 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
8078 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8079 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
8082 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
8083 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8084 mac
->fwd_info
.local
.vid
= vid
;
8086 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8087 inform_client
= true;
8090 if (IS_ZEBRA_DEBUG_VXLAN
)
8092 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
8093 sticky
? "sticky " : "",
8094 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8095 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
8098 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8099 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
8103 * Update any changes and if changes are relevant to
8106 if (mac_sticky
== sticky
8107 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
8108 && mac
->fwd_info
.local
.vid
== vid
) {
8109 if (IS_ZEBRA_DEBUG_VXLAN
)
8111 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
8112 "entry exists and has not changed ",
8113 sticky
? "sticky " : "",
8114 prefix_mac2str(macaddr
, buf
,
8116 ifp
->name
, ifp
->ifindex
, vid
,
8120 if (mac_sticky
!= sticky
) {
8122 SET_FLAG(mac
->flags
,
8125 UNSET_FLAG(mac
->flags
,
8127 inform_client
= true;
8130 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
8131 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8132 mac
->fwd_info
.local
.vid
= vid
;
8134 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
8135 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
8136 bool do_dad
= false;
8139 * MAC has either moved or was "internally" created due
8140 * to a neighbor learn and is now actually learnt. If
8141 * it was learnt as a remote sticky MAC, this is an
8144 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
8146 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
8147 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
8148 prefix_mac2str(macaddr
, buf
,
8150 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
8155 /* If an actual move, compute MAC's seq number */
8156 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8157 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
8159 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
8160 /* Trigger DAD for remote MAC */
8164 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
8165 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
8166 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
8167 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
8168 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8169 mac
->fwd_info
.local
.vid
= vid
;
8171 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8173 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8175 * We have to inform BGP of this MAC as well as process
8178 inform_client
= true;
8181 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
8185 if (is_dup_detect
) {
8186 inform_client
= false;
8192 /* Inform BGP if required. */
8193 if (inform_client
) {
8194 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
8195 mac
->flags
, mac
->loc_seq
))
8199 /* Process all neighbors associated with this MAC, if required. */
8201 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
8207 * Handle message from client to delete a remote VTEP for a VNI.
8209 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
8212 unsigned short l
= 0;
8214 struct in_addr vtep_ip
;
8216 zebra_vtep_t
*zvtep
;
8217 struct interface
*ifp
;
8218 struct zebra_if
*zif
;
8220 if (!is_evpn_enabled()) {
8222 "%s: EVPN is not enabled yet we have received a vtep del command",
8223 __PRETTY_FUNCTION__
);
8227 if (!EVPN_ENABLED(zvrf
)) {
8228 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
8235 while (l
< hdr
->length
) {
8236 int flood_control
__attribute__((unused
));
8238 /* Obtain each remote VTEP and process. */
8239 STREAM_GETL(s
, vni
);
8241 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8242 l
+= IPV4_MAX_BYTELEN
;
8244 /* Flood control is intentionally ignored right now */
8245 STREAM_GETL(s
, flood_control
);
8248 if (IS_ZEBRA_DEBUG_VXLAN
)
8249 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
8250 inet_ntoa(vtep_ip
), vni
,
8251 zebra_route_string(client
->proto
));
8253 /* Locate VNI hash entry - expected to exist. */
8254 zvni
= zvni_lookup(vni
);
8256 if (IS_ZEBRA_DEBUG_VXLAN
)
8258 "Failed to locate VNI hash upon remote VTEP DEL, "
8264 ifp
= zvni
->vxlan_if
;
8267 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
8273 /* If down or not mapped to a bridge, we're done. */
8274 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8277 /* If the remote VTEP does not exist, there's nothing more to
8279 * Otherwise, uninstall any remote MACs pointing to this VTEP
8281 * then, the VTEP entry itself and remove it.
8283 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8287 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
8288 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
8289 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8290 zvni_vtep_del(zvni
, zvtep
);
8298 * Handle message from client to add a remote VTEP for a VNI.
8300 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
8303 unsigned short l
= 0;
8305 struct in_addr vtep_ip
;
8307 struct interface
*ifp
;
8308 struct zebra_if
*zif
;
8310 zebra_vtep_t
*zvtep
;
8312 if (!is_evpn_enabled()) {
8314 "%s: EVPN not enabled yet we received a vtep_add zapi call",
8315 __PRETTY_FUNCTION__
);
8319 if (!EVPN_ENABLED(zvrf
)) {
8320 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
8327 while (l
< hdr
->length
) {
8328 /* Obtain each remote VTEP and process. */
8329 STREAM_GETL(s
, vni
);
8331 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8332 STREAM_GETL(s
, flood_control
);
8333 l
+= IPV4_MAX_BYTELEN
+ 4;
8335 if (IS_ZEBRA_DEBUG_VXLAN
)
8336 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
8337 inet_ntoa(vtep_ip
), vni
, flood_control
,
8338 zebra_route_string(client
->proto
));
8340 /* Locate VNI hash entry - expected to exist. */
8341 zvni
= zvni_lookup(vni
);
8344 EC_ZEBRA_VTEP_ADD_FAILED
,
8345 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
8350 ifp
= zvni
->vxlan_if
;
8353 EC_ZEBRA_VTEP_ADD_FAILED
,
8354 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8361 /* If down or not mapped to a bridge, we're done. */
8362 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8365 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8367 /* If the remote VTEP already exists check if
8368 * the flood mode has changed
8370 if (zvtep
->flood_control
!= flood_control
) {
8371 if (zvtep
->flood_control
8372 == VXLAN_FLOOD_DISABLED
)
8373 /* old mode was head-end-replication but
8374 * is no longer; get rid of the HER fdb
8375 * entry installed before
8377 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8378 zvtep
->flood_control
= flood_control
;
8379 zvni_vtep_install(zvni
, zvtep
);
8382 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8384 zvni_vtep_install(zvni
, zvtep
);
8386 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8387 "Failed to add remote VTEP, VNI %u zvni %p",
8397 * Add/Del gateway macip to evpn
8399 * 1. SVI interface on a vlan aware bridge
8400 * 2. SVI interface on a vlan unaware bridge
8401 * 3. vrr interface (MACVLAN) associated to a SVI
8402 * We advertise macip routes for an interface if it is associated to VxLan vlan
8404 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8408 struct ethaddr macaddr
;
8409 zebra_vni_t
*zvni
= NULL
;
8411 memset(&ip
, 0, sizeof(struct ipaddr
));
8412 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8414 /* Check if EVPN is enabled. */
8415 if (!is_evpn_enabled())
8418 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8419 struct interface
*svi_if
=
8420 NULL
; /* SVI corresponding to the MACVLAN */
8421 struct zebra_if
*ifp_zif
=
8422 NULL
; /* Zebra daemon specific info for MACVLAN */
8423 struct zebra_if
*svi_if_zif
=
8424 NULL
; /* Zebra daemon specific info for SVI*/
8426 ifp_zif
= ifp
->info
;
8431 * for a MACVLAN interface the link represents the svi_if
8433 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8434 ifp_zif
->link_ifindex
);
8436 zlog_debug("MACVLAN %s(%u) without link information",
8437 ifp
->name
, ifp
->ifindex
);
8441 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8443 * If it is a vlan aware bridge then the link gives the
8444 * bridge information
8446 struct interface
*svi_if_link
= NULL
;
8448 svi_if_zif
= svi_if
->info
;
8450 svi_if_link
= if_lookup_by_index_per_ns(
8451 zebra_ns_lookup(NS_DEFAULT
),
8452 svi_if_zif
->link_ifindex
);
8453 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8455 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8457 * If it is a vlan unaware bridge then svi is the bridge
8460 zvni
= zvni_from_svi(svi_if
, svi_if
);
8462 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8463 struct zebra_if
*svi_if_zif
=
8464 NULL
; /* Zebra daemon specific info for SVI */
8465 struct interface
*svi_if_link
=
8466 NULL
; /* link info for the SVI = bridge info */
8468 svi_if_zif
= ifp
->info
;
8470 svi_if_link
= if_lookup_by_index_per_ns(
8471 zebra_ns_lookup(NS_DEFAULT
),
8472 svi_if_zif
->link_ifindex
);
8474 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8476 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8477 zvni
= zvni_from_svi(ifp
, ifp
);
8483 if (!zvni
->vxlan_if
) {
8484 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8490 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8492 if (p
->family
== AF_INET
) {
8493 ip
.ipa_type
= IPADDR_V4
;
8494 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8495 sizeof(struct in_addr
));
8496 } else if (p
->family
== AF_INET6
) {
8497 ip
.ipa_type
= IPADDR_V6
;
8498 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8499 sizeof(struct in6_addr
));
8504 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8506 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8512 * Handle SVI interface going down.
8513 * SVI can be associated to either L3-VNI or L2-VNI.
8514 * For L2-VNI: At this point, this is a NOP since
8515 * the kernel deletes the neighbor entries on this SVI (if any).
8516 * We only need to update the vrf corresponding to zvni.
8517 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8520 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8522 zebra_l3vni_t
*zl3vni
= NULL
;
8524 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8527 /* process l3-vni down */
8528 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8530 /* remove association with svi-if */
8531 zl3vni
->svi_if
= NULL
;
8533 zebra_vni_t
*zvni
= NULL
;
8535 /* since we dont have svi corresponding to zvni, we associate it
8536 * to default vrf. Note: the corresponding neigh entries on the
8537 * SVI would have already been deleted */
8538 zvni
= zvni_from_svi(ifp
, link_if
);
8540 zvni
->vrf_id
= VRF_DEFAULT
;
8542 /* update the tenant vrf in BGP */
8543 zvni_send_add_to_client(zvni
);
8550 * Handle SVI interface coming up.
8551 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8553 * For L2-VNI: we need to install any remote neighbors entried (used for
8555 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8557 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8559 zebra_vni_t
*zvni
= NULL
;
8560 zebra_l3vni_t
*zl3vni
= NULL
;
8562 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8565 /* associate with svi */
8566 zl3vni
->svi_if
= ifp
;
8568 /* process oper-up */
8569 if (is_l3vni_oper_up(zl3vni
))
8570 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8573 /* process SVI up for l2-vni */
8574 struct neigh_walk_ctx n_wctx
;
8576 zvni
= zvni_from_svi(ifp
, link_if
);
8580 if (!zvni
->vxlan_if
) {
8582 "VNI %u hash %p doesn't have intf upon SVI up",
8587 if (IS_ZEBRA_DEBUG_VXLAN
)
8589 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8590 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8591 vrf_id_to_name(ifp
->vrf_id
));
8593 /* update the vrf information for l2-vni and inform bgp */
8594 zvni
->vrf_id
= ifp
->vrf_id
;
8595 zvni_send_add_to_client(zvni
);
8597 /* Install any remote neighbors for this VNI. */
8598 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8600 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8608 * Handle MAC-VLAN interface going down.
8609 * L3VNI: When MAC-VLAN interface goes down,
8610 * find its associated SVI and update type2/type-5 routes
8613 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
8615 zebra_l3vni_t
*zl3vni
= NULL
;
8616 struct zebra_if
*zif
, *link_zif
;
8617 struct interface
*link_ifp
, *link_if
;
8621 link_ifp
= zif
->link
;
8623 if (IS_ZEBRA_DEBUG_VXLAN
) {
8624 struct interface
*ifp
;
8626 ifp
= if_lookup_by_index_all_vrf(zif
->link_ifindex
);
8627 zlog_debug("macvlan parent link is not found. Parent index %d ifp %s",
8628 zif
->link_ifindex
, ifp
? ifp
->name
: " ");
8632 link_zif
= link_ifp
->info
;
8635 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8636 link_zif
->link_ifindex
);
8638 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
8640 zl3vni
->mac_vlan_if
= NULL
;
8641 if (is_l3vni_oper_up(zl3vni
))
8642 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8647 * Handle MAC-VLAN interface going up.
8648 * L3VNI: When MAC-VLAN interface comes up,
8649 * find its associated SVI and update type-2 routes
8650 * with MAC-VLAN's MAC as RMAC and for type-5 routes
8651 * use SVI's MAC as RMAC.
8653 void zebra_vxlan_macvlan_up(struct interface
*ifp
)
8655 zebra_l3vni_t
*zl3vni
= NULL
;
8656 struct zebra_if
*zif
, *link_zif
;
8657 struct interface
*link_ifp
, *link_if
;
8661 link_ifp
= zif
->link
;
8662 link_zif
= link_ifp
->info
;
8665 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8666 link_zif
->link_ifindex
);
8667 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
8669 /* associate with macvlan (VRR) interface */
8670 zl3vni
->mac_vlan_if
= ifp
;
8672 /* process oper-up */
8673 if (is_l3vni_oper_up(zl3vni
))
8674 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8679 * Handle VxLAN interface down
8681 int zebra_vxlan_if_down(struct interface
*ifp
)
8684 struct zebra_if
*zif
= NULL
;
8685 struct zebra_l2info_vxlan
*vxl
= NULL
;
8686 zebra_l3vni_t
*zl3vni
= NULL
;
8689 /* Check if EVPN is enabled. */
8690 if (!is_evpn_enabled())
8695 vxl
= &zif
->l2info
.vxl
;
8698 zl3vni
= zl3vni_lookup(vni
);
8700 /* process-if-down for l3-vni */
8701 if (IS_ZEBRA_DEBUG_VXLAN
)
8702 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8705 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8707 /* process if-down for l2-vni */
8708 if (IS_ZEBRA_DEBUG_VXLAN
)
8709 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8712 /* Locate hash entry; it is expected to exist. */
8713 zvni
= zvni_lookup(vni
);
8716 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8717 ifp
->name
, ifp
->ifindex
, vni
);
8721 assert(zvni
->vxlan_if
== ifp
);
8723 /* Delete this VNI from BGP. */
8724 zvni_send_del_to_client(zvni
->vni
);
8726 /* Free up all neighbors and MACs, if any. */
8727 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8728 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8730 /* Free up all remote VTEPs, if any. */
8731 zvni_vtep_del_all(zvni
, 1);
8737 * Handle VxLAN interface up - update BGP if required.
8739 int zebra_vxlan_if_up(struct interface
*ifp
)
8742 struct zebra_if
*zif
= NULL
;
8743 struct zebra_l2info_vxlan
*vxl
= NULL
;
8744 zebra_vni_t
*zvni
= NULL
;
8745 zebra_l3vni_t
*zl3vni
= NULL
;
8747 /* Check if EVPN is enabled. */
8748 if (!is_evpn_enabled())
8753 vxl
= &zif
->l2info
.vxl
;
8756 zl3vni
= zl3vni_lookup(vni
);
8758 /* we need to associate with SVI, if any, we can associate with
8759 * svi-if only after association with vxlan-intf is complete
8761 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8762 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
8764 if (IS_ZEBRA_DEBUG_VXLAN
)
8765 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
8766 , ifp
->name
, ifp
->ifindex
, vni
,
8767 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
8768 zl3vni
->mac_vlan_if
?
8769 zl3vni
->mac_vlan_if
->name
: "NIL");
8771 if (is_l3vni_oper_up(zl3vni
))
8772 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8774 /* Handle L2-VNI add */
8775 struct interface
*vlan_if
= NULL
;
8777 if (IS_ZEBRA_DEBUG_VXLAN
)
8778 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8781 /* Locate hash entry; it is expected to exist. */
8782 zvni
= zvni_lookup(vni
);
8785 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8786 ifp
->name
, ifp
->ifindex
, vni
);
8790 assert(zvni
->vxlan_if
== ifp
);
8791 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8792 zif
->brslave_info
.br_if
);
8794 zvni
->vrf_id
= vlan_if
->vrf_id
;
8795 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8797 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8800 /* If part of a bridge, inform BGP about this VNI. */
8801 /* Also, read and populate local MACs and neighbors. */
8802 if (zif
->brslave_info
.br_if
) {
8803 zvni_send_add_to_client(zvni
);
8804 zvni_read_mac_neigh(zvni
, ifp
);
8812 * Handle VxLAN interface delete. Locate and remove entry in hash table
8813 * and update BGP, if required.
8815 int zebra_vxlan_if_del(struct interface
*ifp
)
8818 struct zebra_if
*zif
= NULL
;
8819 struct zebra_l2info_vxlan
*vxl
= NULL
;
8820 zebra_vni_t
*zvni
= NULL
;
8821 zebra_l3vni_t
*zl3vni
= NULL
;
8823 /* Check if EVPN is enabled. */
8824 if (!is_evpn_enabled())
8829 vxl
= &zif
->l2info
.vxl
;
8832 zl3vni
= zl3vni_lookup(vni
);
8835 if (IS_ZEBRA_DEBUG_VXLAN
)
8836 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8839 /* process oper-down for l3-vni */
8840 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8842 /* remove the association with vxlan_if */
8843 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8844 zl3vni
->vxlan_if
= NULL
;
8847 /* process if-del for l2-vni*/
8848 if (IS_ZEBRA_DEBUG_VXLAN
)
8849 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8852 /* Locate hash entry; it is expected to exist. */
8853 zvni
= zvni_lookup(vni
);
8856 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8857 ifp
->name
, ifp
->ifindex
, vni
);
8861 /* remove from l3-vni list */
8862 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8864 listnode_delete(zl3vni
->l2vnis
, zvni
);
8866 /* Delete VNI from BGP. */
8867 zvni_send_del_to_client(zvni
->vni
);
8869 /* Free up all neighbors and MAC, if any. */
8870 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8871 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8873 /* Free up all remote VTEPs, if any. */
8874 zvni_vtep_del_all(zvni
, 0);
8876 /* Delete the hash entry. */
8877 if (zvni_del(zvni
)) {
8878 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8879 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8880 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8888 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8890 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8893 struct zebra_if
*zif
= NULL
;
8894 struct zebra_l2info_vxlan
*vxl
= NULL
;
8895 zebra_vni_t
*zvni
= NULL
;
8896 zebra_l3vni_t
*zl3vni
= NULL
;
8898 /* Check if EVPN is enabled. */
8899 if (!is_evpn_enabled())
8904 vxl
= &zif
->l2info
.vxl
;
8907 zl3vni
= zl3vni_lookup(vni
);
8910 if (IS_ZEBRA_DEBUG_VXLAN
)
8912 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8913 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8914 inet_ntoa(vxl
->vtep_ip
),
8915 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8917 /* Removed from bridge? Cleanup and return */
8918 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8919 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8920 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8924 /* access-vlan change - process oper down, associate with new
8925 * svi_if and then process oper up again
8927 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8928 if (if_is_operative(ifp
)) {
8929 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8930 zl3vni
->svi_if
= NULL
;
8931 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8932 zl3vni
->mac_vlan_if
=
8933 zl3vni_map_to_mac_vlan_if(zl3vni
);
8934 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8935 if (is_l3vni_oper_up(zl3vni
))
8936 zebra_vxlan_process_l3vni_oper_up(
8942 * local-ip change - process oper down, associate with new
8943 * local-ip and then process oper up again
8945 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8946 if (if_is_operative(ifp
)) {
8947 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8948 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8949 if (is_l3vni_oper_up(zl3vni
))
8950 zebra_vxlan_process_l3vni_oper_up(
8955 /* Update local tunnel IP. */
8956 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8958 /* if we have a valid new master, process l3-vni oper up */
8959 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8960 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8961 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8965 /* Update VNI hash. */
8966 zvni
= zvni_lookup(vni
);
8969 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8970 ifp
->name
, ifp
->ifindex
, vni
);
8974 if (IS_ZEBRA_DEBUG_VXLAN
)
8976 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8977 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8978 inet_ntoa(vxl
->vtep_ip
),
8979 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8981 /* Removed from bridge? Cleanup and return */
8982 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8983 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8984 /* Delete from client, remove all remote VTEPs */
8985 /* Also, free up all MACs and neighbors. */
8986 zvni_send_del_to_client(zvni
->vni
);
8987 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8988 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8989 zvni_vtep_del_all(zvni
, 1);
8993 /* Handle other changes. */
8994 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8995 /* Remove all existing local neigh and MACs for this VNI
8996 * (including from BGP)
8998 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8999 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
9002 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
9003 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
9004 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
9006 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
9007 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
9008 zvni
->mcast_grp
= vxl
->mcast_grp
;
9010 zvni
->vxlan_if
= ifp
;
9012 /* Take further actions needed.
9013 * Note that if we are here, there is a change of interest.
9015 /* If down or not mapped to a bridge, we're done. */
9016 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9019 /* Inform BGP, if there is a change of interest. */
9021 & (ZEBRA_VXLIF_MASTER_CHANGE
|
9022 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
9023 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
9024 zvni_send_add_to_client(zvni
);
9026 /* If there is a valid new master or a VLAN mapping change,
9027 * read and populate local MACs and neighbors.
9028 * Also, reinstall any remote MACs and neighbors
9029 * for this VNI (based on new VLAN).
9031 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
9032 zvni_read_mac_neigh(zvni
, ifp
);
9033 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
9034 struct mac_walk_ctx m_wctx
;
9035 struct neigh_walk_ctx n_wctx
;
9037 zvni_read_mac_neigh(zvni
, ifp
);
9039 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
9041 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
9044 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
9046 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
9055 * Handle VxLAN interface add.
9057 int zebra_vxlan_if_add(struct interface
*ifp
)
9060 struct zebra_if
*zif
= NULL
;
9061 struct zebra_l2info_vxlan
*vxl
= NULL
;
9062 zebra_vni_t
*zvni
= NULL
;
9063 zebra_l3vni_t
*zl3vni
= NULL
;
9065 /* Check if EVPN is enabled. */
9066 if (!is_evpn_enabled())
9071 vxl
= &zif
->l2info
.vxl
;
9074 zl3vni
= zl3vni_lookup(vni
);
9077 /* process if-add for l3-vni*/
9078 if (IS_ZEBRA_DEBUG_VXLAN
)
9080 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
9081 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
9082 inet_ntoa(vxl
->vtep_ip
),
9083 zif
->brslave_info
.bridge_ifindex
);
9085 /* associate with vxlan_if */
9086 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
9087 zl3vni
->vxlan_if
= ifp
;
9089 /* Associate with SVI, if any. We can associate with svi-if only
9090 * after association with vxlan_if is complete */
9091 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
9093 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
9095 if (is_l3vni_oper_up(zl3vni
))
9096 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9099 /* process if-add for l2-vni */
9100 struct interface
*vlan_if
= NULL
;
9102 /* Create or update VNI hash. */
9103 zvni
= zvni_lookup(vni
);
9105 zvni
= zvni_add(vni
);
9108 EC_ZEBRA_VNI_ADD_FAILED
,
9109 "Failed to add VNI hash, IF %s(%u) VNI %u",
9110 ifp
->name
, ifp
->ifindex
, vni
);
9115 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
9116 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
9117 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
9119 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
9120 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
9121 zvni
->mcast_grp
= vxl
->mcast_grp
;
9123 zvni
->vxlan_if
= ifp
;
9124 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
9125 zif
->brslave_info
.br_if
);
9127 zvni
->vrf_id
= vlan_if
->vrf_id
;
9128 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
9130 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
9133 if (IS_ZEBRA_DEBUG_VXLAN
) {
9134 char addr_buf1
[INET_ADDRSTRLEN
];
9135 char addr_buf2
[INET_ADDRSTRLEN
];
9137 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
9138 addr_buf1
, INET_ADDRSTRLEN
);
9139 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
9140 addr_buf2
, INET_ADDRSTRLEN
);
9143 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
9145 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
9147 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
9148 addr_buf1
, addr_buf2
,
9149 zif
->brslave_info
.bridge_ifindex
);
9152 /* If down or not mapped to a bridge, we're done. */
9153 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9157 zvni_send_add_to_client(zvni
);
9159 /* Read and populate local MACs and neighbors */
9160 zvni_read_mac_neigh(zvni
, ifp
);
9166 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
9167 char *err
, int err_str_sz
, int filter
,
9170 zebra_l3vni_t
*zl3vni
= NULL
;
9171 struct zebra_vrf
*zvrf_evpn
= NULL
;
9173 zvrf_evpn
= zebra_vrf_get_evpn();
9177 if (IS_ZEBRA_DEBUG_VXLAN
)
9178 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
9179 add
? "ADD" : "DEL");
9183 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
9185 /* check if the vni is already present under zvrf */
9187 snprintf(err
, err_str_sz
,
9188 "VNI is already configured under the vrf");
9192 /* check if this VNI is already present in the system */
9193 zl3vni
= zl3vni_lookup(vni
);
9195 snprintf(err
, err_str_sz
,
9196 "VNI is already configured as L3-VNI");
9200 /* add the L3-VNI to the global table */
9201 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
9203 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
9207 /* associate the vrf with vni */
9210 /* set the filter in l3vni to denote if we are using l3vni only
9214 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
9216 /* associate with vxlan-intf;
9217 * we need to associate with the vxlan-intf first
9219 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
9221 /* associate with corresponding SVI interface, we can associate
9222 * with svi-if only after vxlan interface association is
9225 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
9227 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
9229 if (IS_ZEBRA_DEBUG_VXLAN
)
9230 zlog_debug("%s: l3vni %u svi_if %s mac_vlan_if %s",
9231 __PRETTY_FUNCTION__
, vni
,
9233 zl3vni
->svi_if
->name
: "NIL",
9234 zl3vni
->mac_vlan_if
?
9235 zl3vni
->mac_vlan_if
->name
: "NIL");
9237 /* formulate l2vni list */
9238 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
9241 if (is_l3vni_oper_up(zl3vni
))
9242 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9245 zl3vni
= zl3vni_lookup(vni
);
9247 snprintf(err
, err_str_sz
, "VNI doesn't exist");
9251 if (zvrf
->l3vni
!= vni
) {
9252 snprintf(err
, err_str_sz
,
9253 "VNI %d doesn't exist in VRF: %s",
9254 vni
, zvrf
->vrf
->name
);
9258 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
9259 snprintf(err
, ERR_STR_SZ
,
9260 "prefix-routes-only is not set for the vni");
9264 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9266 /* delete and uninstall all rmacs */
9267 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
9270 /* delete and uninstall all next-hops */
9271 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
9277 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
9282 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
9284 zebra_l3vni_t
*zl3vni
= NULL
;
9287 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9291 zl3vni
->vrf_id
= zvrf_id(zvrf
);
9292 if (is_l3vni_oper_up(zl3vni
))
9293 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9297 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
9299 zebra_l3vni_t
*zl3vni
= NULL
;
9302 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9306 zl3vni
->vrf_id
= VRF_UNKNOWN
;
9307 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9311 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
9313 zebra_l3vni_t
*zl3vni
= NULL
;
9317 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9323 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
9329 * Handle message from client to specify the flooding mechanism for
9330 * BUM packets. The default is to do head-end (ingress) replication
9331 * and the other supported option is to disable it. This applies to
9332 * all BUM traffic and disabling it applies to both the transmit and
9333 * receive direction.
9335 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
9338 enum vxlan_flood_control flood_ctrl
;
9340 if (!EVPN_ENABLED(zvrf
)) {
9341 zlog_err("EVPN flood control for non-EVPN VRF %u",
9347 STREAM_GETC(s
, flood_ctrl
);
9349 if (IS_ZEBRA_DEBUG_VXLAN
)
9350 zlog_debug("EVPN flood control %u, currently %u",
9351 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
9353 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
9356 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9358 /* Install or uninstall flood entries corresponding to
9361 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
9369 * Handle message from client to enable/disable advertisement of svi macip
9372 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
9377 zebra_vni_t
*zvni
= NULL
;
9378 struct interface
*ifp
= NULL
;
9380 if (!EVPN_ENABLED(zvrf
)) {
9381 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
9387 STREAM_GETC(s
, advertise
);
9388 STREAM_GETL(s
, vni
);
9391 if (IS_ZEBRA_DEBUG_VXLAN
)
9392 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
9393 advertise
? "enabled" : "disabled",
9394 advertise_svi_macip_enabled(NULL
)
9398 if (zvrf
->advertise_svi_macip
== advertise
)
9403 zvrf
->advertise_svi_macip
= advertise
;
9404 hash_iterate(zvrf
->vni_table
,
9405 zvni_gw_macip_add_for_vni_hash
, NULL
);
9407 hash_iterate(zvrf
->vni_table
,
9408 zvni_svi_macip_del_for_vni_hash
, NULL
);
9409 zvrf
->advertise_svi_macip
= advertise
;
9413 struct zebra_if
*zif
= NULL
;
9414 struct zebra_l2info_vxlan zl2_info
;
9415 struct interface
*vlan_if
= NULL
;
9417 zvni
= zvni_lookup(vni
);
9421 if (IS_ZEBRA_DEBUG_VXLAN
)
9423 "EVPN SVI macip Adv %s on VNI %d , currently %s",
9424 advertise
? "enabled" : "disabled", vni
,
9425 advertise_svi_macip_enabled(zvni
)
9429 if (zvni
->advertise_svi_macip
== advertise
)
9432 /* Store flag even though SVI is not present.
9433 * Once SVI comes up triggers self MAC-IP route add.
9435 zvni
->advertise_svi_macip
= advertise
;
9437 ifp
= zvni
->vxlan_if
;
9443 /* If down or not mapped to a bridge, we're done. */
9444 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9447 zl2_info
= zif
->l2info
.vxl
;
9448 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9449 zif
->brslave_info
.br_if
);
9454 /* Add primary SVI MAC-IP */
9455 zvni_add_macip_for_intf(vlan_if
, zvni
);
9457 /* Del primary SVI MAC-IP */
9458 zvni_del_macip_for_intf(vlan_if
, zvni
);
9467 * Handle message from client to enable/disable advertisement of g/w macip
9470 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9475 zebra_vni_t
*zvni
= NULL
;
9476 struct interface
*ifp
= NULL
;
9477 struct zebra_if
*zif
= NULL
;
9478 struct zebra_l2info_vxlan zl2_info
;
9479 struct interface
*vlan_if
= NULL
;
9481 if (!EVPN_ENABLED(zvrf
)) {
9482 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9488 STREAM_GETC(s
, advertise
);
9489 STREAM_GET(&vni
, s
, 3);
9491 zvni
= zvni_lookup(vni
);
9495 if (zvni
->advertise_subnet
== advertise
)
9498 if (IS_ZEBRA_DEBUG_VXLAN
)
9499 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9500 advertise
? "enabled" : "disabled", vni
,
9501 zvni
->advertise_subnet
? "enabled" : "disabled");
9504 zvni
->advertise_subnet
= advertise
;
9506 ifp
= zvni
->vxlan_if
;
9512 /* If down or not mapped to a bridge, we're done. */
9513 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9516 zl2_info
= zif
->l2info
.vxl
;
9519 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9523 if (zvni
->advertise_subnet
)
9524 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9526 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9533 * Handle message from client to enable/disable advertisement of g/w macip
9536 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9541 zebra_vni_t
*zvni
= NULL
;
9542 struct interface
*ifp
= NULL
;
9544 if (!EVPN_ENABLED(zvrf
)) {
9545 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9551 STREAM_GETC(s
, advertise
);
9552 STREAM_GETL(s
, vni
);
9555 if (IS_ZEBRA_DEBUG_VXLAN
)
9556 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9557 advertise
? "enabled" : "disabled",
9558 advertise_gw_macip_enabled(NULL
)
9562 if (zvrf
->advertise_gw_macip
== advertise
)
9565 zvrf
->advertise_gw_macip
= advertise
;
9567 if (advertise_gw_macip_enabled(zvni
))
9568 hash_iterate(zvrf
->vni_table
,
9569 zvni_gw_macip_add_for_vni_hash
, NULL
);
9571 hash_iterate(zvrf
->vni_table
,
9572 zvni_gw_macip_del_for_vni_hash
, NULL
);
9575 struct zebra_if
*zif
= NULL
;
9576 struct zebra_l2info_vxlan zl2_info
;
9577 struct interface
*vlan_if
= NULL
;
9578 struct interface
*vrr_if
= NULL
;
9580 zvni
= zvni_lookup(vni
);
9584 if (IS_ZEBRA_DEBUG_VXLAN
)
9586 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9587 advertise
? "enabled" : "disabled", vni
,
9588 advertise_gw_macip_enabled(zvni
) ? "enabled"
9591 if (zvni
->advertise_gw_macip
== advertise
)
9594 zvni
->advertise_gw_macip
= advertise
;
9596 ifp
= zvni
->vxlan_if
;
9602 /* If down or not mapped to a bridge, we're done. */
9603 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9606 zl2_info
= zif
->l2info
.vxl
;
9608 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9609 zif
->brslave_info
.br_if
);
9613 if (advertise_gw_macip_enabled(zvni
)) {
9614 /* Add primary SVI MAC-IP */
9615 zvni_add_macip_for_intf(vlan_if
, zvni
);
9617 /* Add VRR MAC-IP - if any*/
9618 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9620 zvni_add_macip_for_intf(vrr_if
, zvni
);
9622 /* Del primary MAC-IP */
9623 zvni_del_macip_for_intf(vlan_if
, zvni
);
9625 /* Del VRR MAC-IP - if any*/
9626 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9628 zvni_del_macip_for_intf(vrr_if
, zvni
);
9638 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9639 * When enabled, the VNI hash table will be built and MAC FDB table read;
9640 * when disabled, the entries should be deleted and remote VTEPs and MACs
9641 * uninstalled from the kernel.
9642 * This also informs the setting for BUM handling at the time this change
9643 * occurs; it is relevant only when specifying "learn".
9645 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9647 struct stream
*s
= NULL
;
9649 enum vxlan_flood_control flood_ctrl
;
9651 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9653 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9657 STREAM_GETC(s
, advertise
);
9658 STREAM_GETC(s
, flood_ctrl
);
9660 if (IS_ZEBRA_DEBUG_VXLAN
)
9661 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9662 zvrf_name(zvrf
), zvrf_id(zvrf
),
9663 advertise
? "enabled" : "disabled",
9664 is_evpn_enabled() ? "enabled" : "disabled",
9667 if (zvrf
->advertise_all_vni
== advertise
)
9670 zvrf
->advertise_all_vni
= advertise
;
9671 if (EVPN_ENABLED(zvrf
)) {
9672 zrouter
.evpn_vrf
= zvrf
;
9674 /* Note BUM handling */
9675 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9677 /* Build VNI hash table and inform BGP. */
9678 zvni_build_hash_table();
9680 /* Add all SVI (L3 GW) MACs to BGP*/
9681 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9684 /* Read the MAC FDB */
9685 macfdb_read(zvrf
->zns
);
9687 /* Read neighbors */
9688 neigh_read(zvrf
->zns
);
9690 /* Cleanup VTEPs for all VNIs - uninstall from
9691 * kernel and free entries.
9693 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9695 /* cleanup all l3vnis */
9696 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9698 /* Mark as "no EVPN VRF" */
9699 zrouter
.evpn_vrf
= NULL
;
9707 * Allocate VNI hash table for this VRF and do other initialization.
9708 * NOTE: Currently supported only for default VRF.
9710 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9714 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9715 "Zebra VRF VNI Table");
9716 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9717 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9720 /* Cleanup VNI info, but don't free the table. */
9721 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9725 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9726 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9729 /* Close all VNI handling */
9730 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9734 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9735 hash_free(zvrf
->vni_table
);
9738 /* init the l3vni table */
9739 void zebra_vxlan_init(void)
9741 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9742 "Zebra VRF L3 VNI table");
9743 zrouter
.evpn_vrf
= NULL
;
9746 /* free l3vni table */
9747 void zebra_vxlan_disable(void)
9749 hash_free(zrouter
.l3vni_table
);
9752 /* get the l3vni svi ifindex */
9753 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9755 zebra_l3vni_t
*zl3vni
= NULL
;
9757 zl3vni
= zl3vni_from_vrf(vrf_id
);
9758 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9761 return zl3vni
->svi_if
->ifindex
;
9764 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9766 struct zebra_vrf
*zvrf
= NULL
;
9767 zebra_neigh_t
*nbr
= NULL
;
9768 zebra_vni_t
*zvni
= NULL
;
9769 char buf1
[INET6_ADDRSTRLEN
];
9770 char buf2
[ETHER_ADDR_STRLEN
];
9772 nbr
= THREAD_ARG(t
);
9774 /* since this is asynchronous we need sanity checks*/
9775 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9779 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9783 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9787 if (IS_ZEBRA_DEBUG_VXLAN
)
9788 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9789 __PRETTY_FUNCTION__
,
9790 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9791 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9793 nbr
->dad_count
, zvni
->vni
);
9795 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9797 nbr
->detect_start_time
.tv_sec
= 0;
9798 nbr
->detect_start_time
.tv_usec
= 0;
9799 nbr
->dad_dup_detect_time
= 0;
9800 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9801 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9804 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9805 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9806 nbr
->flags
, nbr
->loc_seq
);
9807 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9808 zvni_neigh_install(zvni
, nbr
);
9814 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9816 struct zebra_vrf
*zvrf
= NULL
;
9817 zebra_mac_t
*mac
= NULL
;
9818 zebra_vni_t
*zvni
= NULL
;
9819 struct listnode
*node
= NULL
;
9820 zebra_neigh_t
*nbr
= NULL
;
9821 char buf
[ETHER_ADDR_STRLEN
];
9823 mac
= THREAD_ARG(t
);
9825 /* since this is asynchronous we need sanity checks*/
9826 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9830 zvni
= zvni_lookup(mac
->zvni
->vni
);
9834 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9838 if (IS_ZEBRA_DEBUG_VXLAN
)
9839 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9840 __PRETTY_FUNCTION__
,
9841 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9844 listcount(mac
->neigh_list
));
9846 /* Remove all IPs as duplicate associcated with this MAC */
9847 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9848 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9849 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9850 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9851 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9852 zvni_neigh_install(zvni
, nbr
);
9855 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9857 nbr
->detect_start_time
.tv_sec
= 0;
9858 nbr
->dad_dup_detect_time
= 0;
9861 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9863 mac
->detect_start_time
.tv_sec
= 0;
9864 mac
->detect_start_time
.tv_usec
= 0;
9865 mac
->dad_dup_detect_time
= 0;
9866 mac
->dad_mac_auto_recovery_timer
= NULL
;
9868 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9870 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9871 mac
->flags
, mac
->loc_seq
))
9874 /* Process all neighbors associated with this MAC. */
9875 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9877 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9878 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9880 /* Install the entry. */
9881 zvni_mac_install(zvni
, mac
);
9887 /************************** vxlan SG cache management ************************/
9888 /* Inform PIM about the mcast group */
9889 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
9890 struct prefix_sg
*sg
,
9891 char *sg_str
, uint16_t cmd
)
9893 struct zserv
*client
= NULL
;
9894 struct stream
*s
= NULL
;
9896 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9900 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
9903 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9905 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9906 stream_putl(s
, IPV4_MAX_BYTELEN
);
9907 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9908 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9910 /* Write packet size. */
9911 stream_putw_at(s
, 0, stream_get_endp(s
));
9913 if (IS_ZEBRA_DEBUG_VXLAN
)
9916 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9917 zebra_route_string(client
->proto
));
9919 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9920 client
->vxlan_sg_add_cnt
++;
9922 client
->vxlan_sg_del_cnt
++;
9924 return zserv_send_message(client
, s
);
9927 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9929 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9931 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9932 vxlan_sg
->sg
.grp
.s_addr
, 0));
9935 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9937 const zebra_vxlan_sg_t
*sg1
= p1
;
9938 const zebra_vxlan_sg_t
*sg2
= p2
;
9940 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9941 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9944 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9945 struct prefix_sg
*sg
)
9947 zebra_vxlan_sg_t
*vxlan_sg
;
9949 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9951 vxlan_sg
->zvrf
= zvrf
;
9953 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9955 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9957 if (IS_ZEBRA_DEBUG_VXLAN
)
9958 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9963 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9964 struct prefix_sg
*sg
)
9966 zebra_vxlan_sg_t lookup
;
9969 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9972 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9973 struct prefix_sg
*sg
)
9975 zebra_vxlan_sg_t
*vxlan_sg
;
9976 zebra_vxlan_sg_t
*parent
= NULL
;
9979 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9983 /* create a *G entry for every BUM group implicitly -
9984 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9985 * 2. the XG entry is used by pimd to setup the
9986 * vxlan-termination-mroute
9988 if (sg
->src
.s_addr
) {
9989 memset(&sip
, 0, sizeof(sip
));
9990 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9995 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9998 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
10002 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
10003 ZEBRA_VXLAN_SG_ADD
);
10008 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
10010 struct in_addr sip
;
10011 struct zebra_vrf
*zvrf
;
10013 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
10017 /* On SG entry deletion remove the reference to its parent XG
10020 if (vxlan_sg
->sg
.src
.s_addr
) {
10021 memset(&sip
, 0, sizeof(sip
));
10022 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
10025 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
10026 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
10028 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
10030 if (IS_ZEBRA_DEBUG_VXLAN
)
10031 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
10033 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
10036 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
10037 struct in_addr sip
, struct in_addr mcast_grp
)
10039 zebra_vxlan_sg_t
*vxlan_sg
;
10040 struct prefix_sg sg
;
10042 sg
.family
= AF_INET
;
10043 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
10045 sg
.grp
= mcast_grp
;
10046 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
10050 if (vxlan_sg
->ref_cnt
)
10051 --vxlan_sg
->ref_cnt
;
10053 if (!vxlan_sg
->ref_cnt
)
10054 zebra_vxlan_sg_del(vxlan_sg
);
10057 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
10058 struct in_addr sip
, struct in_addr mcast_grp
)
10060 zebra_vxlan_sg_t
*vxlan_sg
;
10061 struct prefix_sg sg
;
10063 sg
.family
= AF_INET
;
10064 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
10066 sg
.grp
= mcast_grp
;
10067 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
10069 ++vxlan_sg
->ref_cnt
;
10074 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
10075 struct in_addr mcast_grp
)
10077 struct zebra_vrf
*zvrf
;
10079 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
10082 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
10086 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
10089 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
10090 struct in_addr mcast_grp
)
10092 struct zebra_vrf
*zvrf
;
10094 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
10097 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
10100 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
10103 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
10105 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
10107 zebra_vxlan_sg_del(vxlan_sg
);
10110 static void zebra_vxlan_sg_replay_send(struct hash_backet
*backet
, void *arg
)
10112 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
10114 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
10115 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
10118 /* Handle message from client to replay vxlan SG entries */
10119 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
10121 if (IS_ZEBRA_DEBUG_VXLAN
)
10122 zlog_debug("VxLAN SG updates to PIM, start");
10124 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
10126 if (!EVPN_ENABLED(zvrf
)) {
10127 if (IS_ZEBRA_DEBUG_VXLAN
)
10128 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
10129 zvrf
->vrf
->vrf_id
);
10133 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
10136 /************************** EVPN BGP config management ************************/
10137 /* Notify Local MACs to the clienti, skips GW MAC */
10138 static void zvni_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
10141 struct mac_walk_ctx
*wctx
= arg
;
10142 zebra_mac_t
*zmac
= bucket
->data
;
10144 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
10147 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
10148 zvni_mac_send_add_to_client(wctx
->zvni
->vni
, &zmac
->macaddr
,
10149 zmac
->flags
, zmac
->loc_seq
);
10152 /* Iterator to Notify Local MACs of a L2VNI */
10153 static void zvni_send_mac_to_client(zebra_vni_t
*zvni
)
10155 struct mac_walk_ctx wctx
;
10157 if (!zvni
->mac_table
)
10160 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
10163 hash_iterate(zvni
->mac_table
, zvni_send_mac_hash_entry_to_client
,
10167 /* Notify Neighbor entries to the Client, skips the GW entry */
10168 static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
10171 struct mac_walk_ctx
*wctx
= arg
;
10172 zebra_neigh_t
*zn
= bucket
->data
;
10173 zebra_mac_t
*zmac
= NULL
;
10175 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
10178 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
10179 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
10180 zmac
= zvni_mac_lookup(wctx
->zvni
, &zn
->emac
);
10184 zvni_neigh_send_add_to_client(wctx
->zvni
->vni
, &zn
->ip
,
10185 &zn
->emac
, zn
->flags
,
10190 /* Iterator of a specific L2VNI */
10191 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
)
10193 struct neigh_walk_ctx wctx
;
10195 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
10198 hash_iterate(zvni
->neigh_table
, zvni_send_neigh_hash_entry_to_client
,
10202 static void zvni_evpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
10204 zebra_vni_t
*zvni
= NULL
;
10206 zvni
= (zebra_vni_t
*)bucket
->data
;
10207 zvni
->advertise_gw_macip
= 0;
10208 zvni
->advertise_svi_macip
= 0;
10209 zvni
->advertise_subnet
= 0;
10211 zvni_neigh_del_all(zvni
, 1, 0,
10212 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
10213 zvni_mac_del_all(zvni
, 1, 0,
10214 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
10215 zvni_vtep_del_all(zvni
, 1);
10218 /* Cleanup EVPN configuration of a specific VRF */
10219 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
10221 zebra_l3vni_t
*zl3vni
= NULL
;
10223 zvrf
->advertise_all_vni
= 0;
10224 zvrf
->advertise_gw_macip
= 0;
10225 zvrf
->advertise_svi_macip
= 0;
10226 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
10228 hash_iterate(zvrf
->vni_table
, zvni_evpn_cfg_cleanup
, NULL
);
10231 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
10233 /* delete and uninstall all rmacs */
10234 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
10236 /* delete and uninstall all next-hops */
10237 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
10242 /* Cleanup BGP EVPN configuration upon client disconnect */
10243 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
10246 struct zebra_vrf
*zvrf
;
10248 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
10251 zebra_evpn_vrf_cfg_cleanup(zvrf
);
10257 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
10259 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
10261 if (CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
10262 if (IS_ZEBRA_DEBUG_VXLAN
)
10263 zlog_debug("VxLAN SG updates to PIM, stop");
10264 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
10270 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
10272 if (client
->proto
== ZEBRA_ROUTE_BGP
)
10273 return zebra_evpn_bgp_cfg_clean_up(client
);
10275 if (client
->proto
== ZEBRA_ROUTE_PIM
)
10276 return zebra_evpn_pim_cfg_clean_up(client
);
10282 * Handle results for vxlan dataplane operations.
10284 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
10286 /* TODO -- anything other than freeing the context? */
10287 dplane_ctx_fini(&ctx
);
10290 /* Cleanup BGP EVPN configuration upon client disconnect */
10291 extern void zebra_evpn_init(void)
10293 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);