2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
5 * This file is part of FRR.
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37 #include <linux/neighbour.h>
40 #include "zebra/zebra_router.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/rib.h"
45 #include "zebra/rt_netlink.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_l2.h"
48 #include "zebra/zebra_memory.h"
49 #include "zebra/zebra_ns.h"
50 #include "zebra/zebra_vrf.h"
51 #include "zebra/zebra_vxlan.h"
52 #include "zebra/zebra_vxlan_private.h"
53 #include "zebra/zebra_router.h"
55 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
56 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI
, "VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
58 DEFINE_MTYPE_STATIC(ZEBRA
, ZVNI_VTEP
, "VNI remote VTEP");
59 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "VNI MAC");
60 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "VNI Neighbor");
61 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
65 #define VXLAN_FLOOD_STR_NO_INFO "-"
66 #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO
67 static const struct message zvtep_flood_str
[] = {
68 {VXLAN_FLOOD_DISABLED
, VXLAN_FLOOD_STR_NO_INFO
},
69 {VXLAN_FLOOD_PIM_SM
, "PIM-SM"},
70 {VXLAN_FLOOD_HEAD_END_REPL
, "HER"},
75 /* static function declarations */
76 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
78 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
79 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
80 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
81 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
83 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
85 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
87 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
88 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
89 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
);
90 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
);
91 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
93 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
94 struct ipaddr
*ip
, uint8_t flags
,
95 uint32_t seq
, int state
, uint16_t cmd
);
96 static unsigned int neigh_hash_keymake(const void *p
);
97 static void *zvni_neigh_alloc(void *p
);
98 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
100 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
101 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
102 struct in_addr
*r_vtep_ip
);
103 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
105 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
);
106 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
107 struct ethaddr
*macaddr
,
108 uint8_t flags
, uint32_t seq
);
109 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
110 struct ethaddr
*macaddr
,
111 uint8_t flags
, int state
);
112 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
113 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
114 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
);
115 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
116 struct interface
*br_if
);
117 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
119 /* l3-vni next-hop neigh related APIs */
120 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
122 static void *zl3vni_nh_alloc(void *p
);
123 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
124 struct ipaddr
*vtep_ip
,
125 struct ethaddr
*rmac
);
126 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
127 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
128 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
130 /* l3-vni rmac related APIs */
131 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
132 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
133 struct ethaddr
*rmac
);
134 static void *zl3vni_rmac_alloc(void *p
);
135 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
136 struct ethaddr
*rmac
);
137 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
138 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
139 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
141 /* l3-vni related APIs*/
142 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
);
143 static void *zl3vni_alloc(void *p
);
144 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
145 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
146 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
);
147 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
);
148 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
149 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
151 static unsigned int mac_hash_keymake(const void *p
);
152 static bool mac_cmp(const void *p1
, const void *p2
);
153 static void *zvni_mac_alloc(void *p
);
154 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
155 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
156 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
157 struct in_addr
*r_vtep_ip
);
158 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
160 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
);
161 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
162 uint8_t flags
, uint32_t seq
);
163 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
);
164 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
165 struct interface
*br_if
, vlanid_t vid
);
166 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
167 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
168 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
170 static unsigned int vni_hash_keymake(const void *p
);
171 static void *zvni_alloc(void *p
);
172 static zebra_vni_t
*zvni_lookup(vni_t vni
);
173 static zebra_vni_t
*zvni_add(vni_t vni
);
174 static int zvni_del(zebra_vni_t
*zvni
);
175 static int zvni_send_add_to_client(zebra_vni_t
*zvni
);
176 static int zvni_send_del_to_client(vni_t vni
);
177 static void zvni_build_hash_table(void);
178 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
179 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
180 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
182 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
183 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
);
184 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
);
185 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
);
186 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
187 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
);
188 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
189 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
190 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
192 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
193 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
);
194 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
);
195 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
196 zebra_mac_t
*old_zmac
,
197 zebra_mac_t
*new_zmac
,
199 static int remote_neigh_count(zebra_mac_t
*zmac
);
200 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
);
201 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
202 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
203 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
205 struct in_addr vtep_ip
,
209 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
211 struct in_addr vtep_ip
,
215 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
216 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
217 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
218 struct in_addr sip
, struct in_addr mcast_grp
);
219 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
220 struct in_addr sip
, struct in_addr mcast_grp
);
221 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
222 struct in_addr mcast_grp
);
223 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
224 struct in_addr mcast_grp
);
225 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
);
227 static void zvni_send_mac_to_client(zebra_vni_t
*zvn
);
228 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
);
230 /* Private functions */
231 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
232 const struct host_rb_entry
*hle2
)
234 if (hle1
->p
.family
< hle2
->p
.family
)
237 if (hle1
->p
.family
> hle2
->p
.family
)
240 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
243 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
246 if (hle1
->p
.family
== AF_INET
) {
247 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
250 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
254 } else if (hle1
->p
.family
== AF_INET6
) {
255 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
258 zlog_debug("%s: Unexpected family type: %d",
259 __PRETTY_FUNCTION__
, hle1
->p
.family
);
263 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
265 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
267 struct host_rb_entry
*hle
;
270 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
277 * Return number of valid MACs in a VNI's MAC hash table - all
278 * remote MACs and non-internal (auto) local MACs count.
280 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
283 uint32_t num_macs
= 0;
285 struct hash_bucket
*hb
;
288 hash
= zvni
->mac_table
;
291 for (i
= 0; i
< hash
->size
; i
++) {
292 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
293 mac
= (zebra_mac_t
*)hb
->data
;
294 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
295 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
296 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
304 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
307 uint32_t num_macs
= 0;
309 struct hash_bucket
*hb
;
312 hash
= zvni
->mac_table
;
315 for (i
= 0; i
< hash
->size
; i
++) {
316 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
317 mac
= (zebra_mac_t
*)hb
->data
;
318 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
326 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
329 uint32_t num_neighs
= 0;
331 struct hash_bucket
*hb
;
334 hash
= zvni
->neigh_table
;
337 for (i
= 0; i
< hash
->size
; i
++) {
338 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
339 nbr
= (zebra_neigh_t
*)hb
->data
;
340 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
348 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
350 struct zebra_vrf
*zvrf
;
352 zvrf
= zebra_vrf_get_evpn();
353 if (zvrf
&& zvrf
->advertise_gw_macip
)
356 if (zvni
&& zvni
->advertise_gw_macip
)
362 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
364 struct zebra_vrf
*zvrf
;
366 zvrf
= zebra_vrf_get_evpn();
367 if (zvrf
&& zvrf
->advertise_svi_macip
)
370 if (zvni
&& zvni
->advertise_svi_macip
)
376 /* As part Duplicate Address Detection (DAD) for IP mobility
377 * MAC binding changes, ensure to inherit duplicate flag
380 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
381 zebra_mac_t
*old_zmac
,
382 zebra_mac_t
*new_zmac
,
385 bool is_old_mac_dup
= false;
386 bool is_new_mac_dup
= false;
388 if (!zvrf
->dup_addr_detect
)
390 /* Check old or new MAC is detected as duplicate
391 * mark this neigh as duplicate
394 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
395 ZEBRA_MAC_DUPLICATE
);
397 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
398 ZEBRA_MAC_DUPLICATE
);
399 /* Old and/or new MAC can be in duplicate state,
400 * based on that IP/Neigh Inherits the flag.
401 * If New MAC is marked duplicate, inherit to the IP.
402 * If old MAC is duplicate but new MAC is not, clear
403 * duplicate flag for IP and reset detection params
404 * and let IP DAD retrigger.
406 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
407 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
408 /* Capture Duplicate detection time */
409 nbr
->dad_dup_detect_time
= monotime(NULL
);
410 /* Mark neigh inactive */
411 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
414 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
415 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
417 nbr
->detect_start_time
.tv_sec
= 0;
418 nbr
->detect_start_time
.tv_usec
= 0;
423 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
425 struct in_addr vtep_ip
,
431 struct listnode
*node
= NULL
;
432 struct timeval elapsed
= {0, 0};
433 char buf
[ETHER_ADDR_STRLEN
];
434 char buf1
[INET6_ADDRSTRLEN
];
435 bool reset_params
= false;
437 if (!(zvrf
->dup_addr_detect
&& do_dad
))
440 /* MAC is detected as duplicate,
441 * Local MAC event -> hold on advertising to BGP.
442 * Remote MAC event -> hold on installing it.
444 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
445 if (IS_ZEBRA_DEBUG_VXLAN
)
447 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
449 prefix_mac2str(&mac
->macaddr
, buf
,
451 mac
->flags
, mac
->dad_count
,
452 zvrf
->dad_freeze_time
);
454 /* For duplicate MAC do not update
455 * client but update neigh due to
458 if (zvrf
->dad_freeze
)
459 *is_dup_detect
= true;
464 /* Check if detection time (M-secs) expired.
465 * Reset learn count and detection start time.
467 monotime_since(&mac
->detect_start_time
, &elapsed
);
468 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
469 if (is_local
&& !reset_params
) {
470 /* RFC-7432: A PE/VTEP that detects a MAC mobility
471 * event via LOCAL learning starts an M-second timer.
473 * NOTE: This is the START of the probe with count is
474 * 0 during LOCAL learn event.
475 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
477 reset_params
= !mac
->dad_count
;
481 if (IS_ZEBRA_DEBUG_VXLAN
)
483 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
484 , __PRETTY_FUNCTION__
,
485 prefix_mac2str(&mac
->macaddr
, buf
,
487 mac
->flags
, mac
->dad_count
);
490 /* Start dup. addr detection (DAD) start time,
491 * ONLY during LOCAL learn.
494 monotime(&mac
->detect_start_time
);
496 } else if (!is_local
) {
497 /* For REMOTE MAC, increment detection count
498 * ONLY while in probe window, once window passed,
499 * next local learn event should trigger DAD.
504 /* For LOCAL MAC learn event, once count is reset above via either
505 * initial/start detection time or passed the probe time, the count
506 * needs to be incremented.
511 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
512 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
513 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
515 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
516 is_local
? "local update, last" :
517 "remote update, from", inet_ntoa(vtep_ip
));
519 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
521 /* Capture Duplicate detection time */
522 mac
->dad_dup_detect_time
= monotime(NULL
);
524 /* Mark all IPs/Neighs as duplicate
525 * associcated with this MAC
527 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
529 /* Ony Mark IPs which are Local */
530 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
533 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
535 nbr
->dad_dup_detect_time
= monotime(NULL
);
537 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
538 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
540 prefix_mac2str(&mac
->macaddr
,
542 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
543 is_local
? "local" : "remote");
546 /* Start auto recovery timer for this MAC */
547 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
548 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
549 if (IS_ZEBRA_DEBUG_VXLAN
)
551 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
552 , __PRETTY_FUNCTION__
,
553 prefix_mac2str(&mac
->macaddr
, buf
,
555 mac
->flags
, zvrf
->dad_freeze_time
);
557 thread_add_timer(zrouter
.master
,
558 zebra_vxlan_dad_mac_auto_recovery_exp
,
559 mac
, zvrf
->dad_freeze_time
,
560 &mac
->dad_mac_auto_recovery_timer
);
563 /* In case of local update, do not inform to client (BGPd),
564 * upd_neigh for neigh sequence change.
566 if (zvrf
->dad_freeze
)
567 *is_dup_detect
= true;
571 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
573 struct in_addr vtep_ip
,
579 struct timeval elapsed
= {0, 0};
580 char buf
[ETHER_ADDR_STRLEN
];
581 char buf1
[INET6_ADDRSTRLEN
];
582 bool reset_params
= false;
584 if (!zvrf
->dup_addr_detect
)
587 /* IP is detected as duplicate or inherit dup
588 * state, hold on to install as remote entry
589 * only if freeze is enabled.
591 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
592 if (IS_ZEBRA_DEBUG_VXLAN
)
594 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
596 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
597 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
598 nbr
->flags
, nbr
->dad_count
,
599 zvrf
->dad_freeze_time
);
601 if (zvrf
->dad_freeze
)
602 *is_dup_detect
= true;
604 /* warn-only action, neigh will be installed.
605 * freeze action, it wil not be installed.
613 /* Check if detection time (M-secs) expired.
614 * Reset learn count and detection start time.
615 * During remote mac add, count should already be 1
616 * via local learning.
618 monotime_since(&nbr
->detect_start_time
, &elapsed
);
619 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
621 if (is_local
&& !reset_params
) {
622 /* RFC-7432: A PE/VTEP that detects a MAC mobility
623 * event via LOCAL learning starts an M-second timer.
625 * NOTE: This is the START of the probe with count is
626 * 0 during LOCAL learn event.
628 reset_params
= !nbr
->dad_count
;
632 if (IS_ZEBRA_DEBUG_VXLAN
)
634 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
636 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
637 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
638 nbr
->flags
, nbr
->dad_count
);
639 /* Reset learn count but do not start detection
640 * during REMOTE learn event.
643 /* Start dup. addr detection (DAD) start time,
644 * ONLY during LOCAL learn.
647 monotime(&nbr
->detect_start_time
);
649 } else if (!is_local
) {
650 /* For REMOTE IP/Neigh, increment detection count
651 * ONLY while in probe window, once window passed,
652 * next local learn event should trigger DAD.
657 /* For LOCAL IP/Neigh learn event, once count is reset above via either
658 * initial/start detection time or passed the probe time, the count
659 * needs to be incremented.
664 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
665 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
666 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
668 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
669 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
670 is_local
? "local update, last" :
671 "remote update, from",
674 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
676 /* Capture Duplicate detection time */
677 nbr
->dad_dup_detect_time
= monotime(NULL
);
679 /* Start auto recovery timer for this IP */
680 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
681 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
682 if (IS_ZEBRA_DEBUG_VXLAN
)
684 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
686 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
687 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
688 nbr
->flags
, zvrf
->dad_freeze_time
);
690 thread_add_timer(zrouter
.master
,
691 zebra_vxlan_dad_ip_auto_recovery_exp
,
692 nbr
, zvrf
->dad_freeze_time
,
693 &nbr
->dad_ip_auto_recovery_timer
);
695 if (zvrf
->dad_freeze
)
696 *is_dup_detect
= true;
701 * Helper function to determine maximum width of neighbor IP address for
702 * display - just because we're dealing with IPv6 addresses that can
705 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
708 char buf
[INET6_ADDRSTRLEN
];
709 struct neigh_walk_ctx
*wctx
= ctxt
;
712 n
= (zebra_neigh_t
*)bucket
->data
;
714 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
716 if (width
> wctx
->addr_width
)
717 wctx
->addr_width
= width
;
722 * Print a specific neighbor entry.
724 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
727 char buf1
[ETHER_ADDR_STRLEN
];
728 char buf2
[INET6_ADDRSTRLEN
];
729 const char *type_str
;
730 const char *state_str
;
731 bool flags_present
= false;
732 struct zebra_vrf
*zvrf
= NULL
;
733 struct timeval detect_start_time
= {0, 0};
735 zvrf
= zebra_vrf_get_evpn();
739 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
740 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
741 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
743 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
744 vty
= (struct vty
*)ctxt
;
746 vty_out(vty
, "IP: %s\n",
747 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
748 vty_out(vty
, " Type: %s\n", type_str
);
749 vty_out(vty
, " State: %s\n", state_str
);
750 vty_out(vty
, " MAC: %s\n",
751 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
753 json_object_string_add(json
, "ip", buf2
);
754 json_object_string_add(json
, "type", type_str
);
755 json_object_string_add(json
, "state", state_str
);
756 json_object_string_add(json
, "mac", buf1
);
758 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
760 vty_out(vty
, " Remote VTEP: %s\n",
761 inet_ntoa(n
->r_vtep_ip
));
763 json_object_string_add(json
, "remoteVtep",
764 inet_ntoa(n
->r_vtep_ip
));
766 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
768 vty_out(vty
, " Flags: Default-gateway");
769 flags_present
= true;
771 json_object_boolean_true_add(json
, "defaultGateway");
773 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
776 flags_present
? " ,Router" : " Flags: Router");
777 flags_present
= true;
783 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
784 n
->loc_seq
, n
->rem_seq
);
786 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
787 vty_out(vty
, " Duplicate, detected at %s",
788 time_to_string(n
->dad_dup_detect_time
));
789 } else if (n
->dad_count
) {
790 monotime_since(&n
->detect_start_time
,
792 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
793 char *buf
= time_to_string(
794 n
->detect_start_time
.tv_sec
);
797 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
799 " Duplicate detection started at %s, detection count %u\n",
800 tmp_buf
, n
->dad_count
);
804 json_object_int_add(json
, "localSequence", n
->loc_seq
);
805 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
806 json_object_int_add(json
, "detectionCount",
808 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
809 json_object_boolean_true_add(json
, "isDuplicate");
811 json_object_boolean_false_add(json
, "isDuplicate");
818 * Print neighbor hash entry - called for display of all neighbors.
820 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
823 json_object
*json_vni
= NULL
, *json_row
= NULL
;
825 char buf1
[ETHER_ADDR_STRLEN
];
826 char buf2
[INET6_ADDRSTRLEN
];
827 struct neigh_walk_ctx
*wctx
= ctxt
;
828 const char *state_str
;
831 json_vni
= wctx
->json
;
832 n
= (zebra_neigh_t
*)bucket
->data
;
835 json_row
= json_object_new_object();
837 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
838 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
839 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
840 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
841 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
844 if (json_vni
== NULL
) {
845 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
846 -wctx
->addr_width
, buf2
, "local",
847 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
849 json_object_string_add(json_row
, "type", "local");
850 json_object_string_add(json_row
, "state", state_str
);
851 json_object_string_add(json_row
, "mac", buf1
);
852 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
853 json_object_boolean_true_add(
854 json_row
, "defaultGateway");
855 json_object_int_add(json_row
, "localSequence",
857 json_object_int_add(json_row
, "remoteSequence",
859 json_object_int_add(json_row
, "detectionCount",
861 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
862 json_object_boolean_true_add(json_row
,
865 json_object_boolean_false_add(json_row
,
869 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
870 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
871 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
874 if (json_vni
== NULL
) {
875 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
878 "%*s %-6s %-8s %-17s %-21s\n",
879 -wctx
->addr_width
, "Neighbor", "Type",
880 "State", "MAC", "Remote VTEP");
881 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
882 -wctx
->addr_width
, buf2
, "remote", state_str
,
883 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
885 json_object_string_add(json_row
, "type", "remote");
886 json_object_string_add(json_row
, "state", state_str
);
887 json_object_string_add(json_row
, "mac", buf1
);
888 json_object_string_add(json_row
, "remoteVtep",
889 inet_ntoa(n
->r_vtep_ip
));
890 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
891 json_object_boolean_true_add(json_row
,
893 json_object_int_add(json_row
, "localSequence",
895 json_object_int_add(json_row
, "remoteSequence",
897 json_object_int_add(json_row
, "detectionCount",
899 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
900 json_object_boolean_true_add(json_row
,
903 json_object_boolean_false_add(json_row
,
910 json_object_object_add(json_vni
, buf2
, json_row
);
914 * Print neighbor hash entry in detail - called for display of all neighbors.
916 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
919 json_object
*json_vni
= NULL
, *json_row
= NULL
;
921 char buf
[INET6_ADDRSTRLEN
];
922 struct neigh_walk_ctx
*wctx
= ctxt
;
925 json_vni
= wctx
->json
;
926 n
= (zebra_neigh_t
*)bucket
->data
;
930 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
932 json_row
= json_object_new_object();
934 zvni_print_neigh(n
, vty
, json_row
);
937 json_object_object_add(json_vni
, buf
, json_row
);
941 * Print neighbors for all VNI.
943 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
947 json_object
*json
= NULL
, *json_vni
= NULL
;
950 struct neigh_walk_ctx wctx
;
951 char vni_str
[VNI_STR_LEN
];
954 vty
= (struct vty
*)args
[0];
955 json
= (json_object
*)args
[1];
956 print_dup
= (uint32_t)(uintptr_t)args
[2];
958 zvni
= (zebra_vni_t
*)bucket
->data
;
960 num_neigh
= hashcount(zvni
->neigh_table
);
963 num_neigh
= num_dup_detected_neighs(zvni
);
967 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
968 zvni
->vni
, num_neigh
);
970 json_vni
= json_object_new_object();
971 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
972 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
977 json_object_object_add(json
, vni_str
, json_vni
);
981 /* Since we have IPv6 addresses to deal with which can vary widely in
982 * size, we try to be a bit more elegant in display by first computing
985 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
988 wctx
.addr_width
= 15;
989 wctx
.json
= json_vni
;
990 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
993 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
994 -wctx
.addr_width
, "IP", "Type",
995 "State", "MAC", "Remote VTEP", "Seq #'s");
998 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
1001 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1004 json_object_object_add(json
, vni_str
, json_vni
);
1007 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1011 nbr
= (zebra_neigh_t
*)bucket
->data
;
1015 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1016 zvni_print_neigh_hash(bucket
, ctxt
);
1019 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1024 nbr
= (zebra_neigh_t
*)bucket
->data
;
1028 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1029 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1033 * Print neighbors for all VNIs in detail.
1035 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1039 json_object
*json
= NULL
, *json_vni
= NULL
;
1042 struct neigh_walk_ctx wctx
;
1043 char vni_str
[VNI_STR_LEN
];
1046 vty
= (struct vty
*)args
[0];
1047 json
= (json_object
*)args
[1];
1048 print_dup
= (uint32_t)(uintptr_t)args
[2];
1050 zvni
= (zebra_vni_t
*)bucket
->data
;
1053 vty_out(vty
, "{}\n");
1056 num_neigh
= hashcount(zvni
->neigh_table
);
1058 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1063 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1064 zvni
->vni
, num_neigh
);
1066 json_vni
= json_object_new_object();
1067 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1068 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1072 json_object_object_add(json
, vni_str
, json_vni
);
1076 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1079 wctx
.addr_width
= 15;
1080 wctx
.json
= json_vni
;
1083 hash_iterate(zvni
->neigh_table
,
1084 zvni_print_dad_neigh_hash_detail
, &wctx
);
1086 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1090 json_object_object_add(json
, vni_str
, json_vni
);
1093 /* print a specific next hop for an l3vni */
1094 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1097 char buf1
[ETHER_ADDR_STRLEN
];
1098 char buf2
[INET6_ADDRSTRLEN
];
1099 json_object
*json_hosts
= NULL
;
1100 struct host_rb_entry
*hle
;
1103 vty_out(vty
, "Ip: %s\n",
1104 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1105 vty_out(vty
, " RMAC: %s\n",
1106 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1107 vty_out(vty
, " Refcount: %d\n",
1108 rb_host_count(&n
->host_rb
));
1109 vty_out(vty
, " Prefixes:\n");
1110 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1111 vty_out(vty
, " %s\n",
1112 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1114 json_hosts
= json_object_new_array();
1115 json_object_string_add(
1116 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1117 json_object_string_add(
1119 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1120 json_object_int_add(json
, "refCount",
1121 rb_host_count(&n
->host_rb
));
1122 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1123 json_object_array_add(json_hosts
,
1124 json_object_new_string(prefix2str(
1125 &hle
->p
, buf2
, sizeof(buf2
))));
1126 json_object_object_add(json
, "prefixList", json_hosts
);
1130 /* Print a specific RMAC entry */
1131 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1134 char buf1
[ETHER_ADDR_STRLEN
];
1135 char buf2
[PREFIX_STRLEN
];
1136 json_object
*json_hosts
= NULL
;
1137 struct host_rb_entry
*hle
;
1140 vty_out(vty
, "MAC: %s\n",
1141 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1142 vty_out(vty
, " Remote VTEP: %s\n",
1143 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1144 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1145 vty_out(vty
, " Prefixes:\n");
1146 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1147 vty_out(vty
, " %s\n",
1148 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1150 json_hosts
= json_object_new_array();
1151 json_object_string_add(
1153 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1154 json_object_string_add(json
, "vtepIp",
1155 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1156 json_object_int_add(json
, "refCount",
1157 rb_host_count(&zrmac
->host_rb
));
1158 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1159 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1160 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1161 json_object_array_add(
1163 json_object_new_string(prefix2str(
1164 &hle
->p
, buf2
, sizeof(buf2
))));
1165 json_object_object_add(json
, "prefixList", json_hosts
);
1170 * Print a specific MAC entry.
1172 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1175 zebra_neigh_t
*n
= NULL
;
1176 struct listnode
*node
= NULL
;
1177 char buf1
[ETHER_ADDR_STRLEN
];
1178 char buf2
[INET6_ADDRSTRLEN
];
1179 struct zebra_vrf
*zvrf
;
1180 struct timeval detect_start_time
= {0, 0};
1182 zvrf
= zebra_vrf_get_evpn();
1186 vty
= (struct vty
*)ctxt
;
1187 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1190 json_object
*json_mac
= json_object_new_object();
1192 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1193 struct zebra_ns
*zns
;
1194 struct interface
*ifp
;
1197 ifindex
= mac
->fwd_info
.local
.ifindex
;
1198 zns
= zebra_ns_lookup(NS_DEFAULT
);
1199 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1202 json_object_string_add(json_mac
, "type", "local");
1203 json_object_string_add(json_mac
, "intf", ifp
->name
);
1204 json_object_int_add(json_mac
, "ifindex", ifindex
);
1205 if (mac
->fwd_info
.local
.vid
)
1206 json_object_int_add(json_mac
, "vlan",
1207 mac
->fwd_info
.local
.vid
);
1208 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1209 json_object_string_add(json_mac
, "type", "remote");
1210 json_object_string_add(
1211 json_mac
, "remoteVtep",
1212 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1213 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1214 json_object_string_add(json_mac
, "type", "auto");
1216 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1217 json_object_boolean_true_add(json_mac
, "stickyMac");
1219 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1220 json_object_boolean_true_add(json_mac
,
1223 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1224 json_object_boolean_true_add(json_mac
,
1225 "remoteGatewayMac");
1227 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1228 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1230 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1231 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1232 json_object_boolean_true_add(json_mac
, "isDuplicate");
1234 json_object_boolean_false_add(json_mac
, "isDuplicate");
1236 /* print all the associated neigh */
1237 if (!listcount(mac
->neigh_list
))
1238 json_object_string_add(json_mac
, "neighbors", "none");
1240 json_object
*json_active_nbrs
= json_object_new_array();
1241 json_object
*json_inactive_nbrs
=
1242 json_object_new_array();
1243 json_object
*json_nbrs
= json_object_new_object();
1245 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1246 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1247 json_object_array_add(
1249 json_object_new_string(
1254 json_object_array_add(
1256 json_object_new_string(
1262 json_object_object_add(json_nbrs
, "active",
1264 json_object_object_add(json_nbrs
, "inactive",
1265 json_inactive_nbrs
);
1266 json_object_object_add(json_mac
, "neighbors",
1270 json_object_object_add(json
, buf1
, json_mac
);
1272 vty_out(vty
, "MAC: %s\n", buf1
);
1274 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1275 struct zebra_ns
*zns
;
1276 struct interface
*ifp
;
1279 ifindex
= mac
->fwd_info
.local
.ifindex
;
1280 zns
= zebra_ns_lookup(NS_DEFAULT
);
1281 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1284 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1285 if (mac
->fwd_info
.local
.vid
)
1286 vty_out(vty
, " VLAN: %u",
1287 mac
->fwd_info
.local
.vid
);
1288 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1289 vty_out(vty
, " Remote VTEP: %s",
1290 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1291 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1292 vty_out(vty
, " Auto Mac ");
1295 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1296 vty_out(vty
, " Sticky Mac ");
1298 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1299 vty_out(vty
, " Default-gateway Mac ");
1301 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1302 vty_out(vty
, " Remote-gateway Mac ");
1305 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1309 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1310 vty_out(vty
, " Duplicate, detected at %s",
1311 time_to_string(mac
->dad_dup_detect_time
));
1312 } else if (mac
->dad_count
) {
1313 monotime_since(&mac
->detect_start_time
,
1314 &detect_start_time
);
1315 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1316 char *buf
= time_to_string(
1317 mac
->detect_start_time
.tv_sec
);
1320 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1322 " Duplicate detection started at %s, detection count %u\n",
1323 tmp_buf
, mac
->dad_count
);
1327 /* print all the associated neigh */
1328 vty_out(vty
, " Neighbors:\n");
1329 if (!listcount(mac
->neigh_list
))
1330 vty_out(vty
, " No Neighbors\n");
1332 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1333 vty_out(vty
, " %s %s\n",
1334 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1335 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1346 * Print MAC hash entry - called for display of all MACs.
1348 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1351 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1353 char buf1
[ETHER_ADDR_STRLEN
];
1354 struct mac_walk_ctx
*wctx
= ctxt
;
1357 json_mac_hdr
= wctx
->json
;
1358 mac
= (zebra_mac_t
*)bucket
->data
;
1360 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1363 json_mac
= json_object_new_object();
1365 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1366 struct zebra_ns
*zns
;
1368 struct interface
*ifp
;
1371 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1374 zns
= zebra_ns_lookup(NS_DEFAULT
);
1375 ifindex
= mac
->fwd_info
.local
.ifindex
;
1376 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1377 if (!ifp
) // unexpected
1379 vid
= mac
->fwd_info
.local
.vid
;
1380 if (json_mac_hdr
== NULL
)
1381 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1384 json_object_string_add(json_mac
, "type", "local");
1385 json_object_string_add(json_mac
, "intf", ifp
->name
);
1388 if (json_mac_hdr
== NULL
)
1389 vty_out(vty
, " %-5u", vid
);
1391 json_object_int_add(json_mac
, "vlan", vid
);
1393 if (json_mac_hdr
== NULL
) {
1396 json_object_int_add(json_mac
, "localSequence",
1398 json_object_int_add(json_mac
, "remoteSequence",
1400 json_object_int_add(json_mac
, "detectionCount",
1402 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1403 json_object_boolean_true_add(json_mac
,
1406 json_object_boolean_false_add(json_mac
,
1408 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1413 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1415 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1416 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1420 if (json_mac_hdr
== NULL
) {
1421 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1422 (wctx
->count
== 0)) {
1423 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1424 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC",
1425 "Type", "Intf/Remote VTEP", "VLAN");
1427 vty_out(vty
, "%-17s %-6s %-21s\n", buf1
, "remote",
1428 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1430 json_object_string_add(json_mac
, "type", "remote");
1431 json_object_string_add(json_mac
, "remoteVtep",
1432 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1433 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1434 json_object_int_add(json_mac
, "localSequence",
1436 json_object_int_add(json_mac
, "remoteSequence",
1438 json_object_int_add(json_mac
, "detectionCount",
1440 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1441 json_object_boolean_true_add(json_mac
,
1444 json_object_boolean_false_add(json_mac
,
1453 /* Print Duplicate MAC */
1454 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1458 mac
= (zebra_mac_t
*)bucket
->data
;
1462 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1463 zvni_print_mac_hash(bucket
, ctxt
);
1467 * Print MAC hash entry in detail - called for display of all MACs.
1469 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1472 json_object
*json_mac_hdr
= NULL
;
1474 struct mac_walk_ctx
*wctx
= ctxt
;
1475 char buf1
[ETHER_ADDR_STRLEN
];
1478 json_mac_hdr
= wctx
->json
;
1479 mac
= (zebra_mac_t
*)bucket
->data
;
1484 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1486 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1489 /* Print Duplicate MAC in detail */
1490 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1495 mac
= (zebra_mac_t
*)bucket
->data
;
1499 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1500 zvni_print_mac_hash_detail(bucket
, ctxt
);
1504 * Print MACs for all VNI.
1506 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1509 json_object
*json
= NULL
, *json_vni
= NULL
;
1510 json_object
*json_mac
= NULL
;
1513 struct mac_walk_ctx
*wctx
= ctxt
;
1514 char vni_str
[VNI_STR_LEN
];
1516 vty
= (struct vty
*)wctx
->vty
;
1517 json
= (struct json_object
*)wctx
->json
;
1519 zvni
= (zebra_vni_t
*)bucket
->data
;
1522 /*We are iterating over a new VNI, set the count to 0*/
1525 num_macs
= num_valid_macs(zvni
);
1529 if (wctx
->print_dup
)
1530 num_macs
= num_dup_detected_macs(zvni
);
1533 json_vni
= json_object_new_object();
1534 json_mac
= json_object_new_object();
1535 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1538 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1540 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1541 zvni
->vni
, num_macs
);
1542 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1543 "Intf/Remote VTEP", "VLAN");
1545 json_object_int_add(json_vni
, "numMacs", num_macs
);
1550 json_object_int_add(json_vni
, "numMacs", num_macs
);
1551 json_object_object_add(json
, vni_str
, json_vni
);
1556 /* assign per-vni to wctx->json object to fill macs
1557 * under the vni. Re-assign primary json object to fill
1558 * next vni information.
1560 wctx
->json
= json_mac
;
1561 if (wctx
->print_dup
)
1562 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1564 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1568 json_object_object_add(json_vni
, "macs", json_mac
);
1569 json_object_object_add(json
, vni_str
, json_vni
);
1574 * Print MACs in detail for all VNI.
1576 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1580 json_object
*json
= NULL
, *json_vni
= NULL
;
1581 json_object
*json_mac
= NULL
;
1584 struct mac_walk_ctx
*wctx
= ctxt
;
1585 char vni_str
[VNI_STR_LEN
];
1587 vty
= (struct vty
*)wctx
->vty
;
1588 json
= (struct json_object
*)wctx
->json
;
1590 zvni
= (zebra_vni_t
*)bucket
->data
;
1593 vty_out(vty
, "{}\n");
1598 /*We are iterating over a new VNI, set the count to 0*/
1601 num_macs
= num_valid_macs(zvni
);
1605 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1609 json_vni
= json_object_new_object();
1610 json_mac
= json_object_new_object();
1611 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1614 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1616 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1617 zvni
->vni
, num_macs
);
1619 json_object_int_add(json_vni
, "numMacs", num_macs
);
1621 /* assign per-vni to wctx->json object to fill macs
1622 * under the vni. Re-assign primary json object to fill
1623 * next vni information.
1625 wctx
->json
= json_mac
;
1626 if (wctx
->print_dup
)
1627 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1630 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1634 json_object_object_add(json_vni
, "macs", json_mac
);
1635 json_object_object_add(json
, vni_str
, json_vni
);
1639 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1641 struct nh_walk_ctx
*wctx
= NULL
;
1642 struct vty
*vty
= NULL
;
1643 struct json_object
*json_vni
= NULL
;
1644 struct json_object
*json_nh
= NULL
;
1645 zebra_neigh_t
*n
= NULL
;
1646 char buf1
[ETHER_ADDR_STRLEN
];
1647 char buf2
[INET6_ADDRSTRLEN
];
1649 wctx
= (struct nh_walk_ctx
*)ctx
;
1651 json_vni
= wctx
->json
;
1653 json_nh
= json_object_new_object();
1654 n
= (zebra_neigh_t
*)bucket
->data
;
1657 vty_out(vty
, "%-15s %-17s\n",
1658 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1659 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1661 json_object_string_add(json_nh
, "nexthopIp",
1662 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1663 json_object_string_add(
1664 json_nh
, "routerMac",
1665 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1666 json_object_object_add(json_vni
,
1667 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1672 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1675 struct vty
*vty
= NULL
;
1676 json_object
*json
= NULL
;
1677 json_object
*json_vni
= NULL
;
1678 zebra_l3vni_t
*zl3vni
= NULL
;
1679 uint32_t num_nh
= 0;
1680 struct nh_walk_ctx wctx
;
1681 char vni_str
[VNI_STR_LEN
];
1683 vty
= (struct vty
*)args
[0];
1684 json
= (struct json_object
*)args
[1];
1686 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1688 num_nh
= hashcount(zl3vni
->nh_table
);
1693 json_vni
= json_object_new_object();
1694 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1698 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1699 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1701 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1703 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1705 wctx
.json
= json_vni
;
1706 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1708 json_object_object_add(json
, vni_str
, json_vni
);
1711 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1714 struct vty
*vty
= NULL
;
1715 json_object
*json
= NULL
;
1716 json_object
*json_vni
= NULL
;
1717 zebra_l3vni_t
*zl3vni
= NULL
;
1719 struct rmac_walk_ctx wctx
;
1720 char vni_str
[VNI_STR_LEN
];
1722 vty
= (struct vty
*)args
[0];
1723 json
= (struct json_object
*)args
[1];
1725 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1727 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1732 json_vni
= json_object_new_object();
1733 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1737 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1738 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1740 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1742 /* assign per-vni to wctx->json object to fill macs
1743 * under the vni. Re-assign primary json object to fill
1744 * next vni information.
1746 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1748 wctx
.json
= json_vni
;
1749 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1751 json_object_object_add(json
, vni_str
, json_vni
);
1754 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1756 zebra_mac_t
*zrmac
= NULL
;
1757 struct rmac_walk_ctx
*wctx
= NULL
;
1758 struct vty
*vty
= NULL
;
1759 struct json_object
*json
= NULL
;
1760 struct json_object
*json_rmac
= NULL
;
1761 char buf
[ETHER_ADDR_STRLEN
];
1763 wctx
= (struct rmac_walk_ctx
*)ctx
;
1767 json_rmac
= json_object_new_object();
1768 zrmac
= (zebra_mac_t
*)bucket
->data
;
1771 vty_out(vty
, "%-17s %-21s\n",
1772 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1773 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1775 json_object_string_add(
1776 json_rmac
, "routerMac",
1777 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1778 json_object_string_add(json_rmac
, "vtepIp",
1779 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1780 json_object_object_add(
1781 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1786 /* print a specific L3 VNI entry */
1787 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1789 char buf
[ETHER_ADDR_STRLEN
];
1790 struct vty
*vty
= NULL
;
1791 json_object
*json
= NULL
;
1792 zebra_vni_t
*zvni
= NULL
;
1793 json_object
*json_vni_list
= NULL
;
1794 struct listnode
*node
= NULL
, *nnode
= NULL
;
1800 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1801 vty_out(vty
, " Type: %s\n", "L3");
1802 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1803 vty_out(vty
, " Local Vtep Ip: %s\n",
1804 inet_ntoa(zl3vni
->local_vtep_ip
));
1805 vty_out(vty
, " Vxlan-Intf: %s\n",
1806 zl3vni_vxlan_if_name(zl3vni
));
1807 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1808 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1809 vty_out(vty
, " VNI Filter: %s\n",
1810 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1811 ? "prefix-routes-only"
1813 vty_out(vty
, " Router MAC: %s\n",
1814 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1815 vty_out(vty
, " L2 VNIs: ");
1816 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1817 vty_out(vty
, "%u ", zvni
->vni
);
1820 json_vni_list
= json_object_new_array();
1821 json_object_int_add(json
, "vni", zl3vni
->vni
);
1822 json_object_string_add(json
, "type", "L3");
1823 json_object_string_add(json
, "localVtepIp",
1824 inet_ntoa(zl3vni
->local_vtep_ip
));
1825 json_object_string_add(json
, "vxlanIntf",
1826 zl3vni_vxlan_if_name(zl3vni
));
1827 json_object_string_add(json
, "sviIntf",
1828 zl3vni_svi_if_name(zl3vni
));
1829 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1830 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1831 json_object_string_add(
1833 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1834 json_object_string_add(
1836 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1837 ? "prefix-routes-only"
1839 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1840 json_object_array_add(json_vni_list
,
1841 json_object_new_int(zvni
->vni
));
1843 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1848 * Print a specific VNI entry.
1850 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1853 zebra_vtep_t
*zvtep
;
1856 json_object
*json
= NULL
;
1857 json_object
*json_vtep_list
= NULL
;
1858 json_object
*json_ip_str
= NULL
;
1864 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1865 vty_out(vty
, " Type: %s\n", "L2");
1866 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1868 json_object_int_add(json
, "vni", zvni
->vni
);
1869 json_object_string_add(json
, "type", "L2");
1870 json_object_string_add(json
, "vrf",
1871 vrf_id_to_name(zvni
->vrf_id
));
1874 if (!zvni
->vxlan_if
) { // unexpected
1876 vty_out(vty
, " VxLAN interface: unknown\n");
1879 num_macs
= num_valid_macs(zvni
);
1880 num_neigh
= hashcount(zvni
->neigh_table
);
1882 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1883 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1884 vty_out(vty
, " Local VTEP IP: %s\n",
1885 inet_ntoa(zvni
->local_vtep_ip
));
1886 vty_out(vty
, " Mcast group: %s\n",
1887 inet_ntoa(zvni
->mcast_grp
));
1889 json_object_string_add(json
, "vxlanInterface",
1890 zvni
->vxlan_if
->name
);
1891 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1892 json_object_string_add(json
, "vtepIp",
1893 inet_ntoa(zvni
->local_vtep_ip
));
1894 json_object_string_add(json
, "mcastGroup",
1895 inet_ntoa(zvni
->mcast_grp
));
1896 json_object_string_add(json
, "advertiseGatewayMacip",
1897 zvni
->advertise_gw_macip
? "Yes" : "No");
1898 json_object_int_add(json
, "numMacs", num_macs
);
1899 json_object_int_add(json
, "numArpNd", num_neigh
);
1903 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1906 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1908 json_vtep_list
= json_object_new_array();
1909 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1910 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1911 zvtep
->flood_control
,
1912 VXLAN_FLOOD_STR_DEFAULT
);
1915 vty_out(vty
, " %s flood: %s\n",
1916 inet_ntoa(zvtep
->vtep_ip
),
1919 json_ip_str
= json_object_new_string(
1920 inet_ntoa(zvtep
->vtep_ip
));
1921 json_object_array_add(json_vtep_list
,
1926 json_object_object_add(json
, "numRemoteVteps",
1931 " Number of MACs (local and remote) known for this VNI: %u\n",
1934 " Number of ARPs (IPv4 and IPv6, local and remote) "
1935 "known for this VNI: %u\n",
1937 vty_out(vty
, " Advertise-gw-macip: %s\n",
1938 zvni
->advertise_gw_macip
? "Yes" : "No");
1942 /* print a L3 VNI hash entry */
1943 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1945 struct vty
*vty
= NULL
;
1946 json_object
*json
= NULL
;
1947 json_object
*json_vni
= NULL
;
1948 zebra_l3vni_t
*zl3vni
= NULL
;
1950 vty
= (struct vty
*)ctx
[0];
1951 json
= (json_object
*)ctx
[1];
1953 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1956 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1957 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1958 hashcount(zl3vni
->rmac_table
),
1959 hashcount(zl3vni
->nh_table
), "n/a",
1960 zl3vni_vrf_name(zl3vni
));
1962 char vni_str
[VNI_STR_LEN
];
1964 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1965 json_vni
= json_object_new_object();
1966 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1967 json_object_string_add(json_vni
, "vxlanIf",
1968 zl3vni_vxlan_if_name(zl3vni
));
1969 json_object_int_add(json_vni
, "numMacs",
1970 hashcount(zl3vni
->rmac_table
));
1971 json_object_int_add(json_vni
, "numArpNd",
1972 hashcount(zl3vni
->nh_table
));
1973 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1974 json_object_string_add(json_vni
, "type", "L3");
1975 json_object_string_add(json_vni
, "tenantVrf",
1976 zl3vni_vrf_name(zl3vni
));
1977 json_object_object_add(json
, vni_str
, json_vni
);
1981 /* Private Structure to pass callback data for hash iterator */
1982 struct zvni_evpn_show
{
1985 struct zebra_vrf
*zvrf
;
1988 /* print a L3 VNI hash entry in detail*/
1989 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1991 struct vty
*vty
= NULL
;
1992 zebra_l3vni_t
*zl3vni
= NULL
;
1993 json_object
*json
= NULL
;
1994 bool use_json
= false;
1995 struct zvni_evpn_show
*zes
= data
;
2003 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2005 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2011 * Print a VNI hash entry - called for display of all VNIs.
2013 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2017 zebra_vtep_t
*zvtep
;
2018 uint32_t num_vteps
= 0;
2019 uint32_t num_macs
= 0;
2020 uint32_t num_neigh
= 0;
2021 json_object
*json
= NULL
;
2022 json_object
*json_vni
= NULL
;
2023 json_object
*json_ip_str
= NULL
;
2024 json_object
*json_vtep_list
= NULL
;
2029 zvni
= (zebra_vni_t
*)bucket
->data
;
2031 zvtep
= zvni
->vteps
;
2034 zvtep
= zvtep
->next
;
2037 num_macs
= num_valid_macs(zvni
);
2038 num_neigh
= hashcount(zvni
->neigh_table
);
2040 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2042 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2043 num_macs
, num_neigh
, num_vteps
,
2044 vrf_id_to_name(zvni
->vrf_id
));
2046 char vni_str
[VNI_STR_LEN
];
2047 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2048 json_vni
= json_object_new_object();
2049 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2050 json_object_string_add(json_vni
, "type", "L2");
2051 json_object_string_add(json_vni
, "vxlanIf",
2052 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2054 json_object_int_add(json_vni
, "numMacs", num_macs
);
2055 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2056 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2057 json_object_string_add(json_vni
, "tenantVrf",
2058 vrf_id_to_name(zvni
->vrf_id
));
2060 json_vtep_list
= json_object_new_array();
2061 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2062 json_ip_str
= json_object_new_string(
2063 inet_ntoa(zvtep
->vtep_ip
));
2064 json_object_array_add(json_vtep_list
,
2067 json_object_object_add(json_vni
, "remoteVteps",
2070 json_object_object_add(json
, vni_str
, json_vni
);
2075 * Print a VNI hash entry in detail - called for display of all VNIs.
2077 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2081 json_object
*json
= NULL
;
2082 bool use_json
= false;
2083 struct zvni_evpn_show
*zes
= data
;
2091 zvni
= (zebra_vni_t
*)bucket
->data
;
2093 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2098 * Inform BGP about local MACIP.
2100 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2101 struct ipaddr
*ip
, uint8_t flags
,
2102 uint32_t seq
, int state
, uint16_t cmd
)
2104 char buf
[ETHER_ADDR_STRLEN
];
2105 char buf2
[INET6_ADDRSTRLEN
];
2107 struct zserv
*client
= NULL
;
2108 struct stream
*s
= NULL
;
2110 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2111 /* BGP may not be running. */
2115 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2117 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2118 stream_putl(s
, vni
);
2119 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2122 if (IS_IPADDR_V4(ip
))
2123 ipa_len
= IPV4_MAX_BYTELEN
;
2124 else if (IS_IPADDR_V6(ip
))
2125 ipa_len
= IPV6_MAX_BYTELEN
;
2127 stream_putl(s
, ipa_len
); /* IP address length */
2129 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2131 stream_putl(s
, 0); /* Just MAC. */
2133 if (cmd
== ZEBRA_MACIP_ADD
) {
2134 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2135 stream_putl(s
, seq
); /* sequence number */
2137 stream_putl(s
, state
); /* state - active/inactive */
2141 /* Write packet size. */
2142 stream_putw_at(s
, 0, stream_get_endp(s
));
2144 if (IS_ZEBRA_DEBUG_VXLAN
)
2146 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2147 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2148 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2149 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2150 zebra_route_string(client
->proto
));
2152 if (cmd
== ZEBRA_MACIP_ADD
)
2153 client
->macipadd_cnt
++;
2155 client
->macipdel_cnt
++;
2157 return zserv_send_message(client
, s
);
2161 * Make hash key for neighbors.
2163 static unsigned int neigh_hash_keymake(const void *p
)
2165 const zebra_neigh_t
*n
= p
;
2166 const struct ipaddr
*ip
= &n
->ip
;
2168 if (IS_IPADDR_V4(ip
))
2169 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2171 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2172 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2176 * Compare two neighbor hash structures.
2178 static bool neigh_cmp(const void *p1
, const void *p2
)
2180 const zebra_neigh_t
*n1
= p1
;
2181 const zebra_neigh_t
*n2
= p2
;
2183 if (n1
== NULL
&& n2
== NULL
)
2186 if (n1
== NULL
|| n2
== NULL
)
2189 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2192 static int neigh_list_cmp(void *p1
, void *p2
)
2194 const zebra_neigh_t
*n1
= p1
;
2195 const zebra_neigh_t
*n2
= p2
;
2197 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2201 * Callback to allocate neighbor hash entry.
2203 static void *zvni_neigh_alloc(void *p
)
2205 const zebra_neigh_t
*tmp_n
= p
;
2208 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2215 * Add neighbor entry.
2217 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2218 struct ethaddr
*mac
)
2220 zebra_neigh_t tmp_n
;
2221 zebra_neigh_t
*n
= NULL
;
2222 zebra_mac_t
*zmac
= NULL
;
2224 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2225 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2226 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2229 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2230 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2232 n
->dad_ip_auto_recovery_timer
= NULL
;
2234 /* Associate the neigh to mac */
2235 zmac
= zvni_mac_lookup(zvni
, mac
);
2237 listnode_add_sort(zmac
->neigh_list
, n
);
2243 * Delete neighbor entry.
2245 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2247 zebra_neigh_t
*tmp_n
;
2248 zebra_mac_t
*zmac
= NULL
;
2250 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2252 listnode_delete(zmac
->neigh_list
, n
);
2254 /* Cancel auto recovery */
2255 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2257 /* Free the VNI hash entry and allocated memory. */
2258 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2259 XFREE(MTYPE_NEIGH
, tmp_n
);
2265 * Free neighbor hash entry (callback)
2267 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2269 struct neigh_walk_ctx
*wctx
= arg
;
2270 zebra_neigh_t
*n
= bucket
->data
;
2272 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2273 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2274 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2275 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2276 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2277 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2278 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2279 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2280 &n
->emac
, 0, n
->state
);
2282 if (wctx
->uninstall
)
2283 zvni_neigh_uninstall(wctx
->zvni
, n
);
2285 zvni_neigh_del(wctx
->zvni
, n
);
2292 * Delete all neighbor entries from specific VTEP for a particular VNI.
2294 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2295 struct in_addr
*r_vtep_ip
)
2297 struct neigh_walk_ctx wctx
;
2299 if (!zvni
->neigh_table
)
2302 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2304 wctx
.uninstall
= uninstall
;
2305 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2306 wctx
.r_vtep_ip
= *r_vtep_ip
;
2308 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2312 * Delete all neighbor entries for this VNI.
2314 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2317 struct neigh_walk_ctx wctx
;
2319 if (!zvni
->neigh_table
)
2322 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2324 wctx
.uninstall
= uninstall
;
2325 wctx
.upd_client
= upd_client
;
2328 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2332 * Look up neighbor hash entry.
2334 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2339 memset(&tmp
, 0, sizeof(tmp
));
2340 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2341 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2347 * Process all neighbors associated with a MAC upon the MAC being learnt
2348 * locally or undergoing any other change (such as sequence number).
2350 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2354 zebra_neigh_t
*n
= NULL
;
2355 struct listnode
*node
= NULL
;
2356 struct zebra_vrf
*zvrf
= NULL
;
2357 char buf
[ETHER_ADDR_STRLEN
];
2359 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2361 if (IS_ZEBRA_DEBUG_VXLAN
)
2362 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2363 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2364 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2366 /* Walk all neighbors and mark any inactive local neighbors as
2367 * active and/or update sequence number upon a move, and inform BGP.
2368 * The action for remote neighbors is TBD.
2369 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2370 * accidentally end up deleting a just-learnt local neighbor.
2372 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2373 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2374 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2375 ZEBRA_NEIGH_SET_ACTIVE(n
);
2376 n
->loc_seq
= zmac
->loc_seq
;
2377 if (!(zvrf
->dup_addr_detect
&&
2378 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2379 ZEBRA_NEIGH_DUPLICATE
)))
2380 zvni_neigh_send_add_to_client(
2381 zvni
->vni
, &n
->ip
, &n
->emac
,
2382 n
->flags
, n
->loc_seq
);
2389 * Process all neighbors associated with a local MAC upon the MAC being
2392 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2395 zebra_neigh_t
*n
= NULL
;
2396 struct listnode
*node
= NULL
;
2397 char buf
[ETHER_ADDR_STRLEN
];
2399 if (IS_ZEBRA_DEBUG_VXLAN
)
2400 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2401 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2404 /* Walk all local neighbors and mark as inactive and inform
2406 * TBD: There is currently no handling for remote neighbors. We
2407 * don't expect them to exist, if they do, do we install the MAC
2408 * as a remote MAC and the neighbor as remote?
2410 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2411 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2412 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2413 ZEBRA_NEIGH_SET_INACTIVE(n
);
2415 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2416 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2423 * Process all neighbors associated with a MAC upon the MAC being remotely
2426 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2429 zebra_neigh_t
*n
= NULL
;
2430 struct listnode
*node
= NULL
;
2431 char buf
[ETHER_ADDR_STRLEN
];
2433 if (IS_ZEBRA_DEBUG_VXLAN
)
2434 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2435 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2438 /* Walk all local neighbors and mark as inactive and inform
2441 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2442 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2443 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2444 ZEBRA_NEIGH_SET_INACTIVE(n
);
2446 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2447 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2454 * Process all neighbors associated with a remote MAC upon the MAC being
2457 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2460 /* NOTE: Currently a NO-OP. */
2463 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2465 zebra_neigh_t
*nbr
= NULL
;
2466 struct listnode
*node
= NULL
;
2468 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2469 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2470 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2471 zvni_neigh_probe(zvni
, nbr
);
2476 * Inform BGP about local neighbor addition.
2478 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2479 struct ethaddr
*macaddr
,
2480 uint8_t neigh_flags
,
2485 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2486 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2487 /* Set router flag (R-bit) based on local neigh entry add */
2488 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2489 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2491 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2492 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2496 * Inform BGP about local neighbor deletion.
2498 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2499 struct ethaddr
*macaddr
, uint8_t flags
,
2502 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2503 0, state
, ZEBRA_MACIP_DEL
);
2507 * Install remote neighbor into the kernel.
2509 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2511 struct zebra_if
*zif
;
2512 struct zebra_l2info_vxlan
*vxl
;
2513 struct interface
*vlan_if
;
2519 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2522 zif
= zvni
->vxlan_if
->info
;
2525 vxl
= &zif
->l2info
.vxl
;
2527 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2531 flags
= NTF_EXT_LEARNED
;
2532 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2533 flags
|= NTF_ROUTER
;
2534 ZEBRA_NEIGH_SET_ACTIVE(n
);
2535 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2541 * Uninstall remote neighbor from the kernel.
2543 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2545 struct zebra_if
*zif
;
2546 struct zebra_l2info_vxlan
*vxl
;
2547 struct interface
*vlan_if
;
2549 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2552 if (!zvni
->vxlan_if
) {
2553 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2558 zif
= zvni
->vxlan_if
->info
;
2561 vxl
= &zif
->l2info
.vxl
;
2562 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2566 ZEBRA_NEIGH_SET_INACTIVE(n
);
2568 return kernel_del_neigh(vlan_if
, &n
->ip
);
2572 * Probe neighbor from the kernel.
2574 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2576 struct zebra_if
*zif
;
2577 struct zebra_l2info_vxlan
*vxl
;
2578 struct interface
*vlan_if
;
2580 zif
= zvni
->vxlan_if
->info
;
2583 vxl
= &zif
->l2info
.vxl
;
2585 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2590 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2598 * Install neighbor hash entry - called upon access VLAN change.
2600 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2603 struct neigh_walk_ctx
*wctx
= ctxt
;
2605 n
= (zebra_neigh_t
*)bucket
->data
;
2607 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2608 zvni_neigh_install(wctx
->zvni
, n
);
2611 /* Get the VRR interface for SVI if any */
2612 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2614 struct zebra_vrf
*zvrf
= NULL
;
2615 struct interface
*tmp_if
= NULL
;
2616 struct zebra_if
*zif
= NULL
;
2618 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2621 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2626 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2629 if (zif
->link
== ifp
)
2636 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2638 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2639 struct connected
*c
= NULL
;
2640 struct ethaddr macaddr
;
2642 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2644 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2647 memset(&ip
, 0, sizeof(struct ipaddr
));
2648 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2651 if (c
->address
->family
== AF_INET
) {
2652 ip
.ipa_type
= IPADDR_V4
;
2653 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2654 sizeof(struct in_addr
));
2655 } else if (c
->address
->family
== AF_INET6
) {
2656 ip
.ipa_type
= IPADDR_V6
;
2657 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2658 sizeof(struct in6_addr
));
2663 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2669 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2671 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2672 struct connected
*c
= NULL
;
2673 struct ethaddr macaddr
;
2675 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2677 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2680 memset(&ip
, 0, sizeof(struct ipaddr
));
2681 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2684 if (c
->address
->family
== AF_INET
) {
2685 ip
.ipa_type
= IPADDR_V4
;
2686 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2687 sizeof(struct in_addr
));
2688 } else if (c
->address
->family
== AF_INET6
) {
2689 ip
.ipa_type
= IPADDR_V6
;
2690 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2691 sizeof(struct in6_addr
));
2696 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2702 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2705 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2706 struct connected
*c
= NULL
;
2707 struct ethaddr macaddr
;
2709 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2711 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2714 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2716 /* skip link local address */
2717 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2722 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2723 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2725 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2726 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2732 * zvni_gw_macip_add_to_client
2734 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2735 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2737 char buf
[ETHER_ADDR_STRLEN
];
2738 char buf2
[INET6_ADDRSTRLEN
];
2739 zebra_neigh_t
*n
= NULL
;
2740 zebra_mac_t
*mac
= NULL
;
2741 struct zebra_if
*zif
= NULL
;
2742 struct zebra_l2info_vxlan
*vxl
= NULL
;
2744 zif
= zvni
->vxlan_if
->info
;
2748 vxl
= &zif
->l2info
.vxl
;
2750 mac
= zvni_mac_lookup(zvni
, macaddr
);
2752 mac
= zvni_mac_add(zvni
, macaddr
);
2754 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2755 "Failed to add MAC %s intf %s(%u) VID %u",
2756 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2757 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2762 /* Set "local" forwarding info. */
2763 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2764 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2765 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2766 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2767 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2768 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2770 n
= zvni_neigh_lookup(zvni
, ip
);
2772 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2775 EC_ZEBRA_MAC_ADD_FAILED
,
2776 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2777 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2778 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2779 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2784 /* Set "local" forwarding info. */
2785 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2786 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2787 ZEBRA_NEIGH_SET_ACTIVE(n
);
2788 /* Set Router flag (R-bit) */
2789 if (ip
->ipa_type
== IPADDR_V6
)
2790 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2791 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2792 n
->ifindex
= ifp
->ifindex
;
2794 /* Only advertise in BGP if the knob is enabled */
2795 if (!advertise_gw_macip_enabled(zvni
))
2798 if (IS_ZEBRA_DEBUG_VXLAN
)
2800 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2801 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2802 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2803 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2805 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2806 n
->flags
, n
->loc_seq
);
2812 * zvni_gw_macip_del_from_client
2814 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2817 char buf1
[ETHER_ADDR_STRLEN
];
2818 char buf2
[INET6_ADDRSTRLEN
];
2819 zebra_neigh_t
*n
= NULL
;
2820 zebra_mac_t
*mac
= NULL
;
2822 /* If the neigh entry is not present nothing to do*/
2823 n
= zvni_neigh_lookup(zvni
, ip
);
2827 /* mac entry should be present */
2828 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2830 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2831 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2832 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2836 /* If the entry is not local nothing to do*/
2837 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2840 /* only need to delete the entry from bgp if we sent it before */
2841 if (IS_ZEBRA_DEBUG_VXLAN
)
2843 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2844 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2845 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2846 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2848 /* Remove neighbor from BGP. */
2849 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2850 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2852 /* Delete this neighbor entry. */
2853 zvni_neigh_del(zvni
, n
);
2855 /* see if the mac needs to be deleted as well*/
2857 zvni_deref_ip2mac(zvni
, mac
);
2862 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2865 zebra_vni_t
*zvni
= NULL
;
2866 struct zebra_if
*zif
= NULL
;
2867 struct zebra_l2info_vxlan zl2_info
;
2868 struct interface
*vlan_if
= NULL
;
2869 struct interface
*vrr_if
= NULL
;
2870 struct interface
*ifp
;
2872 /* Add primary SVI MAC*/
2873 zvni
= (zebra_vni_t
*)bucket
->data
;
2875 /* Global (Zvrf) advertise-default-gw is disabled,
2876 * but zvni advertise-default-gw is enabled
2878 if (zvni
->advertise_gw_macip
) {
2879 if (IS_ZEBRA_DEBUG_VXLAN
)
2880 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
2885 ifp
= zvni
->vxlan_if
;
2890 /* If down or not mapped to a bridge, we're done. */
2891 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2894 zl2_info
= zif
->l2info
.vxl
;
2897 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2901 /* Del primary MAC-IP */
2902 zvni_del_macip_for_intf(vlan_if
, zvni
);
2904 /* Del VRR MAC-IP - if any*/
2905 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2907 zvni_del_macip_for_intf(vrr_if
, zvni
);
2912 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2915 zebra_vni_t
*zvni
= NULL
;
2916 struct zebra_if
*zif
= NULL
;
2917 struct zebra_l2info_vxlan zl2_info
;
2918 struct interface
*vlan_if
= NULL
;
2919 struct interface
*vrr_if
= NULL
;
2920 struct interface
*ifp
= NULL
;
2922 zvni
= (zebra_vni_t
*)bucket
->data
;
2924 ifp
= zvni
->vxlan_if
;
2929 /* If down or not mapped to a bridge, we're done. */
2930 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2932 zl2_info
= zif
->l2info
.vxl
;
2935 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2939 /* Add primary SVI MAC-IP */
2940 zvni_add_macip_for_intf(vlan_if
, zvni
);
2942 if (advertise_gw_macip_enabled(zvni
)) {
2943 /* Add VRR MAC-IP - if any*/
2944 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2946 zvni_add_macip_for_intf(vrr_if
, zvni
);
2952 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2955 zebra_vni_t
*zvni
= NULL
;
2956 struct zebra_if
*zif
= NULL
;
2957 struct zebra_l2info_vxlan zl2_info
;
2958 struct interface
*vlan_if
= NULL
;
2959 struct interface
*ifp
;
2961 /* Add primary SVI MAC*/
2962 zvni
= (zebra_vni_t
*)bucket
->data
;
2966 /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
2969 if (zvni
->advertise_svi_macip
) {
2970 if (IS_ZEBRA_DEBUG_VXLAN
)
2971 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
2976 ifp
= zvni
->vxlan_if
;
2981 /* If down or not mapped to a bridge, we're done. */
2982 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2985 zl2_info
= zif
->l2info
.vxl
;
2987 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2988 zif
->brslave_info
.br_if
);
2992 /* Del primary MAC-IP */
2993 zvni_del_macip_for_intf(vlan_if
, zvni
);
2998 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2999 struct interface
*ifp
,
3001 struct ethaddr
*macaddr
,
3004 char buf
[ETHER_ADDR_STRLEN
];
3005 char buf2
[INET6_ADDRSTRLEN
];
3006 struct zebra_vrf
*zvrf
;
3007 zebra_neigh_t
*n
= NULL
;
3008 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3009 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3010 bool upd_mac_seq
= false;
3011 bool neigh_mac_change
= false;
3012 bool neigh_on_hold
= false;
3013 bool neigh_was_remote
= false;
3014 bool do_dad
= false;
3015 struct in_addr vtep_ip
= {.s_addr
= 0};
3017 /* Check if the MAC exists. */
3018 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3020 /* create a dummy MAC if the MAC is not already present */
3021 if (IS_ZEBRA_DEBUG_VXLAN
)
3023 "AUTO MAC %s created for neigh %s on VNI %u",
3024 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3025 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3027 zmac
= zvni_mac_add(zvni
, macaddr
);
3029 zlog_debug("Failed to add MAC %s VNI %u",
3030 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3035 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3036 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3037 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3039 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3041 * We don't change the MAC to local upon a neighbor
3042 * learn event, we wait for the explicit local MAC
3043 * learn. However, we have to compute its sequence
3044 * number in preparation for when it actually turns
3051 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3053 if (IS_ZEBRA_DEBUG_VXLAN
)
3054 zlog_debug("\tUnable to find vrf for: %d",
3055 zvni
->vxlan_if
->vrf_id
);
3059 /* Check if the neighbor exists. */
3060 n
= zvni_neigh_lookup(zvni
, ip
);
3062 /* New neighbor - create */
3063 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3066 EC_ZEBRA_MAC_ADD_FAILED
,
3067 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3068 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3069 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3070 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3073 /* Set "local" forwarding info. */
3074 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3075 n
->ifindex
= ifp
->ifindex
;
3077 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3081 /* Note any changes and see if of interest to BGP. */
3082 mac_different
= (memcmp(n
->emac
.octet
,
3083 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3084 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3085 ZEBRA_NEIGH_ROUTER_FLAG
);
3086 if (!mac_different
&& is_router
== cur_is_router
) {
3087 if (IS_ZEBRA_DEBUG_VXLAN
)
3089 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3090 n
->ifindex
= ifp
->ifindex
;
3094 if (!mac_different
) {
3095 bool is_neigh_freezed
= false;
3097 /* Only the router flag has changed. */
3100 ZEBRA_NEIGH_ROUTER_FLAG
);
3102 UNSET_FLAG(n
->flags
,
3103 ZEBRA_NEIGH_ROUTER_FLAG
);
3105 /* Neigh is in freeze state and freeze action
3106 * is enabled, do not send update to client.
3108 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3110 CHECK_FLAG(n
->flags
,
3111 ZEBRA_NEIGH_DUPLICATE
));
3113 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3115 return zvni_neigh_send_add_to_client(
3116 zvni
->vni
, ip
, macaddr
,
3117 n
->flags
, n
->loc_seq
);
3119 if (IS_ZEBRA_DEBUG_VXLAN
)
3121 "\tNeighbor active and frozen");
3126 /* The MAC has changed, need to issue a delete
3127 * first as this means a different MACIP route.
3128 * Also, need to do some unlinking/relinking.
3129 * We also need to update the MAC's sequence number
3130 * in different situations.
3132 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3133 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3134 &n
->emac
, 0, n
->state
);
3135 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3137 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3139 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3140 neigh_mac_change
= upd_mac_seq
= true;
3141 listnode_delete(old_zmac
->neigh_list
, n
);
3142 zvni_deref_ip2mac(zvni
, old_zmac
);
3145 /* Update the forwarding info. */
3146 n
->ifindex
= ifp
->ifindex
;
3147 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3149 /* Link to new MAC */
3150 listnode_add_sort(zmac
->neigh_list
, n
);
3151 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3153 * Neighbor has moved from remote to local. Its
3154 * MAC could have also changed as part of the move.
3156 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3158 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3160 old_mac_seq
= CHECK_FLAG(
3165 neigh_mac_change
= upd_mac_seq
= true;
3166 listnode_delete(old_zmac
->neigh_list
,
3168 zvni_deref_ip2mac(zvni
, old_zmac
);
3171 /* Link to new MAC */
3172 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3173 listnode_add_sort(zmac
->neigh_list
, n
);
3175 /* Based on Mobility event Scenario-B from the
3176 * draft, neigh's previous state was remote treat this
3179 neigh_was_remote
= true;
3180 vtep_ip
= n
->r_vtep_ip
;
3181 /* Mark appropriately */
3182 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3183 n
->r_vtep_ip
.s_addr
= 0;
3184 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3185 n
->ifindex
= ifp
->ifindex
;
3189 /* If MAC was previously remote, or the neighbor had a different
3190 * MAC earlier, recompute the sequence number.
3193 uint32_t seq1
, seq2
;
3195 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3196 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3197 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3198 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3199 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3202 /* Mark Router flag (R-bit) */
3204 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3206 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3208 /* Check old and/or new MAC detected as duplicate mark
3209 * the neigh as duplicate
3211 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3212 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3213 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3215 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3216 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3219 /* For IP Duplicate Address Detection (DAD) is trigger,
3220 * when the event is extended mobility based on scenario-B
3221 * from the draft, IP/Neigh's MAC binding changed and
3222 * neigh's previous state was remote.
3224 if (neigh_mac_change
&& neigh_was_remote
)
3227 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3228 &neigh_on_hold
, true);
3230 /* Before we program this in BGP, we need to check if MAC is locally
3231 * learnt. If not, force neighbor to be inactive and reset its seq.
3233 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3234 ZEBRA_NEIGH_SET_INACTIVE(n
);
3236 zmac
->loc_seq
= mac_new_seq
;
3240 /* If the MAC's sequence number has changed, inform the MAC and all
3241 * neighbors associated with the MAC to BGP, else just inform this
3244 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3245 if (IS_ZEBRA_DEBUG_VXLAN
)
3246 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3247 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3248 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3249 zmac
->loc_seq
= mac_new_seq
;
3250 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3251 zmac
->flags
, zmac
->loc_seq
))
3253 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3257 n
->loc_seq
= zmac
->loc_seq
;
3259 if (!neigh_on_hold
) {
3260 ZEBRA_NEIGH_SET_ACTIVE(n
);
3262 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3263 n
->flags
, n
->loc_seq
);
3265 if (IS_ZEBRA_DEBUG_VXLAN
)
3266 zlog_debug("\tNeighbor on hold not sending");
3271 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3272 struct interface
*ifp
,
3274 struct ethaddr
*macaddr
,
3277 char buf
[ETHER_ADDR_STRLEN
];
3278 char buf2
[INET6_ADDRSTRLEN
];
3279 zebra_neigh_t
*n
= NULL
;
3280 zebra_mac_t
*zmac
= NULL
;
3282 /* If the neighbor is unknown, there is no further action. */
3283 n
= zvni_neigh_lookup(zvni
, ip
);
3287 /* If a remote entry, see if it needs to be refreshed */
3288 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3290 if (state
& NUD_STALE
)
3291 zvni_neigh_install(zvni
, n
);
3294 /* We got a "remote" neighbor notification for an entry
3295 * we think is local. This can happen in a multihoming
3296 * scenario - but only if the MAC is already "remote".
3297 * Just mark our entry as "remote".
3299 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3300 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3302 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3303 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3304 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3309 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3310 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3311 ZEBRA_NEIGH_SET_ACTIVE(n
);
3312 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3319 * Make hash key for MAC.
3321 static unsigned int mac_hash_keymake(const void *p
)
3323 const zebra_mac_t
*pmac
= p
;
3324 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3326 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3330 * Compare two MAC addresses.
3332 static bool mac_cmp(const void *p1
, const void *p2
)
3334 const zebra_mac_t
*pmac1
= p1
;
3335 const zebra_mac_t
*pmac2
= p2
;
3337 if (pmac1
== NULL
&& pmac2
== NULL
)
3340 if (pmac1
== NULL
|| pmac2
== NULL
)
3343 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3348 * Callback to allocate MAC hash entry.
3350 static void *zvni_mac_alloc(void *p
)
3352 const zebra_mac_t
*tmp_mac
= p
;
3355 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3358 return ((void *)mac
);
3364 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3366 zebra_mac_t tmp_mac
;
3367 zebra_mac_t
*mac
= NULL
;
3369 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3370 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3371 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3375 mac
->dad_mac_auto_recovery_timer
= NULL
;
3377 mac
->neigh_list
= list_new();
3378 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3386 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3388 zebra_mac_t
*tmp_mac
;
3390 /* Cancel auto recovery */
3391 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3393 list_delete(&mac
->neigh_list
);
3395 /* Free the VNI hash entry and allocated memory. */
3396 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3397 XFREE(MTYPE_MAC
, tmp_mac
);
3403 * Free MAC hash entry (callback)
3405 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3407 struct mac_walk_ctx
*wctx
= arg
;
3408 zebra_mac_t
*mac
= bucket
->data
;
3410 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3411 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3412 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3413 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3414 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3415 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3416 &wctx
->r_vtep_ip
))) {
3417 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3418 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3422 if (wctx
->uninstall
)
3423 zvni_mac_uninstall(wctx
->zvni
, mac
);
3425 zvni_mac_del(wctx
->zvni
, mac
);
3432 * Delete all MAC entries from specific VTEP for a particular VNI.
3434 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3435 struct in_addr
*r_vtep_ip
)
3437 struct mac_walk_ctx wctx
;
3439 if (!zvni
->mac_table
)
3442 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3444 wctx
.uninstall
= uninstall
;
3445 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3446 wctx
.r_vtep_ip
= *r_vtep_ip
;
3448 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3452 * Delete all MAC entries for this VNI.
3454 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3457 struct mac_walk_ctx wctx
;
3459 if (!zvni
->mac_table
)
3462 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3464 wctx
.uninstall
= uninstall
;
3465 wctx
.upd_client
= upd_client
;
3468 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3472 * Look up MAC hash entry.
3474 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3479 memset(&tmp
, 0, sizeof(tmp
));
3480 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3481 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3487 * Inform BGP about local MAC addition.
3489 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3490 uint8_t mac_flags
, uint32_t seq
)
3494 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3495 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3496 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3497 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3499 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3500 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3504 * Inform BGP about local MAC deletion.
3506 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3508 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3509 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3513 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3514 * notifications, to see if they are of interest.
3516 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3517 struct interface
*br_if
, vlanid_t vid
)
3519 struct zebra_ns
*zns
;
3520 struct route_node
*rn
;
3521 struct interface
*tmp_if
= NULL
;
3522 struct zebra_if
*zif
;
3523 struct zebra_l2info_bridge
*br
;
3524 struct zebra_l2info_vxlan
*vxl
= NULL
;
3525 uint8_t bridge_vlan_aware
;
3529 /* Determine if bridge is VLAN-aware or not */
3532 br
= &zif
->l2info
.br
;
3533 bridge_vlan_aware
= br
->vlan_aware
;
3535 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3536 /* TODO: Optimize with a hash. */
3537 zns
= zebra_ns_lookup(NS_DEFAULT
);
3538 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3539 tmp_if
= (struct interface
*)rn
->info
;
3543 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3545 if (!if_is_operative(tmp_if
))
3547 vxl
= &zif
->l2info
.vxl
;
3549 if (zif
->brslave_info
.br_if
!= br_if
)
3552 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3561 zvni
= zvni_lookup(vxl
->vni
);
3566 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3567 * neighbor notifications, to see if they are of interest.
3569 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3570 struct interface
*br_if
)
3572 struct zebra_ns
*zns
;
3573 struct route_node
*rn
;
3574 struct interface
*tmp_if
= NULL
;
3575 struct zebra_if
*zif
;
3576 struct zebra_l2info_bridge
*br
;
3577 struct zebra_l2info_vxlan
*vxl
= NULL
;
3578 uint8_t bridge_vlan_aware
;
3586 /* Make sure the linked interface is a bridge. */
3587 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3590 /* Determine if bridge is VLAN-aware or not */
3593 br
= &zif
->l2info
.br
;
3594 bridge_vlan_aware
= br
->vlan_aware
;
3595 if (bridge_vlan_aware
) {
3596 struct zebra_l2info_vlan
*vl
;
3598 if (!IS_ZEBRA_IF_VLAN(ifp
))
3603 vl
= &zif
->l2info
.vl
;
3607 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3608 /* TODO: Optimize with a hash. */
3609 zns
= zebra_ns_lookup(NS_DEFAULT
);
3610 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3611 tmp_if
= (struct interface
*)rn
->info
;
3615 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3617 if (!if_is_operative(tmp_if
))
3619 vxl
= &zif
->l2info
.vxl
;
3621 if (zif
->brslave_info
.br_if
!= br_if
)
3624 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3633 zvni
= zvni_lookup(vxl
->vni
);
3637 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3639 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3640 * linked to the bridge
3641 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3644 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3646 struct zebra_ns
*zns
;
3647 struct route_node
*rn
;
3648 struct interface
*tmp_if
= NULL
;
3649 struct zebra_if
*zif
;
3650 struct zebra_l2info_bridge
*br
;
3651 struct zebra_l2info_vlan
*vl
;
3652 uint8_t bridge_vlan_aware
;
3655 /* Defensive check, caller expected to invoke only with valid bridge. */
3659 /* Determine if bridge is VLAN-aware or not */
3662 br
= &zif
->l2info
.br
;
3663 bridge_vlan_aware
= br
->vlan_aware
;
3665 /* Check oper status of the SVI. */
3666 if (!bridge_vlan_aware
)
3667 return if_is_operative(br_if
) ? br_if
: NULL
;
3669 /* Identify corresponding VLAN interface. */
3670 /* TODO: Optimize with a hash. */
3671 zns
= zebra_ns_lookup(NS_DEFAULT
);
3672 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3673 tmp_if
= (struct interface
*)rn
->info
;
3674 /* Check oper status of the SVI. */
3675 if (!tmp_if
|| !if_is_operative(tmp_if
))
3678 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3679 || zif
->link
!= br_if
)
3681 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3683 if (vl
->vid
== vid
) {
3689 return found
? tmp_if
: NULL
;
3693 * Install remote MAC into the kernel.
3695 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3697 struct zebra_if
*zif
;
3698 struct zebra_l2info_vxlan
*vxl
;
3701 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3704 zif
= zvni
->vxlan_if
->info
;
3707 vxl
= &zif
->l2info
.vxl
;
3709 sticky
= !!CHECK_FLAG(mac
->flags
,
3710 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3712 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3713 mac
->fwd_info
.r_vtep_ip
, sticky
);
3717 * Uninstall remote MAC from the kernel.
3719 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3721 struct zebra_if
*zif
;
3722 struct zebra_l2info_vxlan
*vxl
;
3723 struct in_addr vtep_ip
;
3724 struct interface
*ifp
;
3726 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3729 if (!zvni
->vxlan_if
) {
3730 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3735 zif
= zvni
->vxlan_if
->info
;
3738 vxl
= &zif
->l2info
.vxl
;
3740 ifp
= zvni
->vxlan_if
;
3741 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3743 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3747 * Install MAC hash entry - called upon access VLAN change.
3749 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3752 struct mac_walk_ctx
*wctx
= ctxt
;
3754 mac
= (zebra_mac_t
*)bucket
->data
;
3756 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3757 zvni_mac_install(wctx
->zvni
, mac
);
3761 * Count of remote neighbors referencing this MAC.
3763 static int remote_neigh_count(zebra_mac_t
*zmac
)
3765 zebra_neigh_t
*n
= NULL
;
3766 struct listnode
*node
= NULL
;
3769 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3770 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3778 * Decrement neighbor refcount of MAC; uninstall and free it if
3781 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3783 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3786 /* If all remote neighbors referencing a remote MAC go away,
3787 * we need to uninstall the MAC.
3789 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3790 remote_neigh_count(mac
) == 0) {
3791 zvni_mac_uninstall(zvni
, mac
);
3792 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3795 /* If no neighbors, delete the MAC. */
3796 if (list_isempty(mac
->neigh_list
))
3797 zvni_mac_del(zvni
, mac
);
3801 * Read and populate local MACs and neighbors corresponding to this VNI.
3803 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3805 struct zebra_ns
*zns
;
3806 struct zebra_if
*zif
;
3807 struct interface
*vlan_if
;
3808 struct zebra_l2info_vxlan
*vxl
;
3809 struct interface
*vrr_if
;
3812 vxl
= &zif
->l2info
.vxl
;
3813 zns
= zebra_ns_lookup(NS_DEFAULT
);
3815 if (IS_ZEBRA_DEBUG_VXLAN
)
3817 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3818 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3819 zif
->brslave_info
.bridge_ifindex
);
3821 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3822 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3825 /* Add SVI MAC-IP */
3826 zvni_add_macip_for_intf(vlan_if
, zvni
);
3828 /* Add VRR MAC-IP - if any*/
3829 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3831 zvni_add_macip_for_intf(vrr_if
, zvni
);
3833 neigh_read_for_vlan(zns
, vlan_if
);
3838 * Hash function for VNI.
3840 static unsigned int vni_hash_keymake(const void *p
)
3842 const zebra_vni_t
*zvni
= p
;
3844 return (jhash_1word(zvni
->vni
, 0));
3848 * Compare 2 VNI hash entries.
3850 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3852 const zebra_vni_t
*zvni1
= p1
;
3853 const zebra_vni_t
*zvni2
= p2
;
3855 return (zvni1
->vni
== zvni2
->vni
);
3858 static int vni_list_cmp(void *p1
, void *p2
)
3860 const zebra_vni_t
*zvni1
= p1
;
3861 const zebra_vni_t
*zvni2
= p2
;
3863 if (zvni1
->vni
== zvni2
->vni
)
3865 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3869 * Callback to allocate VNI hash entry.
3871 static void *zvni_alloc(void *p
)
3873 const zebra_vni_t
*tmp_vni
= p
;
3876 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3877 zvni
->vni
= tmp_vni
->vni
;
3878 return ((void *)zvni
);
3882 * Look up VNI hash entry.
3884 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3886 struct zebra_vrf
*zvrf
;
3887 zebra_vni_t tmp_vni
;
3888 zebra_vni_t
*zvni
= NULL
;
3890 zvrf
= zebra_vrf_get_evpn();
3892 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3894 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3900 * Add VNI hash entry.
3902 static zebra_vni_t
*zvni_add(vni_t vni
)
3904 struct zebra_vrf
*zvrf
;
3905 zebra_vni_t tmp_zvni
;
3906 zebra_vni_t
*zvni
= NULL
;
3908 zvrf
= zebra_vrf_get_evpn();
3910 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3912 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3915 /* Create hash table for MAC */
3917 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3919 /* Create hash table for neighbors */
3920 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3921 "Zebra VNI Neighbor Table");
3927 * Delete VNI hash entry.
3929 static int zvni_del(zebra_vni_t
*zvni
)
3931 struct zebra_vrf
*zvrf
;
3932 zebra_vni_t
*tmp_zvni
;
3934 zvrf
= zebra_vrf_get_evpn();
3937 zvni
->vxlan_if
= NULL
;
3939 /* Remove references to the BUM mcast grp */
3940 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3942 /* Free the neighbor hash table. */
3943 hash_free(zvni
->neigh_table
);
3944 zvni
->neigh_table
= NULL
;
3946 /* Free the MAC hash table. */
3947 hash_free(zvni
->mac_table
);
3948 zvni
->mac_table
= NULL
;
3950 /* Free the VNI hash entry and allocated memory. */
3951 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3952 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3958 * Inform BGP about local VNI addition.
3960 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3962 struct zserv
*client
;
3965 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3966 /* BGP may not be running. */
3970 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3972 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3973 stream_putl(s
, zvni
->vni
);
3974 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3975 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3976 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3978 /* Write packet size. */
3979 stream_putw_at(s
, 0, stream_get_endp(s
));
3981 if (IS_ZEBRA_DEBUG_VXLAN
)
3982 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3983 inet_ntoa(zvni
->local_vtep_ip
),
3984 vrf_id_to_name(zvni
->vrf_id
),
3985 zebra_route_string(client
->proto
));
3987 client
->vniadd_cnt
++;
3988 return zserv_send_message(client
, s
);
3992 * Inform BGP about local VNI deletion.
3994 static int zvni_send_del_to_client(vni_t vni
)
3996 struct zserv
*client
;
3999 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4000 /* BGP may not be running. */
4004 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4007 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4008 stream_putl(s
, vni
);
4010 /* Write packet size. */
4011 stream_putw_at(s
, 0, stream_get_endp(s
));
4013 if (IS_ZEBRA_DEBUG_VXLAN
)
4014 zlog_debug("Send VNI_DEL %u to %s", vni
,
4015 zebra_route_string(client
->proto
));
4017 client
->vnidel_cnt
++;
4018 return zserv_send_message(client
, s
);
4022 * Build the VNI hash table by going over the VxLAN interfaces. This
4023 * is called when EVPN (advertise-all-vni) is enabled.
4025 static void zvni_build_hash_table(void)
4027 struct zebra_ns
*zns
;
4028 struct route_node
*rn
;
4029 struct interface
*ifp
;
4031 /* Walk VxLAN interfaces and create VNI hash. */
4032 zns
= zebra_ns_lookup(NS_DEFAULT
);
4033 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4035 zebra_vni_t
*zvni
= NULL
;
4036 zebra_l3vni_t
*zl3vni
= NULL
;
4037 struct zebra_if
*zif
;
4038 struct zebra_l2info_vxlan
*vxl
;
4040 ifp
= (struct interface
*)rn
->info
;
4044 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4047 vxl
= &zif
->l2info
.vxl
;
4050 /* L3-VNI and L2-VNI are handled seperately */
4051 zl3vni
= zl3vni_lookup(vni
);
4054 if (IS_ZEBRA_DEBUG_VXLAN
)
4056 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4057 ifp
->name
, ifp
->ifindex
, vni
);
4059 /* associate with vxlan_if */
4060 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4061 zl3vni
->vxlan_if
= ifp
;
4064 * we need to associate with SVI.
4065 * we can associate with svi-if only after association
4066 * with vxlan-intf is complete
4068 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4070 if (is_l3vni_oper_up(zl3vni
))
4071 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4074 struct interface
*vlan_if
= NULL
;
4076 if (IS_ZEBRA_DEBUG_VXLAN
)
4078 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4079 ifp
->name
, ifp
->ifindex
, vni
,
4080 inet_ntoa(vxl
->vtep_ip
));
4082 /* VNI hash entry is expected to exist, if the BGP process is killed */
4083 zvni
= zvni_lookup(vni
);
4086 "VNI hash already present for IF %s(%u) L2-VNI %u",
4087 ifp
->name
, ifp
->ifindex
, vni
);
4090 * Inform BGP if intf is up and mapped to
4093 if (if_is_operative(ifp
) &&
4094 zif
->brslave_info
.br_if
)
4095 zvni_send_add_to_client(zvni
);
4097 /* Send Local MAC-entries to client */
4098 zvni_send_mac_to_client(zvni
);
4100 /* Send Loval Neighbor entries to client */
4101 zvni_send_neigh_to_client(zvni
);
4103 zvni
= zvni_add(vni
);
4106 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4107 ifp
->name
, ifp
->ifindex
, vni
);
4111 if (zvni
->local_vtep_ip
.s_addr
!=
4112 vxl
->vtep_ip
.s_addr
||
4113 zvni
->mcast_grp
.s_addr
!=
4114 vxl
->mcast_grp
.s_addr
) {
4115 zebra_vxlan_sg_deref(
4116 zvni
->local_vtep_ip
,
4118 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4120 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4121 zvni
->mcast_grp
= vxl
->mcast_grp
;
4123 zvni
->vxlan_if
= ifp
;
4124 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4125 zif
->brslave_info
.br_if
);
4127 zvni
->vrf_id
= vlan_if
->vrf_id
;
4128 zl3vni
= zl3vni_from_vrf(
4132 zl3vni
->l2vnis
, zvni
);
4136 * Inform BGP if intf is up and mapped to
4139 if (if_is_operative(ifp
) &&
4140 zif
->brslave_info
.br_if
)
4141 zvni_send_add_to_client(zvni
);
4148 * See if remote VTEP matches with prefix.
4150 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4152 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4156 * Locate remote VTEP in VNI hash table.
4158 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4160 zebra_vtep_t
*zvtep
;
4165 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4166 if (zvni_vtep_match(vtep_ip
, zvtep
))
4174 * Add remote VTEP to VNI hash table.
4176 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4180 zebra_vtep_t
*zvtep
;
4182 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4184 zvtep
->vtep_ip
= *vtep_ip
;
4185 zvtep
->flood_control
= flood_control
;
4188 zvni
->vteps
->prev
= zvtep
;
4189 zvtep
->next
= zvni
->vteps
;
4190 zvni
->vteps
= zvtep
;
4196 * Remove remote VTEP from VNI hash table.
4198 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4201 zvtep
->next
->prev
= zvtep
->prev
;
4203 zvtep
->prev
->next
= zvtep
->next
;
4205 zvni
->vteps
= zvtep
->next
;
4207 zvtep
->prev
= zvtep
->next
= NULL
;
4208 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4214 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4215 * uninstall from kernel if asked to.
4217 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4219 zebra_vtep_t
*zvtep
, *zvtep_next
;
4224 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4225 zvtep_next
= zvtep
->next
;
4227 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4228 zvni_vtep_del(zvni
, zvtep
);
4235 * Install remote VTEP into the kernel if the remote VTEP has asked
4236 * for head-end-replication.
4238 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4240 if (is_vxlan_flooding_head_end() &&
4241 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4242 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4248 * Uninstall remote VTEP from the kernel.
4250 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4252 if (!zvni
->vxlan_if
) {
4253 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4258 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4262 * Install or uninstall flood entries in the kernel corresponding to
4263 * remote VTEPs. This is invoked upon change to BUM handling.
4265 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4269 zebra_vtep_t
*zvtep
;
4271 zvni
= (zebra_vni_t
*)bucket
->data
;
4275 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4276 if (is_vxlan_flooding_head_end())
4277 zvni_vtep_install(zvni
, zvtep
);
4279 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4284 * Cleanup VNI/VTEP and update kernel
4286 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4288 zebra_vni_t
*zvni
= NULL
;
4289 zebra_l3vni_t
*zl3vni
= NULL
;
4290 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4292 zvni
= (zebra_vni_t
*)bucket
->data
;
4294 /* remove from l3-vni list */
4296 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4298 listnode_delete(zl3vni
->l2vnis
, zvni
);
4300 /* Free up all neighbors and MACs, if any. */
4301 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4302 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4304 /* Free up all remote VTEPs, if any. */
4305 zvni_vtep_del_all(zvni
, 1);
4307 /* Delete the hash entry. */
4312 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4314 zebra_l3vni_t
*zl3vni
= NULL
;
4316 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4318 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4321 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4322 struct prefix
*host
)
4324 struct host_rb_entry lookup
;
4325 struct host_rb_entry
*hle
;
4327 memset(&lookup
, 0, sizeof(lookup
));
4328 memcpy(&lookup
.p
, host
, sizeof(*host
));
4330 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4334 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4335 memcpy(hle
, &lookup
, sizeof(lookup
));
4337 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4340 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4342 struct host_rb_entry lookup
;
4343 struct host_rb_entry
*hle
;
4345 memset(&lookup
, 0, sizeof(lookup
));
4346 memcpy(&lookup
.p
, host
, sizeof(*host
));
4348 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4350 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4351 XFREE(MTYPE_HOST_PREFIX
, hle
);
4358 * Look up MAC hash entry.
4360 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4361 struct ethaddr
*rmac
)
4366 memset(&tmp
, 0, sizeof(tmp
));
4367 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4368 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4374 * Callback to allocate RMAC hash entry.
4376 static void *zl3vni_rmac_alloc(void *p
)
4378 const zebra_mac_t
*tmp_rmac
= p
;
4381 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4384 return ((void *)zrmac
);
4388 * Add RMAC entry to l3-vni
4390 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4392 zebra_mac_t tmp_rmac
;
4393 zebra_mac_t
*zrmac
= NULL
;
4395 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4396 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4397 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4400 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4402 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4403 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4411 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4413 zebra_mac_t
*tmp_rmac
;
4414 struct host_rb_entry
*hle
;
4416 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4417 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4419 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4420 XFREE(MTYPE_HOST_PREFIX
, hle
);
4423 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4424 XFREE(MTYPE_MAC
, tmp_rmac
);
4430 * Install remote RMAC into the kernel.
4432 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4434 struct zebra_if
*zif
= NULL
;
4435 struct zebra_l2info_vxlan
*vxl
= NULL
;
4437 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4438 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4441 zif
= zl3vni
->vxlan_if
->info
;
4445 vxl
= &zif
->l2info
.vxl
;
4447 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4448 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4452 * Uninstall remote RMAC from the kernel.
4454 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4456 char buf
[ETHER_ADDR_STRLEN
];
4457 struct zebra_if
*zif
= NULL
;
4458 struct zebra_l2info_vxlan
*vxl
= NULL
;
4460 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4461 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4464 if (!zl3vni
->vxlan_if
) {
4466 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4467 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4468 zl3vni
->vni
, zl3vni
);
4472 zif
= zl3vni
->vxlan_if
->info
;
4476 vxl
= &zif
->l2info
.vxl
;
4478 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4479 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4482 /* handle rmac add */
4483 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4484 struct ipaddr
*vtep_ip
,
4485 struct prefix
*host_prefix
)
4487 char buf
[ETHER_ADDR_STRLEN
];
4488 char buf1
[INET6_ADDRSTRLEN
];
4489 zebra_mac_t
*zrmac
= NULL
;
4491 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4494 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4497 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4498 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4500 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4503 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4504 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4506 /* install rmac in kernel */
4507 zl3vni_rmac_install(zl3vni
, zrmac
);
4510 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4516 /* handle rmac delete */
4517 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4518 struct prefix
*host_prefix
)
4520 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4522 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4523 /* uninstall from kernel */
4524 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4526 /* del the rmac entry */
4527 zl3vni_rmac_del(zl3vni
, zrmac
);
4532 * Look up nh hash entry on a l3-vni.
4534 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4539 memset(&tmp
, 0, sizeof(tmp
));
4540 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4541 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4548 * Callback to allocate NH hash entry on L3-VNI.
4550 static void *zl3vni_nh_alloc(void *p
)
4552 const zebra_neigh_t
*tmp_n
= p
;
4555 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4562 * Add neighbor entry.
4564 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4565 struct ethaddr
*mac
)
4567 zebra_neigh_t tmp_n
;
4568 zebra_neigh_t
*n
= NULL
;
4570 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4571 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4572 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4575 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4577 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4578 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4579 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4585 * Delete neighbor entry.
4587 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4589 zebra_neigh_t
*tmp_n
;
4590 struct host_rb_entry
*hle
;
4592 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4593 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4595 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4596 XFREE(MTYPE_HOST_PREFIX
, hle
);
4599 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4600 XFREE(MTYPE_NEIGH
, tmp_n
);
4606 * Install remote nh as neigh into the kernel.
4608 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4615 if (!is_l3vni_oper_up(zl3vni
))
4618 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4619 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4622 flags
= NTF_EXT_LEARNED
;
4623 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4624 flags
|= NTF_ROUTER
;
4625 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4631 * Uninstall remote nh from the kernel.
4633 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4635 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4636 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4639 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4642 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4645 /* add remote vtep as a neigh entry */
4646 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4647 struct ethaddr
*rmac
,
4648 struct prefix
*host_prefix
)
4650 char buf
[ETHER_ADDR_STRLEN
];
4651 char buf1
[INET6_ADDRSTRLEN
];
4652 zebra_neigh_t
*nh
= NULL
;
4654 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4656 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4660 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4661 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4662 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4667 /* install the nh neigh in kernel */
4668 zl3vni_nh_install(zl3vni
, nh
);
4671 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4676 /* handle nh neigh delete */
4677 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4678 struct prefix
*host_prefix
)
4680 rb_delete_host(&nh
->host_rb
, host_prefix
);
4682 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4683 /* uninstall from kernel */
4684 zl3vni_nh_uninstall(zl3vni
, nh
);
4686 /* delete the nh entry */
4687 zl3vni_nh_del(zl3vni
, nh
);
4691 /* handle neigh update from kernel - the only thing of interest is to
4692 * readd stale entries.
4694 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4698 zebra_neigh_t
*n
= NULL
;
4700 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4704 /* all next hop neigh are remote and installed by frr.
4705 * If the kernel has aged this entry, re-install.
4707 if (state
& NUD_STALE
)
4708 zl3vni_nh_install(zl3vni
, n
);
4713 /* handle neigh delete from kernel */
4714 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4716 zebra_neigh_t
*n
= NULL
;
4718 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4722 /* all next hop neigh are remote and installed by frr.
4723 * If we get an age out notification for these neigh entries, we have to
4726 zl3vni_nh_install(zl3vni
, n
);
4732 * Hash function for L3 VNI.
4734 static unsigned int l3vni_hash_keymake(const void *p
)
4736 const zebra_l3vni_t
*zl3vni
= p
;
4738 return jhash_1word(zl3vni
->vni
, 0);
4742 * Compare 2 L3 VNI hash entries.
4744 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4746 const zebra_l3vni_t
*zl3vni1
= p1
;
4747 const zebra_l3vni_t
*zl3vni2
= p2
;
4749 return (zl3vni1
->vni
== zl3vni2
->vni
);
4753 * Callback to allocate L3 VNI hash entry.
4755 static void *zl3vni_alloc(void *p
)
4757 zebra_l3vni_t
*zl3vni
= NULL
;
4758 const zebra_l3vni_t
*tmp_l3vni
= p
;
4760 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4761 zl3vni
->vni
= tmp_l3vni
->vni
;
4762 return ((void *)zl3vni
);
4766 * Look up L3 VNI hash entry.
4768 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4770 zebra_l3vni_t tmp_l3vni
;
4771 zebra_l3vni_t
*zl3vni
= NULL
;
4773 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4774 tmp_l3vni
.vni
= vni
;
4775 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4781 * Add L3 VNI hash entry.
4783 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4785 zebra_l3vni_t tmp_zl3vni
;
4786 zebra_l3vni_t
*zl3vni
= NULL
;
4788 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4789 tmp_zl3vni
.vni
= vni
;
4791 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4794 zl3vni
->vrf_id
= vrf_id
;
4795 zl3vni
->svi_if
= NULL
;
4796 zl3vni
->vxlan_if
= NULL
;
4797 zl3vni
->l2vnis
= list_new();
4798 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4800 /* Create hash table for remote RMAC */
4801 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4802 "Zebra L3-VNI RMAC-Table");
4804 /* Create hash table for neighbors */
4805 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4806 "Zebra L3-VNI next-hop table");
4812 * Delete L3 VNI hash entry.
4814 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4816 zebra_l3vni_t
*tmp_zl3vni
;
4818 /* free the list of l2vnis */
4819 list_delete(&zl3vni
->l2vnis
);
4820 zl3vni
->l2vnis
= NULL
;
4822 /* Free the rmac table */
4823 hash_free(zl3vni
->rmac_table
);
4824 zl3vni
->rmac_table
= NULL
;
4826 /* Free the nh table */
4827 hash_free(zl3vni
->nh_table
);
4828 zl3vni
->nh_table
= NULL
;
4830 /* Free the VNI hash entry and allocated memory. */
4831 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4832 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4837 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4839 struct zebra_ns
*zns
= NULL
;
4840 struct route_node
*rn
= NULL
;
4841 struct interface
*ifp
= NULL
;
4843 /* loop through all vxlan-interface */
4844 zns
= zebra_ns_lookup(NS_DEFAULT
);
4845 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4847 struct zebra_if
*zif
= NULL
;
4848 struct zebra_l2info_vxlan
*vxl
= NULL
;
4850 ifp
= (struct interface
*)rn
->info
;
4855 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4858 vxl
= &zif
->l2info
.vxl
;
4859 if (vxl
->vni
== zl3vni
->vni
) {
4860 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4868 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4870 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4871 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4876 if (!zl3vni
->vxlan_if
)
4879 zif
= zl3vni
->vxlan_if
->info
;
4883 vxl
= &zif
->l2info
.vxl
;
4885 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4888 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4890 struct zebra_vrf
*zvrf
= NULL
;
4892 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4896 return zl3vni_lookup(zvrf
->l3vni
);
4900 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4901 * neighbor notifications, to see if they are of interest.
4903 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4904 struct interface
*br_if
)
4908 uint8_t bridge_vlan_aware
= 0;
4909 zebra_l3vni_t
*zl3vni
= NULL
;
4910 struct zebra_ns
*zns
= NULL
;
4911 struct route_node
*rn
= NULL
;
4912 struct zebra_if
*zif
= NULL
;
4913 struct interface
*tmp_if
= NULL
;
4914 struct zebra_l2info_bridge
*br
= NULL
;
4915 struct zebra_l2info_vxlan
*vxl
= NULL
;
4920 /* Make sure the linked interface is a bridge. */
4921 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4924 /* Determine if bridge is VLAN-aware or not */
4927 br
= &zif
->l2info
.br
;
4928 bridge_vlan_aware
= br
->vlan_aware
;
4929 if (bridge_vlan_aware
) {
4930 struct zebra_l2info_vlan
*vl
;
4932 if (!IS_ZEBRA_IF_VLAN(ifp
))
4937 vl
= &zif
->l2info
.vl
;
4941 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4942 /* TODO: Optimize with a hash. */
4943 zns
= zebra_ns_lookup(NS_DEFAULT
);
4944 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4945 tmp_if
= (struct interface
*)rn
->info
;
4949 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4951 if (!if_is_operative(tmp_if
))
4953 vxl
= &zif
->l2info
.vxl
;
4955 if (zif
->brslave_info
.br_if
!= br_if
)
4958 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4967 zl3vni
= zl3vni_lookup(vxl
->vni
);
4972 * Inform BGP about l3-vni.
4974 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4976 struct stream
*s
= NULL
;
4977 struct zserv
*client
= NULL
;
4978 struct ethaddr rmac
;
4979 char buf
[ETHER_ADDR_STRLEN
];
4981 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4982 /* BGP may not be running. */
4987 memset(&rmac
, 0, sizeof(struct ethaddr
));
4988 zl3vni_get_rmac(zl3vni
, &rmac
);
4990 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4992 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4993 stream_putl(s
, zl3vni
->vni
);
4994 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4995 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4996 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4997 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4999 /* Write packet size. */
5000 stream_putw_at(s
, 0, stream_get_endp(s
));
5002 if (IS_ZEBRA_DEBUG_VXLAN
)
5004 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
5005 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5006 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
5007 inet_ntoa(zl3vni
->local_vtep_ip
),
5008 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5009 ? "prefix-routes-only"
5011 zebra_route_string(client
->proto
));
5013 client
->l3vniadd_cnt
++;
5014 return zserv_send_message(client
, s
);
5018 * Inform BGP about local l3-VNI deletion.
5020 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5022 struct stream
*s
= NULL
;
5023 struct zserv
*client
= NULL
;
5025 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5026 /* BGP may not be running. */
5030 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5032 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5033 stream_putl(s
, zl3vni
->vni
);
5035 /* Write packet size. */
5036 stream_putw_at(s
, 0, stream_get_endp(s
));
5038 if (IS_ZEBRA_DEBUG_VXLAN
)
5039 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5040 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5041 zebra_route_string(client
->proto
));
5043 client
->l3vnidel_cnt
++;
5044 return zserv_send_message(client
, s
);
5047 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5052 /* send l3vni add to BGP */
5053 zl3vni_send_add_to_client(zl3vni
);
5056 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5061 /* send l3-vni del to BGP*/
5062 zl3vni_send_del_to_client(zl3vni
);
5065 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5067 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5068 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5070 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5071 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5075 * handle transition of vni from l2 to l3 and vice versa
5077 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5080 zebra_vni_t
*zvni
= NULL
;
5082 /* There is a possibility that VNI notification was already received
5083 * from kernel and we programmed it as L2-VNI
5084 * In such a case we need to delete this L2-VNI first, so
5085 * that it can be reprogrammed as L3-VNI in the system. It is also
5086 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5087 * interface is still present in kernel. In this case to keep it
5088 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5091 /* Locate hash entry */
5092 zvni
= zvni_lookup(vni
);
5096 if (IS_ZEBRA_DEBUG_VXLAN
)
5097 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5099 /* Delete VNI from BGP. */
5100 zvni_send_del_to_client(zvni
->vni
);
5102 /* Free up all neighbors and MAC, if any. */
5103 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5104 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5106 /* Free up all remote VTEPs, if any. */
5107 zvni_vtep_del_all(zvni
, 0);
5109 /* Delete the hash entry. */
5110 if (zvni_del(zvni
)) {
5111 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5112 "Failed to del VNI hash %p, VNI %u", zvni
,
5117 /* TODO_MITESH: This needs to be thought through. We don't have
5118 * enough information at this point to reprogram the vni as
5119 * l2-vni. One way is to store the required info in l3-vni and
5120 * used it solely for this purpose
5127 /* delete and uninstall rmac hash entry */
5128 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5130 zebra_mac_t
*zrmac
= NULL
;
5131 zebra_l3vni_t
*zl3vni
= NULL
;
5133 zrmac
= (zebra_mac_t
*)bucket
->data
;
5134 zl3vni
= (zebra_l3vni_t
*)ctx
;
5135 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5136 zl3vni_rmac_del(zl3vni
, zrmac
);
5139 /* delete and uninstall nh hash entry */
5140 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5142 zebra_neigh_t
*n
= NULL
;
5143 zebra_l3vni_t
*zl3vni
= NULL
;
5145 n
= (zebra_neigh_t
*)bucket
->data
;
5146 zl3vni
= (zebra_l3vni_t
*)ctx
;
5147 zl3vni_nh_uninstall(zl3vni
, n
);
5148 zl3vni_nh_del(zl3vni
, n
);
5151 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5154 struct zserv
*client
= NULL
;
5155 struct stream
*s
= NULL
;
5156 char buf
[PREFIX_STRLEN
];
5158 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5159 /* BGP may not be running. */
5163 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5165 zclient_create_header(s
, cmd
, vrf_id
);
5166 stream_put(s
, p
, sizeof(struct prefix
));
5168 /* Write packet size. */
5169 stream_putw_at(s
, 0, stream_get_endp(s
));
5171 if (IS_ZEBRA_DEBUG_VXLAN
)
5172 zlog_debug("Send ip prefix %s %s on vrf %s",
5173 prefix2str(p
, buf
, sizeof(buf
)),
5174 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5175 vrf_id_to_name(vrf_id
));
5177 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5178 client
->prefixadd_cnt
++;
5180 client
->prefixdel_cnt
++;
5182 return zserv_send_message(client
, s
);
5185 /* re-add remote rmac if needed */
5186 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5187 struct ethaddr
*rmac
)
5189 char buf
[ETHER_ADDR_STRLEN
];
5190 zebra_mac_t
*zrmac
= NULL
;
5192 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5196 if (IS_ZEBRA_DEBUG_VXLAN
)
5197 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5198 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5200 zl3vni_rmac_install(zl3vni
, zrmac
);
5204 /* Process a remote MACIP add from BGP. */
5205 static void process_remote_macip_add(vni_t vni
,
5206 struct ethaddr
*macaddr
,
5208 struct ipaddr
*ipaddr
,
5211 struct in_addr vtep_ip
)
5214 zebra_vtep_t
*zvtep
;
5215 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5216 zebra_neigh_t
*n
= NULL
;
5217 int update_mac
= 0, update_neigh
= 0;
5218 char buf
[ETHER_ADDR_STRLEN
];
5219 char buf1
[INET6_ADDRSTRLEN
];
5220 struct interface
*ifp
= NULL
;
5221 struct zebra_if
*zif
= NULL
;
5222 struct zebra_vrf
*zvrf
;
5227 bool do_dad
= false;
5228 bool is_dup_detect
= false;
5230 /* Locate VNI hash entry - expected to exist. */
5231 zvni
= zvni_lookup(vni
);
5233 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5237 ifp
= zvni
->vxlan_if
;
5241 !if_is_operative(ifp
) ||
5243 !zif
->brslave_info
.br_if
) {
5244 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5249 /* The remote VTEP specified should normally exist, but it is
5250 * possible that when peering comes up, peer may advertise MACIP
5251 * routes before advertising type-3 routes.
5253 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5255 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5258 EC_ZEBRA_VTEP_ADD_FAILED
,
5259 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5264 zvni_vtep_install(zvni
, zvtep
);
5267 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5268 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5269 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5271 mac
= zvni_mac_lookup(zvni
, macaddr
);
5273 /* Ignore if the mac is already present as a gateway mac */
5275 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5276 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5277 if (IS_ZEBRA_DEBUG_VXLAN
)
5278 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5280 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5281 ipa_len
? " IP " : "",
5283 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5287 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5291 /* check if the remote MAC is unknown or has a change.
5292 * If so, that needs to be updated first. Note that client could
5293 * install MAC and MACIP separately or just install the latter.
5296 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5297 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5298 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5299 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5300 || seq
!= mac
->rem_seq
)
5305 mac
= zvni_mac_add(zvni
, macaddr
);
5308 "Failed to add MAC %s VNI %u Remote VTEP %s",
5309 prefix_mac2str(macaddr
, buf
,
5311 vni
, inet_ntoa(vtep_ip
));
5315 /* Is this MAC created for a MACIP? */
5317 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5319 const char *mac_type
;
5321 /* When host moves but changes its (MAC,IP)
5322 * binding, BGP may install a MACIP entry that
5323 * corresponds to "older" location of the host
5324 * in transient situations (because {IP1,M1}
5325 * is a different route from {IP1,M2}). Check
5326 * the sequence number and ignore this update
5329 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5330 tmp_seq
= mac
->loc_seq
;
5333 tmp_seq
= mac
->rem_seq
;
5334 mac_type
= "remote";
5336 if (seq
< tmp_seq
) {
5337 if (IS_ZEBRA_DEBUG_VXLAN
)
5338 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5340 prefix_mac2str(macaddr
,
5342 ipa_len
? " IP " : "",
5345 buf1
, sizeof(buf1
)) : "",
5352 /* Check MAC's curent state is local (this is the case
5353 * where MAC has moved from L->R) and check previous
5354 * detection started via local learning.
5355 * RFC-7432: A PE/VTEP that detects a MAC mobility
5356 * event via local learning starts an M-second timer.
5358 * VTEP-IP or seq. change alone is not considered
5359 * for dup. detection.
5361 * MAC is already marked duplicate set dad, then
5362 * is_dup_detect will be set to not install the entry.
5364 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5366 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5369 /* Remove local MAC from BGP. */
5370 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5371 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5373 /* Set "auto" and "remote" forwarding info. */
5374 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5375 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5376 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5377 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5380 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5382 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5385 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5387 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5389 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5390 mac
->fwd_info
.r_vtep_ip
,
5391 do_dad
, &is_dup_detect
,
5394 if (!is_dup_detect
) {
5395 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5396 /* Install the entry. */
5397 zvni_mac_install(zvni
, mac
);
5401 /* Update seq number. */
5404 /* If there is no IP, return after clearing AUTO flag of MAC. */
5406 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5413 /* Check if the remote neighbor itself is unknown or has a
5414 * change. If so, create or update and then install the entry.
5416 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5418 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5419 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5420 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5421 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5422 || seq
!= n
->rem_seq
)
5427 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5430 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5431 ipaddr2str(ipaddr
, buf1
,
5433 prefix_mac2str(macaddr
, buf
,
5435 vni
, inet_ntoa(vtep_ip
));
5442 /* When host moves but changes its (MAC,IP)
5443 * binding, BGP may install a MACIP entry that
5444 * corresponds to "older" location of the host
5445 * in transient situations (because {IP1,M1}
5446 * is a different route from {IP1,M2}). Check
5447 * the sequence number and ignore this update
5450 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5451 tmp_seq
= n
->loc_seq
;
5454 tmp_seq
= n
->rem_seq
;
5457 if (seq
< tmp_seq
) {
5458 if (IS_ZEBRA_DEBUG_VXLAN
)
5459 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5461 prefix_mac2str(macaddr
,
5464 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5469 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5470 /* MAC change, send a delete for old
5471 * neigh if learnt locally.
5473 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5474 IS_ZEBRA_NEIGH_ACTIVE(n
))
5475 zvni_neigh_send_del_to_client(
5477 &n
->emac
, 0, n
->state
);
5479 /* update neigh list for macs */
5480 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5482 listnode_delete(old_mac
->neigh_list
, n
);
5483 zvni_deref_ip2mac(zvni
, old_mac
);
5485 listnode_add_sort(mac
->neigh_list
, n
);
5486 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5488 /* Check Neigh's curent state is local
5489 * (this is the case where neigh/host has moved
5490 * from L->R) and check previous detction
5491 * started via local learning.
5493 * RFC-7432: A PE/VTEP that detects a MAC
5494 * mobilit event via local learning starts
5495 * an M-second timer.
5496 * VTEP-IP or seq. change along is not
5497 * considered for dup. detection.
5499 * Mobilty event scenario-B IP-MAC binding
5502 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5509 /* Set "remote" forwarding info. */
5510 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5511 n
->r_vtep_ip
= vtep_ip
;
5512 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5514 /* Set router flag (R-bit) to this Neighbor entry */
5515 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5516 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5518 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5520 /* Check old or new MAC detected as duplicate,
5521 * inherit duplicate flag to this neigh.
5523 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5525 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5526 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5528 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5529 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5532 /* Check duplicate address detection for IP */
5533 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5538 /* Install the entry. */
5540 zvni_neigh_install(zvni
, n
);
5543 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5545 /* Update seq number. */
5549 /* Process a remote MACIP delete from BGP. */
5550 static void process_remote_macip_del(vni_t vni
,
5551 struct ethaddr
*macaddr
,
5553 struct ipaddr
*ipaddr
,
5554 struct in_addr vtep_ip
)
5557 zebra_mac_t
*mac
= NULL
;
5558 zebra_neigh_t
*n
= NULL
;
5559 struct interface
*ifp
= NULL
;
5560 struct zebra_if
*zif
= NULL
;
5561 struct zebra_ns
*zns
;
5562 struct zebra_l2info_vxlan
*vxl
;
5563 struct zebra_vrf
*zvrf
;
5564 char buf
[ETHER_ADDR_STRLEN
];
5565 char buf1
[INET6_ADDRSTRLEN
];
5567 /* Locate VNI hash entry - expected to exist. */
5568 zvni
= zvni_lookup(vni
);
5570 if (IS_ZEBRA_DEBUG_VXLAN
)
5571 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5575 ifp
= zvni
->vxlan_if
;
5579 !if_is_operative(ifp
) ||
5581 !zif
->brslave_info
.br_if
) {
5582 if (IS_ZEBRA_DEBUG_VXLAN
)
5583 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5587 zns
= zebra_ns_lookup(NS_DEFAULT
);
5588 vxl
= &zif
->l2info
.vxl
;
5590 /* The remote VTEP specified is normally expected to exist, but
5591 * it is possible that the peer may delete the VTEP before deleting
5592 * any MACs referring to the VTEP, in which case the handler (see
5593 * remote_vtep_del) would have already deleted the MACs.
5595 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5598 mac
= zvni_mac_lookup(zvni
, macaddr
);
5600 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5603 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5604 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5605 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5609 /* If the remote mac or neighbor doesn't exist there is nothing
5610 * more to do. Otherwise, uninstall the entry and then remove it.
5615 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5617 /* Ignore the delete if this mac is a gateway mac-ip */
5618 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5619 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5621 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5623 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5624 ipa_len
? " IP " : "",
5626 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5630 /* Uninstall remote neighbor or MAC. */
5632 if (zvrf
->dad_freeze
&&
5633 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5634 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5635 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5636 struct interface
*vlan_if
;
5638 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5639 zif
->brslave_info
.br_if
);
5640 if (IS_ZEBRA_DEBUG_VXLAN
)
5641 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5642 __PRETTY_FUNCTION__
,
5643 ipaddr2str(ipaddr
, buf1
,
5644 sizeof(buf1
)), n
->flags
,
5646 neigh_read_specific_ip(ipaddr
, vlan_if
);
5649 /* When the MAC changes for an IP, it is possible the
5650 * client may update the new MAC before trying to delete the
5651 * "old" neighbor (as these are two different MACIP routes).
5652 * Do the delete only if the MAC matches.
5654 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5655 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5656 zvni_neigh_uninstall(zvni
, n
);
5657 zvni_neigh_del(zvni
, n
);
5658 zvni_deref_ip2mac(zvni
, mac
);
5661 /* DAD: when MAC is freeze state as remote learn event,
5662 * remote mac-ip delete event is received will result in freeze
5663 * entry removal, first fetch kernel for the same entry present
5664 * as LOCAL and reachable, avoid deleting this entry instead
5665 * use kerenel local entry to update during unfreeze time.
5667 if (zvrf
->dad_freeze
&&
5668 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5669 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5670 if (IS_ZEBRA_DEBUG_VXLAN
)
5671 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5672 __PRETTY_FUNCTION__
,
5673 prefix_mac2str(macaddr
, buf
,
5676 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5677 macaddr
, vxl
->access_vlan
);
5680 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5681 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5683 * the remote sequence number in the auto mac entry
5684 * needs to be reset to 0 as the mac entry may have
5685 * been removed on all VTEPs (including
5686 * the originating one)
5690 /* If all remote neighbors referencing a remote MAC
5691 * go away, we need to uninstall the MAC.
5693 if (remote_neigh_count(mac
) == 0) {
5694 zvni_mac_uninstall(zvni
, mac
);
5695 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5697 if (list_isempty(mac
->neigh_list
))
5698 zvni_mac_del(zvni
, mac
);
5700 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5706 /* Public functions */
5708 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5710 zebra_l3vni_t
*zl3vni
= NULL
;
5712 zl3vni
= zl3vni_lookup(vni
);
5716 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5719 /* handle evpn route in vrf table */
5720 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5721 struct ipaddr
*vtep_ip
,
5722 struct prefix
*host_prefix
)
5724 zebra_l3vni_t
*zl3vni
= NULL
;
5725 struct ipaddr ipv4_vtep
;
5727 zl3vni
= zl3vni_from_vrf(vrf_id
);
5728 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5732 * add the next hop neighbor -
5733 * neigh to be installed is the ipv6 nexthop neigh
5735 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5738 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5739 * address. Rmac is programmed against the ipv4 vtep because we only
5740 * support ipv4 tunnels in the h/w right now
5742 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5743 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5744 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5745 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5746 &(ipv4_vtep
.ipaddr_v4
));
5748 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5749 sizeof(struct in_addr
));
5752 * add the rmac - remote rmac to be installed is against the ipv4
5755 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5758 /* handle evpn vrf route delete */
5759 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5760 struct ipaddr
*vtep_ip
,
5761 struct prefix
*host_prefix
)
5763 zebra_l3vni_t
*zl3vni
= NULL
;
5764 zebra_neigh_t
*nh
= NULL
;
5765 zebra_mac_t
*zrmac
= NULL
;
5767 zl3vni
= zl3vni_from_vrf(vrf_id
);
5771 /* find the next hop entry and rmac entry */
5772 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5775 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5777 /* delete the next hop entry */
5778 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5780 /* delete the rmac entry */
5782 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5786 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5787 struct ethaddr
*rmac
, bool use_json
)
5789 zebra_l3vni_t
*zl3vni
= NULL
;
5790 zebra_mac_t
*zrmac
= NULL
;
5791 json_object
*json
= NULL
;
5793 if (!is_evpn_enabled()) {
5795 vty_out(vty
, "{}\n");
5800 json
= json_object_new_object();
5802 zl3vni
= zl3vni_lookup(l3vni
);
5805 vty_out(vty
, "{}\n");
5807 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5811 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5814 vty_out(vty
, "{}\n");
5817 "%% Requested RMAC doesn't exist in L3-VNI %u",
5822 zl3vni_print_rmac(zrmac
, vty
, json
);
5825 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5826 json
, JSON_C_TO_STRING_PRETTY
));
5827 json_object_free(json
);
5831 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5833 zebra_l3vni_t
*zl3vni
;
5835 struct rmac_walk_ctx wctx
;
5836 json_object
*json
= NULL
;
5838 if (!is_evpn_enabled())
5841 zl3vni
= zl3vni_lookup(l3vni
);
5844 vty_out(vty
, "{}\n");
5846 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5849 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5854 json
= json_object_new_object();
5856 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5860 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5862 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5864 json_object_int_add(json
, "numRmacs", num_rmacs
);
5866 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5869 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5870 json
, JSON_C_TO_STRING_PRETTY
));
5871 json_object_free(json
);
5875 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5877 json_object
*json
= NULL
;
5880 if (!is_evpn_enabled()) {
5882 vty_out(vty
, "{}\n");
5887 json
= json_object_new_object();
5891 hash_iterate(zrouter
.l3vni_table
,
5892 (void (*)(struct hash_bucket
*,
5893 void *))zl3vni_print_rmac_hash_all_vni
,
5897 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5898 json
, JSON_C_TO_STRING_PRETTY
));
5899 json_object_free(json
);
5903 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5904 struct ipaddr
*ip
, bool use_json
)
5906 zebra_l3vni_t
*zl3vni
= NULL
;
5907 zebra_neigh_t
*n
= NULL
;
5908 json_object
*json
= NULL
;
5910 if (!is_evpn_enabled()) {
5912 vty_out(vty
, "{}\n");
5917 json
= json_object_new_object();
5919 zl3vni
= zl3vni_lookup(l3vni
);
5922 vty_out(vty
, "{}\n");
5924 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5928 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5931 vty_out(vty
, "{}\n");
5934 "%% Requested next-hop not present for L3-VNI %u",
5939 zl3vni_print_nh(n
, vty
, json
);
5942 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5943 json
, JSON_C_TO_STRING_PRETTY
));
5944 json_object_free(json
);
5948 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5951 struct nh_walk_ctx wctx
;
5952 json_object
*json
= NULL
;
5953 zebra_l3vni_t
*zl3vni
= NULL
;
5955 if (!is_evpn_enabled())
5958 zl3vni
= zl3vni_lookup(l3vni
);
5961 vty_out(vty
, "{}\n");
5963 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5967 num_nh
= hashcount(zl3vni
->nh_table
);
5972 json
= json_object_new_object();
5977 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5979 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5981 json_object_int_add(json
, "numNextHops", num_nh
);
5983 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5986 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5987 json
, JSON_C_TO_STRING_PRETTY
));
5988 json_object_free(json
);
5992 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5994 json_object
*json
= NULL
;
5997 if (!is_evpn_enabled()) {
5999 vty_out(vty
, "{}\n");
6004 json
= json_object_new_object();
6008 hash_iterate(zrouter
.l3vni_table
,
6009 (void (*)(struct hash_bucket
*,
6010 void *))zl3vni_print_nh_hash_all_vni
,
6014 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6015 json
, JSON_C_TO_STRING_PRETTY
));
6016 json_object_free(json
);
6021 * Display L3 VNI information (VTY command handler).
6023 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
6026 json_object
*json
= NULL
;
6027 zebra_l3vni_t
*zl3vni
= NULL
;
6029 if (!is_evpn_enabled()) {
6031 vty_out(vty
, "{}\n");
6035 zl3vni
= zl3vni_lookup(vni
);
6038 vty_out(vty
, "{}\n");
6040 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6045 json
= json_object_new_object();
6049 zl3vni_print(zl3vni
, (void *)args
);
6052 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6053 json
, JSON_C_TO_STRING_PRETTY
));
6054 json_object_free(json
);
6058 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6059 json_object
*json_vrfs
)
6061 char buf
[ETHER_ADDR_STRLEN
];
6062 zebra_l3vni_t
*zl3vni
= NULL
;
6064 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6069 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6070 zvrf_name(zvrf
), zl3vni
->vni
,
6071 zl3vni_vxlan_if_name(zl3vni
),
6072 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6073 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6075 json_object
*json_vrf
= NULL
;
6077 json_vrf
= json_object_new_object();
6078 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6079 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6080 json_object_string_add(json_vrf
, "vxlanIntf",
6081 zl3vni_vxlan_if_name(zl3vni
));
6082 json_object_string_add(json_vrf
, "sviIntf",
6083 zl3vni_svi_if_name(zl3vni
));
6084 json_object_string_add(json_vrf
, "state",
6085 zl3vni_state2str(zl3vni
));
6086 json_object_string_add(
6087 json_vrf
, "routerMac",
6088 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6089 json_object_array_add(json_vrfs
, json_vrf
);
6094 * Display Neighbors for a VNI (VTY command handler).
6096 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6097 vni_t vni
, bool use_json
)
6101 struct neigh_walk_ctx wctx
;
6102 json_object
*json
= NULL
;
6104 if (!is_evpn_enabled())
6106 zvni
= zvni_lookup(vni
);
6109 vty_out(vty
, "{}\n");
6111 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6114 num_neigh
= hashcount(zvni
->neigh_table
);
6119 json
= json_object_new_object();
6121 /* Since we have IPv6 addresses to deal with which can vary widely in
6122 * size, we try to be a bit more elegant in display by first computing
6123 * the maximum width.
6125 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6128 wctx
.addr_width
= 15;
6130 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6134 "Number of ARPs (local and remote) known for this VNI: %u\n",
6136 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6137 -wctx
.addr_width
, "IP", "Type",
6138 "State", "MAC", "Remote VTEP");
6140 json_object_int_add(json
, "numArpNd", num_neigh
);
6142 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6144 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6145 json
, JSON_C_TO_STRING_PRETTY
));
6146 json_object_free(json
);
6151 * Display neighbors across all VNIs (VTY command handler).
6153 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6154 bool print_dup
, bool use_json
)
6156 json_object
*json
= NULL
;
6159 if (!is_evpn_enabled())
6163 json
= json_object_new_object();
6167 args
[2] = (void *)(ptrdiff_t)print_dup
;
6169 hash_iterate(zvrf
->vni_table
,
6170 (void (*)(struct hash_bucket
*,
6171 void *))zvni_print_neigh_hash_all_vni
,
6174 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6175 json
, JSON_C_TO_STRING_PRETTY
));
6176 json_object_free(json
);
6181 * Display neighbors across all VNIs in detail(VTY command handler).
6183 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6184 struct zebra_vrf
*zvrf
,
6185 bool print_dup
, bool use_json
)
6187 json_object
*json
= NULL
;
6190 if (!is_evpn_enabled())
6194 json
= json_object_new_object();
6198 args
[2] = (void *)(ptrdiff_t)print_dup
;
6200 hash_iterate(zvrf
->vni_table
,
6201 (void (*)(struct hash_bucket
*,
6202 void *))zvni_print_neigh_hash_all_vni_detail
,
6205 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6206 json
, JSON_C_TO_STRING_PRETTY
));
6207 json_object_free(json
);
6212 * Display specific neighbor for a VNI, if present (VTY command handler).
6214 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6215 struct zebra_vrf
*zvrf
, vni_t vni
,
6216 struct ipaddr
*ip
, bool use_json
)
6220 json_object
*json
= NULL
;
6222 if (!is_evpn_enabled())
6224 zvni
= zvni_lookup(vni
);
6227 vty_out(vty
, "{}\n");
6229 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6232 n
= zvni_neigh_lookup(zvni
, ip
);
6236 "%% Requested neighbor does not exist in VNI %u\n",
6241 json
= json_object_new_object();
6243 zvni_print_neigh(n
, vty
, json
);
6246 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6247 json
, JSON_C_TO_STRING_PRETTY
));
6248 json_object_free(json
);
6253 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6254 * By definition, these are remote neighbors.
6256 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6257 vni_t vni
, struct in_addr vtep_ip
,
6262 struct neigh_walk_ctx wctx
;
6263 json_object
*json
= NULL
;
6265 if (!is_evpn_enabled())
6267 zvni
= zvni_lookup(vni
);
6270 vty_out(vty
, "{}\n");
6272 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6275 num_neigh
= hashcount(zvni
->neigh_table
);
6279 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6282 wctx
.addr_width
= 15;
6283 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6284 wctx
.r_vtep_ip
= vtep_ip
;
6286 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6287 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6290 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6291 json
, JSON_C_TO_STRING_PRETTY
));
6292 json_object_free(json
);
6297 * Display Duplicate detected Neighbors for a VNI
6298 * (VTY command handler).
6300 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6301 struct zebra_vrf
*zvrf
,
6307 struct neigh_walk_ctx wctx
;
6308 json_object
*json
= NULL
;
6310 if (!is_evpn_enabled())
6313 zvni
= zvni_lookup(vni
);
6315 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6319 num_neigh
= hashcount(zvni
->neigh_table
);
6323 num_neigh
= num_dup_detected_neighs(zvni
);
6328 json
= json_object_new_object();
6330 /* Since we have IPv6 addresses to deal with which can vary widely in
6331 * size, we try to be a bit more elegant in display by first computing
6332 * the maximum width.
6334 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6337 wctx
.addr_width
= 15;
6339 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6343 "Number of ARPs (local and remote) known for this VNI: %u\n",
6345 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6346 -wctx
.addr_width
, "IP", "Type",
6347 "State", "MAC", "Remote VTEP");
6349 json_object_int_add(json
, "numArpNd", num_neigh
);
6351 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6354 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6355 json
, JSON_C_TO_STRING_PRETTY
));
6356 json_object_free(json
);
6361 * Display MACs for a VNI (VTY command handler).
6363 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6364 vni_t vni
, bool use_json
)
6368 struct mac_walk_ctx wctx
;
6369 json_object
*json
= NULL
;
6370 json_object
*json_mac
= NULL
;
6372 if (!is_evpn_enabled())
6374 zvni
= zvni_lookup(vni
);
6377 vty_out(vty
, "{}\n");
6379 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6382 num_macs
= num_valid_macs(zvni
);
6387 json
= json_object_new_object();
6388 json_mac
= json_object_new_object();
6391 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6394 wctx
.json
= json_mac
;
6398 "Number of MACs (local and remote) known for this VNI: %u\n",
6400 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6401 "Intf/Remote VTEP", "VLAN");
6403 json_object_int_add(json
, "numMacs", num_macs
);
6405 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6408 json_object_object_add(json
, "macs", json_mac
);
6409 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6410 json
, JSON_C_TO_STRING_PRETTY
));
6411 json_object_free(json
);
6416 * Display MACs for all VNIs (VTY command handler).
6418 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6419 bool print_dup
, bool use_json
)
6421 struct mac_walk_ctx wctx
;
6422 json_object
*json
= NULL
;
6424 if (!is_evpn_enabled()) {
6426 vty_out(vty
, "{}\n");
6430 json
= json_object_new_object();
6432 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6435 wctx
.print_dup
= print_dup
;
6436 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6439 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6440 json
, JSON_C_TO_STRING_PRETTY
));
6441 json_object_free(json
);
6446 * Display MACs in detail for all VNIs (VTY command handler).
6448 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6449 struct zebra_vrf
*zvrf
,
6450 bool print_dup
, bool use_json
)
6452 struct mac_walk_ctx wctx
;
6453 json_object
*json
= NULL
;
6455 if (!is_evpn_enabled()) {
6457 vty_out(vty
, "{}\n");
6461 json
= json_object_new_object();
6463 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6466 wctx
.print_dup
= print_dup
;
6467 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6471 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6472 json
, JSON_C_TO_STRING_PRETTY
));
6473 json_object_free(json
);
6478 * Display MACs for all VNIs (VTY command handler).
6480 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6481 struct zebra_vrf
*zvrf
,
6482 struct in_addr vtep_ip
, bool use_json
)
6484 struct mac_walk_ctx wctx
;
6485 json_object
*json
= NULL
;
6487 if (!is_evpn_enabled())
6491 json
= json_object_new_object();
6493 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6495 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6496 wctx
.r_vtep_ip
= vtep_ip
;
6498 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6501 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6502 json
, JSON_C_TO_STRING_PRETTY
));
6503 json_object_free(json
);
6508 * Display specific MAC for a VNI, if present (VTY command handler).
6510 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6511 vni_t vni
, struct ethaddr
*macaddr
,
6516 json_object
*json
= NULL
;
6518 if (!is_evpn_enabled())
6521 zvni
= zvni_lookup(vni
);
6524 vty_out(vty
, "{}\n");
6526 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6529 mac
= zvni_mac_lookup(zvni
, macaddr
);
6532 vty_out(vty
, "{}\n");
6535 "%% Requested MAC does not exist in VNI %u\n",
6541 json
= json_object_new_object();
6543 zvni_print_mac(mac
, vty
, json
);
6545 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6546 json
, JSON_C_TO_STRING_PRETTY
));
6547 json_object_free(json
);
6551 /* Print Duplicate MACs per VNI */
6552 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6553 struct zebra_vrf
*zvrf
,
6554 vni_t vni
, bool use_json
)
6557 struct mac_walk_ctx wctx
;
6559 json_object
*json
= NULL
;
6560 json_object
*json_mac
= NULL
;
6562 if (!is_evpn_enabled())
6565 zvni
= zvni_lookup(vni
);
6567 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6571 num_macs
= num_valid_macs(zvni
);
6575 num_macs
= num_dup_detected_macs(zvni
);
6580 json
= json_object_new_object();
6581 json_mac
= json_object_new_object();
6584 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6587 wctx
.json
= json_mac
;
6591 "Number of MACs (local and remote) known for this VNI: %u\n",
6593 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6594 "Intf/Remote VTEP", "VLAN");
6596 json_object_int_add(json
, "numMacs", num_macs
);
6598 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6601 json_object_object_add(json
, "macs", json_mac
);
6602 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6603 json
, JSON_C_TO_STRING_PRETTY
));
6604 json_object_free(json
);
6609 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6610 struct zebra_vrf
*zvrf
,
6611 vni_t vni
, struct ethaddr
*macaddr
)
6615 struct listnode
*node
= NULL
;
6616 zebra_neigh_t
*nbr
= NULL
;
6618 if (!is_evpn_enabled())
6621 zvni
= zvni_lookup(vni
);
6623 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6627 mac
= zvni_mac_lookup(zvni
, macaddr
);
6629 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6634 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6635 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6639 /* Remove all IPs as duplicate associcated with this MAC */
6640 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6641 /* For local neigh mark inactive so MACIP update is generated
6642 * to BGP. This is a scenario where MAC update received
6643 * and detected as duplicate which marked neigh as duplicate.
6644 * Later local neigh update did not get a chance to relay
6645 * to BGP. Similarly remote macip update, neigh needs to be
6646 * installed locally.
6648 if (zvrf
->dad_freeze
&&
6649 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6650 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6651 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6652 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6653 zvni_neigh_install(zvni
, nbr
);
6656 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6658 nbr
->detect_start_time
.tv_sec
= 0;
6659 nbr
->dad_dup_detect_time
= 0;
6662 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6664 mac
->detect_start_time
.tv_sec
= 0;
6665 mac
->detect_start_time
.tv_usec
= 0;
6666 mac
->dad_dup_detect_time
= 0;
6667 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6669 /* warn-only action return */
6670 if (!zvrf
->dad_freeze
)
6673 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6674 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6676 if (zvni_mac_send_add_to_client(zvni
->vni
,
6682 /* Process all neighbors associated with this MAC. */
6683 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6685 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6686 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6688 /* Install the entry. */
6689 zvni_mac_install(zvni
, mac
);
6695 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6696 struct zebra_vrf
*zvrf
,
6697 vni_t vni
, struct ipaddr
*ip
)
6702 char buf
[INET6_ADDRSTRLEN
];
6703 char buf2
[ETHER_ADDR_STRLEN
];
6705 if (!is_evpn_enabled())
6708 zvni
= zvni_lookup(vni
);
6710 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6714 nbr
= zvni_neigh_lookup(zvni
, ip
);
6717 "%% Requested host IP does not exist in VNI %u\n",
6722 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6724 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6726 "%% Requsted host IP %s is not duplicate detected\n",
6731 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6733 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6735 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6736 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6737 return CMD_WARNING_CONFIG_FAILED
;
6740 if (IS_ZEBRA_DEBUG_VXLAN
)
6741 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6742 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6745 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6747 nbr
->detect_start_time
.tv_sec
= 0;
6748 nbr
->detect_start_time
.tv_usec
= 0;
6749 nbr
->dad_dup_detect_time
= 0;
6750 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6752 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6753 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6755 nbr
->flags
, nbr
->loc_seq
);
6756 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6757 zvni_neigh_install(zvni
, nbr
);
6763 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6765 struct mac_walk_ctx
*wctx
= ctxt
;
6768 struct listnode
*node
= NULL
;
6769 zebra_neigh_t
*nbr
= NULL
;
6771 mac
= (zebra_mac_t
*)bucket
->data
;
6777 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6780 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6782 mac
->detect_start_time
.tv_sec
= 0;
6783 mac
->detect_start_time
.tv_usec
= 0;
6784 mac
->dad_dup_detect_time
= 0;
6785 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6787 /* Remove all IPs as duplicate associcated with this MAC */
6788 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6789 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6791 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6793 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6795 nbr
->detect_start_time
.tv_sec
= 0;
6796 nbr
->dad_dup_detect_time
= 0;
6799 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6800 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6802 if (zvni_mac_send_add_to_client(zvni
->vni
,
6804 mac
->flags
, mac
->loc_seq
))
6807 /* Process all neighbors associated with this MAC. */
6808 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6810 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6811 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6813 /* Install the entry. */
6814 zvni_mac_install(zvni
, mac
);
6818 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6820 struct neigh_walk_ctx
*wctx
= ctxt
;
6823 char buf
[INET6_ADDRSTRLEN
];
6825 nbr
= (zebra_neigh_t
*)bucket
->data
;
6831 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6834 if (IS_ZEBRA_DEBUG_VXLAN
) {
6835 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6837 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6838 __PRETTY_FUNCTION__
, buf
,
6839 nbr
->flags
, nbr
->loc_seq
);
6842 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6844 nbr
->detect_start_time
.tv_sec
= 0;
6845 nbr
->detect_start_time
.tv_usec
= 0;
6846 nbr
->dad_dup_detect_time
= 0;
6847 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6849 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6850 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6852 nbr
->flags
, nbr
->loc_seq
);
6853 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6854 zvni_neigh_install(zvni
, nbr
);
6858 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6863 struct zebra_vrf
*zvrf
;
6864 struct mac_walk_ctx m_wctx
;
6865 struct neigh_walk_ctx n_wctx
;
6867 zvni
= (zebra_vni_t
*)bucket
->data
;
6871 vty
= (struct vty
*)args
[0];
6872 zvrf
= (struct zebra_vrf
*)args
[1];
6874 if (hashcount(zvni
->neigh_table
)) {
6875 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6879 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6883 if (num_valid_macs(zvni
)) {
6884 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6888 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6893 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6894 struct zebra_vrf
*zvrf
)
6898 if (!is_evpn_enabled())
6904 hash_iterate(zvrf
->vni_table
,
6905 (void (*)(struct hash_bucket
*, void *))
6906 zvni_clear_dup_detect_hash_vni_all
, args
);
6911 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6912 struct zebra_vrf
*zvrf
,
6916 struct mac_walk_ctx m_wctx
;
6917 struct neigh_walk_ctx n_wctx
;
6919 if (!is_evpn_enabled())
6922 zvni
= zvni_lookup(vni
);
6924 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6928 if (hashcount(zvni
->neigh_table
)) {
6929 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6933 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6937 if (num_valid_macs(zvni
)) {
6938 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6942 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6949 * Display MACs for a VNI from specific VTEP (VTY command handler).
6951 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6952 vni_t vni
, struct in_addr vtep_ip
,
6957 struct mac_walk_ctx wctx
;
6958 json_object
*json
= NULL
;
6959 json_object
*json_mac
= NULL
;
6961 if (!is_evpn_enabled())
6963 zvni
= zvni_lookup(vni
);
6966 vty_out(vty
, "{}\n");
6968 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6971 num_macs
= num_valid_macs(zvni
);
6976 json
= json_object_new_object();
6977 json_mac
= json_object_new_object();
6980 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6983 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6984 wctx
.r_vtep_ip
= vtep_ip
;
6985 wctx
.json
= json_mac
;
6986 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6989 json_object_int_add(json
, "numMacs", wctx
.count
);
6991 json_object_object_add(json
, "macs", json_mac
);
6992 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6993 json
, JSON_C_TO_STRING_PRETTY
));
6994 json_object_free(json
);
7000 * Display VNI information (VTY command handler).
7002 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
7005 json_object
*json
= NULL
;
7007 zebra_l3vni_t
*zl3vni
= NULL
;
7008 zebra_vni_t
*zvni
= NULL
;
7010 if (!is_evpn_enabled())
7014 json
= json_object_new_object();
7018 zl3vni
= zl3vni_lookup(vni
);
7020 zl3vni_print(zl3vni
, (void *)args
);
7022 zvni
= zvni_lookup(vni
);
7025 vty_out(vty
, "{}\n");
7027 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7031 zvni_print(zvni
, (void *)args
);
7035 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7036 json
, JSON_C_TO_STRING_PRETTY
));
7037 json_object_free(json
);
7041 /* Display all global details for EVPN */
7042 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7047 json_object
*json
= NULL
;
7048 struct zebra_vrf
*zvrf
= NULL
;
7050 if (!is_evpn_enabled())
7053 zvrf
= zebra_vrf_get_evpn();
7057 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7058 num_l2vnis
= hashcount(zvrf
->vni_table
);
7059 num_vnis
= num_l2vnis
+ num_l3vnis
;
7062 json
= json_object_new_object();
7063 json_object_string_add(json
, "advertiseGatewayMacip",
7064 zvrf
->advertise_gw_macip
? "Yes" : "No");
7065 json_object_int_add(json
, "numVnis", num_vnis
);
7066 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7067 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7068 if (zvrf
->dup_addr_detect
)
7069 json_object_boolean_true_add(json
,
7070 "isDuplicateAddrDetection");
7072 json_object_boolean_false_add(json
,
7073 "isDuplicateAddrDetection");
7074 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7075 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7076 json_object_int_add(json
, "detectionFreezeTime",
7077 zvrf
->dad_freeze_time
);
7080 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7081 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7082 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7083 zvrf
->advertise_gw_macip
? "Yes" : "No");
7084 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7085 zvrf
->advertise_svi_macip
? "Yes" : "No");
7086 vty_out(vty
, "Duplicate address detection: %s\n",
7087 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7088 vty_out(vty
, " Detection max-moves %u, time %d\n",
7089 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7090 if (zvrf
->dad_freeze
) {
7091 if (zvrf
->dad_freeze_time
)
7092 vty_out(vty
, " Detection freeze %u\n",
7093 zvrf
->dad_freeze_time
);
7095 vty_out(vty
, " Detection freeze %s\n",
7101 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7102 json
, JSON_C_TO_STRING_PRETTY
));
7103 json_object_free(json
);
7108 * Display VNI hash table (VTY command handler).
7110 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7113 json_object
*json
= NULL
;
7116 if (!is_evpn_enabled())
7120 json
= json_object_new_object();
7122 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7123 "Type", "VxLAN IF", "# MACs", "# ARPs",
7124 "# Remote VTEPs", "Tenant VRF");
7129 /* Display all L2-VNIs */
7130 hash_iterate(zvrf
->vni_table
,
7131 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7134 /* Display all L3-VNIs */
7135 hash_iterate(zrouter
.l3vni_table
,
7136 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7140 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7141 json
, JSON_C_TO_STRING_PRETTY
));
7142 json_object_free(json
);
7146 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7150 uint32_t max_moves
= 0;
7151 uint32_t freeze_time
= 0;
7152 bool dup_addr_detect
= false;
7153 bool freeze
= false;
7156 STREAM_GETL(s
, dup_addr_detect
);
7157 STREAM_GETL(s
, time
);
7158 STREAM_GETL(s
, max_moves
);
7159 STREAM_GETL(s
, freeze
);
7160 STREAM_GETL(s
, freeze_time
);
7162 /* DAD previous state was enabled, and new state is disable,
7163 * clear all duplicate detected addresses.
7165 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7166 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7168 zvrf
->dup_addr_detect
= dup_addr_detect
;
7169 zvrf
->dad_time
= time
;
7170 zvrf
->dad_max_moves
= max_moves
;
7171 zvrf
->dad_freeze
= freeze
;
7172 zvrf
->dad_freeze_time
= freeze_time
;
7174 if (IS_ZEBRA_DEBUG_VXLAN
)
7176 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7177 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7178 zvrf
->dup_addr_detect
? "enable" : "disable",
7179 zvrf
->dad_max_moves
,
7181 zvrf
->dad_freeze
? "enable" : "disable",
7182 zvrf
->dad_freeze_time
);
7189 * Display VNI hash table in detail(VTY command handler).
7191 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7194 json_object
*json
= NULL
;
7195 struct zebra_ns
*zns
= NULL
;
7196 struct zvni_evpn_show zes
;
7198 if (!is_evpn_enabled())
7201 zns
= zebra_ns_lookup(NS_DEFAULT
);
7207 json
= json_object_new_object();
7213 /* Display all L2-VNIs */
7216 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7219 /* Display all L3-VNIs */
7220 hash_iterate(zrouter
.l3vni_table
,
7221 (void (*)(struct hash_bucket
*,
7222 void *))zl3vni_print_hash_detail
,
7226 vty_out(vty
, "%s\n",
7227 json_object_to_json_string_ext(
7228 json
, JSON_C_TO_STRING_PRETTY
));
7229 json_object_free(json
);
7234 * Handle neighbor delete notification from the kernel (on a VLAN device
7235 * / L3 interface). This may result in either the neighbor getting deleted
7236 * from our database or being re-added to the kernel (if it is a valid
7239 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7240 struct interface
*link_if
,
7243 char buf
[INET6_ADDRSTRLEN
];
7244 char buf2
[ETHER_ADDR_STRLEN
];
7245 zebra_neigh_t
*n
= NULL
;
7246 zebra_vni_t
*zvni
= NULL
;
7247 zebra_mac_t
*zmac
= NULL
;
7248 zebra_l3vni_t
*zl3vni
= NULL
;
7249 struct zebra_vrf
*zvrf
;
7251 /* check if this is a remote neigh entry corresponding to remote
7254 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7256 return zl3vni_local_nh_del(zl3vni
, ip
);
7258 /* We are only interested in neighbors on an SVI that resides on top
7259 * of a VxLAN bridge.
7261 zvni
= zvni_from_svi(ifp
, link_if
);
7265 if (!zvni
->vxlan_if
) {
7267 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7272 if (IS_ZEBRA_DEBUG_VXLAN
)
7273 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7274 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7275 ifp
->ifindex
, zvni
->vni
);
7277 /* If entry doesn't exist, nothing to do. */
7278 n
= zvni_neigh_lookup(zvni
, ip
);
7282 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7284 if (IS_ZEBRA_DEBUG_VXLAN
)
7286 "Trying to del a neigh %s without a mac %s on VNI %u",
7287 ipaddr2str(ip
, buf
, sizeof(buf
)),
7288 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7294 /* If it is a remote entry, the kernel has aged this out or someone has
7295 * deleted it, it needs to be re-installed as Quagga is the owner.
7297 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7298 zvni_neigh_install(zvni
, n
);
7302 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7304 zlog_debug("%s: VNI %u vrf lookup failed.",
7305 __PRETTY_FUNCTION__
, zvni
->vni
);
7309 /* In case of feeze action, if local neigh is in duplicate state,
7310 * Mark the Neigh as inactive before sending delete request to BGPd,
7311 * If BGPd has remote entry, it will re-install
7313 if (zvrf
->dad_freeze
&&
7314 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7315 ZEBRA_NEIGH_SET_INACTIVE(n
);
7317 /* Remove neighbor from BGP. */
7318 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7320 /* Delete this neighbor entry. */
7321 zvni_neigh_del(zvni
, n
);
7323 /* see if the AUTO mac needs to be deleted */
7324 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7325 && !listcount(zmac
->neigh_list
))
7326 zvni_mac_del(zvni
, zmac
);
7332 * Handle neighbor add or update notification from the kernel (on a VLAN
7333 * device / L3 interface). This is typically for a local neighbor but can
7334 * also be for a remote neighbor (e.g., ageout notification). It could
7335 * also be a "move" scenario.
7337 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7338 struct interface
*link_if
,
7340 struct ethaddr
*macaddr
,
7345 char buf
[ETHER_ADDR_STRLEN
];
7346 char buf2
[INET6_ADDRSTRLEN
];
7347 zebra_vni_t
*zvni
= NULL
;
7348 zebra_l3vni_t
*zl3vni
= NULL
;
7350 /* check if this is a remote neigh entry corresponding to remote
7353 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7355 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7357 /* We are only interested in neighbors on an SVI that resides on top
7358 * of a VxLAN bridge.
7360 zvni
= zvni_from_svi(ifp
, link_if
);
7364 if (IS_ZEBRA_DEBUG_VXLAN
)
7366 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7367 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7368 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7369 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7370 is_router
? "router " : "",
7373 /* Is this about a local neighbor or a remote one? */
7375 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7378 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7383 * Handle message from client to delete a remote MACIP for a VNI.
7385 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7389 struct ethaddr macaddr
;
7391 struct in_addr vtep_ip
;
7392 uint16_t l
= 0, ipa_len
;
7393 char buf
[ETHER_ADDR_STRLEN
];
7394 char buf1
[INET6_ADDRSTRLEN
];
7396 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7397 memset(&ip
, 0, sizeof(struct ipaddr
));
7398 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7402 while (l
< hdr
->length
) {
7403 /* Obtain each remote MACIP and process. */
7404 /* Message contains VNI, followed by MAC followed by IP (if any)
7405 * followed by remote VTEP IP.
7407 memset(&ip
, 0, sizeof(ip
));
7408 STREAM_GETL(s
, vni
);
7409 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7410 STREAM_GETL(s
, ipa_len
);
7412 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7414 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7416 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7417 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7418 l
+= IPV4_MAX_BYTELEN
;
7420 if (IS_ZEBRA_DEBUG_VXLAN
)
7422 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7424 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7425 ipa_len
? " IP " : "",
7427 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7429 zebra_route_string(client
->proto
));
7431 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7439 * Handle message from client to add a remote MACIP for a VNI. This
7440 * could be just the add of a MAC address or the add of a neighbor
7443 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7447 struct ethaddr macaddr
;
7449 struct in_addr vtep_ip
;
7450 uint16_t l
= 0, ipa_len
;
7453 char buf
[ETHER_ADDR_STRLEN
];
7454 char buf1
[INET6_ADDRSTRLEN
];
7456 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7457 memset(&ip
, 0, sizeof(struct ipaddr
));
7458 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7460 if (!EVPN_ENABLED(zvrf
)) {
7461 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7467 while (l
< hdr
->length
) {
7468 /* Obtain each remote MACIP and process. */
7469 /* Message contains VNI, followed by MAC followed by IP (if any)
7470 * followed by remote VTEP IP.
7472 memset(&ip
, 0, sizeof(ip
));
7473 STREAM_GETL(s
, vni
);
7474 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7475 STREAM_GETL(s
, ipa_len
);
7477 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7479 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7481 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7482 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7483 l
+= IPV4_MAX_BYTELEN
;
7485 /* Get flags - sticky mac and/or gateway mac */
7486 STREAM_GETC(s
, flags
);
7488 STREAM_GETL(s
, seq
);
7491 if (IS_ZEBRA_DEBUG_VXLAN
)
7493 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7495 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7496 ipa_len
? " IP " : "",
7498 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7499 flags
, seq
, inet_ntoa(vtep_ip
),
7500 zebra_route_string(client
->proto
));
7502 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7503 flags
, seq
, vtep_ip
);
7511 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7512 * us, this must involve a multihoming scenario. Treat this as implicit delete
7513 * of any prior local MAC.
7515 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7516 struct interface
*br_if
,
7517 struct ethaddr
*macaddr
, vlanid_t vid
)
7519 struct zebra_if
*zif
;
7520 struct zebra_l2info_vxlan
*vxl
;
7524 char buf
[ETHER_ADDR_STRLEN
];
7528 vxl
= &zif
->l2info
.vxl
;
7531 /* Check if EVPN is enabled. */
7532 if (!is_evpn_enabled())
7535 /* Locate hash entry; it is expected to exist. */
7536 zvni
= zvni_lookup(vni
);
7540 /* If entry doesn't exist, nothing to do. */
7541 mac
= zvni_mac_lookup(zvni
, macaddr
);
7545 /* Is it a local entry? */
7546 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7549 if (IS_ZEBRA_DEBUG_VXLAN
)
7551 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7552 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7553 ifp
->ifindex
, vni
, mac
->flags
);
7555 /* Remove MAC from BGP. */
7556 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7559 * If there are no neigh associated with the mac delete the mac
7560 * else mark it as AUTO for forward reference
7562 if (!listcount(mac
->neigh_list
)) {
7563 zvni_mac_del(zvni
, mac
);
7565 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7566 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7567 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7574 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7575 * This can happen because the remote MAC entries are also added as "dynamic",
7576 * so the kernel can ageout the entry.
7578 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7579 struct interface
*br_if
,
7580 struct ethaddr
*macaddr
, vlanid_t vid
)
7582 struct zebra_if
*zif
= NULL
;
7583 struct zebra_l2info_vxlan
*vxl
= NULL
;
7585 zebra_vni_t
*zvni
= NULL
;
7586 zebra_l3vni_t
*zl3vni
= NULL
;
7587 zebra_mac_t
*mac
= NULL
;
7588 char buf
[ETHER_ADDR_STRLEN
];
7592 vxl
= &zif
->l2info
.vxl
;
7595 /* Check if EVPN is enabled. */
7596 if (!is_evpn_enabled())
7599 /* check if this is a remote RMAC and readd simillar to remote macs */
7600 zl3vni
= zl3vni_lookup(vni
);
7602 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7604 /* Locate hash entry; it is expected to exist. */
7605 zvni
= zvni_lookup(vni
);
7609 /* If entry doesn't exist, nothing to do. */
7610 mac
= zvni_mac_lookup(zvni
, macaddr
);
7614 /* Is it a remote entry? */
7615 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7618 if (IS_ZEBRA_DEBUG_VXLAN
)
7619 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7620 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7623 zvni_mac_install(zvni
, mac
);
7628 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7630 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7631 struct ethaddr
*macaddr
, vlanid_t vid
)
7635 char buf
[ETHER_ADDR_STRLEN
];
7637 /* We are interested in MACs only on ports or (port, VLAN) that
7640 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7643 if (!zvni
->vxlan_if
) {
7645 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7650 /* If entry doesn't exist, nothing to do. */
7651 mac
= zvni_mac_lookup(zvni
, macaddr
);
7655 /* Is it a local entry? */
7656 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7659 if (IS_ZEBRA_DEBUG_VXLAN
)
7660 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7661 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7662 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7664 /* Update all the neigh entries associated with this mac */
7665 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7667 /* Remove MAC from BGP. */
7668 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7671 * If there are no neigh associated with the mac delete the mac
7672 * else mark it as AUTO for forward reference
7674 if (!listcount(mac
->neigh_list
)) {
7675 zvni_mac_del(zvni
, mac
);
7677 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7678 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7679 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7686 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7688 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7689 struct interface
*br_if
,
7690 struct ethaddr
*macaddr
, vlanid_t vid
,
7695 struct zebra_vrf
*zvrf
;
7696 char buf
[ETHER_ADDR_STRLEN
];
7697 bool mac_sticky
= false;
7698 bool inform_client
= false;
7699 bool upd_neigh
= false;
7700 bool is_dup_detect
= false;
7701 struct in_addr vtep_ip
= {.s_addr
= 0};
7703 /* We are interested in MACs only on ports or (port, VLAN) that
7706 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7708 if (IS_ZEBRA_DEBUG_VXLAN
)
7710 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7711 sticky
? "sticky " : "",
7712 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7713 ifp
->name
, ifp
->ifindex
, vid
);
7717 if (!zvni
->vxlan_if
) {
7718 if (IS_ZEBRA_DEBUG_VXLAN
)
7720 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7725 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7727 if (IS_ZEBRA_DEBUG_VXLAN
)
7728 zlog_debug("\tNo Vrf found for vrf_id: %d",
7729 zvni
->vxlan_if
->vrf_id
);
7733 /* Check if we need to create or update or it is a NO-OP. */
7734 mac
= zvni_mac_lookup(zvni
, macaddr
);
7736 if (IS_ZEBRA_DEBUG_VXLAN
)
7738 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7739 sticky
? "sticky " : "",
7740 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7741 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7743 mac
= zvni_mac_add(zvni
, macaddr
);
7746 EC_ZEBRA_MAC_ADD_FAILED
,
7747 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7748 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7749 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7752 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7753 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7754 mac
->fwd_info
.local
.vid
= vid
;
7756 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7757 inform_client
= true;
7760 if (IS_ZEBRA_DEBUG_VXLAN
)
7762 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7763 sticky
? "sticky " : "",
7764 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7765 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7768 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7769 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7773 * Update any changes and if changes are relevant to
7776 if (mac_sticky
== sticky
7777 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7778 && mac
->fwd_info
.local
.vid
== vid
) {
7779 if (IS_ZEBRA_DEBUG_VXLAN
)
7781 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7782 "entry exists and has not changed ",
7783 sticky
? "sticky " : "",
7784 prefix_mac2str(macaddr
, buf
,
7786 ifp
->name
, ifp
->ifindex
, vid
,
7790 if (mac_sticky
!= sticky
) {
7792 SET_FLAG(mac
->flags
,
7795 UNSET_FLAG(mac
->flags
,
7797 inform_client
= true;
7800 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7801 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7802 mac
->fwd_info
.local
.vid
= vid
;
7804 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7805 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7806 bool do_dad
= false;
7809 * MAC has either moved or was "internally" created due
7810 * to a neighbor learn and is now actually learnt. If
7811 * it was learnt as a remote sticky MAC, this is an
7814 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7816 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7817 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7818 prefix_mac2str(macaddr
, buf
,
7820 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7825 /* If an actual move, compute MAC's seq number */
7826 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7827 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7829 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7830 /* Trigger DAD for remote MAC */
7834 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7835 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7836 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7837 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7838 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7839 mac
->fwd_info
.local
.vid
= vid
;
7841 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7843 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7845 * We have to inform BGP of this MAC as well as process
7848 inform_client
= true;
7851 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7855 if (is_dup_detect
) {
7856 inform_client
= false;
7862 /* Inform BGP if required. */
7863 if (inform_client
) {
7864 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7865 mac
->flags
, mac
->loc_seq
))
7869 /* Process all neighbors associated with this MAC, if required. */
7871 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7877 * Handle message from client to delete a remote VTEP for a VNI.
7879 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7882 unsigned short l
= 0;
7884 struct in_addr vtep_ip
;
7886 zebra_vtep_t
*zvtep
;
7887 struct interface
*ifp
;
7888 struct zebra_if
*zif
;
7890 if (!is_evpn_enabled()) {
7892 "%s: EVPN is not enabled yet we have received a vtep del command",
7893 __PRETTY_FUNCTION__
);
7897 if (!EVPN_ENABLED(zvrf
)) {
7898 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7905 while (l
< hdr
->length
) {
7906 int flood_control
__attribute__((unused
));
7908 /* Obtain each remote VTEP and process. */
7909 STREAM_GETL(s
, vni
);
7911 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7912 l
+= IPV4_MAX_BYTELEN
;
7914 /* Flood control is intentionally ignored right now */
7915 STREAM_GETL(s
, flood_control
);
7918 if (IS_ZEBRA_DEBUG_VXLAN
)
7919 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7920 inet_ntoa(vtep_ip
), vni
,
7921 zebra_route_string(client
->proto
));
7923 /* Locate VNI hash entry - expected to exist. */
7924 zvni
= zvni_lookup(vni
);
7926 if (IS_ZEBRA_DEBUG_VXLAN
)
7928 "Failed to locate VNI hash upon remote VTEP DEL, "
7934 ifp
= zvni
->vxlan_if
;
7937 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7943 /* If down or not mapped to a bridge, we're done. */
7944 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7947 /* If the remote VTEP does not exist, there's nothing more to
7949 * Otherwise, uninstall any remote MACs pointing to this VTEP
7951 * then, the VTEP entry itself and remove it.
7953 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7957 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7958 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7959 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7960 zvni_vtep_del(zvni
, zvtep
);
7968 * Handle message from client to add a remote VTEP for a VNI.
7970 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7973 unsigned short l
= 0;
7975 struct in_addr vtep_ip
;
7977 struct interface
*ifp
;
7978 struct zebra_if
*zif
;
7980 zebra_vtep_t
*zvtep
;
7982 if (!is_evpn_enabled()) {
7984 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7985 __PRETTY_FUNCTION__
);
7989 if (!EVPN_ENABLED(zvrf
)) {
7990 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7997 while (l
< hdr
->length
) {
7998 /* Obtain each remote VTEP and process. */
7999 STREAM_GETL(s
, vni
);
8001 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
8002 STREAM_GETL(s
, flood_control
);
8003 l
+= IPV4_MAX_BYTELEN
+ 4;
8005 if (IS_ZEBRA_DEBUG_VXLAN
)
8006 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
8007 inet_ntoa(vtep_ip
), vni
, flood_control
,
8008 zebra_route_string(client
->proto
));
8010 /* Locate VNI hash entry - expected to exist. */
8011 zvni
= zvni_lookup(vni
);
8014 EC_ZEBRA_VTEP_ADD_FAILED
,
8015 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
8020 ifp
= zvni
->vxlan_if
;
8023 EC_ZEBRA_VTEP_ADD_FAILED
,
8024 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
8031 /* If down or not mapped to a bridge, we're done. */
8032 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8035 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
8037 /* If the remote VTEP already exists check if
8038 * the flood mode has changed
8040 if (zvtep
->flood_control
!= flood_control
) {
8041 if (zvtep
->flood_control
8042 == VXLAN_FLOOD_DISABLED
)
8043 /* old mode was head-end-replication but
8044 * is no longer; get rid of the HER fdb
8045 * entry installed before
8047 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8048 zvtep
->flood_control
= flood_control
;
8049 zvni_vtep_install(zvni
, zvtep
);
8052 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8054 zvni_vtep_install(zvni
, zvtep
);
8056 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8057 "Failed to add remote VTEP, VNI %u zvni %p",
8067 * Add/Del gateway macip to evpn
8069 * 1. SVI interface on a vlan aware bridge
8070 * 2. SVI interface on a vlan unaware bridge
8071 * 3. vrr interface (MACVLAN) associated to a SVI
8072 * We advertise macip routes for an interface if it is associated to VxLan vlan
8074 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8078 struct ethaddr macaddr
;
8079 zebra_vni_t
*zvni
= NULL
;
8081 memset(&ip
, 0, sizeof(struct ipaddr
));
8082 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8084 /* Check if EVPN is enabled. */
8085 if (!is_evpn_enabled())
8088 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8089 struct interface
*svi_if
=
8090 NULL
; /* SVI corresponding to the MACVLAN */
8091 struct zebra_if
*ifp_zif
=
8092 NULL
; /* Zebra daemon specific info for MACVLAN */
8093 struct zebra_if
*svi_if_zif
=
8094 NULL
; /* Zebra daemon specific info for SVI*/
8096 ifp_zif
= ifp
->info
;
8101 * for a MACVLAN interface the link represents the svi_if
8103 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8104 ifp_zif
->link_ifindex
);
8106 zlog_debug("MACVLAN %s(%u) without link information",
8107 ifp
->name
, ifp
->ifindex
);
8111 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8113 * If it is a vlan aware bridge then the link gives the
8114 * bridge information
8116 struct interface
*svi_if_link
= NULL
;
8118 svi_if_zif
= svi_if
->info
;
8120 svi_if_link
= if_lookup_by_index_per_ns(
8121 zebra_ns_lookup(NS_DEFAULT
),
8122 svi_if_zif
->link_ifindex
);
8123 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8125 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8127 * If it is a vlan unaware bridge then svi is the bridge
8130 zvni
= zvni_from_svi(svi_if
, svi_if
);
8132 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8133 struct zebra_if
*svi_if_zif
=
8134 NULL
; /* Zebra daemon specific info for SVI */
8135 struct interface
*svi_if_link
=
8136 NULL
; /* link info for the SVI = bridge info */
8138 svi_if_zif
= ifp
->info
;
8140 svi_if_link
= if_lookup_by_index_per_ns(
8141 zebra_ns_lookup(NS_DEFAULT
),
8142 svi_if_zif
->link_ifindex
);
8144 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8146 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8147 zvni
= zvni_from_svi(ifp
, ifp
);
8153 if (!zvni
->vxlan_if
) {
8154 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8160 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8162 if (p
->family
== AF_INET
) {
8163 ip
.ipa_type
= IPADDR_V4
;
8164 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8165 sizeof(struct in_addr
));
8166 } else if (p
->family
== AF_INET6
) {
8167 ip
.ipa_type
= IPADDR_V6
;
8168 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8169 sizeof(struct in6_addr
));
8174 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8176 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8182 * Handle SVI interface going down.
8183 * SVI can be associated to either L3-VNI or L2-VNI.
8184 * For L2-VNI: At this point, this is a NOP since
8185 * the kernel deletes the neighbor entries on this SVI (if any).
8186 * We only need to update the vrf corresponding to zvni.
8187 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8190 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8192 zebra_l3vni_t
*zl3vni
= NULL
;
8194 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8197 /* process l3-vni down */
8198 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8200 /* remove association with svi-if */
8201 zl3vni
->svi_if
= NULL
;
8203 zebra_vni_t
*zvni
= NULL
;
8205 /* since we dont have svi corresponding to zvni, we associate it
8206 * to default vrf. Note: the corresponding neigh entries on the
8207 * SVI would have already been deleted */
8208 zvni
= zvni_from_svi(ifp
, link_if
);
8210 zvni
->vrf_id
= VRF_DEFAULT
;
8212 /* update the tenant vrf in BGP */
8213 zvni_send_add_to_client(zvni
);
8220 * Handle SVI interface coming up.
8221 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8223 * For L2-VNI: we need to install any remote neighbors entried (used for
8225 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8227 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8229 zebra_vni_t
*zvni
= NULL
;
8230 zebra_l3vni_t
*zl3vni
= NULL
;
8232 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8235 /* associate with svi */
8236 zl3vni
->svi_if
= ifp
;
8238 /* process oper-up */
8239 if (is_l3vni_oper_up(zl3vni
))
8240 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8243 /* process SVI up for l2-vni */
8244 struct neigh_walk_ctx n_wctx
;
8246 zvni
= zvni_from_svi(ifp
, link_if
);
8250 if (!zvni
->vxlan_if
) {
8252 "VNI %u hash %p doesn't have intf upon SVI up",
8257 if (IS_ZEBRA_DEBUG_VXLAN
)
8259 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8260 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8261 vrf_id_to_name(ifp
->vrf_id
));
8263 /* update the vrf information for l2-vni and inform bgp */
8264 zvni
->vrf_id
= ifp
->vrf_id
;
8265 zvni_send_add_to_client(zvni
);
8267 /* Install any remote neighbors for this VNI. */
8268 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8270 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8278 * Handle VxLAN interface down
8280 int zebra_vxlan_if_down(struct interface
*ifp
)
8283 struct zebra_if
*zif
= NULL
;
8284 struct zebra_l2info_vxlan
*vxl
= NULL
;
8285 zebra_l3vni_t
*zl3vni
= NULL
;
8288 /* Check if EVPN is enabled. */
8289 if (!is_evpn_enabled())
8294 vxl
= &zif
->l2info
.vxl
;
8297 zl3vni
= zl3vni_lookup(vni
);
8299 /* process-if-down for l3-vni */
8300 if (IS_ZEBRA_DEBUG_VXLAN
)
8301 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8304 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8306 /* process if-down for l2-vni */
8307 if (IS_ZEBRA_DEBUG_VXLAN
)
8308 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8311 /* Locate hash entry; it is expected to exist. */
8312 zvni
= zvni_lookup(vni
);
8315 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8316 ifp
->name
, ifp
->ifindex
, vni
);
8320 assert(zvni
->vxlan_if
== ifp
);
8322 /* Delete this VNI from BGP. */
8323 zvni_send_del_to_client(zvni
->vni
);
8325 /* Free up all neighbors and MACs, if any. */
8326 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8327 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8329 /* Free up all remote VTEPs, if any. */
8330 zvni_vtep_del_all(zvni
, 1);
8336 * Handle VxLAN interface up - update BGP if required.
8338 int zebra_vxlan_if_up(struct interface
*ifp
)
8341 struct zebra_if
*zif
= NULL
;
8342 struct zebra_l2info_vxlan
*vxl
= NULL
;
8343 zebra_vni_t
*zvni
= NULL
;
8344 zebra_l3vni_t
*zl3vni
= NULL
;
8346 /* Check if EVPN is enabled. */
8347 if (!is_evpn_enabled())
8352 vxl
= &zif
->l2info
.vxl
;
8355 zl3vni
= zl3vni_lookup(vni
);
8358 if (IS_ZEBRA_DEBUG_VXLAN
)
8359 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8362 /* we need to associate with SVI, if any, we can associate with
8363 * svi-if only after association with vxlan-intf is complete
8365 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8367 if (is_l3vni_oper_up(zl3vni
))
8368 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8370 /* Handle L2-VNI add */
8371 struct interface
*vlan_if
= NULL
;
8373 if (IS_ZEBRA_DEBUG_VXLAN
)
8374 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8377 /* Locate hash entry; it is expected to exist. */
8378 zvni
= zvni_lookup(vni
);
8381 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8382 ifp
->name
, ifp
->ifindex
, vni
);
8386 assert(zvni
->vxlan_if
== ifp
);
8387 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8388 zif
->brslave_info
.br_if
);
8390 zvni
->vrf_id
= vlan_if
->vrf_id
;
8391 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8393 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8396 /* If part of a bridge, inform BGP about this VNI. */
8397 /* Also, read and populate local MACs and neighbors. */
8398 if (zif
->brslave_info
.br_if
) {
8399 zvni_send_add_to_client(zvni
);
8400 zvni_read_mac_neigh(zvni
, ifp
);
8408 * Handle VxLAN interface delete. Locate and remove entry in hash table
8409 * and update BGP, if required.
8411 int zebra_vxlan_if_del(struct interface
*ifp
)
8414 struct zebra_if
*zif
= NULL
;
8415 struct zebra_l2info_vxlan
*vxl
= NULL
;
8416 zebra_vni_t
*zvni
= NULL
;
8417 zebra_l3vni_t
*zl3vni
= NULL
;
8419 /* Check if EVPN is enabled. */
8420 if (!is_evpn_enabled())
8425 vxl
= &zif
->l2info
.vxl
;
8428 zl3vni
= zl3vni_lookup(vni
);
8431 if (IS_ZEBRA_DEBUG_VXLAN
)
8432 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8435 /* process oper-down for l3-vni */
8436 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8438 /* remove the association with vxlan_if */
8439 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8440 zl3vni
->vxlan_if
= NULL
;
8443 /* process if-del for l2-vni*/
8444 if (IS_ZEBRA_DEBUG_VXLAN
)
8445 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8448 /* Locate hash entry; it is expected to exist. */
8449 zvni
= zvni_lookup(vni
);
8452 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8453 ifp
->name
, ifp
->ifindex
, vni
);
8457 /* remove from l3-vni list */
8458 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8460 listnode_delete(zl3vni
->l2vnis
, zvni
);
8462 /* Delete VNI from BGP. */
8463 zvni_send_del_to_client(zvni
->vni
);
8465 /* Free up all neighbors and MAC, if any. */
8466 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8467 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8469 /* Free up all remote VTEPs, if any. */
8470 zvni_vtep_del_all(zvni
, 0);
8472 /* Delete the hash entry. */
8473 if (zvni_del(zvni
)) {
8474 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8475 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8476 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8484 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8486 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8489 struct zebra_if
*zif
= NULL
;
8490 struct zebra_l2info_vxlan
*vxl
= NULL
;
8491 zebra_vni_t
*zvni
= NULL
;
8492 zebra_l3vni_t
*zl3vni
= NULL
;
8494 /* Check if EVPN is enabled. */
8495 if (!is_evpn_enabled())
8500 vxl
= &zif
->l2info
.vxl
;
8503 zl3vni
= zl3vni_lookup(vni
);
8506 if (IS_ZEBRA_DEBUG_VXLAN
)
8508 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8509 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8510 inet_ntoa(vxl
->vtep_ip
),
8511 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8513 /* Removed from bridge? Cleanup and return */
8514 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8515 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8516 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8520 /* access-vlan change - process oper down, associate with new
8521 * svi_if and then process oper up again
8523 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8524 if (if_is_operative(ifp
)) {
8525 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8526 zl3vni
->svi_if
= NULL
;
8527 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8528 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8529 if (is_l3vni_oper_up(zl3vni
))
8530 zebra_vxlan_process_l3vni_oper_up(
8536 * local-ip change - process oper down, associate with new
8537 * local-ip and then process oper up again
8539 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8540 if (if_is_operative(ifp
)) {
8541 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8542 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8543 if (is_l3vni_oper_up(zl3vni
))
8544 zebra_vxlan_process_l3vni_oper_up(
8549 /* Update local tunnel IP. */
8550 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8552 /* if we have a valid new master, process l3-vni oper up */
8553 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8554 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8555 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8559 /* Update VNI hash. */
8560 zvni
= zvni_lookup(vni
);
8563 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8564 ifp
->name
, ifp
->ifindex
, vni
);
8568 if (IS_ZEBRA_DEBUG_VXLAN
)
8570 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8571 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8572 inet_ntoa(vxl
->vtep_ip
),
8573 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8575 /* Removed from bridge? Cleanup and return */
8576 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8577 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8578 /* Delete from client, remove all remote VTEPs */
8579 /* Also, free up all MACs and neighbors. */
8580 zvni_send_del_to_client(zvni
->vni
);
8581 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8582 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8583 zvni_vtep_del_all(zvni
, 1);
8587 /* Handle other changes. */
8588 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8589 /* Remove all existing local neigh and MACs for this VNI
8590 * (including from BGP)
8592 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8593 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8596 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8597 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8598 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8600 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8601 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8602 zvni
->mcast_grp
= vxl
->mcast_grp
;
8604 zvni
->vxlan_if
= ifp
;
8606 /* Take further actions needed.
8607 * Note that if we are here, there is a change of interest.
8609 /* If down or not mapped to a bridge, we're done. */
8610 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8613 /* Inform BGP, if there is a change of interest. */
8615 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8616 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8617 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8618 zvni_send_add_to_client(zvni
);
8620 /* If there is a valid new master or a VLAN mapping change,
8621 * read and populate local MACs and neighbors.
8622 * Also, reinstall any remote MACs and neighbors
8623 * for this VNI (based on new VLAN).
8625 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8626 zvni_read_mac_neigh(zvni
, ifp
);
8627 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8628 struct mac_walk_ctx m_wctx
;
8629 struct neigh_walk_ctx n_wctx
;
8631 zvni_read_mac_neigh(zvni
, ifp
);
8633 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8635 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8638 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8640 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8649 * Handle VxLAN interface add.
8651 int zebra_vxlan_if_add(struct interface
*ifp
)
8654 struct zebra_if
*zif
= NULL
;
8655 struct zebra_l2info_vxlan
*vxl
= NULL
;
8656 zebra_vni_t
*zvni
= NULL
;
8657 zebra_l3vni_t
*zl3vni
= NULL
;
8659 /* Check if EVPN is enabled. */
8660 if (!is_evpn_enabled())
8665 vxl
= &zif
->l2info
.vxl
;
8668 zl3vni
= zl3vni_lookup(vni
);
8671 /* process if-add for l3-vni*/
8672 if (IS_ZEBRA_DEBUG_VXLAN
)
8674 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8675 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8676 inet_ntoa(vxl
->vtep_ip
),
8677 zif
->brslave_info
.bridge_ifindex
);
8679 /* associate with vxlan_if */
8680 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8681 zl3vni
->vxlan_if
= ifp
;
8683 /* Associate with SVI, if any. We can associate with svi-if only
8684 * after association with vxlan_if is complete */
8685 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8687 if (is_l3vni_oper_up(zl3vni
))
8688 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8691 /* process if-add for l2-vni */
8692 struct interface
*vlan_if
= NULL
;
8694 /* Create or update VNI hash. */
8695 zvni
= zvni_lookup(vni
);
8697 zvni
= zvni_add(vni
);
8700 EC_ZEBRA_VNI_ADD_FAILED
,
8701 "Failed to add VNI hash, IF %s(%u) VNI %u",
8702 ifp
->name
, ifp
->ifindex
, vni
);
8707 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8708 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8709 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8711 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8712 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8713 zvni
->mcast_grp
= vxl
->mcast_grp
;
8715 zvni
->vxlan_if
= ifp
;
8716 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8717 zif
->brslave_info
.br_if
);
8719 zvni
->vrf_id
= vlan_if
->vrf_id
;
8720 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8722 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8725 if (IS_ZEBRA_DEBUG_VXLAN
) {
8726 char addr_buf1
[INET_ADDRSTRLEN
];
8727 char addr_buf2
[INET_ADDRSTRLEN
];
8729 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8730 addr_buf1
, INET_ADDRSTRLEN
);
8731 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8732 addr_buf2
, INET_ADDRSTRLEN
);
8735 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8737 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8739 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8740 addr_buf1
, addr_buf2
,
8741 zif
->brslave_info
.bridge_ifindex
);
8744 /* If down or not mapped to a bridge, we're done. */
8745 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8749 zvni_send_add_to_client(zvni
);
8751 /* Read and populate local MACs and neighbors */
8752 zvni_read_mac_neigh(zvni
, ifp
);
8758 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8759 char *err
, int err_str_sz
, int filter
,
8762 zebra_l3vni_t
*zl3vni
= NULL
;
8763 struct zebra_vrf
*zvrf_evpn
= NULL
;
8765 zvrf_evpn
= zebra_vrf_get_evpn();
8769 if (IS_ZEBRA_DEBUG_VXLAN
)
8770 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8771 add
? "ADD" : "DEL");
8775 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8777 /* check if the vni is already present under zvrf */
8779 snprintf(err
, err_str_sz
,
8780 "VNI is already configured under the vrf");
8784 /* check if this VNI is already present in the system */
8785 zl3vni
= zl3vni_lookup(vni
);
8787 snprintf(err
, err_str_sz
,
8788 "VNI is already configured as L3-VNI");
8792 /* add the L3-VNI to the global table */
8793 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8795 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8799 /* associate the vrf with vni */
8802 /* set the filter in l3vni to denote if we are using l3vni only
8806 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8808 /* associate with vxlan-intf;
8809 * we need to associate with the vxlan-intf first
8811 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8813 /* associate with corresponding SVI interface, we can associate
8814 * with svi-if only after vxlan interface association is
8817 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8819 /* formulate l2vni list */
8820 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8823 if (is_l3vni_oper_up(zl3vni
))
8824 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8827 zl3vni
= zl3vni_lookup(vni
);
8829 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8833 if (zvrf
->l3vni
!= vni
) {
8834 snprintf(err
, err_str_sz
,
8835 "VNI %d doesn't exist in VRF: %s",
8836 vni
, zvrf
->vrf
->name
);
8840 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8841 snprintf(err
, ERR_STR_SZ
,
8842 "prefix-routes-only is not set for the vni");
8846 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8848 /* delete and uninstall all rmacs */
8849 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8852 /* delete and uninstall all next-hops */
8853 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8859 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8864 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8866 zebra_l3vni_t
*zl3vni
= NULL
;
8869 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8873 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8874 if (is_l3vni_oper_up(zl3vni
))
8875 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8879 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8881 zebra_l3vni_t
*zl3vni
= NULL
;
8884 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8888 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8889 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8893 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8895 zebra_l3vni_t
*zl3vni
= NULL
;
8899 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8905 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8911 * Handle message from client to specify the flooding mechanism for
8912 * BUM packets. The default is to do head-end (ingress) replication
8913 * and the other supported option is to disable it. This applies to
8914 * all BUM traffic and disabling it applies to both the transmit and
8915 * receive direction.
8917 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8920 enum vxlan_flood_control flood_ctrl
;
8922 if (!EVPN_ENABLED(zvrf
)) {
8923 zlog_err("EVPN flood control for non-EVPN VRF %u",
8929 STREAM_GETC(s
, flood_ctrl
);
8931 if (IS_ZEBRA_DEBUG_VXLAN
)
8932 zlog_debug("EVPN flood control %u, currently %u",
8933 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8935 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8938 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8940 /* Install or uninstall flood entries corresponding to
8943 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8951 * Handle message from client to enable/disable advertisement of svi macip
8954 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8959 zebra_vni_t
*zvni
= NULL
;
8960 struct interface
*ifp
= NULL
;
8962 if (!EVPN_ENABLED(zvrf
)) {
8963 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
8969 STREAM_GETC(s
, advertise
);
8970 STREAM_GETL(s
, vni
);
8973 if (IS_ZEBRA_DEBUG_VXLAN
)
8974 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
8975 advertise
? "enabled" : "disabled",
8976 advertise_gw_macip_enabled(NULL
)
8980 if (zvrf
->advertise_svi_macip
== advertise
)
8985 zvrf
->advertise_svi_macip
= advertise
;
8986 hash_iterate(zvrf
->vni_table
,
8987 zvni_gw_macip_add_for_vni_hash
, NULL
);
8989 hash_iterate(zvrf
->vni_table
,
8990 zvni_svi_macip_del_for_vni_hash
, NULL
);
8991 zvrf
->advertise_svi_macip
= advertise
;
8995 struct zebra_if
*zif
= NULL
;
8996 struct zebra_l2info_vxlan zl2_info
;
8997 struct interface
*vlan_if
= NULL
;
8999 zvni
= zvni_lookup(vni
);
9003 if (IS_ZEBRA_DEBUG_VXLAN
)
9005 "EVPN SVI macip Adv %s on VNI %d , currently %s",
9006 advertise
? "enabled" : "disabled", vni
,
9007 advertise_svi_macip_enabled(zvni
)
9011 if (zvni
->advertise_svi_macip
== advertise
)
9014 ifp
= zvni
->vxlan_if
;
9020 /* If down or not mapped to a bridge, we're done. */
9021 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9024 zl2_info
= zif
->l2info
.vxl
;
9026 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9027 zif
->brslave_info
.br_if
);
9032 zvni
->advertise_svi_macip
= advertise
;
9033 /* Add primary SVI MAC-IP */
9034 zvni_add_macip_for_intf(vlan_if
, zvni
);
9036 /* Del primary MAC-IP */
9037 zvni_del_macip_for_intf(vlan_if
, zvni
);
9038 zvni
->advertise_svi_macip
= advertise
;
9047 * Handle message from client to enable/disable advertisement of g/w macip
9050 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9055 zebra_vni_t
*zvni
= NULL
;
9056 struct interface
*ifp
= NULL
;
9057 struct zebra_if
*zif
= NULL
;
9058 struct zebra_l2info_vxlan zl2_info
;
9059 struct interface
*vlan_if
= NULL
;
9061 if (!EVPN_ENABLED(zvrf
)) {
9062 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9068 STREAM_GETC(s
, advertise
);
9069 vni
= stream_get3(s
);
9071 zvni
= zvni_lookup(vni
);
9075 if (zvni
->advertise_subnet
== advertise
)
9078 if (IS_ZEBRA_DEBUG_VXLAN
)
9079 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9080 advertise
? "enabled" : "disabled", vni
,
9081 zvni
->advertise_subnet
? "enabled" : "disabled");
9084 zvni
->advertise_subnet
= advertise
;
9086 ifp
= zvni
->vxlan_if
;
9092 /* If down or not mapped to a bridge, we're done. */
9093 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9096 zl2_info
= zif
->l2info
.vxl
;
9099 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9103 if (zvni
->advertise_subnet
)
9104 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9106 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9113 * Handle message from client to enable/disable advertisement of g/w macip
9116 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9121 zebra_vni_t
*zvni
= NULL
;
9122 struct interface
*ifp
= NULL
;
9124 if (!EVPN_ENABLED(zvrf
)) {
9125 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9131 STREAM_GETC(s
, advertise
);
9132 STREAM_GETL(s
, vni
);
9135 if (IS_ZEBRA_DEBUG_VXLAN
)
9136 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9137 advertise
? "enabled" : "disabled",
9138 advertise_gw_macip_enabled(NULL
)
9142 if (zvrf
->advertise_gw_macip
== advertise
)
9145 zvrf
->advertise_gw_macip
= advertise
;
9147 if (advertise_gw_macip_enabled(zvni
))
9148 hash_iterate(zvrf
->vni_table
,
9149 zvni_gw_macip_add_for_vni_hash
, NULL
);
9151 hash_iterate(zvrf
->vni_table
,
9152 zvni_gw_macip_del_for_vni_hash
, NULL
);
9155 struct zebra_if
*zif
= NULL
;
9156 struct zebra_l2info_vxlan zl2_info
;
9157 struct interface
*vlan_if
= NULL
;
9158 struct interface
*vrr_if
= NULL
;
9160 zvni
= zvni_lookup(vni
);
9164 if (IS_ZEBRA_DEBUG_VXLAN
)
9166 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9167 advertise
? "enabled" : "disabled", vni
,
9168 advertise_gw_macip_enabled(zvni
) ? "enabled"
9171 if (zvni
->advertise_gw_macip
== advertise
)
9174 zvni
->advertise_gw_macip
= advertise
;
9176 ifp
= zvni
->vxlan_if
;
9182 /* If down or not mapped to a bridge, we're done. */
9183 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9186 zl2_info
= zif
->l2info
.vxl
;
9188 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9189 zif
->brslave_info
.br_if
);
9193 if (advertise_gw_macip_enabled(zvni
)) {
9194 /* Add primary SVI MAC-IP */
9195 zvni_add_macip_for_intf(vlan_if
, zvni
);
9197 /* Add VRR MAC-IP - if any*/
9198 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9200 zvni_add_macip_for_intf(vrr_if
, zvni
);
9202 /* Del primary MAC-IP */
9203 zvni_del_macip_for_intf(vlan_if
, zvni
);
9205 /* Del VRR MAC-IP - if any*/
9206 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9208 zvni_del_macip_for_intf(vrr_if
, zvni
);
9218 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9219 * When enabled, the VNI hash table will be built and MAC FDB table read;
9220 * when disabled, the entries should be deleted and remote VTEPs and MACs
9221 * uninstalled from the kernel.
9222 * This also informs the setting for BUM handling at the time this change
9223 * occurs; it is relevant only when specifying "learn".
9225 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9227 struct stream
*s
= NULL
;
9229 enum vxlan_flood_control flood_ctrl
;
9231 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9233 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9237 STREAM_GETC(s
, advertise
);
9238 STREAM_GETC(s
, flood_ctrl
);
9240 if (IS_ZEBRA_DEBUG_VXLAN
)
9241 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9242 zvrf_name(zvrf
), zvrf_id(zvrf
),
9243 advertise
? "enabled" : "disabled",
9244 is_evpn_enabled() ? "enabled" : "disabled",
9247 if (zvrf
->advertise_all_vni
== advertise
)
9250 zvrf
->advertise_all_vni
= advertise
;
9251 if (EVPN_ENABLED(zvrf
)) {
9252 zrouter
.evpn_vrf
= zvrf
;
9254 /* Note BUM handling */
9255 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9257 /* Build VNI hash table and inform BGP. */
9258 zvni_build_hash_table();
9260 /* Add all SVI (L3 GW) MACs to BGP*/
9261 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9264 /* Read the MAC FDB */
9265 macfdb_read(zvrf
->zns
);
9267 /* Read neighbors */
9268 neigh_read(zvrf
->zns
);
9270 /* Cleanup VTEPs for all VNIs - uninstall from
9271 * kernel and free entries.
9273 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9275 /* cleanup all l3vnis */
9276 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9278 /* Mark as "no EVPN VRF" */
9279 zrouter
.evpn_vrf
= NULL
;
9287 * Allocate VNI hash table for this VRF and do other initialization.
9288 * NOTE: Currently supported only for default VRF.
9290 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9294 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9295 "Zebra VRF VNI Table");
9296 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9297 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9300 /* Cleanup VNI info, but don't free the table. */
9301 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9305 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9306 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9309 /* Close all VNI handling */
9310 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9314 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9315 hash_free(zvrf
->vni_table
);
9318 /* init the l3vni table */
9319 void zebra_vxlan_init(void)
9321 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9322 "Zebra VRF L3 VNI table");
9323 zrouter
.evpn_vrf
= NULL
;
9326 /* free l3vni table */
9327 void zebra_vxlan_disable(void)
9329 hash_free(zrouter
.l3vni_table
);
9332 /* get the l3vni svi ifindex */
9333 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9335 zebra_l3vni_t
*zl3vni
= NULL
;
9337 zl3vni
= zl3vni_from_vrf(vrf_id
);
9338 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9341 return zl3vni
->svi_if
->ifindex
;
9344 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9346 struct zebra_vrf
*zvrf
= NULL
;
9347 zebra_neigh_t
*nbr
= NULL
;
9348 zebra_vni_t
*zvni
= NULL
;
9349 char buf1
[INET6_ADDRSTRLEN
];
9350 char buf2
[ETHER_ADDR_STRLEN
];
9352 nbr
= THREAD_ARG(t
);
9354 /* since this is asynchronous we need sanity checks*/
9355 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9359 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9363 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9367 if (IS_ZEBRA_DEBUG_VXLAN
)
9368 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9369 __PRETTY_FUNCTION__
,
9370 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9371 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9373 nbr
->dad_count
, zvni
->vni
);
9375 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9377 nbr
->detect_start_time
.tv_sec
= 0;
9378 nbr
->detect_start_time
.tv_usec
= 0;
9379 nbr
->dad_dup_detect_time
= 0;
9380 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9381 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9384 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9385 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9386 nbr
->flags
, nbr
->loc_seq
);
9387 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9388 zvni_neigh_install(zvni
, nbr
);
9394 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9396 struct zebra_vrf
*zvrf
= NULL
;
9397 zebra_mac_t
*mac
= NULL
;
9398 zebra_vni_t
*zvni
= NULL
;
9399 struct listnode
*node
= NULL
;
9400 zebra_neigh_t
*nbr
= NULL
;
9401 char buf
[ETHER_ADDR_STRLEN
];
9403 mac
= THREAD_ARG(t
);
9405 /* since this is asynchronous we need sanity checks*/
9406 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9410 zvni
= zvni_lookup(mac
->zvni
->vni
);
9414 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9418 if (IS_ZEBRA_DEBUG_VXLAN
)
9419 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9420 __PRETTY_FUNCTION__
,
9421 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9424 listcount(mac
->neigh_list
));
9426 /* Remove all IPs as duplicate associcated with this MAC */
9427 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9428 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9429 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9430 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9431 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9432 zvni_neigh_install(zvni
, nbr
);
9435 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9437 nbr
->detect_start_time
.tv_sec
= 0;
9438 nbr
->dad_dup_detect_time
= 0;
9441 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9443 mac
->detect_start_time
.tv_sec
= 0;
9444 mac
->detect_start_time
.tv_usec
= 0;
9445 mac
->dad_dup_detect_time
= 0;
9446 mac
->dad_mac_auto_recovery_timer
= NULL
;
9448 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9450 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9451 mac
->flags
, mac
->loc_seq
))
9454 /* Process all neighbors associated with this MAC. */
9455 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9457 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9458 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9460 /* Install the entry. */
9461 zvni_mac_install(zvni
, mac
);
9467 /************************** vxlan SG cache management ************************/
9468 /* Inform PIM about the mcast group */
9469 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9470 char *sg_str
, uint16_t cmd
)
9472 struct zserv
*client
= NULL
;
9473 struct stream
*s
= NULL
;
9475 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9479 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9481 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9482 stream_putl(s
, IPV4_MAX_BYTELEN
);
9483 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9484 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9486 /* Write packet size. */
9487 stream_putw_at(s
, 0, stream_get_endp(s
));
9489 if (IS_ZEBRA_DEBUG_VXLAN
)
9492 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9493 zebra_route_string(client
->proto
));
9495 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9496 client
->vxlan_sg_add_cnt
++;
9498 client
->vxlan_sg_del_cnt
++;
9500 return zserv_send_message(client
, s
);
9503 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9505 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9507 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9508 vxlan_sg
->sg
.grp
.s_addr
, 0));
9511 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9513 const zebra_vxlan_sg_t
*sg1
= p1
;
9514 const zebra_vxlan_sg_t
*sg2
= p2
;
9516 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9517 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9520 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9521 struct prefix_sg
*sg
)
9523 zebra_vxlan_sg_t
*vxlan_sg
;
9525 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9527 vxlan_sg
->zvrf
= zvrf
;
9529 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9531 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9533 if (IS_ZEBRA_DEBUG_VXLAN
)
9534 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9539 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9540 struct prefix_sg
*sg
)
9542 zebra_vxlan_sg_t lookup
;
9545 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9548 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9549 struct prefix_sg
*sg
)
9551 zebra_vxlan_sg_t
*vxlan_sg
;
9552 zebra_vxlan_sg_t
*parent
= NULL
;
9555 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9559 /* create a *G entry for every BUM group implicitly -
9560 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9561 * 2. the XG entry is used by pimd to setup the
9562 * vxlan-termination-mroute
9564 if (sg
->src
.s_addr
) {
9565 memset(&sip
, 0, sizeof(sip
));
9566 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9571 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9574 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9578 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9583 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9586 struct zebra_vrf
*zvrf
;
9588 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9592 /* On SG entry deletion remove the reference to its parent XG
9595 if (vxlan_sg
->sg
.src
.s_addr
) {
9596 memset(&sip
, 0, sizeof(sip
));
9597 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9600 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9601 ZEBRA_VXLAN_SG_DEL
);
9603 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9605 if (IS_ZEBRA_DEBUG_VXLAN
)
9606 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9608 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9611 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9612 struct in_addr sip
, struct in_addr mcast_grp
)
9614 zebra_vxlan_sg_t
*vxlan_sg
;
9615 struct prefix_sg sg
;
9617 sg
.family
= AF_INET
;
9618 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9621 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9625 if (vxlan_sg
->ref_cnt
)
9626 --vxlan_sg
->ref_cnt
;
9628 if (!vxlan_sg
->ref_cnt
)
9629 zebra_vxlan_sg_del(vxlan_sg
);
9632 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9633 struct in_addr sip
, struct in_addr mcast_grp
)
9635 zebra_vxlan_sg_t
*vxlan_sg
;
9636 struct prefix_sg sg
;
9638 sg
.family
= AF_INET
;
9639 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9642 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9644 ++vxlan_sg
->ref_cnt
;
9649 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9650 struct in_addr mcast_grp
)
9652 struct zebra_vrf
*zvrf
;
9654 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9657 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9661 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9664 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9665 struct in_addr mcast_grp
)
9667 struct zebra_vrf
*zvrf
;
9669 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9672 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9675 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9678 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9680 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9682 zebra_vxlan_sg_del(vxlan_sg
);
9685 /************************** EVPN BGP config management ************************/
9686 /* Notify Local MACs to the clienti, skips GW MAC */
9687 static void zvni_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
9690 struct mac_walk_ctx
*wctx
= arg
;
9691 zebra_mac_t
*zmac
= bucket
->data
;
9693 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
9696 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
9697 zvni_mac_send_add_to_client(wctx
->zvni
->vni
, &zmac
->macaddr
,
9698 zmac
->flags
, zmac
->loc_seq
);
9701 /* Iterator to Notify Local MACs of a L2VNI */
9702 static void zvni_send_mac_to_client(zebra_vni_t
*zvni
)
9704 struct mac_walk_ctx wctx
;
9706 if (!zvni
->mac_table
)
9709 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
9712 hash_iterate(zvni
->mac_table
, zvni_send_mac_hash_entry_to_client
,
9716 /* Notify Neighbor entries to the Client, skips the GW entry */
9717 static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
9720 struct mac_walk_ctx
*wctx
= arg
;
9721 zebra_neigh_t
*zn
= bucket
->data
;
9722 zebra_mac_t
*zmac
= NULL
;
9724 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
9727 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
9728 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
9729 zmac
= zvni_mac_lookup(wctx
->zvni
, &zn
->emac
);
9733 zvni_neigh_send_add_to_client(wctx
->zvni
->vni
, &zn
->ip
,
9734 &zn
->emac
, zn
->flags
,
9739 /* Iterator of a specific L2VNI */
9740 static void zvni_send_neigh_to_client(zebra_vni_t
*zvni
)
9742 struct neigh_walk_ctx wctx
;
9744 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
9747 hash_iterate(zvni
->neigh_table
, zvni_send_neigh_hash_entry_to_client
,
9751 static void zvni_evpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
9753 zebra_vni_t
*zvni
= NULL
;
9755 zvni
= (zebra_vni_t
*)bucket
->data
;
9756 zvni
->advertise_gw_macip
= 0;
9757 zvni
->advertise_svi_macip
= 0;
9758 zvni
->advertise_subnet
= 0;
9760 zvni_neigh_del_all(zvni
, 0, 0,
9761 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
9762 zvni_mac_del_all(zvni
, 0, 0,
9763 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
9764 zvni_vtep_del_all(zvni
, 0);
9767 /* Cleanup EVPN configuration of a specific VRF */
9768 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
9770 zvrf
->advertise_all_vni
= 0;
9771 zvrf
->advertise_gw_macip
= 0;
9772 zvrf
->advertise_svi_macip
= 0;
9773 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
9775 hash_iterate(zvrf
->vni_table
, zvni_evpn_cfg_cleanup
, NULL
);
9778 /* Cleanup BGP EVPN configuration upon client disconnect */
9779 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
9782 struct zebra_vrf
*zvrf
;
9784 if (client
->proto
!= ZEBRA_ROUTE_BGP
)
9787 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
9790 zebra_evpn_vrf_cfg_cleanup(zvrf
);
9796 /* Cleanup BGP EVPN configuration upon client disconnect */
9797 extern void zebra_evpn_init(void)
9799 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);