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
;
1999 /* print a L3 VNI hash entry in detail*/
2000 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2002 struct vty
*vty
= NULL
;
2003 zebra_l3vni_t
*zl3vni
= NULL
;
2004 json_object
*json
= NULL
;
2005 bool use_json
= false;
2006 struct zvni_evpn_show
*zes
= data
;
2014 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2016 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2022 * Print a VNI hash entry - called for display of all VNIs.
2024 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2028 zebra_vtep_t
*zvtep
;
2029 uint32_t num_vteps
= 0;
2030 uint32_t num_macs
= 0;
2031 uint32_t num_neigh
= 0;
2032 json_object
*json
= NULL
;
2033 json_object
*json_vni
= NULL
;
2034 json_object
*json_ip_str
= NULL
;
2035 json_object
*json_vtep_list
= NULL
;
2040 zvni
= (zebra_vni_t
*)bucket
->data
;
2042 zvtep
= zvni
->vteps
;
2045 zvtep
= zvtep
->next
;
2048 num_macs
= num_valid_macs(zvni
);
2049 num_neigh
= hashcount(zvni
->neigh_table
);
2051 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2053 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2054 num_macs
, num_neigh
, num_vteps
,
2055 vrf_id_to_name(zvni
->vrf_id
));
2057 char vni_str
[VNI_STR_LEN
];
2058 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2059 json_vni
= json_object_new_object();
2060 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2061 json_object_string_add(json_vni
, "type", "L2");
2062 json_object_string_add(json_vni
, "vxlanIf",
2063 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2065 json_object_int_add(json_vni
, "numMacs", num_macs
);
2066 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2067 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2068 json_object_string_add(json_vni
, "tenantVrf",
2069 vrf_id_to_name(zvni
->vrf_id
));
2071 json_vtep_list
= json_object_new_array();
2072 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2073 json_ip_str
= json_object_new_string(
2074 inet_ntoa(zvtep
->vtep_ip
));
2075 json_object_array_add(json_vtep_list
,
2078 json_object_object_add(json_vni
, "remoteVteps",
2081 json_object_object_add(json
, vni_str
, json_vni
);
2086 * Print a VNI hash entry in detail - called for display of all VNIs.
2088 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2092 json_object
*json
= NULL
;
2093 bool use_json
= false;
2094 struct zvni_evpn_show
*zes
= data
;
2102 zvni
= (zebra_vni_t
*)bucket
->data
;
2104 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2109 * Inform BGP about local MACIP.
2111 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2112 struct ipaddr
*ip
, uint8_t flags
,
2113 uint32_t seq
, int state
, uint16_t cmd
)
2115 char buf
[ETHER_ADDR_STRLEN
];
2116 char buf2
[INET6_ADDRSTRLEN
];
2118 struct zserv
*client
= NULL
;
2119 struct stream
*s
= NULL
;
2121 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2122 /* BGP may not be running. */
2126 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2128 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2129 stream_putl(s
, vni
);
2130 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2133 if (IS_IPADDR_V4(ip
))
2134 ipa_len
= IPV4_MAX_BYTELEN
;
2135 else if (IS_IPADDR_V6(ip
))
2136 ipa_len
= IPV6_MAX_BYTELEN
;
2138 stream_putl(s
, ipa_len
); /* IP address length */
2140 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2142 stream_putl(s
, 0); /* Just MAC. */
2144 if (cmd
== ZEBRA_MACIP_ADD
) {
2145 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2146 stream_putl(s
, seq
); /* sequence number */
2148 stream_putl(s
, state
); /* state - active/inactive */
2152 /* Write packet size. */
2153 stream_putw_at(s
, 0, stream_get_endp(s
));
2155 if (IS_ZEBRA_DEBUG_VXLAN
)
2157 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2158 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2159 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2160 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2161 zebra_route_string(client
->proto
));
2163 if (cmd
== ZEBRA_MACIP_ADD
)
2164 client
->macipadd_cnt
++;
2166 client
->macipdel_cnt
++;
2168 return zserv_send_message(client
, s
);
2172 * Make hash key for neighbors.
2174 static unsigned int neigh_hash_keymake(const void *p
)
2176 const zebra_neigh_t
*n
= p
;
2177 const struct ipaddr
*ip
= &n
->ip
;
2179 if (IS_IPADDR_V4(ip
))
2180 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2182 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2183 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2187 * Compare two neighbor hash structures.
2189 static bool neigh_cmp(const void *p1
, const void *p2
)
2191 const zebra_neigh_t
*n1
= p1
;
2192 const zebra_neigh_t
*n2
= p2
;
2194 if (n1
== NULL
&& n2
== NULL
)
2197 if (n1
== NULL
|| n2
== NULL
)
2200 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2203 static int neigh_list_cmp(void *p1
, void *p2
)
2205 const zebra_neigh_t
*n1
= p1
;
2206 const zebra_neigh_t
*n2
= p2
;
2208 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2212 * Callback to allocate neighbor hash entry.
2214 static void *zvni_neigh_alloc(void *p
)
2216 const zebra_neigh_t
*tmp_n
= p
;
2219 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2226 * Add neighbor entry.
2228 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2229 struct ethaddr
*mac
)
2231 zebra_neigh_t tmp_n
;
2232 zebra_neigh_t
*n
= NULL
;
2233 zebra_mac_t
*zmac
= NULL
;
2235 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2236 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2237 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2240 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2241 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2243 n
->dad_ip_auto_recovery_timer
= NULL
;
2245 /* Associate the neigh to mac */
2246 zmac
= zvni_mac_lookup(zvni
, mac
);
2248 listnode_add_sort(zmac
->neigh_list
, n
);
2254 * Delete neighbor entry.
2256 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2258 zebra_neigh_t
*tmp_n
;
2259 zebra_mac_t
*zmac
= NULL
;
2261 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2263 listnode_delete(zmac
->neigh_list
, n
);
2265 /* Cancel auto recovery */
2266 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2268 /* Free the VNI hash entry and allocated memory. */
2269 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2270 XFREE(MTYPE_NEIGH
, tmp_n
);
2276 * Free neighbor hash entry (callback)
2278 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2280 struct neigh_walk_ctx
*wctx
= arg
;
2281 zebra_neigh_t
*n
= bucket
->data
;
2283 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2284 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2285 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2286 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2287 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2288 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2289 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2290 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2291 &n
->emac
, 0, n
->state
);
2293 if (wctx
->uninstall
)
2294 zvni_neigh_uninstall(wctx
->zvni
, n
);
2296 zvni_neigh_del(wctx
->zvni
, n
);
2303 * Delete all neighbor entries from specific VTEP for a particular VNI.
2305 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2306 struct in_addr
*r_vtep_ip
)
2308 struct neigh_walk_ctx wctx
;
2310 if (!zvni
->neigh_table
)
2313 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2315 wctx
.uninstall
= uninstall
;
2316 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2317 wctx
.r_vtep_ip
= *r_vtep_ip
;
2319 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2323 * Delete all neighbor entries for this VNI.
2325 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2328 struct neigh_walk_ctx wctx
;
2330 if (!zvni
->neigh_table
)
2333 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2335 wctx
.uninstall
= uninstall
;
2336 wctx
.upd_client
= upd_client
;
2339 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2343 * Look up neighbor hash entry.
2345 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2350 memset(&tmp
, 0, sizeof(tmp
));
2351 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2352 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2358 * Process all neighbors associated with a MAC upon the MAC being learnt
2359 * locally or undergoing any other change (such as sequence number).
2361 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2365 zebra_neigh_t
*n
= NULL
;
2366 struct listnode
*node
= NULL
;
2367 struct zebra_vrf
*zvrf
= NULL
;
2368 char buf
[ETHER_ADDR_STRLEN
];
2370 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2372 if (IS_ZEBRA_DEBUG_VXLAN
)
2373 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2374 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2375 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2377 /* Walk all neighbors and mark any inactive local neighbors as
2378 * active and/or update sequence number upon a move, and inform BGP.
2379 * The action for remote neighbors is TBD.
2380 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2381 * accidentally end up deleting a just-learnt local neighbor.
2383 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2384 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2385 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2386 ZEBRA_NEIGH_SET_ACTIVE(n
);
2387 n
->loc_seq
= zmac
->loc_seq
;
2388 if (!(zvrf
->dup_addr_detect
&&
2389 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2390 ZEBRA_NEIGH_DUPLICATE
)))
2391 zvni_neigh_send_add_to_client(
2392 zvni
->vni
, &n
->ip
, &n
->emac
,
2393 n
->flags
, n
->loc_seq
);
2400 * Process all neighbors associated with a local MAC upon the MAC being
2403 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2406 zebra_neigh_t
*n
= NULL
;
2407 struct listnode
*node
= NULL
;
2408 char buf
[ETHER_ADDR_STRLEN
];
2410 if (IS_ZEBRA_DEBUG_VXLAN
)
2411 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2412 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2415 /* Walk all local neighbors and mark as inactive and inform
2417 * TBD: There is currently no handling for remote neighbors. We
2418 * don't expect them to exist, if they do, do we install the MAC
2419 * as a remote MAC and the neighbor as remote?
2421 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2422 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2423 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2424 ZEBRA_NEIGH_SET_INACTIVE(n
);
2426 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2427 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2434 * Process all neighbors associated with a MAC upon the MAC being remotely
2437 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2440 zebra_neigh_t
*n
= NULL
;
2441 struct listnode
*node
= NULL
;
2442 char buf
[ETHER_ADDR_STRLEN
];
2444 if (IS_ZEBRA_DEBUG_VXLAN
)
2445 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2446 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2449 /* Walk all local neighbors and mark as inactive and inform
2452 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2453 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2454 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2455 ZEBRA_NEIGH_SET_INACTIVE(n
);
2457 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2458 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2465 * Process all neighbors associated with a remote MAC upon the MAC being
2468 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2471 /* NOTE: Currently a NO-OP. */
2474 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2476 zebra_neigh_t
*nbr
= NULL
;
2477 struct listnode
*node
= NULL
;
2479 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2480 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2481 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2482 zvni_neigh_probe(zvni
, nbr
);
2487 * Inform BGP about local neighbor addition.
2489 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2490 struct ethaddr
*macaddr
,
2491 uint8_t neigh_flags
,
2496 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2497 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2498 /* Set router flag (R-bit) based on local neigh entry add */
2499 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2500 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2501 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_SVI_IP
))
2502 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_SVI_IP
);
2504 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2505 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2509 * Inform BGP about local neighbor deletion.
2511 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2512 struct ethaddr
*macaddr
, uint8_t flags
,
2515 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2516 0, state
, ZEBRA_MACIP_DEL
);
2520 * Install remote neighbor into the kernel.
2522 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2524 struct zebra_if
*zif
;
2525 struct zebra_l2info_vxlan
*vxl
;
2526 struct interface
*vlan_if
;
2530 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2533 zif
= zvni
->vxlan_if
->info
;
2536 vxl
= &zif
->l2info
.vxl
;
2538 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2542 flags
= DPLANE_NTF_EXT_LEARNED
;
2543 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2544 flags
|= DPLANE_NTF_ROUTER
;
2545 ZEBRA_NEIGH_SET_ACTIVE(n
);
2547 dplane_neigh_add(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2553 * Uninstall remote neighbor from the kernel.
2555 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2557 struct zebra_if
*zif
;
2558 struct zebra_l2info_vxlan
*vxl
;
2559 struct interface
*vlan_if
;
2561 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2564 if (!zvni
->vxlan_if
) {
2565 if (IS_ZEBRA_DEBUG_VXLAN
)
2566 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2571 zif
= zvni
->vxlan_if
->info
;
2574 vxl
= &zif
->l2info
.vxl
;
2575 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2579 ZEBRA_NEIGH_SET_INACTIVE(n
);
2582 dplane_neigh_delete(vlan_if
, &n
->ip
);
2588 * Probe neighbor from the kernel.
2590 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2592 struct zebra_if
*zif
;
2593 struct zebra_l2info_vxlan
*vxl
;
2594 struct interface
*vlan_if
;
2596 zif
= zvni
->vxlan_if
->info
;
2599 vxl
= &zif
->l2info
.vxl
;
2601 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2605 dplane_neigh_update(vlan_if
, &n
->ip
, &n
->emac
);
2611 * Install neighbor hash entry - called upon access VLAN change.
2613 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2616 struct neigh_walk_ctx
*wctx
= ctxt
;
2618 n
= (zebra_neigh_t
*)bucket
->data
;
2620 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2621 zvni_neigh_install(wctx
->zvni
, n
);
2624 /* Get the VRR interface for SVI if any */
2625 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2627 struct zebra_vrf
*zvrf
= NULL
;
2628 struct interface
*tmp_if
= NULL
;
2629 struct zebra_if
*zif
= NULL
;
2631 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2634 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2639 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2642 if (zif
->link
== ifp
)
2649 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2651 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2652 struct connected
*c
= NULL
;
2653 struct ethaddr macaddr
;
2655 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2657 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2660 memset(&ip
, 0, sizeof(struct ipaddr
));
2661 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2664 if (c
->address
->family
== AF_INET
) {
2665 ip
.ipa_type
= IPADDR_V4
;
2666 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2667 sizeof(struct in_addr
));
2668 } else if (c
->address
->family
== AF_INET6
) {
2669 ip
.ipa_type
= IPADDR_V6
;
2670 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2671 sizeof(struct in6_addr
));
2676 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2682 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2684 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2685 struct connected
*c
= NULL
;
2686 struct ethaddr macaddr
;
2688 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2690 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2693 memset(&ip
, 0, sizeof(struct ipaddr
));
2694 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2697 if (c
->address
->family
== AF_INET
) {
2698 ip
.ipa_type
= IPADDR_V4
;
2699 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2700 sizeof(struct in_addr
));
2701 } else if (c
->address
->family
== AF_INET6
) {
2702 ip
.ipa_type
= IPADDR_V6
;
2703 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2704 sizeof(struct in6_addr
));
2709 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2715 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2718 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2719 struct connected
*c
= NULL
;
2720 struct ethaddr macaddr
;
2722 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2724 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2727 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2729 /* skip link local address */
2730 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2735 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2736 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2738 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2739 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2745 * zvni_gw_macip_add_to_client
2747 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2748 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2750 char buf
[ETHER_ADDR_STRLEN
];
2751 char buf2
[INET6_ADDRSTRLEN
];
2752 zebra_neigh_t
*n
= NULL
;
2753 zebra_mac_t
*mac
= NULL
;
2754 struct zebra_if
*zif
= NULL
;
2755 struct zebra_l2info_vxlan
*vxl
= NULL
;
2757 zif
= zvni
->vxlan_if
->info
;
2761 vxl
= &zif
->l2info
.vxl
;
2763 mac
= zvni_mac_lookup(zvni
, macaddr
);
2765 mac
= zvni_mac_add(zvni
, macaddr
);
2767 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2768 "Failed to add MAC %s intf %s(%u) VID %u",
2769 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2770 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2775 /* Set "local" forwarding info. */
2776 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2777 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2778 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2779 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2780 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2781 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2783 n
= zvni_neigh_lookup(zvni
, ip
);
2785 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2788 EC_ZEBRA_MAC_ADD_FAILED
,
2789 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2790 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2791 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2792 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2797 /* Set "local" forwarding info. */
2798 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2799 ZEBRA_NEIGH_SET_ACTIVE(n
);
2800 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2801 n
->ifindex
= ifp
->ifindex
;
2803 /* Only advertise in BGP if the knob is enabled */
2804 if (advertise_gw_macip_enabled(zvni
)) {
2806 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2807 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2808 /* Set Router flag (R-bit) */
2809 if (ip
->ipa_type
== IPADDR_V6
)
2810 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2812 if (IS_ZEBRA_DEBUG_VXLAN
)
2814 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2815 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2816 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2817 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2819 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2820 n
->flags
, n
->loc_seq
);
2821 } else if (advertise_svi_macip_enabled(zvni
)) {
2823 SET_FLAG(n
->flags
, ZEBRA_NEIGH_SVI_IP
);
2824 if (IS_ZEBRA_DEBUG_VXLAN
)
2826 "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
2827 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2828 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2829 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2831 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2832 n
->flags
, n
->loc_seq
);
2839 * zvni_gw_macip_del_from_client
2841 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2844 char buf1
[ETHER_ADDR_STRLEN
];
2845 char buf2
[INET6_ADDRSTRLEN
];
2846 zebra_neigh_t
*n
= NULL
;
2847 zebra_mac_t
*mac
= NULL
;
2849 /* If the neigh entry is not present nothing to do*/
2850 n
= zvni_neigh_lookup(zvni
, ip
);
2854 /* mac entry should be present */
2855 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2857 if (IS_ZEBRA_DEBUG_VXLAN
)
2858 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2859 prefix_mac2str(&n
->emac
,
2860 buf1
, sizeof(buf1
)),
2861 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2866 /* If the entry is not local nothing to do*/
2867 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2870 /* only need to delete the entry from bgp if we sent it before */
2871 if (IS_ZEBRA_DEBUG_VXLAN
)
2873 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2874 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2875 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2876 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2878 /* Remove neighbor from BGP. */
2879 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2880 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2882 /* Delete this neighbor entry. */
2883 zvni_neigh_del(zvni
, n
);
2885 /* see if the mac needs to be deleted as well*/
2887 zvni_deref_ip2mac(zvni
, mac
);
2892 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2895 zebra_vni_t
*zvni
= NULL
;
2896 struct zebra_if
*zif
= NULL
;
2897 struct zebra_l2info_vxlan zl2_info
;
2898 struct interface
*vlan_if
= NULL
;
2899 struct interface
*vrr_if
= NULL
;
2900 struct interface
*ifp
;
2902 /* Add primary SVI MAC*/
2903 zvni
= (zebra_vni_t
*)bucket
->data
;
2905 /* Global (Zvrf) advertise-default-gw is disabled,
2906 * but zvni advertise-default-gw is enabled
2908 if (zvni
->advertise_gw_macip
) {
2909 if (IS_ZEBRA_DEBUG_VXLAN
)
2910 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
2915 ifp
= zvni
->vxlan_if
;
2920 /* If down or not mapped to a bridge, we're done. */
2921 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2924 zl2_info
= zif
->l2info
.vxl
;
2927 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2931 /* Del primary MAC-IP */
2932 zvni_del_macip_for_intf(vlan_if
, zvni
);
2934 /* Del VRR MAC-IP - if any*/
2935 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2937 zvni_del_macip_for_intf(vrr_if
, zvni
);
2942 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2945 zebra_vni_t
*zvni
= NULL
;
2946 struct zebra_if
*zif
= NULL
;
2947 struct zebra_l2info_vxlan zl2_info
;
2948 struct interface
*vlan_if
= NULL
;
2949 struct interface
*vrr_if
= NULL
;
2950 struct interface
*ifp
= NULL
;
2952 zvni
= (zebra_vni_t
*)bucket
->data
;
2954 ifp
= zvni
->vxlan_if
;
2959 /* If down or not mapped to a bridge, we're done. */
2960 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2962 zl2_info
= zif
->l2info
.vxl
;
2965 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2969 /* Add primary SVI MAC-IP */
2970 zvni_add_macip_for_intf(vlan_if
, zvni
);
2972 if (advertise_gw_macip_enabled(zvni
)) {
2973 /* Add VRR MAC-IP - if any*/
2974 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2976 zvni_add_macip_for_intf(vrr_if
, zvni
);
2982 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2985 zebra_vni_t
*zvni
= NULL
;
2986 struct zebra_if
*zif
= NULL
;
2987 struct zebra_l2info_vxlan zl2_info
;
2988 struct interface
*vlan_if
= NULL
;
2989 struct interface
*ifp
;
2991 /* Add primary SVI MAC*/
2992 zvni
= (zebra_vni_t
*)bucket
->data
;
2996 /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
2999 if (zvni
->advertise_svi_macip
) {
3000 if (IS_ZEBRA_DEBUG_VXLAN
)
3001 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
3006 ifp
= zvni
->vxlan_if
;
3011 /* If down or not mapped to a bridge, we're done. */
3012 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3015 zl2_info
= zif
->l2info
.vxl
;
3017 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
3018 zif
->brslave_info
.br_if
);
3022 /* Del primary MAC-IP */
3023 zvni_del_macip_for_intf(vlan_if
, zvni
);
3028 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
3029 struct interface
*ifp
,
3031 struct ethaddr
*macaddr
,
3034 char buf
[ETHER_ADDR_STRLEN
];
3035 char buf2
[INET6_ADDRSTRLEN
];
3036 struct zebra_vrf
*zvrf
;
3037 zebra_neigh_t
*n
= NULL
;
3038 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3039 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3040 bool upd_mac_seq
= false;
3041 bool neigh_mac_change
= false;
3042 bool neigh_on_hold
= false;
3043 bool neigh_was_remote
= false;
3044 bool do_dad
= false;
3045 struct in_addr vtep_ip
= {.s_addr
= 0};
3047 /* Check if the MAC exists. */
3048 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3050 /* create a dummy MAC if the MAC is not already present */
3051 if (IS_ZEBRA_DEBUG_VXLAN
)
3053 "AUTO MAC %s created for neigh %s on VNI %u",
3054 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3055 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3057 zmac
= zvni_mac_add(zvni
, macaddr
);
3059 zlog_debug("Failed to add MAC %s VNI %u",
3060 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3065 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3066 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3067 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3069 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3071 * We don't change the MAC to local upon a neighbor
3072 * learn event, we wait for the explicit local MAC
3073 * learn. However, we have to compute its sequence
3074 * number in preparation for when it actually turns
3081 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3083 if (IS_ZEBRA_DEBUG_VXLAN
)
3084 zlog_debug("\tUnable to find vrf for: %d",
3085 zvni
->vxlan_if
->vrf_id
);
3089 /* Check if the neighbor exists. */
3090 n
= zvni_neigh_lookup(zvni
, ip
);
3092 /* New neighbor - create */
3093 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3096 EC_ZEBRA_MAC_ADD_FAILED
,
3097 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3098 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3099 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3100 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3103 /* Set "local" forwarding info. */
3104 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3105 n
->ifindex
= ifp
->ifindex
;
3107 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3111 /* Note any changes and see if of interest to BGP. */
3112 mac_different
= (memcmp(n
->emac
.octet
,
3113 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3114 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3115 ZEBRA_NEIGH_ROUTER_FLAG
);
3116 if (!mac_different
&& is_router
== cur_is_router
) {
3117 if (IS_ZEBRA_DEBUG_VXLAN
)
3119 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3120 n
->ifindex
= ifp
->ifindex
;
3124 if (!mac_different
) {
3125 bool is_neigh_freezed
= false;
3127 /* Only the router flag has changed. */
3130 ZEBRA_NEIGH_ROUTER_FLAG
);
3132 UNSET_FLAG(n
->flags
,
3133 ZEBRA_NEIGH_ROUTER_FLAG
);
3135 /* Neigh is in freeze state and freeze action
3136 * is enabled, do not send update to client.
3138 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3140 CHECK_FLAG(n
->flags
,
3141 ZEBRA_NEIGH_DUPLICATE
));
3143 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3145 return zvni_neigh_send_add_to_client(
3146 zvni
->vni
, ip
, macaddr
,
3147 n
->flags
, n
->loc_seq
);
3149 if (IS_ZEBRA_DEBUG_VXLAN
)
3151 "\tNeighbor active and frozen");
3156 /* The MAC has changed, need to issue a delete
3157 * first as this means a different MACIP route.
3158 * Also, need to do some unlinking/relinking.
3159 * We also need to update the MAC's sequence number
3160 * in different situations.
3162 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3163 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3164 &n
->emac
, 0, n
->state
);
3165 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3167 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3169 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3170 neigh_mac_change
= upd_mac_seq
= true;
3171 listnode_delete(old_zmac
->neigh_list
, n
);
3172 zvni_deref_ip2mac(zvni
, old_zmac
);
3175 /* Update the forwarding info. */
3176 n
->ifindex
= ifp
->ifindex
;
3177 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3179 /* Link to new MAC */
3180 listnode_add_sort(zmac
->neigh_list
, n
);
3181 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3183 * Neighbor has moved from remote to local. Its
3184 * MAC could have also changed as part of the move.
3186 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3188 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3190 old_mac_seq
= CHECK_FLAG(
3195 neigh_mac_change
= upd_mac_seq
= true;
3196 listnode_delete(old_zmac
->neigh_list
,
3198 zvni_deref_ip2mac(zvni
, old_zmac
);
3201 /* Link to new MAC */
3202 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3203 listnode_add_sort(zmac
->neigh_list
, n
);
3205 /* Based on Mobility event Scenario-B from the
3206 * draft, neigh's previous state was remote treat this
3209 neigh_was_remote
= true;
3210 vtep_ip
= n
->r_vtep_ip
;
3211 /* Mark appropriately */
3212 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3213 n
->r_vtep_ip
.s_addr
= 0;
3214 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3215 n
->ifindex
= ifp
->ifindex
;
3219 /* If MAC was previously remote, or the neighbor had a different
3220 * MAC earlier, recompute the sequence number.
3223 uint32_t seq1
, seq2
;
3225 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3226 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3227 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3228 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3229 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3232 /* Mark Router flag (R-bit) */
3234 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3236 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3238 /* Check old and/or new MAC detected as duplicate mark
3239 * the neigh as duplicate
3241 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3242 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3243 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3245 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3246 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3249 /* For IP Duplicate Address Detection (DAD) is trigger,
3250 * when the event is extended mobility based on scenario-B
3251 * from the draft, IP/Neigh's MAC binding changed and
3252 * neigh's previous state was remote.
3254 if (neigh_mac_change
&& neigh_was_remote
)
3257 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3258 &neigh_on_hold
, true);
3260 /* Before we program this in BGP, we need to check if MAC is locally
3261 * learnt. If not, force neighbor to be inactive and reset its seq.
3263 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3264 ZEBRA_NEIGH_SET_INACTIVE(n
);
3266 zmac
->loc_seq
= mac_new_seq
;
3270 /* If the MAC's sequence number has changed, inform the MAC and all
3271 * neighbors associated with the MAC to BGP, else just inform this
3274 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3275 if (IS_ZEBRA_DEBUG_VXLAN
)
3276 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3277 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3278 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3279 zmac
->loc_seq
= mac_new_seq
;
3280 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3281 zmac
->flags
, zmac
->loc_seq
))
3283 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3287 n
->loc_seq
= zmac
->loc_seq
;
3289 if (!neigh_on_hold
) {
3290 ZEBRA_NEIGH_SET_ACTIVE(n
);
3292 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3293 n
->flags
, n
->loc_seq
);
3295 if (IS_ZEBRA_DEBUG_VXLAN
)
3296 zlog_debug("\tNeighbor on hold not sending");
3301 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3302 struct interface
*ifp
,
3304 struct ethaddr
*macaddr
,
3307 char buf
[ETHER_ADDR_STRLEN
];
3308 char buf2
[INET6_ADDRSTRLEN
];
3309 zebra_neigh_t
*n
= NULL
;
3310 zebra_mac_t
*zmac
= NULL
;
3312 /* If the neighbor is unknown, there is no further action. */
3313 n
= zvni_neigh_lookup(zvni
, ip
);
3317 /* If a remote entry, see if it needs to be refreshed */
3318 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3320 if (state
& NUD_STALE
)
3321 zvni_neigh_install(zvni
, n
);
3324 /* We got a "remote" neighbor notification for an entry
3325 * we think is local. This can happen in a multihoming
3326 * scenario - but only if the MAC is already "remote".
3327 * Just mark our entry as "remote".
3329 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3330 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3332 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3333 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3334 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3339 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3340 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3341 ZEBRA_NEIGH_SET_ACTIVE(n
);
3342 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3349 * Make hash key for MAC.
3351 static unsigned int mac_hash_keymake(const void *p
)
3353 const zebra_mac_t
*pmac
= p
;
3354 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3356 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3360 * Compare two MAC addresses.
3362 static bool mac_cmp(const void *p1
, const void *p2
)
3364 const zebra_mac_t
*pmac1
= p1
;
3365 const zebra_mac_t
*pmac2
= p2
;
3367 if (pmac1
== NULL
&& pmac2
== NULL
)
3370 if (pmac1
== NULL
|| pmac2
== NULL
)
3373 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3378 * Callback to allocate MAC hash entry.
3380 static void *zvni_mac_alloc(void *p
)
3382 const zebra_mac_t
*tmp_mac
= p
;
3385 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3388 return ((void *)mac
);
3394 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3396 zebra_mac_t tmp_mac
;
3397 zebra_mac_t
*mac
= NULL
;
3399 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3400 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3401 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3405 mac
->dad_mac_auto_recovery_timer
= NULL
;
3407 mac
->neigh_list
= list_new();
3408 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3416 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3418 zebra_mac_t
*tmp_mac
;
3420 /* Cancel auto recovery */
3421 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3423 list_delete(&mac
->neigh_list
);
3425 /* Free the VNI hash entry and allocated memory. */
3426 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3427 XFREE(MTYPE_MAC
, tmp_mac
);
3432 static bool zvni_check_mac_del_from_db(struct mac_walk_ctx
*wctx
,
3435 if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3436 (mac
->flags
& ZEBRA_MAC_LOCAL
))
3438 else if ((wctx
->flags
& DEL_REMOTE_MAC
) &&
3439 (mac
->flags
& ZEBRA_MAC_REMOTE
))
3441 else if ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
) &&
3442 (mac
->flags
& ZEBRA_MAC_REMOTE
) &&
3443 IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &wctx
->r_vtep_ip
))
3445 else if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3446 (mac
->flags
& ZEBRA_MAC_AUTO
) &&
3447 !listcount(mac
->neigh_list
)) {
3448 if (IS_ZEBRA_DEBUG_VXLAN
) {
3449 char buf
[ETHER_ADDR_STRLEN
];
3451 zlog_debug("%s: Del MAC %s flags 0x%x",
3452 __PRETTY_FUNCTION__
,
3453 prefix_mac2str(&mac
->macaddr
,
3457 wctx
->uninstall
= 0;
3466 * Free MAC hash entry (callback)
3468 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3470 struct mac_walk_ctx
*wctx
= arg
;
3471 zebra_mac_t
*mac
= bucket
->data
;
3473 if (zvni_check_mac_del_from_db(wctx
, mac
)) {
3474 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3475 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3478 if (wctx
->uninstall
)
3479 zvni_mac_uninstall(wctx
->zvni
, mac
);
3481 zvni_mac_del(wctx
->zvni
, mac
);
3488 * Delete all MAC entries from specific VTEP for a particular VNI.
3490 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3491 struct in_addr
*r_vtep_ip
)
3493 struct mac_walk_ctx wctx
;
3495 if (!zvni
->mac_table
)
3498 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3500 wctx
.uninstall
= uninstall
;
3501 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3502 wctx
.r_vtep_ip
= *r_vtep_ip
;
3504 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3508 * Delete all MAC entries for this VNI.
3510 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3513 struct mac_walk_ctx wctx
;
3515 if (!zvni
->mac_table
)
3518 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3520 wctx
.uninstall
= uninstall
;
3521 wctx
.upd_client
= upd_client
;
3524 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3528 * Look up MAC hash entry.
3530 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3535 memset(&tmp
, 0, sizeof(tmp
));
3536 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3537 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3543 * Inform BGP about local MAC addition.
3545 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3546 uint8_t mac_flags
, uint32_t seq
)
3550 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3551 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3552 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3553 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3555 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3556 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3560 * Inform BGP about local MAC deletion.
3562 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3564 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3565 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3569 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3570 * notifications, to see if they are of interest.
3572 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3573 struct interface
*br_if
, vlanid_t vid
)
3575 struct zebra_ns
*zns
;
3576 struct route_node
*rn
;
3577 struct interface
*tmp_if
= NULL
;
3578 struct zebra_if
*zif
;
3579 struct zebra_l2info_bridge
*br
;
3580 struct zebra_l2info_vxlan
*vxl
= NULL
;
3581 uint8_t bridge_vlan_aware
;
3585 /* Determine if bridge is VLAN-aware or not */
3588 br
= &zif
->l2info
.br
;
3589 bridge_vlan_aware
= br
->vlan_aware
;
3591 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3592 /* TODO: Optimize with a hash. */
3593 zns
= zebra_ns_lookup(NS_DEFAULT
);
3594 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3595 tmp_if
= (struct interface
*)rn
->info
;
3599 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3601 if (!if_is_operative(tmp_if
))
3603 vxl
= &zif
->l2info
.vxl
;
3605 if (zif
->brslave_info
.br_if
!= br_if
)
3608 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3617 zvni
= zvni_lookup(vxl
->vni
);
3622 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3623 * neighbor notifications, to see if they are of interest.
3625 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3626 struct interface
*br_if
)
3628 struct zebra_ns
*zns
;
3629 struct route_node
*rn
;
3630 struct interface
*tmp_if
= NULL
;
3631 struct zebra_if
*zif
;
3632 struct zebra_l2info_bridge
*br
;
3633 struct zebra_l2info_vxlan
*vxl
= NULL
;
3634 uint8_t bridge_vlan_aware
;
3642 /* Make sure the linked interface is a bridge. */
3643 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3646 /* Determine if bridge is VLAN-aware or not */
3649 br
= &zif
->l2info
.br
;
3650 bridge_vlan_aware
= br
->vlan_aware
;
3651 if (bridge_vlan_aware
) {
3652 struct zebra_l2info_vlan
*vl
;
3654 if (!IS_ZEBRA_IF_VLAN(ifp
))
3659 vl
= &zif
->l2info
.vl
;
3663 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3664 /* TODO: Optimize with a hash. */
3665 zns
= zebra_ns_lookup(NS_DEFAULT
);
3666 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3667 tmp_if
= (struct interface
*)rn
->info
;
3671 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3673 if (!if_is_operative(tmp_if
))
3675 vxl
= &zif
->l2info
.vxl
;
3677 if (zif
->brslave_info
.br_if
!= br_if
)
3680 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3689 zvni
= zvni_lookup(vxl
->vni
);
3693 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3695 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3696 * linked to the bridge
3697 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
3700 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3702 struct zebra_ns
*zns
;
3703 struct route_node
*rn
;
3704 struct interface
*tmp_if
= NULL
;
3705 struct zebra_if
*zif
;
3706 struct zebra_l2info_bridge
*br
;
3707 struct zebra_l2info_vlan
*vl
;
3708 uint8_t bridge_vlan_aware
;
3711 /* Defensive check, caller expected to invoke only with valid bridge. */
3715 /* Determine if bridge is VLAN-aware or not */
3718 br
= &zif
->l2info
.br
;
3719 bridge_vlan_aware
= br
->vlan_aware
;
3721 /* Check oper status of the SVI. */
3722 if (!bridge_vlan_aware
)
3723 return if_is_operative(br_if
) ? br_if
: NULL
;
3725 /* Identify corresponding VLAN interface. */
3726 /* TODO: Optimize with a hash. */
3727 zns
= zebra_ns_lookup(NS_DEFAULT
);
3728 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3729 tmp_if
= (struct interface
*)rn
->info
;
3730 /* Check oper status of the SVI. */
3731 if (!tmp_if
|| !if_is_operative(tmp_if
))
3734 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3735 || zif
->link
!= br_if
)
3737 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3739 if (vl
->vid
== vid
) {
3745 return found
? tmp_if
: NULL
;
3748 /* Map to MAC-VLAN interface corresponding to specified SVI interface.
3750 static struct interface
*zvni_map_to_macvlan(struct interface
*br_if
,
3751 struct interface
*svi_if
)
3753 struct zebra_ns
*zns
;
3754 struct route_node
*rn
;
3755 struct interface
*tmp_if
= NULL
;
3756 struct zebra_if
*zif
;
3759 /* Defensive check, caller expected to invoke only with valid bridge. */
3764 zlog_debug("svi_if is not passed.");
3768 /* Determine if bridge is VLAN-aware or not */
3772 /* Identify corresponding VLAN interface. */
3773 zns
= zebra_ns_lookup(NS_DEFAULT
);
3774 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3775 tmp_if
= (struct interface
*)rn
->info
;
3776 /* Check oper status of the SVI. */
3777 if (!tmp_if
|| !if_is_operative(tmp_if
))
3781 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_MACVLAN
)
3784 if (zif
->link
== svi_if
) {
3790 return found
? tmp_if
: NULL
;
3795 * Install remote MAC into the forwarding plane.
3797 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3799 const struct zebra_if
*zif
, *br_zif
;
3800 const struct zebra_l2info_vxlan
*vxl
;
3802 enum zebra_dplane_result res
;
3803 const struct interface
*br_ifp
;
3806 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3809 zif
= zvni
->vxlan_if
->info
;
3813 br_ifp
= zif
->brslave_info
.br_if
;
3817 vxl
= &zif
->l2info
.vxl
;
3819 sticky
= !!CHECK_FLAG(mac
->flags
,
3820 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3822 br_zif
= (const struct zebra_if
*)(br_ifp
->info
);
3824 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3825 vid
= vxl
->access_vlan
;
3829 res
= dplane_mac_add(zvni
->vxlan_if
, br_ifp
, vid
,
3830 &mac
->macaddr
, mac
->fwd_info
.r_vtep_ip
, sticky
);
3831 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3838 * Uninstall remote MAC from the forwarding plane.
3840 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3842 const struct zebra_if
*zif
, *br_zif
;
3843 const struct zebra_l2info_vxlan
*vxl
;
3844 struct in_addr vtep_ip
;
3845 const struct interface
*ifp
, *br_ifp
;
3847 enum zebra_dplane_result res
;
3849 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3852 if (!zvni
->vxlan_if
) {
3853 if (IS_ZEBRA_DEBUG_VXLAN
)
3854 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3859 zif
= zvni
->vxlan_if
->info
;
3863 br_ifp
= zif
->brslave_info
.br_if
;
3867 vxl
= &zif
->l2info
.vxl
;
3869 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
3871 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
3872 vid
= vxl
->access_vlan
;
3876 ifp
= zvni
->vxlan_if
;
3877 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3879 res
= dplane_mac_del(ifp
, br_ifp
, vid
, &mac
->macaddr
, vtep_ip
);
3880 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
3887 * Install MAC hash entry - called upon access VLAN change.
3889 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3892 struct mac_walk_ctx
*wctx
= ctxt
;
3894 mac
= (zebra_mac_t
*)bucket
->data
;
3896 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3897 zvni_mac_install(wctx
->zvni
, mac
);
3901 * Count of remote neighbors referencing this MAC.
3903 static int remote_neigh_count(zebra_mac_t
*zmac
)
3905 zebra_neigh_t
*n
= NULL
;
3906 struct listnode
*node
= NULL
;
3909 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3910 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3918 * Decrement neighbor refcount of MAC; uninstall and free it if
3921 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3923 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3926 /* If all remote neighbors referencing a remote MAC go away,
3927 * we need to uninstall the MAC.
3929 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3930 remote_neigh_count(mac
) == 0) {
3931 zvni_mac_uninstall(zvni
, mac
);
3932 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3935 /* If no neighbors, delete the MAC. */
3936 if (list_isempty(mac
->neigh_list
))
3937 zvni_mac_del(zvni
, mac
);
3941 * Read and populate local MACs and neighbors corresponding to this VNI.
3943 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3945 struct zebra_ns
*zns
;
3946 struct zebra_if
*zif
;
3947 struct interface
*vlan_if
;
3948 struct zebra_l2info_vxlan
*vxl
;
3949 struct interface
*vrr_if
;
3952 vxl
= &zif
->l2info
.vxl
;
3953 zns
= zebra_ns_lookup(NS_DEFAULT
);
3955 if (IS_ZEBRA_DEBUG_VXLAN
)
3957 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3958 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3959 zif
->brslave_info
.bridge_ifindex
);
3961 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3962 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3965 /* Add SVI MAC-IP */
3966 zvni_add_macip_for_intf(vlan_if
, zvni
);
3968 /* Add VRR MAC-IP - if any*/
3969 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3971 zvni_add_macip_for_intf(vrr_if
, zvni
);
3973 neigh_read_for_vlan(zns
, vlan_if
);
3978 * Hash function for VNI.
3980 static unsigned int vni_hash_keymake(const void *p
)
3982 const zebra_vni_t
*zvni
= p
;
3984 return (jhash_1word(zvni
->vni
, 0));
3988 * Compare 2 VNI hash entries.
3990 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3992 const zebra_vni_t
*zvni1
= p1
;
3993 const zebra_vni_t
*zvni2
= p2
;
3995 return (zvni1
->vni
== zvni2
->vni
);
3998 static int vni_list_cmp(void *p1
, void *p2
)
4000 const zebra_vni_t
*zvni1
= p1
;
4001 const zebra_vni_t
*zvni2
= p2
;
4003 if (zvni1
->vni
== zvni2
->vni
)
4005 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
4009 * Callback to allocate VNI hash entry.
4011 static void *zvni_alloc(void *p
)
4013 const zebra_vni_t
*tmp_vni
= p
;
4016 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
4017 zvni
->vni
= tmp_vni
->vni
;
4018 return ((void *)zvni
);
4022 * Look up VNI hash entry.
4024 static zebra_vni_t
*zvni_lookup(vni_t vni
)
4026 struct zebra_vrf
*zvrf
;
4027 zebra_vni_t tmp_vni
;
4028 zebra_vni_t
*zvni
= NULL
;
4030 zvrf
= zebra_vrf_get_evpn();
4032 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
4034 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
4040 * Add VNI hash entry.
4042 static zebra_vni_t
*zvni_add(vni_t vni
)
4044 struct zebra_vrf
*zvrf
;
4045 zebra_vni_t tmp_zvni
;
4046 zebra_vni_t
*zvni
= NULL
;
4048 zvrf
= zebra_vrf_get_evpn();
4050 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
4052 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
4055 /* Create hash table for MAC */
4057 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
4059 /* Create hash table for neighbors */
4060 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4061 "Zebra VNI Neighbor Table");
4067 * Delete VNI hash entry.
4069 static int zvni_del(zebra_vni_t
*zvni
)
4071 struct zebra_vrf
*zvrf
;
4072 zebra_vni_t
*tmp_zvni
;
4074 zvrf
= zebra_vrf_get_evpn();
4077 zvni
->vxlan_if
= NULL
;
4079 /* Remove references to the BUM mcast grp */
4080 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
4082 /* Free the neighbor hash table. */
4083 hash_free(zvni
->neigh_table
);
4084 zvni
->neigh_table
= NULL
;
4086 /* Free the MAC hash table. */
4087 hash_free(zvni
->mac_table
);
4088 zvni
->mac_table
= NULL
;
4090 /* Free the VNI hash entry and allocated memory. */
4091 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
4092 XFREE(MTYPE_ZVNI
, tmp_zvni
);
4098 * Inform BGP about local VNI addition.
4100 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
4102 struct zserv
*client
;
4105 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4106 /* BGP may not be running. */
4110 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4112 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
4113 stream_putl(s
, zvni
->vni
);
4114 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
4115 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
4116 stream_put_in_addr(s
, &zvni
->mcast_grp
);
4118 /* Write packet size. */
4119 stream_putw_at(s
, 0, stream_get_endp(s
));
4121 if (IS_ZEBRA_DEBUG_VXLAN
)
4122 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
4123 inet_ntoa(zvni
->local_vtep_ip
),
4124 vrf_id_to_name(zvni
->vrf_id
),
4125 zebra_route_string(client
->proto
));
4127 client
->vniadd_cnt
++;
4128 return zserv_send_message(client
, s
);
4132 * Inform BGP about local VNI deletion.
4134 static int zvni_send_del_to_client(vni_t vni
)
4136 struct zserv
*client
;
4139 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4140 /* BGP may not be running. */
4144 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4147 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4148 stream_putl(s
, vni
);
4150 /* Write packet size. */
4151 stream_putw_at(s
, 0, stream_get_endp(s
));
4153 if (IS_ZEBRA_DEBUG_VXLAN
)
4154 zlog_debug("Send VNI_DEL %u to %s", vni
,
4155 zebra_route_string(client
->proto
));
4157 client
->vnidel_cnt
++;
4158 return zserv_send_message(client
, s
);
4162 * Build the VNI hash table by going over the VxLAN interfaces. This
4163 * is called when EVPN (advertise-all-vni) is enabled.
4165 static void zvni_build_hash_table(void)
4167 struct zebra_ns
*zns
;
4168 struct route_node
*rn
;
4169 struct interface
*ifp
;
4171 /* Walk VxLAN interfaces and create VNI hash. */
4172 zns
= zebra_ns_lookup(NS_DEFAULT
);
4173 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4175 zebra_vni_t
*zvni
= NULL
;
4176 zebra_l3vni_t
*zl3vni
= NULL
;
4177 struct zebra_if
*zif
;
4178 struct zebra_l2info_vxlan
*vxl
;
4180 ifp
= (struct interface
*)rn
->info
;
4184 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4187 vxl
= &zif
->l2info
.vxl
;
4190 /* L3-VNI and L2-VNI are handled seperately */
4191 zl3vni
= zl3vni_lookup(vni
);
4194 if (IS_ZEBRA_DEBUG_VXLAN
)
4196 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4197 ifp
->name
, ifp
->ifindex
, vni
);
4199 /* associate with vxlan_if */
4200 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4201 zl3vni
->vxlan_if
= ifp
;
4204 * we need to associate with SVI.
4205 * we can associate with svi-if only after association
4206 * with vxlan-intf is complete
4208 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4210 /* Associate l3vni to mac-vlan and extract VRR MAC */
4211 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4213 if (IS_ZEBRA_DEBUG_VXLAN
)
4214 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
4215 vni
, zl3vni
->svi_if
? zl3vni
->svi_if
->name
4217 zl3vni
->mac_vlan_if
?
4218 zl3vni
->mac_vlan_if
->name
: "NIL");
4220 if (is_l3vni_oper_up(zl3vni
))
4221 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4224 struct interface
*vlan_if
= NULL
;
4226 if (IS_ZEBRA_DEBUG_VXLAN
)
4228 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4229 ifp
->name
, ifp
->ifindex
, vni
,
4230 inet_ntoa(vxl
->vtep_ip
));
4232 /* VNI hash entry is expected to exist, if the BGP process is killed */
4233 zvni
= zvni_lookup(vni
);
4236 "VNI hash already present for IF %s(%u) L2-VNI %u",
4237 ifp
->name
, ifp
->ifindex
, vni
);
4240 * Inform BGP if intf is up and mapped to
4243 if (if_is_operative(ifp
) &&
4244 zif
->brslave_info
.br_if
)
4245 zvni_send_add_to_client(zvni
);
4247 /* Send Local MAC-entries to client */
4248 zvni_send_mac_to_client(zvni
);
4250 /* Send Loval Neighbor entries to client */
4251 zvni_send_neigh_to_client(zvni
);
4253 zvni
= zvni_add(vni
);
4256 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4257 ifp
->name
, ifp
->ifindex
, vni
);
4261 if (zvni
->local_vtep_ip
.s_addr
!=
4262 vxl
->vtep_ip
.s_addr
||
4263 zvni
->mcast_grp
.s_addr
!=
4264 vxl
->mcast_grp
.s_addr
) {
4265 zebra_vxlan_sg_deref(
4266 zvni
->local_vtep_ip
,
4268 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4270 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4271 zvni
->mcast_grp
= vxl
->mcast_grp
;
4273 zvni
->vxlan_if
= ifp
;
4274 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4275 zif
->brslave_info
.br_if
);
4277 zvni
->vrf_id
= vlan_if
->vrf_id
;
4278 zl3vni
= zl3vni_from_vrf(
4282 zl3vni
->l2vnis
, zvni
);
4286 * Inform BGP if intf is up and mapped to
4289 if (if_is_operative(ifp
) &&
4290 zif
->brslave_info
.br_if
)
4291 zvni_send_add_to_client(zvni
);
4298 * See if remote VTEP matches with prefix.
4300 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4302 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4306 * Locate remote VTEP in VNI hash table.
4308 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4310 zebra_vtep_t
*zvtep
;
4315 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4316 if (zvni_vtep_match(vtep_ip
, zvtep
))
4324 * Add remote VTEP to VNI hash table.
4326 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4330 zebra_vtep_t
*zvtep
;
4332 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4334 zvtep
->vtep_ip
= *vtep_ip
;
4335 zvtep
->flood_control
= flood_control
;
4338 zvni
->vteps
->prev
= zvtep
;
4339 zvtep
->next
= zvni
->vteps
;
4340 zvni
->vteps
= zvtep
;
4346 * Remove remote VTEP from VNI hash table.
4348 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4351 zvtep
->next
->prev
= zvtep
->prev
;
4353 zvtep
->prev
->next
= zvtep
->next
;
4355 zvni
->vteps
= zvtep
->next
;
4357 zvtep
->prev
= zvtep
->next
= NULL
;
4358 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4364 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4365 * uninstall from kernel if asked to.
4367 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4369 zebra_vtep_t
*zvtep
, *zvtep_next
;
4374 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4375 zvtep_next
= zvtep
->next
;
4377 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4378 zvni_vtep_del(zvni
, zvtep
);
4385 * Install remote VTEP into the kernel if the remote VTEP has asked
4386 * for head-end-replication.
4388 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4390 if (is_vxlan_flooding_head_end() &&
4391 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
)) {
4392 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4393 dplane_vtep_add(zvni
->vxlan_if
,
4394 &zvtep
->vtep_ip
, zvni
->vni
))
4402 * Uninstall remote VTEP from the kernel.
4404 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4406 if (!zvni
->vxlan_if
) {
4407 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4412 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4413 dplane_vtep_delete(zvni
->vxlan_if
, vtep_ip
, zvni
->vni
))
4420 * Install or uninstall flood entries in the kernel corresponding to
4421 * remote VTEPs. This is invoked upon change to BUM handling.
4423 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4427 zebra_vtep_t
*zvtep
;
4429 zvni
= (zebra_vni_t
*)bucket
->data
;
4433 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4434 if (is_vxlan_flooding_head_end())
4435 zvni_vtep_install(zvni
, zvtep
);
4437 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4442 * Cleanup VNI/VTEP and update kernel
4444 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4446 zebra_vni_t
*zvni
= NULL
;
4447 zebra_l3vni_t
*zl3vni
= NULL
;
4448 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4450 zvni
= (zebra_vni_t
*)bucket
->data
;
4452 /* remove from l3-vni list */
4454 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4456 listnode_delete(zl3vni
->l2vnis
, zvni
);
4458 /* Free up all neighbors and MACs, if any. */
4459 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4460 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4462 /* Free up all remote VTEPs, if any. */
4463 zvni_vtep_del_all(zvni
, 1);
4465 /* Delete the hash entry. */
4470 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4472 zebra_l3vni_t
*zl3vni
= NULL
;
4474 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4476 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4479 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4480 struct prefix
*host
)
4482 struct host_rb_entry lookup
;
4483 struct host_rb_entry
*hle
;
4485 memset(&lookup
, 0, sizeof(lookup
));
4486 memcpy(&lookup
.p
, host
, sizeof(*host
));
4488 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4492 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4493 memcpy(hle
, &lookup
, sizeof(lookup
));
4495 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4498 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4500 struct host_rb_entry lookup
;
4501 struct host_rb_entry
*hle
;
4503 memset(&lookup
, 0, sizeof(lookup
));
4504 memcpy(&lookup
.p
, host
, sizeof(*host
));
4506 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4508 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4509 XFREE(MTYPE_HOST_PREFIX
, hle
);
4516 * Look up MAC hash entry.
4518 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4519 struct ethaddr
*rmac
)
4524 memset(&tmp
, 0, sizeof(tmp
));
4525 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4526 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4532 * Callback to allocate RMAC hash entry.
4534 static void *zl3vni_rmac_alloc(void *p
)
4536 const zebra_mac_t
*tmp_rmac
= p
;
4539 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4542 return ((void *)zrmac
);
4546 * Add RMAC entry to l3-vni
4548 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4550 zebra_mac_t tmp_rmac
;
4551 zebra_mac_t
*zrmac
= NULL
;
4553 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4554 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4555 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4558 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4560 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4561 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4569 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4571 zebra_mac_t
*tmp_rmac
;
4572 struct host_rb_entry
*hle
;
4574 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4575 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4577 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4578 XFREE(MTYPE_HOST_PREFIX
, hle
);
4581 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4582 XFREE(MTYPE_MAC
, tmp_rmac
);
4588 * Install remote RMAC into the forwarding plane.
4590 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4592 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
4593 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4594 const struct interface
*br_ifp
;
4595 enum zebra_dplane_result res
;
4598 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4599 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4602 zif
= zl3vni
->vxlan_if
->info
;
4606 br_ifp
= zif
->brslave_info
.br_if
;
4610 vxl
= &zif
->l2info
.vxl
;
4612 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4614 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4615 vid
= vxl
->access_vlan
;
4619 res
= dplane_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
,
4620 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4621 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4628 * Uninstall remote RMAC from the forwarding plane.
4630 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4632 char buf
[ETHER_ADDR_STRLEN
];
4633 const struct zebra_if
*zif
= NULL
, *br_zif
;
4634 const struct zebra_l2info_vxlan
*vxl
= NULL
;
4635 const struct interface
*br_ifp
;
4637 enum zebra_dplane_result res
;
4639 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4640 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4643 if (!zl3vni
->vxlan_if
) {
4644 if (IS_ZEBRA_DEBUG_VXLAN
)
4646 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4647 prefix_mac2str(&zrmac
->macaddr
,
4649 zl3vni
->vni
, zl3vni
);
4653 zif
= zl3vni
->vxlan_if
->info
;
4657 br_ifp
= zif
->brslave_info
.br_if
;
4661 vxl
= &zif
->l2info
.vxl
;
4663 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4664 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4665 vid
= vxl
->access_vlan
;
4669 res
= dplane_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
,
4670 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4671 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4677 /* handle rmac add */
4678 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4679 struct ipaddr
*vtep_ip
,
4680 struct prefix
*host_prefix
)
4682 char buf
[ETHER_ADDR_STRLEN
];
4683 char buf1
[INET6_ADDRSTRLEN
];
4684 char buf2
[PREFIX_STRLEN
];
4685 zebra_mac_t
*zrmac
= NULL
;
4687 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4690 /* Create the RMAC entry, or update its vtep, if necessary. */
4691 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4694 "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s",
4695 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4697 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4698 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4701 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4702 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4704 /* Send RMAC for FPM processing */
4705 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
4708 /* install rmac in kernel */
4709 zl3vni_rmac_install(zl3vni
, zrmac
);
4710 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
4711 &vtep_ip
->ipaddr_v4
)) {
4712 if (IS_ZEBRA_DEBUG_VXLAN
)
4714 "L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s",
4716 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
),
4717 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4718 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4719 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4721 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4723 /* install rmac in kernel */
4724 zl3vni_rmac_install(zl3vni
, zrmac
);
4727 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4733 /* handle rmac delete */
4734 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4735 struct prefix
*host_prefix
)
4737 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4739 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4740 /* uninstall from kernel */
4741 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4743 /* Send RMAC for FPM processing */
4744 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
4747 /* del the rmac entry */
4748 zl3vni_rmac_del(zl3vni
, zrmac
);
4753 * Look up nh hash entry on a l3-vni.
4755 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4760 memset(&tmp
, 0, sizeof(tmp
));
4761 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4762 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4769 * Callback to allocate NH hash entry on L3-VNI.
4771 static void *zl3vni_nh_alloc(void *p
)
4773 const zebra_neigh_t
*tmp_n
= p
;
4776 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4783 * Add neighbor entry.
4785 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4786 struct ethaddr
*mac
)
4788 zebra_neigh_t tmp_n
;
4789 zebra_neigh_t
*n
= NULL
;
4791 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4792 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4793 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4796 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4798 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4799 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4800 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4806 * Delete neighbor entry.
4808 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4810 zebra_neigh_t
*tmp_n
;
4811 struct host_rb_entry
*hle
;
4813 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4814 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4816 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4817 XFREE(MTYPE_HOST_PREFIX
, hle
);
4820 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4821 XFREE(MTYPE_NEIGH
, tmp_n
);
4827 * Install remote nh as neigh into the kernel.
4829 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4834 if (!is_l3vni_oper_up(zl3vni
))
4837 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4838 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4841 flags
= DPLANE_NTF_EXT_LEARNED
;
4842 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4843 flags
|= DPLANE_NTF_ROUTER
;
4845 dplane_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4851 * Uninstall remote nh from the kernel.
4853 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4855 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4856 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4859 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4862 dplane_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
4867 /* add remote vtep as a neigh entry */
4868 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4869 struct ethaddr
*rmac
,
4870 struct prefix
*host_prefix
)
4872 char buf
[ETHER_ADDR_STRLEN
];
4873 char buf1
[ETHER_ADDR_STRLEN
];
4874 char buf2
[INET6_ADDRSTRLEN
];
4875 char buf3
[PREFIX_STRLEN
];
4876 zebra_neigh_t
*nh
= NULL
;
4878 /* Create the next hop entry, or update its mac, if necessary. */
4879 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4881 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4884 "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)",
4885 ipaddr2str(vtep_ip
, buf1
, sizeof(buf2
)),
4886 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4888 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
4892 /* install the nh neigh in kernel */
4893 zl3vni_nh_install(zl3vni
, nh
);
4894 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
4895 if (IS_ZEBRA_DEBUG_VXLAN
)
4896 zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s",
4898 prefix_mac2str(&nh
->emac
, buf
, sizeof(buf
)),
4899 prefix_mac2str(rmac
, buf1
, sizeof(buf1
)),
4900 ipaddr2str(vtep_ip
, buf2
, sizeof(buf2
)),
4901 prefix2str(host_prefix
, buf3
, sizeof(buf3
)));
4903 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
4904 /* install (update) the nh neigh in kernel */
4905 zl3vni_nh_install(zl3vni
, nh
);
4908 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4913 /* handle nh neigh delete */
4914 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4915 struct prefix
*host_prefix
)
4917 rb_delete_host(&nh
->host_rb
, host_prefix
);
4919 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4920 /* uninstall from kernel */
4921 zl3vni_nh_uninstall(zl3vni
, nh
);
4923 /* delete the nh entry */
4924 zl3vni_nh_del(zl3vni
, nh
);
4928 /* handle neigh update from kernel - the only thing of interest is to
4929 * readd stale entries.
4931 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4935 zebra_neigh_t
*n
= NULL
;
4937 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4941 /* all next hop neigh are remote and installed by frr.
4942 * If the kernel has aged this entry, re-install.
4944 if (state
& NUD_STALE
)
4945 zl3vni_nh_install(zl3vni
, n
);
4950 /* handle neigh delete from kernel */
4951 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4953 zebra_neigh_t
*n
= NULL
;
4955 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4959 /* all next hop neigh are remote and installed by frr.
4960 * If we get an age out notification for these neigh entries, we have to
4963 zl3vni_nh_install(zl3vni
, n
);
4969 * Hash function for L3 VNI.
4971 static unsigned int l3vni_hash_keymake(const void *p
)
4973 const zebra_l3vni_t
*zl3vni
= p
;
4975 return jhash_1word(zl3vni
->vni
, 0);
4979 * Compare 2 L3 VNI hash entries.
4981 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4983 const zebra_l3vni_t
*zl3vni1
= p1
;
4984 const zebra_l3vni_t
*zl3vni2
= p2
;
4986 return (zl3vni1
->vni
== zl3vni2
->vni
);
4990 * Callback to allocate L3 VNI hash entry.
4992 static void *zl3vni_alloc(void *p
)
4994 zebra_l3vni_t
*zl3vni
= NULL
;
4995 const zebra_l3vni_t
*tmp_l3vni
= p
;
4997 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4998 zl3vni
->vni
= tmp_l3vni
->vni
;
4999 return ((void *)zl3vni
);
5003 * Look up L3 VNI hash entry.
5005 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
5007 zebra_l3vni_t tmp_l3vni
;
5008 zebra_l3vni_t
*zl3vni
= NULL
;
5010 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
5011 tmp_l3vni
.vni
= vni
;
5012 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
5018 * Add L3 VNI hash entry.
5020 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
5022 zebra_l3vni_t tmp_zl3vni
;
5023 zebra_l3vni_t
*zl3vni
= NULL
;
5025 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
5026 tmp_zl3vni
.vni
= vni
;
5028 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
5031 zl3vni
->vrf_id
= vrf_id
;
5032 zl3vni
->svi_if
= NULL
;
5033 zl3vni
->vxlan_if
= NULL
;
5034 zl3vni
->l2vnis
= list_new();
5035 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
5037 /* Create hash table for remote RMAC */
5038 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
5039 "Zebra L3-VNI RMAC-Table");
5041 /* Create hash table for neighbors */
5042 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
5043 "Zebra L3-VNI next-hop table");
5049 * Delete L3 VNI hash entry.
5051 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
5053 zebra_l3vni_t
*tmp_zl3vni
;
5055 /* free the list of l2vnis */
5056 list_delete(&zl3vni
->l2vnis
);
5057 zl3vni
->l2vnis
= NULL
;
5059 /* Free the rmac table */
5060 hash_free(zl3vni
->rmac_table
);
5061 zl3vni
->rmac_table
= NULL
;
5063 /* Free the nh table */
5064 hash_free(zl3vni
->nh_table
);
5065 zl3vni
->nh_table
= NULL
;
5067 /* Free the VNI hash entry and allocated memory. */
5068 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
5069 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
5074 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
5076 struct zebra_ns
*zns
= NULL
;
5077 struct route_node
*rn
= NULL
;
5078 struct interface
*ifp
= NULL
;
5080 /* loop through all vxlan-interface */
5081 zns
= zebra_ns_lookup(NS_DEFAULT
);
5082 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5084 struct zebra_if
*zif
= NULL
;
5085 struct zebra_l2info_vxlan
*vxl
= NULL
;
5087 ifp
= (struct interface
*)rn
->info
;
5092 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5095 vxl
= &zif
->l2info
.vxl
;
5096 if (vxl
->vni
== zl3vni
->vni
) {
5097 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
5105 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
5107 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5108 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
5113 if (!zl3vni
->vxlan_if
)
5116 zif
= zl3vni
->vxlan_if
->info
;
5120 vxl
= &zif
->l2info
.vxl
;
5122 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
5125 struct interface
*zl3vni_map_to_mac_vlan_if(zebra_l3vni_t
*zl3vni
)
5127 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5132 if (!zl3vni
->vxlan_if
)
5135 zif
= zl3vni
->vxlan_if
->info
;
5139 return zvni_map_to_macvlan(zif
->brslave_info
.br_if
, zl3vni
->svi_if
);
5143 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
5145 struct zebra_vrf
*zvrf
= NULL
;
5147 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
5151 return zl3vni_lookup(zvrf
->l3vni
);
5155 * Map SVI and associated bridge to a VNI. This is invoked upon getting
5156 * neighbor notifications, to see if they are of interest.
5158 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
5159 struct interface
*br_if
)
5163 uint8_t bridge_vlan_aware
= 0;
5164 zebra_l3vni_t
*zl3vni
= NULL
;
5165 struct zebra_ns
*zns
= NULL
;
5166 struct route_node
*rn
= NULL
;
5167 struct zebra_if
*zif
= NULL
;
5168 struct interface
*tmp_if
= NULL
;
5169 struct zebra_l2info_bridge
*br
= NULL
;
5170 struct zebra_l2info_vxlan
*vxl
= NULL
;
5175 /* Make sure the linked interface is a bridge. */
5176 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
5179 /* Determine if bridge is VLAN-aware or not */
5182 br
= &zif
->l2info
.br
;
5183 bridge_vlan_aware
= br
->vlan_aware
;
5184 if (bridge_vlan_aware
) {
5185 struct zebra_l2info_vlan
*vl
;
5187 if (!IS_ZEBRA_IF_VLAN(ifp
))
5192 vl
= &zif
->l2info
.vl
;
5196 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
5197 /* TODO: Optimize with a hash. */
5198 zns
= zebra_ns_lookup(NS_DEFAULT
);
5199 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5200 tmp_if
= (struct interface
*)rn
->info
;
5204 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5206 if (!if_is_operative(tmp_if
))
5208 vxl
= &zif
->l2info
.vxl
;
5210 if (zif
->brslave_info
.br_if
!= br_if
)
5213 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
5222 zl3vni
= zl3vni_lookup(vxl
->vni
);
5226 static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t
*zl3vni
,
5227 struct ethaddr
*rmac
)
5232 if (!is_l3vni_oper_up(zl3vni
))
5235 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
5236 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
5240 * Inform BGP about l3-vni.
5242 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
5244 struct stream
*s
= NULL
;
5245 struct zserv
*client
= NULL
;
5246 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
5247 struct zebra_vrf
*zvrf
;
5248 char buf
[ETHER_ADDR_STRLEN
];
5249 char buf1
[ETHER_ADDR_STRLEN
];
5250 bool is_anycast_mac
= true;
5252 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5253 /* BGP may not be running. */
5257 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
5260 /* get the svi and vrr rmac values */
5261 memset(&svi_rmac
, 0, sizeof(struct ethaddr
));
5262 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
5263 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
5265 /* In absence of vrr mac use svi mac as anycast MAC value */
5266 if (is_zero_mac(&vrr_rmac
)) {
5267 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
5268 is_anycast_mac
= false;
5271 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5273 /* The message is used for both vni add and/or update like
5274 * vrr mac is added for l3vni SVI.
5276 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
5277 stream_putl(s
, zl3vni
->vni
);
5278 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
5279 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
5280 stream_put(s
, &zl3vni
->filter
, sizeof(int));
5281 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
5282 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
5283 stream_putl(s
, is_anycast_mac
);
5285 /* Write packet size. */
5286 stream_putw_at(s
, 0, stream_get_endp(s
));
5288 if (IS_ZEBRA_DEBUG_VXLAN
)
5290 "Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %s filter %s to %s",
5291 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5292 prefix_mac2str(&svi_rmac
, buf
, sizeof(buf
)),
5293 prefix_mac2str(&vrr_rmac
, buf1
, sizeof(buf1
)),
5294 inet_ntoa(zl3vni
->local_vtep_ip
),
5295 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5296 ? "prefix-routes-only"
5298 zebra_route_string(client
->proto
));
5300 client
->l3vniadd_cnt
++;
5301 return zserv_send_message(client
, s
);
5305 * Inform BGP about local l3-VNI deletion.
5307 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5309 struct stream
*s
= NULL
;
5310 struct zserv
*client
= NULL
;
5312 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5313 /* BGP may not be running. */
5317 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5319 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5320 stream_putl(s
, zl3vni
->vni
);
5322 /* Write packet size. */
5323 stream_putw_at(s
, 0, stream_get_endp(s
));
5325 if (IS_ZEBRA_DEBUG_VXLAN
)
5326 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5327 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5328 zebra_route_string(client
->proto
));
5330 client
->l3vnidel_cnt
++;
5331 return zserv_send_message(client
, s
);
5334 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5339 /* send l3vni add to BGP */
5340 zl3vni_send_add_to_client(zl3vni
);
5343 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5348 /* send l3-vni del to BGP*/
5349 zl3vni_send_del_to_client(zl3vni
);
5352 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5354 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5355 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5357 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5358 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5362 * handle transition of vni from l2 to l3 and vice versa
5364 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5367 zebra_vni_t
*zvni
= NULL
;
5369 /* There is a possibility that VNI notification was already received
5370 * from kernel and we programmed it as L2-VNI
5371 * In such a case we need to delete this L2-VNI first, so
5372 * that it can be reprogrammed as L3-VNI in the system. It is also
5373 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5374 * interface is still present in kernel. In this case to keep it
5375 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5378 /* Locate hash entry */
5379 zvni
= zvni_lookup(vni
);
5383 if (IS_ZEBRA_DEBUG_VXLAN
)
5384 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5386 /* Delete VNI from BGP. */
5387 zvni_send_del_to_client(zvni
->vni
);
5389 /* Free up all neighbors and MAC, if any. */
5390 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5391 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5393 /* Free up all remote VTEPs, if any. */
5394 zvni_vtep_del_all(zvni
, 0);
5396 /* Delete the hash entry. */
5397 if (zvni_del(zvni
)) {
5398 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5399 "Failed to del VNI hash %p, VNI %u", zvni
,
5404 /* TODO_MITESH: This needs to be thought through. We don't have
5405 * enough information at this point to reprogram the vni as
5406 * l2-vni. One way is to store the required info in l3-vni and
5407 * used it solely for this purpose
5414 /* delete and uninstall rmac hash entry */
5415 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5417 zebra_mac_t
*zrmac
= NULL
;
5418 zebra_l3vni_t
*zl3vni
= NULL
;
5420 zrmac
= (zebra_mac_t
*)bucket
->data
;
5421 zl3vni
= (zebra_l3vni_t
*)ctx
;
5422 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5424 /* Send RMAC for FPM processing */
5425 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5427 zl3vni_rmac_del(zl3vni
, zrmac
);
5430 /* delete and uninstall nh hash entry */
5431 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5433 zebra_neigh_t
*n
= NULL
;
5434 zebra_l3vni_t
*zl3vni
= NULL
;
5436 n
= (zebra_neigh_t
*)bucket
->data
;
5437 zl3vni
= (zebra_l3vni_t
*)ctx
;
5438 zl3vni_nh_uninstall(zl3vni
, n
);
5439 zl3vni_nh_del(zl3vni
, n
);
5442 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5445 struct zserv
*client
= NULL
;
5446 struct stream
*s
= NULL
;
5447 char buf
[PREFIX_STRLEN
];
5449 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5450 /* BGP may not be running. */
5454 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5456 zclient_create_header(s
, cmd
, vrf_id
);
5457 stream_put(s
, p
, sizeof(struct prefix
));
5459 /* Write packet size. */
5460 stream_putw_at(s
, 0, stream_get_endp(s
));
5462 if (IS_ZEBRA_DEBUG_VXLAN
)
5463 zlog_debug("Send ip prefix %s %s on vrf %s",
5464 prefix2str(p
, buf
, sizeof(buf
)),
5465 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5466 vrf_id_to_name(vrf_id
));
5468 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5469 client
->prefixadd_cnt
++;
5471 client
->prefixdel_cnt
++;
5473 return zserv_send_message(client
, s
);
5476 /* re-add remote rmac if needed */
5477 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5478 struct ethaddr
*rmac
)
5480 char buf
[ETHER_ADDR_STRLEN
];
5481 zebra_mac_t
*zrmac
= NULL
;
5483 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5487 if (IS_ZEBRA_DEBUG_VXLAN
)
5488 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5489 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5491 zl3vni_rmac_install(zl3vni
, zrmac
);
5495 /* Process a remote MACIP add from BGP. */
5496 static void process_remote_macip_add(vni_t vni
,
5497 struct ethaddr
*macaddr
,
5499 struct ipaddr
*ipaddr
,
5502 struct in_addr vtep_ip
)
5505 zebra_vtep_t
*zvtep
;
5506 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5507 zebra_neigh_t
*n
= NULL
;
5508 int update_mac
= 0, update_neigh
= 0;
5509 char buf
[ETHER_ADDR_STRLEN
];
5510 char buf1
[INET6_ADDRSTRLEN
];
5511 struct interface
*ifp
= NULL
;
5512 struct zebra_if
*zif
= NULL
;
5513 struct zebra_vrf
*zvrf
;
5518 bool do_dad
= false;
5519 bool is_dup_detect
= false;
5521 /* Locate VNI hash entry - expected to exist. */
5522 zvni
= zvni_lookup(vni
);
5524 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5528 ifp
= zvni
->vxlan_if
;
5532 !if_is_operative(ifp
) ||
5534 !zif
->brslave_info
.br_if
) {
5535 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5540 /* The remote VTEP specified should normally exist, but it is
5541 * possible that when peering comes up, peer may advertise MACIP
5542 * routes before advertising type-3 routes.
5544 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5546 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5549 EC_ZEBRA_VTEP_ADD_FAILED
,
5550 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5555 zvni_vtep_install(zvni
, zvtep
);
5558 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5559 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5560 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5562 mac
= zvni_mac_lookup(zvni
, macaddr
);
5564 /* Ignore if the mac is already present as a gateway mac */
5566 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5567 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5568 if (IS_ZEBRA_DEBUG_VXLAN
)
5569 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5571 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5572 ipa_len
? " IP " : "",
5574 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5578 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5582 /* check if the remote MAC is unknown or has a change.
5583 * If so, that needs to be updated first. Note that client could
5584 * install MAC and MACIP separately or just install the latter.
5587 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5588 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5589 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5590 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5591 || seq
!= mac
->rem_seq
)
5596 mac
= zvni_mac_add(zvni
, macaddr
);
5599 "Failed to add MAC %s VNI %u Remote VTEP %s",
5600 prefix_mac2str(macaddr
, buf
,
5602 vni
, inet_ntoa(vtep_ip
));
5606 /* Is this MAC created for a MACIP? */
5608 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5610 /* When host moves but changes its (MAC,IP)
5611 * binding, BGP may install a MACIP entry that
5612 * corresponds to "older" location of the host
5613 * in transient situations (because {IP1,M1}
5614 * is a different route from {IP1,M2}). Check
5615 * the sequence number and ignore this update
5618 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5619 tmp_seq
= mac
->loc_seq
;
5621 tmp_seq
= mac
->rem_seq
;
5623 if (seq
< tmp_seq
) {
5624 if (IS_ZEBRA_DEBUG_VXLAN
)
5625 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
5627 prefix_mac2str(macaddr
,
5629 ipa_len
? " IP " : "",
5632 buf1
, sizeof(buf1
)) : "",
5633 tmp_seq
, mac
->flags
);
5638 /* Check MAC's curent state is local (this is the case
5639 * where MAC has moved from L->R) and check previous
5640 * detection started via local learning.
5641 * RFC-7432: A PE/VTEP that detects a MAC mobility
5642 * event via local learning starts an M-second timer.
5644 * VTEP-IP or seq. change alone is not considered
5645 * for dup. detection.
5647 * MAC is already marked duplicate set dad, then
5648 * is_dup_detect will be set to not install the entry.
5650 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5652 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5655 /* Remove local MAC from BGP. */
5656 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5657 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5659 /* Set "auto" and "remote" forwarding info. */
5660 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5661 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5662 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5663 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5666 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5668 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5671 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5673 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5675 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5676 mac
->fwd_info
.r_vtep_ip
,
5677 do_dad
, &is_dup_detect
,
5680 if (!is_dup_detect
) {
5681 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5682 /* Install the entry. */
5683 zvni_mac_install(zvni
, mac
);
5687 /* Update seq number. */
5690 /* If there is no IP, return after clearing AUTO flag of MAC. */
5692 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5699 /* Check if the remote neighbor itself is unknown or has a
5700 * change. If so, create or update and then install the entry.
5702 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5704 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5705 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5706 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5707 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5708 || seq
!= n
->rem_seq
)
5713 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5716 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5717 ipaddr2str(ipaddr
, buf1
,
5719 prefix_mac2str(macaddr
, buf
,
5721 vni
, inet_ntoa(vtep_ip
));
5728 /* When host moves but changes its (MAC,IP)
5729 * binding, BGP may install a MACIP entry that
5730 * corresponds to "older" location of the host
5731 * in transient situations (because {IP1,M1}
5732 * is a different route from {IP1,M2}). Check
5733 * the sequence number and ignore this update
5736 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5737 tmp_seq
= n
->loc_seq
;
5740 tmp_seq
= n
->rem_seq
;
5743 if (seq
< tmp_seq
) {
5744 if (IS_ZEBRA_DEBUG_VXLAN
)
5745 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5747 prefix_mac2str(macaddr
,
5750 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5755 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5756 /* MAC change, send a delete for old
5757 * neigh if learnt locally.
5759 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5760 IS_ZEBRA_NEIGH_ACTIVE(n
))
5761 zvni_neigh_send_del_to_client(
5763 &n
->emac
, 0, n
->state
);
5765 /* update neigh list for macs */
5766 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5768 listnode_delete(old_mac
->neigh_list
, n
);
5769 zvni_deref_ip2mac(zvni
, old_mac
);
5771 listnode_add_sort(mac
->neigh_list
, n
);
5772 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5774 /* Check Neigh's curent state is local
5775 * (this is the case where neigh/host has moved
5776 * from L->R) and check previous detction
5777 * started via local learning.
5779 * RFC-7432: A PE/VTEP that detects a MAC
5780 * mobilit event via local learning starts
5781 * an M-second timer.
5782 * VTEP-IP or seq. change along is not
5783 * considered for dup. detection.
5785 * Mobilty event scenario-B IP-MAC binding
5788 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5795 /* Set "remote" forwarding info. */
5796 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5797 n
->r_vtep_ip
= vtep_ip
;
5798 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5800 /* Set router flag (R-bit) to this Neighbor entry */
5801 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5802 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5804 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5806 /* Check old or new MAC detected as duplicate,
5807 * inherit duplicate flag to this neigh.
5809 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5811 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5812 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5814 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5815 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5818 /* Check duplicate address detection for IP */
5819 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5824 /* Install the entry. */
5826 zvni_neigh_install(zvni
, n
);
5829 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5831 /* Update seq number. */
5835 /* Process a remote MACIP delete from BGP. */
5836 static void process_remote_macip_del(vni_t vni
,
5837 struct ethaddr
*macaddr
,
5839 struct ipaddr
*ipaddr
,
5840 struct in_addr vtep_ip
)
5843 zebra_mac_t
*mac
= NULL
;
5844 zebra_neigh_t
*n
= NULL
;
5845 struct interface
*ifp
= NULL
;
5846 struct zebra_if
*zif
= NULL
;
5847 struct zebra_ns
*zns
;
5848 struct zebra_l2info_vxlan
*vxl
;
5849 struct zebra_vrf
*zvrf
;
5850 char buf
[ETHER_ADDR_STRLEN
];
5851 char buf1
[INET6_ADDRSTRLEN
];
5853 /* Locate VNI hash entry - expected to exist. */
5854 zvni
= zvni_lookup(vni
);
5856 if (IS_ZEBRA_DEBUG_VXLAN
)
5857 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5861 ifp
= zvni
->vxlan_if
;
5865 !if_is_operative(ifp
) ||
5867 !zif
->brslave_info
.br_if
) {
5868 if (IS_ZEBRA_DEBUG_VXLAN
)
5869 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5873 zns
= zebra_ns_lookup(NS_DEFAULT
);
5874 vxl
= &zif
->l2info
.vxl
;
5876 /* The remote VTEP specified is normally expected to exist, but
5877 * it is possible that the peer may delete the VTEP before deleting
5878 * any MACs referring to the VTEP, in which case the handler (see
5879 * remote_vtep_del) would have already deleted the MACs.
5881 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5884 mac
= zvni_mac_lookup(zvni
, macaddr
);
5886 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5889 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5890 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5891 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5895 /* If the remote mac or neighbor doesn't exist there is nothing
5896 * more to do. Otherwise, uninstall the entry and then remove it.
5901 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5903 /* Ignore the delete if this mac is a gateway mac-ip */
5904 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5905 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5907 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5909 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5910 ipa_len
? " IP " : "",
5912 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5916 /* Uninstall remote neighbor or MAC. */
5918 if (zvrf
->dad_freeze
&&
5919 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5920 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5921 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5922 struct interface
*vlan_if
;
5924 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5925 zif
->brslave_info
.br_if
);
5926 if (IS_ZEBRA_DEBUG_VXLAN
)
5928 "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5929 __PRETTY_FUNCTION__
,
5930 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5932 vlan_if
? vlan_if
->name
: "Unknown");
5934 neigh_read_specific_ip(ipaddr
, vlan_if
);
5937 /* When the MAC changes for an IP, it is possible the
5938 * client may update the new MAC before trying to delete the
5939 * "old" neighbor (as these are two different MACIP routes).
5940 * Do the delete only if the MAC matches.
5942 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5943 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5944 zvni_neigh_uninstall(zvni
, n
);
5945 zvni_neigh_del(zvni
, n
);
5946 zvni_deref_ip2mac(zvni
, mac
);
5949 /* DAD: when MAC is freeze state as remote learn event,
5950 * remote mac-ip delete event is received will result in freeze
5951 * entry removal, first fetch kernel for the same entry present
5952 * as LOCAL and reachable, avoid deleting this entry instead
5953 * use kerenel local entry to update during unfreeze time.
5955 if (zvrf
->dad_freeze
&&
5956 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5957 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5958 if (IS_ZEBRA_DEBUG_VXLAN
)
5959 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5960 __PRETTY_FUNCTION__
,
5961 prefix_mac2str(macaddr
, buf
,
5964 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5965 macaddr
, vxl
->access_vlan
);
5968 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5969 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5971 * the remote sequence number in the auto mac entry
5972 * needs to be reset to 0 as the mac entry may have
5973 * been removed on all VTEPs (including
5974 * the originating one)
5978 /* If all remote neighbors referencing a remote MAC
5979 * go away, we need to uninstall the MAC.
5981 if (remote_neigh_count(mac
) == 0) {
5982 zvni_mac_uninstall(zvni
, mac
);
5983 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5985 if (list_isempty(mac
->neigh_list
))
5986 zvni_mac_del(zvni
, mac
);
5988 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5994 /* Public functions */
5996 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5998 zebra_l3vni_t
*zl3vni
= NULL
;
6000 zl3vni
= zl3vni_lookup(vni
);
6004 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
6007 /* handle evpn route in vrf table */
6008 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
6009 struct ipaddr
*vtep_ip
,
6010 struct prefix
*host_prefix
)
6012 zebra_l3vni_t
*zl3vni
= NULL
;
6013 struct ipaddr ipv4_vtep
;
6015 zl3vni
= zl3vni_from_vrf(vrf_id
);
6016 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
6020 * add the next hop neighbor -
6021 * neigh to be installed is the ipv6 nexthop neigh
6023 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
6026 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
6027 * address. Rmac is programmed against the ipv4 vtep because we only
6028 * support ipv4 tunnels in the h/w right now
6030 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
6031 ipv4_vtep
.ipa_type
= IPADDR_V4
;
6032 if (vtep_ip
->ipa_type
== IPADDR_V6
)
6033 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
6034 &(ipv4_vtep
.ipaddr_v4
));
6036 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
6037 sizeof(struct in_addr
));
6040 * add the rmac - remote rmac to be installed is against the ipv4
6043 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
6046 /* handle evpn vrf route delete */
6047 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
6048 struct ipaddr
*vtep_ip
,
6049 struct prefix
*host_prefix
)
6051 zebra_l3vni_t
*zl3vni
= NULL
;
6052 zebra_neigh_t
*nh
= NULL
;
6053 zebra_mac_t
*zrmac
= NULL
;
6055 zl3vni
= zl3vni_from_vrf(vrf_id
);
6059 /* find the next hop entry and rmac entry */
6060 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
6063 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
6065 /* delete the next hop entry */
6066 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
6068 /* delete the rmac entry */
6070 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
6074 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
6075 struct ethaddr
*rmac
, bool use_json
)
6077 zebra_l3vni_t
*zl3vni
= NULL
;
6078 zebra_mac_t
*zrmac
= NULL
;
6079 json_object
*json
= NULL
;
6081 if (!is_evpn_enabled()) {
6083 vty_out(vty
, "{}\n");
6088 json
= json_object_new_object();
6090 zl3vni
= zl3vni_lookup(l3vni
);
6093 vty_out(vty
, "{}\n");
6095 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
6099 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
6102 vty_out(vty
, "{}\n");
6105 "%% Requested RMAC doesn't exist in L3-VNI %u",
6110 zl3vni_print_rmac(zrmac
, vty
, json
);
6113 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6114 json
, JSON_C_TO_STRING_PRETTY
));
6115 json_object_free(json
);
6119 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6121 zebra_l3vni_t
*zl3vni
;
6123 struct rmac_walk_ctx wctx
;
6124 json_object
*json
= NULL
;
6126 if (!is_evpn_enabled())
6129 zl3vni
= zl3vni_lookup(l3vni
);
6132 vty_out(vty
, "{}\n");
6134 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6137 num_rmacs
= hashcount(zl3vni
->rmac_table
);
6142 json
= json_object_new_object();
6144 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
6148 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
6150 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
6152 json_object_int_add(json
, "numRmacs", num_rmacs
);
6154 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
6157 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6158 json
, JSON_C_TO_STRING_PRETTY
));
6159 json_object_free(json
);
6163 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
6165 json_object
*json
= NULL
;
6168 if (!is_evpn_enabled()) {
6170 vty_out(vty
, "{}\n");
6175 json
= json_object_new_object();
6179 hash_iterate(zrouter
.l3vni_table
,
6180 (void (*)(struct hash_bucket
*,
6181 void *))zl3vni_print_rmac_hash_all_vni
,
6185 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6186 json
, JSON_C_TO_STRING_PRETTY
));
6187 json_object_free(json
);
6191 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
6192 struct ipaddr
*ip
, bool use_json
)
6194 zebra_l3vni_t
*zl3vni
= NULL
;
6195 zebra_neigh_t
*n
= NULL
;
6196 json_object
*json
= NULL
;
6198 if (!is_evpn_enabled()) {
6200 vty_out(vty
, "{}\n");
6205 json
= json_object_new_object();
6207 zl3vni
= zl3vni_lookup(l3vni
);
6210 vty_out(vty
, "{}\n");
6212 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6216 n
= zl3vni_nh_lookup(zl3vni
, ip
);
6219 vty_out(vty
, "{}\n");
6222 "%% Requested next-hop not present for L3-VNI %u",
6227 zl3vni_print_nh(n
, vty
, json
);
6230 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6231 json
, JSON_C_TO_STRING_PRETTY
));
6232 json_object_free(json
);
6236 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
6239 struct nh_walk_ctx wctx
;
6240 json_object
*json
= NULL
;
6241 zebra_l3vni_t
*zl3vni
= NULL
;
6243 if (!is_evpn_enabled())
6246 zl3vni
= zl3vni_lookup(l3vni
);
6249 vty_out(vty
, "{}\n");
6251 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
6255 num_nh
= hashcount(zl3vni
->nh_table
);
6260 json
= json_object_new_object();
6265 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
6267 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
6269 json_object_int_add(json
, "numNextHops", num_nh
);
6271 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
6274 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6275 json
, JSON_C_TO_STRING_PRETTY
));
6276 json_object_free(json
);
6280 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
6282 json_object
*json
= NULL
;
6285 if (!is_evpn_enabled()) {
6287 vty_out(vty
, "{}\n");
6292 json
= json_object_new_object();
6296 hash_iterate(zrouter
.l3vni_table
,
6297 (void (*)(struct hash_bucket
*,
6298 void *))zl3vni_print_nh_hash_all_vni
,
6302 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6303 json
, JSON_C_TO_STRING_PRETTY
));
6304 json_object_free(json
);
6309 * Display L3 VNI information (VTY command handler).
6311 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
6314 json_object
*json
= NULL
;
6315 zebra_l3vni_t
*zl3vni
= NULL
;
6317 if (!is_evpn_enabled()) {
6319 vty_out(vty
, "{}\n");
6323 zl3vni
= zl3vni_lookup(vni
);
6326 vty_out(vty
, "{}\n");
6328 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6333 json
= json_object_new_object();
6337 zl3vni_print(zl3vni
, (void *)args
);
6340 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6341 json
, JSON_C_TO_STRING_PRETTY
));
6342 json_object_free(json
);
6346 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6347 json_object
*json_vrfs
)
6349 char buf
[ETHER_ADDR_STRLEN
];
6350 zebra_l3vni_t
*zl3vni
= NULL
;
6352 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6357 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6358 zvrf_name(zvrf
), zl3vni
->vni
,
6359 zl3vni_vxlan_if_name(zl3vni
),
6360 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6361 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6363 json_object
*json_vrf
= NULL
;
6365 json_vrf
= json_object_new_object();
6366 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6367 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6368 json_object_string_add(json_vrf
, "vxlanIntf",
6369 zl3vni_vxlan_if_name(zl3vni
));
6370 json_object_string_add(json_vrf
, "sviIntf",
6371 zl3vni_svi_if_name(zl3vni
));
6372 json_object_string_add(json_vrf
, "state",
6373 zl3vni_state2str(zl3vni
));
6374 json_object_string_add(
6375 json_vrf
, "routerMac",
6376 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6377 json_object_array_add(json_vrfs
, json_vrf
);
6382 * Display Neighbors for a VNI (VTY command handler).
6384 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6385 vni_t vni
, bool use_json
)
6389 struct neigh_walk_ctx wctx
;
6390 json_object
*json
= NULL
;
6392 if (!is_evpn_enabled())
6394 zvni
= zvni_lookup(vni
);
6397 vty_out(vty
, "{}\n");
6399 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6402 num_neigh
= hashcount(zvni
->neigh_table
);
6407 json
= json_object_new_object();
6409 /* Since we have IPv6 addresses to deal with which can vary widely in
6410 * size, we try to be a bit more elegant in display by first computing
6411 * the maximum width.
6413 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6416 wctx
.addr_width
= 15;
6418 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6422 "Number of ARPs (local and remote) known for this VNI: %u\n",
6424 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx
.addr_width
,
6425 "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s");
6427 json_object_int_add(json
, "numArpNd", num_neigh
);
6429 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6431 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6432 json
, JSON_C_TO_STRING_PRETTY
));
6433 json_object_free(json
);
6438 * Display neighbors across all VNIs (VTY command handler).
6440 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6441 bool print_dup
, bool use_json
)
6443 json_object
*json
= NULL
;
6446 if (!is_evpn_enabled())
6450 json
= json_object_new_object();
6454 args
[2] = (void *)(ptrdiff_t)print_dup
;
6456 hash_iterate(zvrf
->vni_table
,
6457 (void (*)(struct hash_bucket
*,
6458 void *))zvni_print_neigh_hash_all_vni
,
6461 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6462 json
, JSON_C_TO_STRING_PRETTY
));
6463 json_object_free(json
);
6468 * Display neighbors across all VNIs in detail(VTY command handler).
6470 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6471 struct zebra_vrf
*zvrf
,
6472 bool print_dup
, bool use_json
)
6474 json_object
*json
= NULL
;
6477 if (!is_evpn_enabled())
6481 json
= json_object_new_object();
6485 args
[2] = (void *)(ptrdiff_t)print_dup
;
6487 hash_iterate(zvrf
->vni_table
,
6488 (void (*)(struct hash_bucket
*,
6489 void *))zvni_print_neigh_hash_all_vni_detail
,
6492 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6493 json
, JSON_C_TO_STRING_PRETTY
));
6494 json_object_free(json
);
6499 * Display specific neighbor for a VNI, if present (VTY command handler).
6501 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6502 struct zebra_vrf
*zvrf
, vni_t vni
,
6503 struct ipaddr
*ip
, bool use_json
)
6507 json_object
*json
= NULL
;
6509 if (!is_evpn_enabled())
6511 zvni
= zvni_lookup(vni
);
6514 vty_out(vty
, "{}\n");
6516 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6519 n
= zvni_neigh_lookup(zvni
, ip
);
6523 "%% Requested neighbor does not exist in VNI %u\n",
6528 json
= json_object_new_object();
6530 zvni_print_neigh(n
, vty
, json
);
6533 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6534 json
, JSON_C_TO_STRING_PRETTY
));
6535 json_object_free(json
);
6540 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6541 * By definition, these are remote neighbors.
6543 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6544 vni_t vni
, struct in_addr vtep_ip
,
6549 struct neigh_walk_ctx wctx
;
6550 json_object
*json
= NULL
;
6552 if (!is_evpn_enabled())
6554 zvni
= zvni_lookup(vni
);
6557 vty_out(vty
, "{}\n");
6559 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6562 num_neigh
= hashcount(zvni
->neigh_table
);
6566 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6569 wctx
.addr_width
= 15;
6570 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6571 wctx
.r_vtep_ip
= vtep_ip
;
6573 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6574 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6577 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6578 json
, JSON_C_TO_STRING_PRETTY
));
6579 json_object_free(json
);
6584 * Display Duplicate detected Neighbors for a VNI
6585 * (VTY command handler).
6587 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6588 struct zebra_vrf
*zvrf
,
6594 struct neigh_walk_ctx wctx
;
6595 json_object
*json
= NULL
;
6597 if (!is_evpn_enabled())
6600 zvni
= zvni_lookup(vni
);
6602 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6606 num_neigh
= hashcount(zvni
->neigh_table
);
6610 num_neigh
= num_dup_detected_neighs(zvni
);
6615 json
= json_object_new_object();
6617 /* Since we have IPv6 addresses to deal with which can vary widely in
6618 * size, we try to be a bit more elegant in display by first computing
6619 * the maximum width.
6621 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6624 wctx
.addr_width
= 15;
6626 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6630 "Number of ARPs (local and remote) known for this VNI: %u\n",
6632 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6633 -wctx
.addr_width
, "IP", "Type",
6634 "State", "MAC", "Remote VTEP");
6636 json_object_int_add(json
, "numArpNd", num_neigh
);
6638 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6641 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6642 json
, JSON_C_TO_STRING_PRETTY
));
6643 json_object_free(json
);
6648 * Display MACs for a VNI (VTY command handler).
6650 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6651 vni_t vni
, bool use_json
)
6655 struct mac_walk_ctx wctx
;
6656 json_object
*json
= NULL
;
6657 json_object
*json_mac
= NULL
;
6659 if (!is_evpn_enabled())
6661 zvni
= zvni_lookup(vni
);
6664 vty_out(vty
, "{}\n");
6666 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6669 num_macs
= num_valid_macs(zvni
);
6674 json
= json_object_new_object();
6675 json_mac
= json_object_new_object();
6678 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6681 wctx
.json
= json_mac
;
6685 "Number of MACs (local and remote) known for this VNI: %u\n",
6687 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type",
6688 "Intf/Remote VTEP", "VLAN", "Seq #'s");
6690 json_object_int_add(json
, "numMacs", num_macs
);
6692 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6695 json_object_object_add(json
, "macs", json_mac
);
6696 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6697 json
, JSON_C_TO_STRING_PRETTY
));
6698 json_object_free(json
);
6703 * Display MACs for all VNIs (VTY command handler).
6705 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6706 bool print_dup
, bool use_json
)
6708 struct mac_walk_ctx wctx
;
6709 json_object
*json
= NULL
;
6711 if (!is_evpn_enabled()) {
6713 vty_out(vty
, "{}\n");
6717 json
= json_object_new_object();
6719 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6722 wctx
.print_dup
= print_dup
;
6723 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6726 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6727 json
, JSON_C_TO_STRING_PRETTY
));
6728 json_object_free(json
);
6733 * Display MACs in detail for all VNIs (VTY command handler).
6735 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6736 struct zebra_vrf
*zvrf
,
6737 bool print_dup
, bool use_json
)
6739 struct mac_walk_ctx wctx
;
6740 json_object
*json
= NULL
;
6742 if (!is_evpn_enabled()) {
6744 vty_out(vty
, "{}\n");
6748 json
= json_object_new_object();
6750 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6753 wctx
.print_dup
= print_dup
;
6754 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6758 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6759 json
, JSON_C_TO_STRING_PRETTY
));
6760 json_object_free(json
);
6765 * Display MACs for all VNIs (VTY command handler).
6767 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6768 struct zebra_vrf
*zvrf
,
6769 struct in_addr vtep_ip
, bool use_json
)
6771 struct mac_walk_ctx wctx
;
6772 json_object
*json
= NULL
;
6774 if (!is_evpn_enabled())
6778 json
= json_object_new_object();
6780 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6782 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6783 wctx
.r_vtep_ip
= vtep_ip
;
6785 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6788 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6789 json
, JSON_C_TO_STRING_PRETTY
));
6790 json_object_free(json
);
6795 * Display specific MAC for a VNI, if present (VTY command handler).
6797 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6798 vni_t vni
, struct ethaddr
*macaddr
,
6803 json_object
*json
= NULL
;
6805 if (!is_evpn_enabled())
6808 zvni
= zvni_lookup(vni
);
6811 vty_out(vty
, "{}\n");
6813 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6816 mac
= zvni_mac_lookup(zvni
, macaddr
);
6819 vty_out(vty
, "{}\n");
6822 "%% Requested MAC does not exist in VNI %u\n",
6828 json
= json_object_new_object();
6830 zvni_print_mac(mac
, vty
, json
);
6832 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6833 json
, JSON_C_TO_STRING_PRETTY
));
6834 json_object_free(json
);
6838 /* Print Duplicate MACs per VNI */
6839 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6840 struct zebra_vrf
*zvrf
,
6841 vni_t vni
, bool use_json
)
6844 struct mac_walk_ctx wctx
;
6846 json_object
*json
= NULL
;
6847 json_object
*json_mac
= NULL
;
6849 if (!is_evpn_enabled())
6852 zvni
= zvni_lookup(vni
);
6854 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6858 num_macs
= num_valid_macs(zvni
);
6862 num_macs
= num_dup_detected_macs(zvni
);
6867 json
= json_object_new_object();
6868 json_mac
= json_object_new_object();
6871 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6874 wctx
.json
= json_mac
;
6878 "Number of MACs (local and remote) known for this VNI: %u\n",
6880 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6881 "Intf/Remote VTEP", "VLAN");
6883 json_object_int_add(json
, "numMacs", num_macs
);
6885 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6888 json_object_object_add(json
, "macs", json_mac
);
6889 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6890 json
, JSON_C_TO_STRING_PRETTY
));
6891 json_object_free(json
);
6896 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6897 struct zebra_vrf
*zvrf
,
6898 vni_t vni
, struct ethaddr
*macaddr
)
6902 struct listnode
*node
= NULL
;
6903 zebra_neigh_t
*nbr
= NULL
;
6905 if (!is_evpn_enabled())
6908 zvni
= zvni_lookup(vni
);
6910 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6914 mac
= zvni_mac_lookup(zvni
, macaddr
);
6916 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6921 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6922 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6926 /* Remove all IPs as duplicate associcated with this MAC */
6927 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6928 /* For local neigh mark inactive so MACIP update is generated
6929 * to BGP. This is a scenario where MAC update received
6930 * and detected as duplicate which marked neigh as duplicate.
6931 * Later local neigh update did not get a chance to relay
6932 * to BGP. Similarly remote macip update, neigh needs to be
6933 * installed locally.
6935 if (zvrf
->dad_freeze
&&
6936 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6937 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6938 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6939 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6940 zvni_neigh_install(zvni
, nbr
);
6943 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6945 nbr
->detect_start_time
.tv_sec
= 0;
6946 nbr
->dad_dup_detect_time
= 0;
6949 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6951 mac
->detect_start_time
.tv_sec
= 0;
6952 mac
->detect_start_time
.tv_usec
= 0;
6953 mac
->dad_dup_detect_time
= 0;
6954 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6956 /* warn-only action return */
6957 if (!zvrf
->dad_freeze
)
6960 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6961 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6963 if (zvni_mac_send_add_to_client(zvni
->vni
,
6969 /* Process all neighbors associated with this MAC. */
6970 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6972 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6973 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6975 /* Install the entry. */
6976 zvni_mac_install(zvni
, mac
);
6982 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6983 struct zebra_vrf
*zvrf
,
6984 vni_t vni
, struct ipaddr
*ip
)
6989 char buf
[INET6_ADDRSTRLEN
];
6990 char buf2
[ETHER_ADDR_STRLEN
];
6992 if (!is_evpn_enabled())
6995 zvni
= zvni_lookup(vni
);
6997 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7001 nbr
= zvni_neigh_lookup(zvni
, ip
);
7004 "%% Requested host IP does not exist in VNI %u\n",
7009 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
7011 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
7013 "%% Requested host IP %s is not duplicate detected\n",
7018 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
7020 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
7022 "%% Requested IP's associated MAC %s is still in duplicate state\n",
7023 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
7024 return CMD_WARNING_CONFIG_FAILED
;
7027 if (IS_ZEBRA_DEBUG_VXLAN
)
7028 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
7029 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
7032 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7034 nbr
->detect_start_time
.tv_sec
= 0;
7035 nbr
->detect_start_time
.tv_usec
= 0;
7036 nbr
->dad_dup_detect_time
= 0;
7037 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
7039 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7040 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
7042 nbr
->flags
, nbr
->loc_seq
);
7043 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7044 zvni_neigh_install(zvni
, nbr
);
7050 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
7052 struct mac_walk_ctx
*wctx
= ctxt
;
7055 struct listnode
*node
= NULL
;
7056 zebra_neigh_t
*nbr
= NULL
;
7058 mac
= (zebra_mac_t
*)bucket
->data
;
7064 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
7067 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
7069 mac
->detect_start_time
.tv_sec
= 0;
7070 mac
->detect_start_time
.tv_usec
= 0;
7071 mac
->dad_dup_detect_time
= 0;
7072 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
7074 /* Remove all IPs as duplicate associcated with this MAC */
7075 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
7076 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
7078 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
7080 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7082 nbr
->detect_start_time
.tv_sec
= 0;
7083 nbr
->dad_dup_detect_time
= 0;
7086 /* Local: Notify Peer VTEPs, Remote: Install the entry */
7087 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7089 if (zvni_mac_send_add_to_client(zvni
->vni
,
7091 mac
->flags
, mac
->loc_seq
))
7094 /* Process all neighbors associated with this MAC. */
7095 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7097 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7098 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
7100 /* Install the entry. */
7101 zvni_mac_install(zvni
, mac
);
7105 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
7107 struct neigh_walk_ctx
*wctx
= ctxt
;
7110 char buf
[INET6_ADDRSTRLEN
];
7112 nbr
= (zebra_neigh_t
*)bucket
->data
;
7118 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7121 if (IS_ZEBRA_DEBUG_VXLAN
) {
7122 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
7124 "%s: clear neigh %s dup state, flags 0x%x seq %u",
7125 __PRETTY_FUNCTION__
, buf
,
7126 nbr
->flags
, nbr
->loc_seq
);
7129 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
7131 nbr
->detect_start_time
.tv_sec
= 0;
7132 nbr
->detect_start_time
.tv_usec
= 0;
7133 nbr
->dad_dup_detect_time
= 0;
7134 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
7136 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7137 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
7139 nbr
->flags
, nbr
->loc_seq
);
7140 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7141 zvni_neigh_install(zvni
, nbr
);
7145 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
7150 struct zebra_vrf
*zvrf
;
7151 struct mac_walk_ctx m_wctx
;
7152 struct neigh_walk_ctx n_wctx
;
7154 zvni
= (zebra_vni_t
*)bucket
->data
;
7158 vty
= (struct vty
*)args
[0];
7159 zvrf
= (struct zebra_vrf
*)args
[1];
7161 if (hashcount(zvni
->neigh_table
)) {
7162 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7166 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7170 if (num_valid_macs(zvni
)) {
7171 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7175 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7180 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
7181 struct zebra_vrf
*zvrf
)
7185 if (!is_evpn_enabled())
7191 hash_iterate(zvrf
->vni_table
,
7192 (void (*)(struct hash_bucket
*, void *))
7193 zvni_clear_dup_detect_hash_vni_all
, args
);
7198 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
7199 struct zebra_vrf
*zvrf
,
7203 struct mac_walk_ctx m_wctx
;
7204 struct neigh_walk_ctx n_wctx
;
7206 if (!is_evpn_enabled())
7209 zvni
= zvni_lookup(vni
);
7211 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7215 if (hashcount(zvni
->neigh_table
)) {
7216 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
7220 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
7224 if (num_valid_macs(zvni
)) {
7225 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
7229 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
7236 * Display MACs for a VNI from specific VTEP (VTY command handler).
7238 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7239 vni_t vni
, struct in_addr vtep_ip
,
7244 struct mac_walk_ctx wctx
;
7245 json_object
*json
= NULL
;
7246 json_object
*json_mac
= NULL
;
7248 if (!is_evpn_enabled())
7250 zvni
= zvni_lookup(vni
);
7253 vty_out(vty
, "{}\n");
7255 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7258 num_macs
= num_valid_macs(zvni
);
7263 json
= json_object_new_object();
7264 json_mac
= json_object_new_object();
7267 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
7270 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
7271 wctx
.r_vtep_ip
= vtep_ip
;
7272 wctx
.json
= json_mac
;
7273 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
7276 json_object_int_add(json
, "numMacs", wctx
.count
);
7278 json_object_object_add(json
, "macs", json_mac
);
7279 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7280 json
, JSON_C_TO_STRING_PRETTY
));
7281 json_object_free(json
);
7287 * Display VNI information (VTY command handler).
7289 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
7292 json_object
*json
= NULL
;
7294 zebra_l3vni_t
*zl3vni
= NULL
;
7295 zebra_vni_t
*zvni
= NULL
;
7297 if (!is_evpn_enabled())
7301 json
= json_object_new_object();
7305 zl3vni
= zl3vni_lookup(vni
);
7307 zl3vni_print(zl3vni
, (void *)args
);
7309 zvni
= zvni_lookup(vni
);
7312 vty_out(vty
, "{}\n");
7314 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7318 zvni_print(zvni
, (void *)args
);
7322 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7323 json
, JSON_C_TO_STRING_PRETTY
));
7324 json_object_free(json
);
7328 /* Display all global details for EVPN */
7329 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7334 json_object
*json
= NULL
;
7335 struct zebra_vrf
*zvrf
= NULL
;
7337 if (!is_evpn_enabled())
7340 zvrf
= zebra_vrf_get_evpn();
7344 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7345 num_l2vnis
= hashcount(zvrf
->vni_table
);
7346 num_vnis
= num_l2vnis
+ num_l3vnis
;
7349 json
= json_object_new_object();
7350 json_object_string_add(json
, "advertiseGatewayMacip",
7351 zvrf
->advertise_gw_macip
? "Yes" : "No");
7352 json_object_int_add(json
, "numVnis", num_vnis
);
7353 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7354 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7355 if (zvrf
->dup_addr_detect
)
7356 json_object_boolean_true_add(json
,
7357 "isDuplicateAddrDetection");
7359 json_object_boolean_false_add(json
,
7360 "isDuplicateAddrDetection");
7361 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7362 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7363 json_object_int_add(json
, "detectionFreezeTime",
7364 zvrf
->dad_freeze_time
);
7367 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7368 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7369 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7370 zvrf
->advertise_gw_macip
? "Yes" : "No");
7371 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7372 zvrf
->advertise_svi_macip
? "Yes" : "No");
7373 vty_out(vty
, "Duplicate address detection: %s\n",
7374 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7375 vty_out(vty
, " Detection max-moves %u, time %d\n",
7376 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7377 if (zvrf
->dad_freeze
) {
7378 if (zvrf
->dad_freeze_time
)
7379 vty_out(vty
, " Detection freeze %u\n",
7380 zvrf
->dad_freeze_time
);
7382 vty_out(vty
, " Detection freeze %s\n",
7388 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7389 json
, JSON_C_TO_STRING_PRETTY
));
7390 json_object_free(json
);
7395 * Display VNI hash table (VTY command handler).
7397 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7400 json_object
*json
= NULL
;
7403 if (!is_evpn_enabled())
7407 json
= json_object_new_object();
7409 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7410 "Type", "VxLAN IF", "# MACs", "# ARPs",
7411 "# Remote VTEPs", "Tenant VRF");
7416 /* Display all L2-VNIs */
7417 hash_iterate(zvrf
->vni_table
,
7418 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7421 /* Display all L3-VNIs */
7422 hash_iterate(zrouter
.l3vni_table
,
7423 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7427 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7428 json
, JSON_C_TO_STRING_PRETTY
));
7429 json_object_free(json
);
7433 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7437 uint32_t max_moves
= 0;
7438 uint32_t freeze_time
= 0;
7439 bool dup_addr_detect
= false;
7440 bool freeze
= false;
7443 STREAM_GETL(s
, dup_addr_detect
);
7444 STREAM_GETL(s
, time
);
7445 STREAM_GETL(s
, max_moves
);
7446 STREAM_GETL(s
, freeze
);
7447 STREAM_GETL(s
, freeze_time
);
7449 /* DAD previous state was enabled, and new state is disable,
7450 * clear all duplicate detected addresses.
7452 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7453 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7455 zvrf
->dup_addr_detect
= dup_addr_detect
;
7456 zvrf
->dad_time
= time
;
7457 zvrf
->dad_max_moves
= max_moves
;
7458 zvrf
->dad_freeze
= freeze
;
7459 zvrf
->dad_freeze_time
= freeze_time
;
7461 if (IS_ZEBRA_DEBUG_VXLAN
)
7463 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7464 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7465 zvrf
->dup_addr_detect
? "enable" : "disable",
7466 zvrf
->dad_max_moves
,
7468 zvrf
->dad_freeze
? "enable" : "disable",
7469 zvrf
->dad_freeze_time
);
7476 * Display VNI hash table in detail(VTY command handler).
7478 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7481 json_object
*json
= NULL
;
7482 struct zebra_ns
*zns
= NULL
;
7483 struct zvni_evpn_show zes
;
7485 if (!is_evpn_enabled())
7488 zns
= zebra_ns_lookup(NS_DEFAULT
);
7494 json
= json_object_new_object();
7500 /* Display all L2-VNIs */
7503 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7506 /* Display all L3-VNIs */
7507 hash_iterate(zrouter
.l3vni_table
,
7508 (void (*)(struct hash_bucket
*,
7509 void *))zl3vni_print_hash_detail
,
7513 vty_out(vty
, "%s\n",
7514 json_object_to_json_string_ext(
7515 json
, JSON_C_TO_STRING_PRETTY
));
7516 json_object_free(json
);
7521 * Handle neighbor delete notification from the kernel (on a VLAN device
7522 * / L3 interface). This may result in either the neighbor getting deleted
7523 * from our database or being re-added to the kernel (if it is a valid
7526 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7527 struct interface
*link_if
,
7530 char buf
[INET6_ADDRSTRLEN
];
7531 char buf2
[ETHER_ADDR_STRLEN
];
7532 zebra_neigh_t
*n
= NULL
;
7533 zebra_vni_t
*zvni
= NULL
;
7534 zebra_mac_t
*zmac
= NULL
;
7535 zebra_l3vni_t
*zl3vni
= NULL
;
7536 struct zebra_vrf
*zvrf
;
7538 /* check if this is a remote neigh entry corresponding to remote
7541 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7543 return zl3vni_local_nh_del(zl3vni
, ip
);
7545 /* We are only interested in neighbors on an SVI that resides on top
7546 * of a VxLAN bridge.
7548 zvni
= zvni_from_svi(ifp
, link_if
);
7550 if (IS_ZEBRA_DEBUG_VXLAN
)
7551 zlog_debug("%s: Del neighbor %s VNI is not present for interface %s",
7552 __PRETTY_FUNCTION__
,
7553 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
);
7557 if (!zvni
->vxlan_if
) {
7559 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7564 if (IS_ZEBRA_DEBUG_VXLAN
)
7565 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7566 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7567 ifp
->ifindex
, zvni
->vni
);
7569 /* If entry doesn't exist, nothing to do. */
7570 n
= zvni_neigh_lookup(zvni
, ip
);
7574 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7576 if (IS_ZEBRA_DEBUG_VXLAN
)
7578 "Trying to del a neigh %s without a mac %s on VNI %u",
7579 ipaddr2str(ip
, buf
, sizeof(buf
)),
7580 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7586 /* If it is a remote entry, the kernel has aged this out or someone has
7587 * deleted it, it needs to be re-installed as Quagga is the owner.
7589 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7590 zvni_neigh_install(zvni
, n
);
7594 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7596 zlog_debug("%s: VNI %u vrf lookup failed.",
7597 __PRETTY_FUNCTION__
, zvni
->vni
);
7601 /* In case of feeze action, if local neigh is in duplicate state,
7602 * Mark the Neigh as inactive before sending delete request to BGPd,
7603 * If BGPd has remote entry, it will re-install
7605 if (zvrf
->dad_freeze
&&
7606 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7607 ZEBRA_NEIGH_SET_INACTIVE(n
);
7609 /* Remove neighbor from BGP. */
7610 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7612 /* Delete this neighbor entry. */
7613 zvni_neigh_del(zvni
, n
);
7615 /* see if the AUTO mac needs to be deleted */
7616 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7617 && !listcount(zmac
->neigh_list
))
7618 zvni_mac_del(zvni
, zmac
);
7624 * Handle neighbor add or update notification from the kernel (on a VLAN
7625 * device / L3 interface). This is typically for a local neighbor but can
7626 * also be for a remote neighbor (e.g., ageout notification). It could
7627 * also be a "move" scenario.
7629 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7630 struct interface
*link_if
,
7632 struct ethaddr
*macaddr
,
7637 char buf
[ETHER_ADDR_STRLEN
];
7638 char buf2
[INET6_ADDRSTRLEN
];
7639 zebra_vni_t
*zvni
= NULL
;
7640 zebra_l3vni_t
*zl3vni
= NULL
;
7642 /* check if this is a remote neigh entry corresponding to remote
7645 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7647 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7649 /* We are only interested in neighbors on an SVI that resides on top
7650 * of a VxLAN bridge.
7652 zvni
= zvni_from_svi(ifp
, link_if
);
7656 if (IS_ZEBRA_DEBUG_VXLAN
)
7658 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7659 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7660 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7661 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7662 is_router
? "router " : "",
7665 /* Is this about a local neighbor or a remote one? */
7667 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7670 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7675 * Handle message from client to delete a remote MACIP for a VNI.
7677 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7681 struct ethaddr macaddr
;
7683 struct in_addr vtep_ip
;
7684 uint16_t l
= 0, ipa_len
;
7685 char buf
[ETHER_ADDR_STRLEN
];
7686 char buf1
[INET6_ADDRSTRLEN
];
7688 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7689 memset(&ip
, 0, sizeof(struct ipaddr
));
7690 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7694 while (l
< hdr
->length
) {
7695 /* Obtain each remote MACIP and process. */
7696 /* Message contains VNI, followed by MAC followed by IP (if any)
7697 * followed by remote VTEP IP.
7699 memset(&ip
, 0, sizeof(ip
));
7700 STREAM_GETL(s
, vni
);
7701 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7702 STREAM_GETL(s
, ipa_len
);
7704 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7706 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7708 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7709 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7710 l
+= IPV4_MAX_BYTELEN
;
7712 if (IS_ZEBRA_DEBUG_VXLAN
)
7714 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7716 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7717 ipa_len
? " IP " : "",
7719 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7721 zebra_route_string(client
->proto
));
7723 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7731 * Handle message from client to add a remote MACIP for a VNI. This
7732 * could be just the add of a MAC address or the add of a neighbor
7735 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7739 struct ethaddr macaddr
;
7741 struct in_addr vtep_ip
;
7742 uint16_t l
= 0, ipa_len
;
7745 char buf
[ETHER_ADDR_STRLEN
];
7746 char buf1
[INET6_ADDRSTRLEN
];
7748 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7749 memset(&ip
, 0, sizeof(struct ipaddr
));
7750 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7752 if (!EVPN_ENABLED(zvrf
)) {
7753 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7759 while (l
< hdr
->length
) {
7760 /* Obtain each remote MACIP and process. */
7761 /* Message contains VNI, followed by MAC followed by IP (if any)
7762 * followed by remote VTEP IP.
7764 memset(&ip
, 0, sizeof(ip
));
7765 STREAM_GETL(s
, vni
);
7766 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7767 STREAM_GETL(s
, ipa_len
);
7769 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7771 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7773 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7774 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7775 l
+= IPV4_MAX_BYTELEN
;
7777 /* Get flags - sticky mac and/or gateway mac */
7778 STREAM_GETC(s
, flags
);
7780 STREAM_GETL(s
, seq
);
7783 if (IS_ZEBRA_DEBUG_VXLAN
)
7785 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7787 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7788 ipa_len
? " IP " : "",
7790 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7791 flags
, seq
, inet_ntoa(vtep_ip
),
7792 zebra_route_string(client
->proto
));
7794 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7795 flags
, seq
, vtep_ip
);
7803 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7804 * us, this must involve a multihoming scenario. Treat this as implicit delete
7805 * of any prior local MAC.
7807 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7808 struct interface
*br_if
,
7809 struct ethaddr
*macaddr
, vlanid_t vid
)
7811 struct zebra_if
*zif
;
7812 struct zebra_l2info_vxlan
*vxl
;
7816 char buf
[ETHER_ADDR_STRLEN
];
7820 vxl
= &zif
->l2info
.vxl
;
7823 /* Check if EVPN is enabled. */
7824 if (!is_evpn_enabled())
7827 /* Locate hash entry; it is expected to exist. */
7828 zvni
= zvni_lookup(vni
);
7832 /* If entry doesn't exist, nothing to do. */
7833 mac
= zvni_mac_lookup(zvni
, macaddr
);
7837 /* Is it a local entry? */
7838 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7841 if (IS_ZEBRA_DEBUG_VXLAN
)
7843 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7844 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7845 ifp
->ifindex
, vni
, mac
->flags
);
7847 /* Remove MAC from BGP. */
7848 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7851 * If there are no neigh associated with the mac delete the mac
7852 * else mark it as AUTO for forward reference
7854 if (!listcount(mac
->neigh_list
)) {
7855 zvni_mac_del(zvni
, mac
);
7857 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7858 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7859 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7866 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7867 * This can happen because the remote MAC entries are also added as "dynamic",
7868 * so the kernel can ageout the entry.
7870 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7871 struct interface
*br_if
,
7872 struct ethaddr
*macaddr
, vlanid_t vid
)
7874 struct zebra_if
*zif
= NULL
;
7875 struct zebra_l2info_vxlan
*vxl
= NULL
;
7877 zebra_vni_t
*zvni
= NULL
;
7878 zebra_l3vni_t
*zl3vni
= NULL
;
7879 zebra_mac_t
*mac
= NULL
;
7880 char buf
[ETHER_ADDR_STRLEN
];
7884 vxl
= &zif
->l2info
.vxl
;
7887 /* Check if EVPN is enabled. */
7888 if (!is_evpn_enabled())
7891 /* check if this is a remote RMAC and readd simillar to remote macs */
7892 zl3vni
= zl3vni_lookup(vni
);
7894 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7896 /* Locate hash entry; it is expected to exist. */
7897 zvni
= zvni_lookup(vni
);
7901 /* If entry doesn't exist, nothing to do. */
7902 mac
= zvni_mac_lookup(zvni
, macaddr
);
7906 /* Is it a remote entry? */
7907 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7910 if (IS_ZEBRA_DEBUG_VXLAN
)
7911 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7912 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7915 zvni_mac_install(zvni
, mac
);
7920 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7922 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7923 struct ethaddr
*macaddr
, vlanid_t vid
)
7927 char buf
[ETHER_ADDR_STRLEN
];
7929 /* We are interested in MACs only on ports or (port, VLAN) that
7932 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7935 if (!zvni
->vxlan_if
) {
7937 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7942 /* If entry doesn't exist, nothing to do. */
7943 mac
= zvni_mac_lookup(zvni
, macaddr
);
7947 /* Is it a local entry? */
7948 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7951 if (IS_ZEBRA_DEBUG_VXLAN
)
7952 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
7953 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7954 ifp
->ifindex
, vid
, zvni
->vni
, mac
->loc_seq
,
7955 mac
->flags
, listcount(mac
->neigh_list
));
7957 /* Update all the neigh entries associated with this mac */
7958 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7960 /* Remove MAC from BGP. */
7961 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7964 * If there are no neigh associated with the mac delete the mac
7965 * else mark it as AUTO for forward reference
7967 if (!listcount(mac
->neigh_list
)) {
7968 zvni_mac_del(zvni
, mac
);
7970 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7971 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7972 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7979 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7981 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7982 struct interface
*br_if
,
7983 struct ethaddr
*macaddr
, vlanid_t vid
,
7988 struct zebra_vrf
*zvrf
;
7989 char buf
[ETHER_ADDR_STRLEN
];
7990 bool mac_sticky
= false;
7991 bool inform_client
= false;
7992 bool upd_neigh
= false;
7993 bool is_dup_detect
= false;
7994 struct in_addr vtep_ip
= {.s_addr
= 0};
7996 /* We are interested in MACs only on ports or (port, VLAN) that
7999 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
8001 if (IS_ZEBRA_DEBUG_VXLAN
)
8003 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
8004 sticky
? "sticky " : "",
8005 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8006 ifp
->name
, ifp
->ifindex
, vid
);
8010 if (!zvni
->vxlan_if
) {
8011 if (IS_ZEBRA_DEBUG_VXLAN
)
8013 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
8018 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
8020 if (IS_ZEBRA_DEBUG_VXLAN
)
8021 zlog_debug("\tNo Vrf found for vrf_id: %d",
8022 zvni
->vxlan_if
->vrf_id
);
8026 /* Check if we need to create or update or it is a NO-OP. */
8027 mac
= zvni_mac_lookup(zvni
, macaddr
);
8029 if (IS_ZEBRA_DEBUG_VXLAN
)
8031 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
8032 sticky
? "sticky " : "",
8033 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8034 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
8036 mac
= zvni_mac_add(zvni
, macaddr
);
8039 EC_ZEBRA_MAC_ADD_FAILED
,
8040 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
8041 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8042 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
8045 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
8046 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8047 mac
->fwd_info
.local
.vid
= vid
;
8049 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8050 inform_client
= true;
8053 if (IS_ZEBRA_DEBUG_VXLAN
)
8055 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
8056 sticky
? "sticky " : "",
8057 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
8058 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
8061 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8062 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
8066 * Update any changes and if changes are relevant to
8069 if (mac_sticky
== sticky
8070 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
8071 && mac
->fwd_info
.local
.vid
== vid
) {
8072 if (IS_ZEBRA_DEBUG_VXLAN
)
8074 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
8075 "entry exists and has not changed ",
8076 sticky
? "sticky " : "",
8077 prefix_mac2str(macaddr
, buf
,
8079 ifp
->name
, ifp
->ifindex
, vid
,
8083 if (mac_sticky
!= sticky
) {
8085 SET_FLAG(mac
->flags
,
8088 UNSET_FLAG(mac
->flags
,
8090 inform_client
= true;
8093 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
8094 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
8095 mac
->fwd_info
.local
.vid
= vid
;
8097 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
8098 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
8099 bool do_dad
= false;
8102 * MAC has either moved or was "internally" created due
8103 * to a neighbor learn and is now actually learnt. If
8104 * it was learnt as a remote sticky MAC, this is an
8107 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
8109 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
8110 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
8111 prefix_mac2str(macaddr
, buf
,
8113 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
8118 /* If an actual move, compute MAC's seq number */
8119 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8120 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
8122 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
8123 /* Trigger DAD for remote MAC */
8127 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
8128 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
8129 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
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 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8136 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
8138 * We have to inform BGP of this MAC as well as process
8141 inform_client
= true;
8144 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
8148 if (is_dup_detect
) {
8149 inform_client
= false;
8155 /* Inform BGP if required. */
8156 if (inform_client
) {
8157 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
8158 mac
->flags
, mac
->loc_seq
))
8162 /* Process all neighbors associated with this MAC, if required. */
8164 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
8170 * Handle message from client to delete a remote VTEP for a VNI.
8172 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
8175 unsigned short l
= 0;
8177 struct in_addr vtep_ip
;
8179 zebra_vtep_t
*zvtep
;
8180 struct interface
*ifp
;
8181 struct zebra_if
*zif
;
8183 if (!is_evpn_enabled()) {
8185 "%s: EVPN is not enabled yet we have received a vtep del command",
8186 __PRETTY_FUNCTION__
);
8190 if (!EVPN_ENABLED(zvrf
)) {
8191 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
8198 while (l
< hdr
->length
) {
8199 int flood_control
__attribute__((unused
));
8201 /* Obtain each remote VTEP and process. */
8202 STREAM_GETL(s
, vni
);
8204 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8205 l
+= IPV4_MAX_BYTELEN
;
8207 /* Flood control is intentionally ignored right now */
8208 STREAM_GETL(s
, flood_control
);
8211 if (IS_ZEBRA_DEBUG_VXLAN
)
8212 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
8213 inet_ntoa(vtep_ip
), vni
,
8214 zebra_route_string(client
->proto
));
8216 /* Locate VNI hash entry - expected to exist. */
8217 zvni
= zvni_lookup(vni
);
8219 if (IS_ZEBRA_DEBUG_VXLAN
)
8221 "Failed to locate VNI hash upon remote VTEP DEL, "
8227 ifp
= zvni
->vxlan_if
;
8230 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
8236 /* If down or not mapped to a bridge, we're done. */
8237 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8240 /* If the remote VTEP does not exist, there's nothing more to
8242 * Otherwise, uninstall any remote MACs pointing to this VTEP
8244 * then, the VTEP entry itself and remove it.
8246 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8250 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
8251 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
8252 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8253 zvni_vtep_del(zvni
, zvtep
);
8261 * Handle message from client to add a remote VTEP for a VNI.
8263 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
8266 unsigned short l
= 0;
8268 struct in_addr vtep_ip
;
8270 struct interface
*ifp
;
8271 struct zebra_if
*zif
;
8273 zebra_vtep_t
*zvtep
;
8275 if (!is_evpn_enabled()) {
8277 "%s: EVPN not enabled yet we received a vtep_add zapi call",
8278 __PRETTY_FUNCTION__
);
8282 if (!EVPN_ENABLED(zvrf
)) {
8283 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
8290 while (l
< hdr
->length
) {
8291 /* Obtain each remote VTEP and process. */
8292 STREAM_GETL(s
, vni
);
8294 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8295 STREAM_GETL(s
, flood_control
);
8296 l
+= IPV4_MAX_BYTELEN
+ 4;
8298 if (IS_ZEBRA_DEBUG_VXLAN
)
8299 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
8300 inet_ntoa(vtep_ip
), vni
, flood_control
,
8301 zebra_route_string(client
->proto
));
8303 /* Locate VNI hash entry - expected to exist. */
8304 zvni
= zvni_lookup(vni
);
8307 EC_ZEBRA_VTEP_ADD_FAILED
,
8308 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
8313 ifp
= zvni
->vxlan_if
;
8316 EC_ZEBRA_VTEP_ADD_FAILED
,
8317 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8324 /* If down or not mapped to a bridge, we're done. */
8325 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8328 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8330 /* If the remote VTEP already exists check if
8331 * the flood mode has changed
8333 if (zvtep
->flood_control
!= flood_control
) {
8334 if (zvtep
->flood_control
8335 == VXLAN_FLOOD_DISABLED
)
8336 /* old mode was head-end-replication but
8337 * is no longer; get rid of the HER fdb
8338 * entry installed before
8340 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8341 zvtep
->flood_control
= flood_control
;
8342 zvni_vtep_install(zvni
, zvtep
);
8345 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8347 zvni_vtep_install(zvni
, zvtep
);
8349 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8350 "Failed to add remote VTEP, VNI %u zvni %p",
8360 * Add/Del gateway macip to evpn
8362 * 1. SVI interface on a vlan aware bridge
8363 * 2. SVI interface on a vlan unaware bridge
8364 * 3. vrr interface (MACVLAN) associated to a SVI
8365 * We advertise macip routes for an interface if it is associated to VxLan vlan
8367 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8371 struct ethaddr macaddr
;
8372 zebra_vni_t
*zvni
= NULL
;
8374 memset(&ip
, 0, sizeof(struct ipaddr
));
8375 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8377 /* Check if EVPN is enabled. */
8378 if (!is_evpn_enabled())
8381 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8382 struct interface
*svi_if
=
8383 NULL
; /* SVI corresponding to the MACVLAN */
8384 struct zebra_if
*ifp_zif
=
8385 NULL
; /* Zebra daemon specific info for MACVLAN */
8386 struct zebra_if
*svi_if_zif
=
8387 NULL
; /* Zebra daemon specific info for SVI*/
8389 ifp_zif
= ifp
->info
;
8394 * for a MACVLAN interface the link represents the svi_if
8396 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8397 ifp_zif
->link_ifindex
);
8399 zlog_debug("MACVLAN %s(%u) without link information",
8400 ifp
->name
, ifp
->ifindex
);
8404 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8406 * If it is a vlan aware bridge then the link gives the
8407 * bridge information
8409 struct interface
*svi_if_link
= NULL
;
8411 svi_if_zif
= svi_if
->info
;
8413 svi_if_link
= if_lookup_by_index_per_ns(
8414 zebra_ns_lookup(NS_DEFAULT
),
8415 svi_if_zif
->link_ifindex
);
8416 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8418 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8420 * If it is a vlan unaware bridge then svi is the bridge
8423 zvni
= zvni_from_svi(svi_if
, svi_if
);
8425 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8426 struct zebra_if
*svi_if_zif
=
8427 NULL
; /* Zebra daemon specific info for SVI */
8428 struct interface
*svi_if_link
=
8429 NULL
; /* link info for the SVI = bridge info */
8431 svi_if_zif
= ifp
->info
;
8433 svi_if_link
= if_lookup_by_index_per_ns(
8434 zebra_ns_lookup(NS_DEFAULT
),
8435 svi_if_zif
->link_ifindex
);
8437 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8439 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8440 zvni
= zvni_from_svi(ifp
, ifp
);
8446 if (!zvni
->vxlan_if
) {
8447 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8453 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8455 if (p
->family
== AF_INET
) {
8456 ip
.ipa_type
= IPADDR_V4
;
8457 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8458 sizeof(struct in_addr
));
8459 } else if (p
->family
== AF_INET6
) {
8460 ip
.ipa_type
= IPADDR_V6
;
8461 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8462 sizeof(struct in6_addr
));
8467 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8469 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8475 * Handle SVI interface going down.
8476 * SVI can be associated to either L3-VNI or L2-VNI.
8477 * For L2-VNI: At this point, this is a NOP since
8478 * the kernel deletes the neighbor entries on this SVI (if any).
8479 * We only need to update the vrf corresponding to zvni.
8480 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8483 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8485 zebra_l3vni_t
*zl3vni
= NULL
;
8487 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8490 /* process l3-vni down */
8491 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8493 /* remove association with svi-if */
8494 zl3vni
->svi_if
= NULL
;
8496 zebra_vni_t
*zvni
= NULL
;
8498 /* since we dont have svi corresponding to zvni, we associate it
8499 * to default vrf. Note: the corresponding neigh entries on the
8500 * SVI would have already been deleted */
8501 zvni
= zvni_from_svi(ifp
, link_if
);
8503 zvni
->vrf_id
= VRF_DEFAULT
;
8505 /* update the tenant vrf in BGP */
8506 zvni_send_add_to_client(zvni
);
8513 * Handle SVI interface coming up.
8514 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8516 * For L2-VNI: we need to install any remote neighbors entried (used for
8518 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8520 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8522 zebra_vni_t
*zvni
= NULL
;
8523 zebra_l3vni_t
*zl3vni
= NULL
;
8525 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8528 /* associate with svi */
8529 zl3vni
->svi_if
= ifp
;
8531 /* process oper-up */
8532 if (is_l3vni_oper_up(zl3vni
))
8533 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8536 /* process SVI up for l2-vni */
8537 struct neigh_walk_ctx n_wctx
;
8539 zvni
= zvni_from_svi(ifp
, link_if
);
8543 if (!zvni
->vxlan_if
) {
8545 "VNI %u hash %p doesn't have intf upon SVI up",
8550 if (IS_ZEBRA_DEBUG_VXLAN
)
8552 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8553 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8554 vrf_id_to_name(ifp
->vrf_id
));
8556 /* update the vrf information for l2-vni and inform bgp */
8557 zvni
->vrf_id
= ifp
->vrf_id
;
8558 zvni_send_add_to_client(zvni
);
8560 /* Install any remote neighbors for this VNI. */
8561 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8563 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8571 * Handle MAC-VLAN interface going down.
8572 * L3VNI: When MAC-VLAN interface goes down,
8573 * find its associated SVI and update type2/type-5 routes
8576 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
8578 zebra_l3vni_t
*zl3vni
= NULL
;
8579 struct zebra_if
*zif
, *link_zif
;
8580 struct interface
*link_ifp
, *link_if
;
8584 link_ifp
= zif
->link
;
8586 if (IS_ZEBRA_DEBUG_VXLAN
)
8587 zlog_debug("macvlan %s parent link is not found. Parent index %d ifp %s",
8588 ifp
->name
, zif
->link_ifindex
,
8589 if_lookup_by_index_all_vrf(zif
->link_ifindex
));
8592 link_zif
= link_ifp
->info
;
8595 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8596 link_zif
->link_ifindex
);
8598 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
8600 zl3vni
->mac_vlan_if
= NULL
;
8601 if (is_l3vni_oper_up(zl3vni
))
8602 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8607 * Handle MAC-VLAN interface going up.
8608 * L3VNI: When MAC-VLAN interface comes up,
8609 * find its associated SVI and update type-2 routes
8610 * with MAC-VLAN's MAC as RMAC and for type-5 routes
8611 * use SVI's MAC as RMAC.
8613 void zebra_vxlan_macvlan_up(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
;
8622 link_zif
= link_ifp
->info
;
8625 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8626 link_zif
->link_ifindex
);
8627 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
8629 /* associate with macvlan (VRR) interface */
8630 zl3vni
->mac_vlan_if
= ifp
;
8632 /* process oper-up */
8633 if (is_l3vni_oper_up(zl3vni
))
8634 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8639 * Handle VxLAN interface down
8641 int zebra_vxlan_if_down(struct interface
*ifp
)
8644 struct zebra_if
*zif
= NULL
;
8645 struct zebra_l2info_vxlan
*vxl
= NULL
;
8646 zebra_l3vni_t
*zl3vni
= NULL
;
8649 /* Check if EVPN is enabled. */
8650 if (!is_evpn_enabled())
8655 vxl
= &zif
->l2info
.vxl
;
8658 zl3vni
= zl3vni_lookup(vni
);
8660 /* process-if-down for l3-vni */
8661 if (IS_ZEBRA_DEBUG_VXLAN
)
8662 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8665 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8667 /* process if-down for l2-vni */
8668 if (IS_ZEBRA_DEBUG_VXLAN
)
8669 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8672 /* Locate hash entry; it is expected to exist. */
8673 zvni
= zvni_lookup(vni
);
8676 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8677 ifp
->name
, ifp
->ifindex
, vni
);
8681 assert(zvni
->vxlan_if
== ifp
);
8683 /* Delete this VNI from BGP. */
8684 zvni_send_del_to_client(zvni
->vni
);
8686 /* Free up all neighbors and MACs, if any. */
8687 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8688 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8690 /* Free up all remote VTEPs, if any. */
8691 zvni_vtep_del_all(zvni
, 1);
8697 * Handle VxLAN interface up - update BGP if required.
8699 int zebra_vxlan_if_up(struct interface
*ifp
)
8702 struct zebra_if
*zif
= NULL
;
8703 struct zebra_l2info_vxlan
*vxl
= NULL
;
8704 zebra_vni_t
*zvni
= NULL
;
8705 zebra_l3vni_t
*zl3vni
= NULL
;
8707 /* Check if EVPN is enabled. */
8708 if (!is_evpn_enabled())
8713 vxl
= &zif
->l2info
.vxl
;
8716 zl3vni
= zl3vni_lookup(vni
);
8718 /* we need to associate with SVI, if any, we can associate with
8719 * svi-if only after association with vxlan-intf is complete
8721 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8722 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
8724 if (IS_ZEBRA_DEBUG_VXLAN
)
8725 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
8726 , ifp
->name
, ifp
->ifindex
, vni
,
8727 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
8728 zl3vni
->mac_vlan_if
?
8729 zl3vni
->mac_vlan_if
->name
: "NIL");
8731 if (is_l3vni_oper_up(zl3vni
))
8732 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8734 /* Handle L2-VNI add */
8735 struct interface
*vlan_if
= NULL
;
8737 if (IS_ZEBRA_DEBUG_VXLAN
)
8738 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8741 /* Locate hash entry; it is expected to exist. */
8742 zvni
= zvni_lookup(vni
);
8745 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8746 ifp
->name
, ifp
->ifindex
, vni
);
8750 assert(zvni
->vxlan_if
== ifp
);
8751 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8752 zif
->brslave_info
.br_if
);
8754 zvni
->vrf_id
= vlan_if
->vrf_id
;
8755 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8757 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8760 /* If part of a bridge, inform BGP about this VNI. */
8761 /* Also, read and populate local MACs and neighbors. */
8762 if (zif
->brslave_info
.br_if
) {
8763 zvni_send_add_to_client(zvni
);
8764 zvni_read_mac_neigh(zvni
, ifp
);
8772 * Handle VxLAN interface delete. Locate and remove entry in hash table
8773 * and update BGP, if required.
8775 int zebra_vxlan_if_del(struct interface
*ifp
)
8778 struct zebra_if
*zif
= NULL
;
8779 struct zebra_l2info_vxlan
*vxl
= NULL
;
8780 zebra_vni_t
*zvni
= NULL
;
8781 zebra_l3vni_t
*zl3vni
= NULL
;
8783 /* Check if EVPN is enabled. */
8784 if (!is_evpn_enabled())
8789 vxl
= &zif
->l2info
.vxl
;
8792 zl3vni
= zl3vni_lookup(vni
);
8795 if (IS_ZEBRA_DEBUG_VXLAN
)
8796 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8799 /* process oper-down for l3-vni */
8800 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8802 /* remove the association with vxlan_if */
8803 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8804 zl3vni
->vxlan_if
= NULL
;
8807 /* process if-del for l2-vni*/
8808 if (IS_ZEBRA_DEBUG_VXLAN
)
8809 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8812 /* Locate hash entry; it is expected to exist. */
8813 zvni
= zvni_lookup(vni
);
8816 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8817 ifp
->name
, ifp
->ifindex
, vni
);
8821 /* remove from l3-vni list */
8822 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8824 listnode_delete(zl3vni
->l2vnis
, zvni
);
8826 /* Delete VNI from BGP. */
8827 zvni_send_del_to_client(zvni
->vni
);
8829 /* Free up all neighbors and MAC, if any. */
8830 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8831 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8833 /* Free up all remote VTEPs, if any. */
8834 zvni_vtep_del_all(zvni
, 0);
8836 /* Delete the hash entry. */
8837 if (zvni_del(zvni
)) {
8838 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8839 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8840 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8848 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8850 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8853 struct zebra_if
*zif
= NULL
;
8854 struct zebra_l2info_vxlan
*vxl
= NULL
;
8855 zebra_vni_t
*zvni
= NULL
;
8856 zebra_l3vni_t
*zl3vni
= NULL
;
8858 /* Check if EVPN is enabled. */
8859 if (!is_evpn_enabled())
8864 vxl
= &zif
->l2info
.vxl
;
8867 zl3vni
= zl3vni_lookup(vni
);
8870 if (IS_ZEBRA_DEBUG_VXLAN
)
8872 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8873 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8874 inet_ntoa(vxl
->vtep_ip
),
8875 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8877 /* Removed from bridge? Cleanup and return */
8878 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8879 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8880 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8884 /* access-vlan change - process oper down, associate with new
8885 * svi_if and then process oper up again
8887 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8888 if (if_is_operative(ifp
)) {
8889 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8890 zl3vni
->svi_if
= NULL
;
8891 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8892 zl3vni
->mac_vlan_if
=
8893 zl3vni_map_to_mac_vlan_if(zl3vni
);
8894 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8895 if (is_l3vni_oper_up(zl3vni
))
8896 zebra_vxlan_process_l3vni_oper_up(
8902 * local-ip change - process oper down, associate with new
8903 * local-ip and then process oper up again
8905 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8906 if (if_is_operative(ifp
)) {
8907 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8908 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8909 if (is_l3vni_oper_up(zl3vni
))
8910 zebra_vxlan_process_l3vni_oper_up(
8915 /* Update local tunnel IP. */
8916 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8918 /* if we have a valid new master, process l3-vni oper up */
8919 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8920 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8921 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8925 /* Update VNI hash. */
8926 zvni
= zvni_lookup(vni
);
8929 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8930 ifp
->name
, ifp
->ifindex
, vni
);
8934 if (IS_ZEBRA_DEBUG_VXLAN
)
8936 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8937 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8938 inet_ntoa(vxl
->vtep_ip
),
8939 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8941 /* Removed from bridge? Cleanup and return */
8942 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8943 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8944 /* Delete from client, remove all remote VTEPs */
8945 /* Also, free up all MACs and neighbors. */
8946 zvni_send_del_to_client(zvni
->vni
);
8947 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8948 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8949 zvni_vtep_del_all(zvni
, 1);
8953 /* Handle other changes. */
8954 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8955 /* Remove all existing local neigh and MACs for this VNI
8956 * (including from BGP)
8958 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8959 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8962 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8963 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8964 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8966 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8967 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8968 zvni
->mcast_grp
= vxl
->mcast_grp
;
8970 zvni
->vxlan_if
= ifp
;
8972 /* Take further actions needed.
8973 * Note that if we are here, there is a change of interest.
8975 /* If down or not mapped to a bridge, we're done. */
8976 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8979 /* Inform BGP, if there is a change of interest. */
8981 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8982 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8983 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8984 zvni_send_add_to_client(zvni
);
8986 /* If there is a valid new master or a VLAN mapping change,
8987 * read and populate local MACs and neighbors.
8988 * Also, reinstall any remote MACs and neighbors
8989 * for this VNI (based on new VLAN).
8991 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8992 zvni_read_mac_neigh(zvni
, ifp
);
8993 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8994 struct mac_walk_ctx m_wctx
;
8995 struct neigh_walk_ctx n_wctx
;
8997 zvni_read_mac_neigh(zvni
, ifp
);
8999 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
9001 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
9004 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
9006 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
9015 * Handle VxLAN interface add.
9017 int zebra_vxlan_if_add(struct interface
*ifp
)
9020 struct zebra_if
*zif
= NULL
;
9021 struct zebra_l2info_vxlan
*vxl
= NULL
;
9022 zebra_vni_t
*zvni
= NULL
;
9023 zebra_l3vni_t
*zl3vni
= NULL
;
9025 /* Check if EVPN is enabled. */
9026 if (!is_evpn_enabled())
9031 vxl
= &zif
->l2info
.vxl
;
9034 zl3vni
= zl3vni_lookup(vni
);
9037 /* process if-add for l3-vni*/
9038 if (IS_ZEBRA_DEBUG_VXLAN
)
9040 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
9041 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
9042 inet_ntoa(vxl
->vtep_ip
),
9043 zif
->brslave_info
.bridge_ifindex
);
9045 /* associate with vxlan_if */
9046 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
9047 zl3vni
->vxlan_if
= ifp
;
9049 /* Associate with SVI, if any. We can associate with svi-if only
9050 * after association with vxlan_if is complete */
9051 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
9053 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
9055 if (is_l3vni_oper_up(zl3vni
))
9056 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9059 /* process if-add for l2-vni */
9060 struct interface
*vlan_if
= NULL
;
9062 /* Create or update VNI hash. */
9063 zvni
= zvni_lookup(vni
);
9065 zvni
= zvni_add(vni
);
9068 EC_ZEBRA_VNI_ADD_FAILED
,
9069 "Failed to add VNI hash, IF %s(%u) VNI %u",
9070 ifp
->name
, ifp
->ifindex
, vni
);
9075 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
9076 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
9077 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
9079 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
9080 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
9081 zvni
->mcast_grp
= vxl
->mcast_grp
;
9083 zvni
->vxlan_if
= ifp
;
9084 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
9085 zif
->brslave_info
.br_if
);
9087 zvni
->vrf_id
= vlan_if
->vrf_id
;
9088 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
9090 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
9093 if (IS_ZEBRA_DEBUG_VXLAN
) {
9094 char addr_buf1
[INET_ADDRSTRLEN
];
9095 char addr_buf2
[INET_ADDRSTRLEN
];
9097 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
9098 addr_buf1
, INET_ADDRSTRLEN
);
9099 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
9100 addr_buf2
, INET_ADDRSTRLEN
);
9103 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
9105 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
9107 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
9108 addr_buf1
, addr_buf2
,
9109 zif
->brslave_info
.bridge_ifindex
);
9112 /* If down or not mapped to a bridge, we're done. */
9113 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9117 zvni_send_add_to_client(zvni
);
9119 /* Read and populate local MACs and neighbors */
9120 zvni_read_mac_neigh(zvni
, ifp
);
9126 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
9127 char *err
, int err_str_sz
, int filter
,
9130 zebra_l3vni_t
*zl3vni
= NULL
;
9131 struct zebra_vrf
*zvrf_evpn
= NULL
;
9133 zvrf_evpn
= zebra_vrf_get_evpn();
9137 if (IS_ZEBRA_DEBUG_VXLAN
)
9138 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
9139 add
? "ADD" : "DEL");
9143 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
9145 /* check if the vni is already present under zvrf */
9147 snprintf(err
, err_str_sz
,
9148 "VNI is already configured under the vrf");
9152 /* check if this VNI is already present in the system */
9153 zl3vni
= zl3vni_lookup(vni
);
9155 snprintf(err
, err_str_sz
,
9156 "VNI is already configured as L3-VNI");
9160 /* add the L3-VNI to the global table */
9161 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
9163 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
9167 /* associate the vrf with vni */
9170 /* set the filter in l3vni to denote if we are using l3vni only
9174 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
9176 /* associate with vxlan-intf;
9177 * we need to associate with the vxlan-intf first
9179 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
9181 /* associate with corresponding SVI interface, we can associate
9182 * with svi-if only after vxlan interface association is
9185 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
9187 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
9189 if (IS_ZEBRA_DEBUG_VXLAN
)
9190 zlog_debug("%s: l3vni %u svi_if %s mac_vlan_if %s",
9191 __PRETTY_FUNCTION__
, vni
,
9193 zl3vni
->svi_if
->name
: "NIL",
9194 zl3vni
->mac_vlan_if
?
9195 zl3vni
->mac_vlan_if
->name
: "NIL");
9197 /* formulate l2vni list */
9198 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
9201 if (is_l3vni_oper_up(zl3vni
))
9202 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9205 zl3vni
= zl3vni_lookup(vni
);
9207 snprintf(err
, err_str_sz
, "VNI doesn't exist");
9211 if (zvrf
->l3vni
!= vni
) {
9212 snprintf(err
, err_str_sz
,
9213 "VNI %d doesn't exist in VRF: %s",
9214 vni
, zvrf
->vrf
->name
);
9218 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
9219 snprintf(err
, ERR_STR_SZ
,
9220 "prefix-routes-only is not set for the vni");
9224 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9226 /* delete and uninstall all rmacs */
9227 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
9230 /* delete and uninstall all next-hops */
9231 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
9237 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
9242 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
9244 zebra_l3vni_t
*zl3vni
= NULL
;
9247 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9251 zl3vni
->vrf_id
= zvrf_id(zvrf
);
9252 if (is_l3vni_oper_up(zl3vni
))
9253 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
9257 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
9259 zebra_l3vni_t
*zl3vni
= NULL
;
9262 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9266 zl3vni
->vrf_id
= VRF_UNKNOWN
;
9267 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
9271 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
9273 zebra_l3vni_t
*zl3vni
= NULL
;
9277 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
9283 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
9289 * Handle message from client to specify the flooding mechanism for
9290 * BUM packets. The default is to do head-end (ingress) replication
9291 * and the other supported option is to disable it. This applies to
9292 * all BUM traffic and disabling it applies to both the transmit and
9293 * receive direction.
9295 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
9298 enum vxlan_flood_control flood_ctrl
;
9300 if (!EVPN_ENABLED(zvrf
)) {
9301 zlog_err("EVPN flood control for non-EVPN VRF %u",
9307 STREAM_GETC(s
, flood_ctrl
);
9309 if (IS_ZEBRA_DEBUG_VXLAN
)
9310 zlog_debug("EVPN flood control %u, currently %u",
9311 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
9313 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
9316 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9318 /* Install or uninstall flood entries corresponding to
9321 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
9329 * Handle message from client to enable/disable advertisement of svi macip
9332 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
9337 zebra_vni_t
*zvni
= NULL
;
9338 struct interface
*ifp
= NULL
;
9340 if (!EVPN_ENABLED(zvrf
)) {
9341 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
9347 STREAM_GETC(s
, advertise
);
9348 STREAM_GETL(s
, vni
);
9351 if (IS_ZEBRA_DEBUG_VXLAN
)
9352 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
9353 advertise
? "enabled" : "disabled",
9354 advertise_svi_macip_enabled(NULL
)
9358 if (zvrf
->advertise_svi_macip
== advertise
)
9363 zvrf
->advertise_svi_macip
= advertise
;
9364 hash_iterate(zvrf
->vni_table
,
9365 zvni_gw_macip_add_for_vni_hash
, NULL
);
9367 hash_iterate(zvrf
->vni_table
,
9368 zvni_svi_macip_del_for_vni_hash
, NULL
);
9369 zvrf
->advertise_svi_macip
= advertise
;
9373 struct zebra_if
*zif
= NULL
;
9374 struct zebra_l2info_vxlan zl2_info
;
9375 struct interface
*vlan_if
= NULL
;
9377 zvni
= zvni_lookup(vni
);
9381 if (IS_ZEBRA_DEBUG_VXLAN
)
9383 "EVPN SVI macip Adv %s on VNI %d , currently %s",
9384 advertise
? "enabled" : "disabled", vni
,
9385 advertise_svi_macip_enabled(zvni
)
9389 if (zvni
->advertise_svi_macip
== advertise
)
9392 /* Store flag even though SVI is not present.
9393 * Once SVI comes up triggers self MAC-IP route add.
9395 zvni
->advertise_svi_macip
= advertise
;
9397 ifp
= zvni
->vxlan_if
;
9403 /* If down or not mapped to a bridge, we're done. */
9404 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9407 zl2_info
= zif
->l2info
.vxl
;
9408 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9409 zif
->brslave_info
.br_if
);
9414 /* Add primary SVI MAC-IP */
9415 zvni_add_macip_for_intf(vlan_if
, zvni
);
9417 /* Del primary SVI MAC-IP */
9418 zvni_del_macip_for_intf(vlan_if
, zvni
);
9427 * Handle message from client to enable/disable advertisement of g/w macip
9430 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9435 zebra_vni_t
*zvni
= NULL
;
9436 struct interface
*ifp
= NULL
;
9437 struct zebra_if
*zif
= NULL
;
9438 struct zebra_l2info_vxlan zl2_info
;
9439 struct interface
*vlan_if
= NULL
;
9441 if (!EVPN_ENABLED(zvrf
)) {
9442 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9448 STREAM_GETC(s
, advertise
);
9449 vni
= stream_get3(s
);
9451 zvni
= zvni_lookup(vni
);
9455 if (zvni
->advertise_subnet
== advertise
)
9458 if (IS_ZEBRA_DEBUG_VXLAN
)
9459 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9460 advertise
? "enabled" : "disabled", vni
,
9461 zvni
->advertise_subnet
? "enabled" : "disabled");
9464 zvni
->advertise_subnet
= advertise
;
9466 ifp
= zvni
->vxlan_if
;
9472 /* If down or not mapped to a bridge, we're done. */
9473 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9476 zl2_info
= zif
->l2info
.vxl
;
9479 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9483 if (zvni
->advertise_subnet
)
9484 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9486 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9493 * Handle message from client to enable/disable advertisement of g/w macip
9496 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9501 zebra_vni_t
*zvni
= NULL
;
9502 struct interface
*ifp
= NULL
;
9504 if (!EVPN_ENABLED(zvrf
)) {
9505 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9511 STREAM_GETC(s
, advertise
);
9512 STREAM_GETL(s
, vni
);
9515 if (IS_ZEBRA_DEBUG_VXLAN
)
9516 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9517 advertise
? "enabled" : "disabled",
9518 advertise_gw_macip_enabled(NULL
)
9522 if (zvrf
->advertise_gw_macip
== advertise
)
9525 zvrf
->advertise_gw_macip
= advertise
;
9527 if (advertise_gw_macip_enabled(zvni
))
9528 hash_iterate(zvrf
->vni_table
,
9529 zvni_gw_macip_add_for_vni_hash
, NULL
);
9531 hash_iterate(zvrf
->vni_table
,
9532 zvni_gw_macip_del_for_vni_hash
, NULL
);
9535 struct zebra_if
*zif
= NULL
;
9536 struct zebra_l2info_vxlan zl2_info
;
9537 struct interface
*vlan_if
= NULL
;
9538 struct interface
*vrr_if
= NULL
;
9540 zvni
= zvni_lookup(vni
);
9544 if (IS_ZEBRA_DEBUG_VXLAN
)
9546 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9547 advertise
? "enabled" : "disabled", vni
,
9548 advertise_gw_macip_enabled(zvni
) ? "enabled"
9551 if (zvni
->advertise_gw_macip
== advertise
)
9554 zvni
->advertise_gw_macip
= advertise
;
9556 ifp
= zvni
->vxlan_if
;
9562 /* If down or not mapped to a bridge, we're done. */
9563 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9566 zl2_info
= zif
->l2info
.vxl
;
9568 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9569 zif
->brslave_info
.br_if
);
9573 if (advertise_gw_macip_enabled(zvni
)) {
9574 /* Add primary SVI MAC-IP */
9575 zvni_add_macip_for_intf(vlan_if
, zvni
);
9577 /* Add VRR MAC-IP - if any*/
9578 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9580 zvni_add_macip_for_intf(vrr_if
, zvni
);
9582 /* Del primary MAC-IP */
9583 zvni_del_macip_for_intf(vlan_if
, zvni
);
9585 /* Del VRR MAC-IP - if any*/
9586 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9588 zvni_del_macip_for_intf(vrr_if
, zvni
);
9598 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9599 * When enabled, the VNI hash table will be built and MAC FDB table read;
9600 * when disabled, the entries should be deleted and remote VTEPs and MACs
9601 * uninstalled from the kernel.
9602 * This also informs the setting for BUM handling at the time this change
9603 * occurs; it is relevant only when specifying "learn".
9605 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9607 struct stream
*s
= NULL
;
9609 enum vxlan_flood_control flood_ctrl
;
9611 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9613 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9617 STREAM_GETC(s
, advertise
);
9618 STREAM_GETC(s
, flood_ctrl
);
9620 if (IS_ZEBRA_DEBUG_VXLAN
)
9621 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9622 zvrf_name(zvrf
), zvrf_id(zvrf
),
9623 advertise
? "enabled" : "disabled",
9624 is_evpn_enabled() ? "enabled" : "disabled",
9627 if (zvrf
->advertise_all_vni
== advertise
)
9630 zvrf
->advertise_all_vni
= advertise
;
9631 if (EVPN_ENABLED(zvrf
)) {
9632 zrouter
.evpn_vrf
= zvrf
;
9634 /* Note BUM handling */
9635 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9637 /* Build VNI hash table and inform BGP. */
9638 zvni_build_hash_table();
9640 /* Add all SVI (L3 GW) MACs to BGP*/
9641 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9644 /* Read the MAC FDB */
9645 macfdb_read(zvrf
->zns
);
9647 /* Read neighbors */
9648 neigh_read(zvrf
->zns
);
9650 /* Cleanup VTEPs for all VNIs - uninstall from
9651 * kernel and free entries.
9653 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9655 /* cleanup all l3vnis */
9656 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9658 /* Mark as "no EVPN VRF" */
9659 zrouter
.evpn_vrf
= NULL
;
9667 * Allocate VNI hash table for this VRF and do other initialization.
9668 * NOTE: Currently supported only for default VRF.
9670 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9674 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9675 "Zebra VRF VNI Table");
9676 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9677 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9680 /* Cleanup VNI info, but don't free the table. */
9681 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9685 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9686 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9689 /* Close all VNI handling */
9690 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9694 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9695 hash_free(zvrf
->vni_table
);
9698 /* init the l3vni table */
9699 void zebra_vxlan_init(void)
9701 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9702 "Zebra VRF L3 VNI table");
9703 zrouter
.evpn_vrf
= NULL
;
9706 /* free l3vni table */
9707 void zebra_vxlan_disable(void)
9709 hash_free(zrouter
.l3vni_table
);
9712 /* get the l3vni svi ifindex */
9713 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9715 zebra_l3vni_t
*zl3vni
= NULL
;
9717 zl3vni
= zl3vni_from_vrf(vrf_id
);
9718 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9721 return zl3vni
->svi_if
->ifindex
;
9724 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9726 struct zebra_vrf
*zvrf
= NULL
;
9727 zebra_neigh_t
*nbr
= NULL
;
9728 zebra_vni_t
*zvni
= NULL
;
9729 char buf1
[INET6_ADDRSTRLEN
];
9730 char buf2
[ETHER_ADDR_STRLEN
];
9732 nbr
= THREAD_ARG(t
);
9734 /* since this is asynchronous we need sanity checks*/
9735 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9739 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9743 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9747 if (IS_ZEBRA_DEBUG_VXLAN
)
9748 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9749 __PRETTY_FUNCTION__
,
9750 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9751 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9753 nbr
->dad_count
, zvni
->vni
);
9755 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9757 nbr
->detect_start_time
.tv_sec
= 0;
9758 nbr
->detect_start_time
.tv_usec
= 0;
9759 nbr
->dad_dup_detect_time
= 0;
9760 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9761 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9764 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9765 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9766 nbr
->flags
, nbr
->loc_seq
);
9767 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9768 zvni_neigh_install(zvni
, nbr
);
9774 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9776 struct zebra_vrf
*zvrf
= NULL
;
9777 zebra_mac_t
*mac
= NULL
;
9778 zebra_vni_t
*zvni
= NULL
;
9779 struct listnode
*node
= NULL
;
9780 zebra_neigh_t
*nbr
= NULL
;
9781 char buf
[ETHER_ADDR_STRLEN
];
9783 mac
= THREAD_ARG(t
);
9785 /* since this is asynchronous we need sanity checks*/
9786 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9790 zvni
= zvni_lookup(mac
->zvni
->vni
);
9794 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9798 if (IS_ZEBRA_DEBUG_VXLAN
)
9799 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9800 __PRETTY_FUNCTION__
,
9801 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9804 listcount(mac
->neigh_list
));
9806 /* Remove all IPs as duplicate associcated with this MAC */
9807 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9808 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9809 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9810 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9811 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9812 zvni_neigh_install(zvni
, nbr
);
9815 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9817 nbr
->detect_start_time
.tv_sec
= 0;
9818 nbr
->dad_dup_detect_time
= 0;
9821 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9823 mac
->detect_start_time
.tv_sec
= 0;
9824 mac
->detect_start_time
.tv_usec
= 0;
9825 mac
->dad_dup_detect_time
= 0;
9826 mac
->dad_mac_auto_recovery_timer
= NULL
;
9828 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9830 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9831 mac
->flags
, mac
->loc_seq
))
9834 /* Process all neighbors associated with this MAC. */
9835 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9837 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9838 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9840 /* Install the entry. */
9841 zvni_mac_install(zvni
, mac
);
9847 /************************** vxlan SG cache management ************************/
9848 /* Inform PIM about the mcast group */
9849 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
9850 struct prefix_sg
*sg
,
9851 char *sg_str
, uint16_t cmd
)
9853 struct zserv
*client
= NULL
;
9854 struct stream
*s
= NULL
;
9856 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9860 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
9863 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9865 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9866 stream_putl(s
, IPV4_MAX_BYTELEN
);
9867 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9868 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9870 /* Write packet size. */
9871 stream_putw_at(s
, 0, stream_get_endp(s
));
9873 if (IS_ZEBRA_DEBUG_VXLAN
)
9876 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9877 zebra_route_string(client
->proto
));
9879 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9880 client
->vxlan_sg_add_cnt
++;
9882 client
->vxlan_sg_del_cnt
++;
9884 return zserv_send_message(client
, s
);
9887 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9889 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9891 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9892 vxlan_sg
->sg
.grp
.s_addr
, 0));
9895 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9897 const zebra_vxlan_sg_t
*sg1
= p1
;
9898 const zebra_vxlan_sg_t
*sg2
= p2
;
9900 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9901 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9904 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9905 struct prefix_sg
*sg
)
9907 zebra_vxlan_sg_t
*vxlan_sg
;
9909 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9911 vxlan_sg
->zvrf
= zvrf
;
9913 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9915 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9917 if (IS_ZEBRA_DEBUG_VXLAN
)
9918 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9923 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9924 struct prefix_sg
*sg
)
9926 zebra_vxlan_sg_t lookup
;
9929 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9932 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9933 struct prefix_sg
*sg
)
9935 zebra_vxlan_sg_t
*vxlan_sg
;
9936 zebra_vxlan_sg_t
*parent
= NULL
;
9939 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9943 /* create a *G entry for every BUM group implicitly -
9944 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9945 * 2. the XG entry is used by pimd to setup the
9946 * vxlan-termination-mroute
9948 if (sg
->src
.s_addr
) {
9949 memset(&sip
, 0, sizeof(sip
));
9950 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9955 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9958 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9962 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
9963 ZEBRA_VXLAN_SG_ADD
);
9968 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9971 struct zebra_vrf
*zvrf
;
9973 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9977 /* On SG entry deletion remove the reference to its parent XG
9980 if (vxlan_sg
->sg
.src
.s_addr
) {
9981 memset(&sip
, 0, sizeof(sip
));
9982 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9985 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
9986 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
9988 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9990 if (IS_ZEBRA_DEBUG_VXLAN
)
9991 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9993 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9996 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9997 struct in_addr sip
, struct in_addr mcast_grp
)
9999 zebra_vxlan_sg_t
*vxlan_sg
;
10000 struct prefix_sg sg
;
10002 sg
.family
= AF_INET
;
10003 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
10005 sg
.grp
= mcast_grp
;
10006 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
10010 if (vxlan_sg
->ref_cnt
)
10011 --vxlan_sg
->ref_cnt
;
10013 if (!vxlan_sg
->ref_cnt
)
10014 zebra_vxlan_sg_del(vxlan_sg
);
10017 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
10018 struct in_addr sip
, struct in_addr mcast_grp
)
10020 zebra_vxlan_sg_t
*vxlan_sg
;
10021 struct prefix_sg sg
;
10023 sg
.family
= AF_INET
;
10024 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
10026 sg
.grp
= mcast_grp
;
10027 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
10029 ++vxlan_sg
->ref_cnt
;
10034 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
10035 struct in_addr mcast_grp
)
10037 struct zebra_vrf
*zvrf
;
10039 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
10042 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
10046 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
10049 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
10050 struct in_addr mcast_grp
)
10052 struct zebra_vrf
*zvrf
;
10054 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
10057 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
10060 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
10063 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
10065 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
10067 zebra_vxlan_sg_del(vxlan_sg
);
10070 static void zebra_vxlan_sg_replay_send(struct hash_backet
*backet
, void *arg
)
10072 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
10074 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
10075 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
10078 /* Handle message from client to replay vxlan SG entries */
10079 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
10081 if (IS_ZEBRA_DEBUG_VXLAN
)
10082 zlog_debug("VxLAN SG updates to PIM, start");
10084 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
10086 if (!EVPN_ENABLED(zvrf
)) {
10087 if (IS_ZEBRA_DEBUG_VXLAN
)
10088 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
10089 zvrf
->vrf
->vrf_id
);
10093 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
10096 /************************** EVPN BGP config management ************************/
10097 /* Notify Local MACs to the clienti, skips GW MAC */
10098 static void zvni_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
10101 struct mac_walk_ctx
*wctx
= arg
;
10102 zebra_mac_t
*zmac
= bucket
->data
;
10104 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
10107 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
10108 zvni_mac_send_add_to_client(wctx
->zvni
->vni
, &zmac
->macaddr
,
10109 zmac
->flags
, zmac
->loc_seq
);
10112 /* Iterator to Notify Local MACs of a L2VNI */
10113 static void zvni_send_mac_to_client(zebra_vni_t
*zvni
)
10115 struct mac_walk_ctx wctx
;
10117 if (!zvni
->mac_table
)
10120 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
10123 hash_iterate(zvni
->mac_table
, zvni_send_mac_hash_entry_to_client
,
10127 /* Notify Neighbor entries to the Client, skips the GW entry */
10128 static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
10131 struct mac_walk_ctx
*wctx
= arg
;
10132 zebra_neigh_t
*zn
= bucket
->data
;
10133 zebra_mac_t
*zmac
= NULL
;
10135 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
10138 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
10139 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
10140 zmac
= zvni_mac_lookup(wctx
->zvni
, &zn
->emac
);
10144 zvni_neigh_send_add_to_client(wctx
->zvni
->vni
, &zn
->ip
,
10145 &zn
->emac
, zn
->flags
,
10150 /* Iterator of a specific L2VNI */
10151 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
)
10153 struct neigh_walk_ctx wctx
;
10155 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
10158 hash_iterate(zvni
->neigh_table
, zvni_send_neigh_hash_entry_to_client
,
10162 static void zvni_evpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
10164 zebra_vni_t
*zvni
= NULL
;
10166 zvni
= (zebra_vni_t
*)bucket
->data
;
10167 zvni
->advertise_gw_macip
= 0;
10168 zvni
->advertise_svi_macip
= 0;
10169 zvni
->advertise_subnet
= 0;
10171 zvni_neigh_del_all(zvni
, 1, 0,
10172 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
10173 zvni_mac_del_all(zvni
, 1, 0,
10174 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
10175 zvni_vtep_del_all(zvni
, 1);
10178 /* Cleanup EVPN configuration of a specific VRF */
10179 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
10181 zebra_l3vni_t
*zl3vni
= NULL
;
10183 zvrf
->advertise_all_vni
= 0;
10184 zvrf
->advertise_gw_macip
= 0;
10185 zvrf
->advertise_svi_macip
= 0;
10186 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
10188 hash_iterate(zvrf
->vni_table
, zvni_evpn_cfg_cleanup
, NULL
);
10191 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
10193 /* delete and uninstall all rmacs */
10194 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
10196 /* delete and uninstall all next-hops */
10197 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
10202 /* Cleanup BGP EVPN configuration upon client disconnect */
10203 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
10206 struct zebra_vrf
*zvrf
;
10208 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
10211 zebra_evpn_vrf_cfg_cleanup(zvrf
);
10217 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
10219 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
10221 if (CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
10222 if (IS_ZEBRA_DEBUG_VXLAN
)
10223 zlog_debug("VxLAN SG updates to PIM, stop");
10224 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
10230 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
10232 if (client
->proto
== ZEBRA_ROUTE_BGP
)
10233 return zebra_evpn_bgp_cfg_clean_up(client
);
10235 if (client
->proto
== ZEBRA_ROUTE_PIM
)
10236 return zebra_evpn_pim_cfg_clean_up(client
);
10242 * Handle results for vxlan dataplane operations.
10244 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
10246 /* TODO -- anything other than freeing the context? */
10247 dplane_ctx_fini(&ctx
);
10250 /* Cleanup BGP EVPN configuration upon client disconnect */
10251 extern void zebra_evpn_init(void)
10253 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);