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 /* Private functions */
228 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
229 const struct host_rb_entry
*hle2
)
231 if (hle1
->p
.family
< hle2
->p
.family
)
234 if (hle1
->p
.family
> hle2
->p
.family
)
237 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
240 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
243 if (hle1
->p
.family
== AF_INET
) {
244 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
247 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
251 } else if (hle1
->p
.family
== AF_INET6
) {
252 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
255 zlog_debug("%s: Unexpected family type: %d",
256 __PRETTY_FUNCTION__
, hle1
->p
.family
);
260 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
262 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
264 struct host_rb_entry
*hle
;
267 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
274 * Return number of valid MACs in a VNI's MAC hash table - all
275 * remote MACs and non-internal (auto) local MACs count.
277 static uint32_t num_valid_macs(zebra_vni_t
*zvni
)
280 uint32_t num_macs
= 0;
282 struct hash_bucket
*hb
;
285 hash
= zvni
->mac_table
;
288 for (i
= 0; i
< hash
->size
; i
++) {
289 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
290 mac
= (zebra_mac_t
*)hb
->data
;
291 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
292 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
293 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
301 static uint32_t num_dup_detected_macs(zebra_vni_t
*zvni
)
304 uint32_t num_macs
= 0;
306 struct hash_bucket
*hb
;
309 hash
= zvni
->mac_table
;
312 for (i
= 0; i
< hash
->size
; i
++) {
313 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
314 mac
= (zebra_mac_t
*)hb
->data
;
315 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
323 static uint32_t num_dup_detected_neighs(zebra_vni_t
*zvni
)
326 uint32_t num_neighs
= 0;
328 struct hash_bucket
*hb
;
331 hash
= zvni
->neigh_table
;
334 for (i
= 0; i
< hash
->size
; i
++) {
335 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
336 nbr
= (zebra_neigh_t
*)hb
->data
;
337 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
345 static int advertise_gw_macip_enabled(zebra_vni_t
*zvni
)
347 struct zebra_vrf
*zvrf
;
349 zvrf
= zebra_vrf_get_evpn();
350 if (zvrf
&& zvrf
->advertise_gw_macip
)
353 if (zvni
&& zvni
->advertise_gw_macip
)
359 static int advertise_svi_macip_enabled(zebra_vni_t
*zvni
)
361 struct zebra_vrf
*zvrf
;
363 zvrf
= zebra_vrf_get_evpn();
364 if (zvrf
&& zvrf
->advertise_svi_macip
)
367 if (zvni
&& zvni
->advertise_svi_macip
)
373 /* As part Duplicate Address Detection (DAD) for IP mobility
374 * MAC binding changes, ensure to inherit duplicate flag
377 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
378 zebra_mac_t
*old_zmac
,
379 zebra_mac_t
*new_zmac
,
382 bool is_old_mac_dup
= false;
383 bool is_new_mac_dup
= false;
385 if (!zvrf
->dup_addr_detect
)
387 /* Check old or new MAC is detected as duplicate
388 * mark this neigh as duplicate
391 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
392 ZEBRA_MAC_DUPLICATE
);
394 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
395 ZEBRA_MAC_DUPLICATE
);
396 /* Old and/or new MAC can be in duplicate state,
397 * based on that IP/Neigh Inherits the flag.
398 * If New MAC is marked duplicate, inherit to the IP.
399 * If old MAC is duplicate but new MAC is not, clear
400 * duplicate flag for IP and reset detection params
401 * and let IP DAD retrigger.
403 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
404 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
405 /* Capture Duplicate detection time */
406 nbr
->dad_dup_detect_time
= monotime(NULL
);
407 /* Mark neigh inactive */
408 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
411 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
412 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
414 nbr
->detect_start_time
.tv_sec
= 0;
415 nbr
->detect_start_time
.tv_usec
= 0;
420 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
422 struct in_addr vtep_ip
,
428 struct listnode
*node
= NULL
;
429 struct timeval elapsed
= {0, 0};
430 char buf
[ETHER_ADDR_STRLEN
];
431 char buf1
[INET6_ADDRSTRLEN
];
432 bool reset_params
= false;
434 if (!(zvrf
->dup_addr_detect
&& do_dad
))
437 /* MAC is detected as duplicate,
438 * Local MAC event -> hold on advertising to BGP.
439 * Remote MAC event -> hold on installing it.
441 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
442 if (IS_ZEBRA_DEBUG_VXLAN
)
444 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
446 prefix_mac2str(&mac
->macaddr
, buf
,
448 mac
->flags
, mac
->dad_count
,
449 zvrf
->dad_freeze_time
);
451 /* For duplicate MAC do not update
452 * client but update neigh due to
455 if (zvrf
->dad_freeze
)
456 *is_dup_detect
= true;
461 /* Check if detection time (M-secs) expired.
462 * Reset learn count and detection start time.
464 monotime_since(&mac
->detect_start_time
, &elapsed
);
465 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
466 if (is_local
&& !reset_params
) {
467 /* RFC-7432: A PE/VTEP that detects a MAC mobility
468 * event via LOCAL learning starts an M-second timer.
470 * NOTE: This is the START of the probe with count is
471 * 0 during LOCAL learn event.
472 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
474 reset_params
= !mac
->dad_count
;
478 if (IS_ZEBRA_DEBUG_VXLAN
)
480 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
481 , __PRETTY_FUNCTION__
,
482 prefix_mac2str(&mac
->macaddr
, buf
,
484 mac
->flags
, mac
->dad_count
);
487 /* Start dup. addr detection (DAD) start time,
488 * ONLY during LOCAL learn.
491 monotime(&mac
->detect_start_time
);
493 } else if (!is_local
) {
494 /* For REMOTE MAC, increment detection count
495 * ONLY while in probe window, once window passed,
496 * next local learn event should trigger DAD.
501 /* For LOCAL MAC learn event, once count is reset above via either
502 * initial/start detection time or passed the probe time, the count
503 * needs to be incremented.
508 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
509 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
510 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
512 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
513 is_local
? "local update, last" :
514 "remote update, from", inet_ntoa(vtep_ip
));
516 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
518 /* Capture Duplicate detection time */
519 mac
->dad_dup_detect_time
= monotime(NULL
);
521 /* Mark all IPs/Neighs as duplicate
522 * associcated with this MAC
524 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
526 /* Ony Mark IPs which are Local */
527 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
530 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
532 nbr
->dad_dup_detect_time
= monotime(NULL
);
534 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
535 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
537 prefix_mac2str(&mac
->macaddr
,
539 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
540 is_local
? "local" : "remote");
543 /* Start auto recovery timer for this MAC */
544 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
545 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
546 if (IS_ZEBRA_DEBUG_VXLAN
)
548 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
549 , __PRETTY_FUNCTION__
,
550 prefix_mac2str(&mac
->macaddr
, buf
,
552 mac
->flags
, zvrf
->dad_freeze_time
);
554 thread_add_timer(zrouter
.master
,
555 zebra_vxlan_dad_mac_auto_recovery_exp
,
556 mac
, zvrf
->dad_freeze_time
,
557 &mac
->dad_mac_auto_recovery_timer
);
560 /* In case of local update, do not inform to client (BGPd),
561 * upd_neigh for neigh sequence change.
563 if (zvrf
->dad_freeze
)
564 *is_dup_detect
= true;
568 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
570 struct in_addr vtep_ip
,
576 struct timeval elapsed
= {0, 0};
577 char buf
[ETHER_ADDR_STRLEN
];
578 char buf1
[INET6_ADDRSTRLEN
];
579 bool reset_params
= false;
581 if (!zvrf
->dup_addr_detect
)
584 /* IP is detected as duplicate or inherit dup
585 * state, hold on to install as remote entry
586 * only if freeze is enabled.
588 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
589 if (IS_ZEBRA_DEBUG_VXLAN
)
591 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
593 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
594 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
595 nbr
->flags
, nbr
->dad_count
,
596 zvrf
->dad_freeze_time
);
598 if (zvrf
->dad_freeze
)
599 *is_dup_detect
= true;
601 /* warn-only action, neigh will be installed.
602 * freeze action, it wil not be installed.
610 /* Check if detection time (M-secs) expired.
611 * Reset learn count and detection start time.
612 * During remote mac add, count should already be 1
613 * via local learning.
615 monotime_since(&nbr
->detect_start_time
, &elapsed
);
616 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
618 if (is_local
&& !reset_params
) {
619 /* RFC-7432: A PE/VTEP that detects a MAC mobility
620 * event via LOCAL learning starts an M-second timer.
622 * NOTE: This is the START of the probe with count is
623 * 0 during LOCAL learn event.
625 reset_params
= !nbr
->dad_count
;
629 if (IS_ZEBRA_DEBUG_VXLAN
)
631 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
633 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
634 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
635 nbr
->flags
, nbr
->dad_count
);
636 /* Reset learn count but do not start detection
637 * during REMOTE learn event.
640 /* Start dup. addr detection (DAD) start time,
641 * ONLY during LOCAL learn.
644 monotime(&nbr
->detect_start_time
);
646 } else if (!is_local
) {
647 /* For REMOTE IP/Neigh, increment detection count
648 * ONLY while in probe window, once window passed,
649 * next local learn event should trigger DAD.
654 /* For LOCAL IP/Neigh learn event, once count is reset above via either
655 * initial/start detection time or passed the probe time, the count
656 * needs to be incremented.
661 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
662 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
663 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
665 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
666 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
667 is_local
? "local update, last" :
668 "remote update, from",
671 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
673 /* Capture Duplicate detection time */
674 nbr
->dad_dup_detect_time
= monotime(NULL
);
676 /* Start auto recovery timer for this IP */
677 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
678 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
679 if (IS_ZEBRA_DEBUG_VXLAN
)
681 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
683 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
684 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
685 nbr
->flags
, zvrf
->dad_freeze_time
);
687 thread_add_timer(zrouter
.master
,
688 zebra_vxlan_dad_ip_auto_recovery_exp
,
689 nbr
, zvrf
->dad_freeze_time
,
690 &nbr
->dad_ip_auto_recovery_timer
);
692 if (zvrf
->dad_freeze
)
693 *is_dup_detect
= true;
698 * Helper function to determine maximum width of neighbor IP address for
699 * display - just because we're dealing with IPv6 addresses that can
702 static void zvni_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
705 char buf
[INET6_ADDRSTRLEN
];
706 struct neigh_walk_ctx
*wctx
= ctxt
;
709 n
= (zebra_neigh_t
*)bucket
->data
;
711 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
713 if (width
> wctx
->addr_width
)
714 wctx
->addr_width
= width
;
719 * Print a specific neighbor entry.
721 static void zvni_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
724 char buf1
[ETHER_ADDR_STRLEN
];
725 char buf2
[INET6_ADDRSTRLEN
];
726 const char *type_str
;
727 const char *state_str
;
728 bool flags_present
= false;
729 struct zebra_vrf
*zvrf
= NULL
;
730 struct timeval detect_start_time
= {0, 0};
732 zvrf
= zebra_vrf_get_evpn();
736 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
737 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
738 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
740 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
741 vty
= (struct vty
*)ctxt
;
743 vty_out(vty
, "IP: %s\n",
744 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
745 vty_out(vty
, " Type: %s\n", type_str
);
746 vty_out(vty
, " State: %s\n", state_str
);
747 vty_out(vty
, " MAC: %s\n",
748 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
750 json_object_string_add(json
, "ip", buf2
);
751 json_object_string_add(json
, "type", type_str
);
752 json_object_string_add(json
, "state", state_str
);
753 json_object_string_add(json
, "mac", buf1
);
755 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
757 vty_out(vty
, " Remote VTEP: %s\n",
758 inet_ntoa(n
->r_vtep_ip
));
760 json_object_string_add(json
, "remoteVtep",
761 inet_ntoa(n
->r_vtep_ip
));
763 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
765 vty_out(vty
, " Flags: Default-gateway");
766 flags_present
= true;
768 json_object_boolean_true_add(json
, "defaultGateway");
770 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
773 flags_present
? " ,Router" : " Flags: Router");
774 flags_present
= true;
780 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
781 n
->loc_seq
, n
->rem_seq
);
783 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
784 vty_out(vty
, " Duplicate, detected at %s",
785 time_to_string(n
->dad_dup_detect_time
));
786 } else if (n
->dad_count
) {
787 monotime_since(&n
->detect_start_time
,
789 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
790 char *buf
= time_to_string(
791 n
->detect_start_time
.tv_sec
);
794 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
796 " Duplicate detection started at %s, detection count %u\n",
797 tmp_buf
, n
->dad_count
);
801 json_object_int_add(json
, "localSequence", n
->loc_seq
);
802 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
803 json_object_int_add(json
, "detectionCount",
805 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
806 json_object_boolean_true_add(json
, "isDuplicate");
808 json_object_boolean_false_add(json
, "isDuplicate");
815 * Print neighbor hash entry - called for display of all neighbors.
817 static void zvni_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
820 json_object
*json_vni
= NULL
, *json_row
= NULL
;
822 char buf1
[ETHER_ADDR_STRLEN
];
823 char buf2
[INET6_ADDRSTRLEN
];
824 struct neigh_walk_ctx
*wctx
= ctxt
;
825 const char *state_str
;
828 json_vni
= wctx
->json
;
829 n
= (zebra_neigh_t
*)bucket
->data
;
832 json_row
= json_object_new_object();
834 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
835 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
836 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
837 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
838 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
841 if (json_vni
== NULL
) {
842 vty_out(vty
, "%*s %-6s %-8s %-17s %u/%u\n",
843 -wctx
->addr_width
, buf2
, "local",
844 state_str
, buf1
, n
->loc_seq
, n
->rem_seq
);
846 json_object_string_add(json_row
, "type", "local");
847 json_object_string_add(json_row
, "state", state_str
);
848 json_object_string_add(json_row
, "mac", buf1
);
849 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
850 json_object_boolean_true_add(
851 json_row
, "defaultGateway");
852 json_object_int_add(json_row
, "localSequence",
854 json_object_int_add(json_row
, "remoteSequence",
856 json_object_int_add(json_row
, "detectionCount",
858 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
859 json_object_boolean_true_add(json_row
,
862 json_object_boolean_false_add(json_row
,
866 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
867 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
868 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
871 if (json_vni
== NULL
) {
872 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
875 "%*s %-6s %-8s %-17s %-21s\n",
876 -wctx
->addr_width
, "Neighbor", "Type",
877 "State", "MAC", "Remote VTEP");
878 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
879 -wctx
->addr_width
, buf2
, "remote", state_str
,
880 buf1
, inet_ntoa(n
->r_vtep_ip
), n
->loc_seq
, n
->rem_seq
);
882 json_object_string_add(json_row
, "type", "remote");
883 json_object_string_add(json_row
, "state", state_str
);
884 json_object_string_add(json_row
, "mac", buf1
);
885 json_object_string_add(json_row
, "remoteVtep",
886 inet_ntoa(n
->r_vtep_ip
));
887 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
888 json_object_boolean_true_add(json_row
,
890 json_object_int_add(json_row
, "localSequence",
892 json_object_int_add(json_row
, "remoteSequence",
894 json_object_int_add(json_row
, "detectionCount",
896 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
897 json_object_boolean_true_add(json_row
,
900 json_object_boolean_false_add(json_row
,
907 json_object_object_add(json_vni
, buf2
, json_row
);
911 * Print neighbor hash entry in detail - called for display of all neighbors.
913 static void zvni_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
916 json_object
*json_vni
= NULL
, *json_row
= NULL
;
918 char buf
[INET6_ADDRSTRLEN
];
919 struct neigh_walk_ctx
*wctx
= ctxt
;
922 json_vni
= wctx
->json
;
923 n
= (zebra_neigh_t
*)bucket
->data
;
927 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
929 json_row
= json_object_new_object();
931 zvni_print_neigh(n
, vty
, json_row
);
934 json_object_object_add(json_vni
, buf
, json_row
);
938 * Print neighbors for all VNI.
940 static void zvni_print_neigh_hash_all_vni(struct hash_bucket
*bucket
,
944 json_object
*json
= NULL
, *json_vni
= NULL
;
947 struct neigh_walk_ctx wctx
;
948 char vni_str
[VNI_STR_LEN
];
951 vty
= (struct vty
*)args
[0];
952 json
= (json_object
*)args
[1];
953 print_dup
= (uint32_t)(uintptr_t)args
[2];
955 zvni
= (zebra_vni_t
*)bucket
->data
;
957 num_neigh
= hashcount(zvni
->neigh_table
);
960 num_neigh
= num_dup_detected_neighs(zvni
);
964 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
965 zvni
->vni
, num_neigh
);
967 json_vni
= json_object_new_object();
968 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
969 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
974 json_object_object_add(json
, vni_str
, json_vni
);
978 /* Since we have IPv6 addresses to deal with which can vary widely in
979 * size, we try to be a bit more elegant in display by first computing
982 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
985 wctx
.addr_width
= 15;
986 wctx
.json
= json_vni
;
987 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
990 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s %s\n",
991 -wctx
.addr_width
, "IP", "Type",
992 "State", "MAC", "Remote VTEP", "Seq #'s");
995 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
,
998 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
1001 json_object_object_add(json
, vni_str
, json_vni
);
1004 static void zvni_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1008 nbr
= (zebra_neigh_t
*)bucket
->data
;
1012 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1013 zvni_print_neigh_hash(bucket
, ctxt
);
1016 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1021 nbr
= (zebra_neigh_t
*)bucket
->data
;
1025 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1026 zvni_print_neigh_hash_detail(bucket
, ctxt
);
1030 * Print neighbors for all VNIs in detail.
1032 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket
*bucket
,
1036 json_object
*json
= NULL
, *json_vni
= NULL
;
1039 struct neigh_walk_ctx wctx
;
1040 char vni_str
[VNI_STR_LEN
];
1043 vty
= (struct vty
*)args
[0];
1044 json
= (json_object
*)args
[1];
1045 print_dup
= (uint32_t)(uintptr_t)args
[2];
1047 zvni
= (zebra_vni_t
*)bucket
->data
;
1050 vty_out(vty
, "{}\n");
1053 num_neigh
= hashcount(zvni
->neigh_table
);
1055 if (print_dup
&& num_dup_detected_neighs(zvni
) == 0)
1060 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1061 zvni
->vni
, num_neigh
);
1063 json_vni
= json_object_new_object();
1064 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
1065 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1069 json_object_object_add(json
, vni_str
, json_vni
);
1073 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1076 wctx
.addr_width
= 15;
1077 wctx
.json
= json_vni
;
1080 hash_iterate(zvni
->neigh_table
,
1081 zvni_print_dad_neigh_hash_detail
, &wctx
);
1083 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash_detail
,
1087 json_object_object_add(json
, vni_str
, json_vni
);
1090 /* print a specific next hop for an l3vni */
1091 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1094 char buf1
[ETHER_ADDR_STRLEN
];
1095 char buf2
[INET6_ADDRSTRLEN
];
1096 json_object
*json_hosts
= NULL
;
1097 struct host_rb_entry
*hle
;
1100 vty_out(vty
, "Ip: %s\n",
1101 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1102 vty_out(vty
, " RMAC: %s\n",
1103 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1104 vty_out(vty
, " Refcount: %d\n",
1105 rb_host_count(&n
->host_rb
));
1106 vty_out(vty
, " Prefixes:\n");
1107 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1108 vty_out(vty
, " %s\n",
1109 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1111 json_hosts
= json_object_new_array();
1112 json_object_string_add(
1113 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1114 json_object_string_add(
1116 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1117 json_object_int_add(json
, "refCount",
1118 rb_host_count(&n
->host_rb
));
1119 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1120 json_object_array_add(json_hosts
,
1121 json_object_new_string(prefix2str(
1122 &hle
->p
, buf2
, sizeof(buf2
))));
1123 json_object_object_add(json
, "prefixList", json_hosts
);
1127 /* Print a specific RMAC entry */
1128 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1131 char buf1
[ETHER_ADDR_STRLEN
];
1132 char buf2
[PREFIX_STRLEN
];
1133 json_object
*json_hosts
= NULL
;
1134 struct host_rb_entry
*hle
;
1137 vty_out(vty
, "MAC: %s\n",
1138 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1139 vty_out(vty
, " Remote VTEP: %s\n",
1140 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1141 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1142 vty_out(vty
, " Prefixes:\n");
1143 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1144 vty_out(vty
, " %s\n",
1145 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1147 json_hosts
= json_object_new_array();
1148 json_object_string_add(
1150 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1151 json_object_string_add(json
, "vtepIp",
1152 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1153 json_object_int_add(json
, "refCount",
1154 rb_host_count(&zrmac
->host_rb
));
1155 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1156 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1157 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1158 json_object_array_add(
1160 json_object_new_string(prefix2str(
1161 &hle
->p
, buf2
, sizeof(buf2
))));
1162 json_object_object_add(json
, "prefixList", json_hosts
);
1167 * Print a specific MAC entry.
1169 static void zvni_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1172 zebra_neigh_t
*n
= NULL
;
1173 struct listnode
*node
= NULL
;
1174 char buf1
[ETHER_ADDR_STRLEN
];
1175 char buf2
[INET6_ADDRSTRLEN
];
1176 struct zebra_vrf
*zvrf
;
1177 struct timeval detect_start_time
= {0, 0};
1179 zvrf
= zebra_vrf_get_evpn();
1183 vty
= (struct vty
*)ctxt
;
1184 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1187 json_object
*json_mac
= json_object_new_object();
1189 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1190 struct zebra_ns
*zns
;
1191 struct interface
*ifp
;
1194 ifindex
= mac
->fwd_info
.local
.ifindex
;
1195 zns
= zebra_ns_lookup(NS_DEFAULT
);
1196 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1199 json_object_string_add(json_mac
, "type", "local");
1200 json_object_string_add(json_mac
, "intf", ifp
->name
);
1201 json_object_int_add(json_mac
, "ifindex", ifindex
);
1202 if (mac
->fwd_info
.local
.vid
)
1203 json_object_int_add(json_mac
, "vlan",
1204 mac
->fwd_info
.local
.vid
);
1205 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1206 json_object_string_add(json_mac
, "type", "remote");
1207 json_object_string_add(
1208 json_mac
, "remoteVtep",
1209 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1210 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1211 json_object_string_add(json_mac
, "type", "auto");
1213 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1214 json_object_boolean_true_add(json_mac
, "stickyMac");
1216 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1217 json_object_boolean_true_add(json_mac
,
1220 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1221 json_object_boolean_true_add(json_mac
,
1222 "remoteGatewayMac");
1224 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1225 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1227 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1228 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1229 json_object_boolean_true_add(json_mac
, "isDuplicate");
1231 json_object_boolean_false_add(json_mac
, "isDuplicate");
1233 /* print all the associated neigh */
1234 if (!listcount(mac
->neigh_list
))
1235 json_object_string_add(json_mac
, "neighbors", "none");
1237 json_object
*json_active_nbrs
= json_object_new_array();
1238 json_object
*json_inactive_nbrs
=
1239 json_object_new_array();
1240 json_object
*json_nbrs
= json_object_new_object();
1242 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1243 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1244 json_object_array_add(
1246 json_object_new_string(
1251 json_object_array_add(
1253 json_object_new_string(
1259 json_object_object_add(json_nbrs
, "active",
1261 json_object_object_add(json_nbrs
, "inactive",
1262 json_inactive_nbrs
);
1263 json_object_object_add(json_mac
, "neighbors",
1267 json_object_object_add(json
, buf1
, json_mac
);
1269 vty_out(vty
, "MAC: %s\n", buf1
);
1271 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1272 struct zebra_ns
*zns
;
1273 struct interface
*ifp
;
1276 ifindex
= mac
->fwd_info
.local
.ifindex
;
1277 zns
= zebra_ns_lookup(NS_DEFAULT
);
1278 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1281 vty_out(vty
, " Intf: %s(%u)", ifp
->name
, ifindex
);
1282 if (mac
->fwd_info
.local
.vid
)
1283 vty_out(vty
, " VLAN: %u",
1284 mac
->fwd_info
.local
.vid
);
1285 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1286 vty_out(vty
, " Remote VTEP: %s",
1287 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1288 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1289 vty_out(vty
, " Auto Mac ");
1292 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1293 vty_out(vty
, " Sticky Mac ");
1295 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1296 vty_out(vty
, " Default-gateway Mac ");
1298 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1299 vty_out(vty
, " Remote-gateway Mac ");
1302 vty_out(vty
, " Local Seq: %u Remote Seq: %u", mac
->loc_seq
,
1306 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1307 vty_out(vty
, " Duplicate, detected at %s",
1308 time_to_string(mac
->dad_dup_detect_time
));
1309 } else if (mac
->dad_count
) {
1310 monotime_since(&mac
->detect_start_time
,
1311 &detect_start_time
);
1312 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1313 char *buf
= time_to_string(
1314 mac
->detect_start_time
.tv_sec
);
1317 strlcpy(tmp_buf
, buf
, sizeof(tmp_buf
));
1319 " Duplicate detection started at %s, detection count %u\n",
1320 tmp_buf
, mac
->dad_count
);
1324 /* print all the associated neigh */
1325 vty_out(vty
, " Neighbors:\n");
1326 if (!listcount(mac
->neigh_list
))
1327 vty_out(vty
, " No Neighbors\n");
1329 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1330 vty_out(vty
, " %s %s\n",
1331 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1332 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1343 * Print MAC hash entry - called for display of all MACs.
1345 static void zvni_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1348 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1350 char buf1
[ETHER_ADDR_STRLEN
];
1351 struct mac_walk_ctx
*wctx
= ctxt
;
1354 json_mac_hdr
= wctx
->json
;
1355 mac
= (zebra_mac_t
*)bucket
->data
;
1357 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1360 json_mac
= json_object_new_object();
1362 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1363 struct zebra_ns
*zns
;
1365 struct interface
*ifp
;
1368 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1371 zns
= zebra_ns_lookup(NS_DEFAULT
);
1372 ifindex
= mac
->fwd_info
.local
.ifindex
;
1373 ifp
= if_lookup_by_index_per_ns(zns
, ifindex
);
1374 if (!ifp
) // unexpected
1376 vid
= mac
->fwd_info
.local
.vid
;
1377 if (json_mac_hdr
== NULL
)
1378 vty_out(vty
, "%-17s %-6s %-21s", buf1
, "local",
1381 json_object_string_add(json_mac
, "type", "local");
1382 json_object_string_add(json_mac
, "intf", ifp
->name
);
1385 if (json_mac_hdr
== NULL
)
1386 vty_out(vty
, " %-5u", vid
);
1388 json_object_int_add(json_mac
, "vlan", vid
);
1389 } else /* No vid? fill out the space */
1390 vty_out(vty
, " %-5s", "");
1391 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1392 if (json_mac_hdr
== NULL
) {
1395 json_object_int_add(json_mac
, "localSequence",
1397 json_object_int_add(json_mac
, "remoteSequence",
1399 json_object_int_add(json_mac
, "detectionCount",
1401 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1402 json_object_boolean_true_add(json_mac
,
1405 json_object_boolean_false_add(json_mac
,
1407 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1412 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1414 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1415 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1419 if (json_mac_hdr
== NULL
) {
1420 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1421 (wctx
->count
== 0)) {
1422 vty_out(vty
, "\nVNI %u\n\n", wctx
->zvni
->vni
);
1423 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n",
1424 "MAC", "Type", "Intf/Remote VTEP",
1427 vty_out(vty
, "%-17s %-6s %-21s %-5s %u/%u\n", buf1
,
1428 "remote", inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1429 "", mac
->loc_seq
, mac
->rem_seq
);
1431 json_object_string_add(json_mac
, "type", "remote");
1432 json_object_string_add(json_mac
, "remoteVtep",
1433 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1434 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1435 json_object_int_add(json_mac
, "localSequence",
1437 json_object_int_add(json_mac
, "remoteSequence",
1439 json_object_int_add(json_mac
, "detectionCount",
1441 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1442 json_object_boolean_true_add(json_mac
,
1445 json_object_boolean_false_add(json_mac
,
1454 /* Print Duplicate MAC */
1455 static void zvni_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1459 mac
= (zebra_mac_t
*)bucket
->data
;
1463 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1464 zvni_print_mac_hash(bucket
, ctxt
);
1468 * Print MAC hash entry in detail - called for display of all MACs.
1470 static void zvni_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1473 json_object
*json_mac_hdr
= NULL
;
1475 struct mac_walk_ctx
*wctx
= ctxt
;
1476 char buf1
[ETHER_ADDR_STRLEN
];
1479 json_mac_hdr
= wctx
->json
;
1480 mac
= (zebra_mac_t
*)bucket
->data
;
1485 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1487 zvni_print_mac(mac
, vty
, json_mac_hdr
);
1490 /* Print Duplicate MAC in detail */
1491 static void zvni_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1496 mac
= (zebra_mac_t
*)bucket
->data
;
1500 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1501 zvni_print_mac_hash_detail(bucket
, ctxt
);
1505 * Print MACs for all VNI.
1507 static void zvni_print_mac_hash_all_vni(struct hash_bucket
*bucket
, void *ctxt
)
1510 json_object
*json
= NULL
, *json_vni
= NULL
;
1511 json_object
*json_mac
= NULL
;
1514 struct mac_walk_ctx
*wctx
= ctxt
;
1515 char vni_str
[VNI_STR_LEN
];
1517 vty
= (struct vty
*)wctx
->vty
;
1518 json
= (struct json_object
*)wctx
->json
;
1520 zvni
= (zebra_vni_t
*)bucket
->data
;
1523 /*We are iterating over a new VNI, set the count to 0*/
1526 num_macs
= num_valid_macs(zvni
);
1530 if (wctx
->print_dup
)
1531 num_macs
= num_dup_detected_macs(zvni
);
1534 json_vni
= json_object_new_object();
1535 json_mac
= json_object_new_object();
1536 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1539 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1541 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1542 zvni
->vni
, num_macs
);
1543 vty_out(vty
, "%-17s %-6s %-21s %-5s %s\n", "MAC",
1544 "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
1546 json_object_int_add(json_vni
, "numMacs", num_macs
);
1551 json_object_int_add(json_vni
, "numMacs", num_macs
);
1552 json_object_object_add(json
, vni_str
, json_vni
);
1557 /* assign per-vni to wctx->json object to fill macs
1558 * under the vni. Re-assign primary json object to fill
1559 * next vni information.
1561 wctx
->json
= json_mac
;
1562 if (wctx
->print_dup
)
1563 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, wctx
);
1565 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, wctx
);
1569 json_object_object_add(json_vni
, "macs", json_mac
);
1570 json_object_object_add(json
, vni_str
, json_vni
);
1575 * Print MACs in detail for all VNI.
1577 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket
*bucket
,
1581 json_object
*json
= NULL
, *json_vni
= NULL
;
1582 json_object
*json_mac
= NULL
;
1585 struct mac_walk_ctx
*wctx
= ctxt
;
1586 char vni_str
[VNI_STR_LEN
];
1588 vty
= (struct vty
*)wctx
->vty
;
1589 json
= (struct json_object
*)wctx
->json
;
1591 zvni
= (zebra_vni_t
*)bucket
->data
;
1594 vty_out(vty
, "{}\n");
1599 /*We are iterating over a new VNI, set the count to 0*/
1602 num_macs
= num_valid_macs(zvni
);
1606 if (wctx
->print_dup
&& (num_dup_detected_macs(zvni
) == 0))
1610 json_vni
= json_object_new_object();
1611 json_mac
= json_object_new_object();
1612 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
1615 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1617 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1618 zvni
->vni
, num_macs
);
1620 json_object_int_add(json_vni
, "numMacs", num_macs
);
1622 /* assign per-vni to wctx->json object to fill macs
1623 * under the vni. Re-assign primary json object to fill
1624 * next vni information.
1626 wctx
->json
= json_mac
;
1627 if (wctx
->print_dup
)
1628 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash_detail
,
1631 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash_detail
, wctx
);
1635 json_object_object_add(json_vni
, "macs", json_mac
);
1636 json_object_object_add(json
, vni_str
, json_vni
);
1640 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1642 struct nh_walk_ctx
*wctx
= NULL
;
1643 struct vty
*vty
= NULL
;
1644 struct json_object
*json_vni
= NULL
;
1645 struct json_object
*json_nh
= NULL
;
1646 zebra_neigh_t
*n
= NULL
;
1647 char buf1
[ETHER_ADDR_STRLEN
];
1648 char buf2
[INET6_ADDRSTRLEN
];
1650 wctx
= (struct nh_walk_ctx
*)ctx
;
1652 json_vni
= wctx
->json
;
1654 json_nh
= json_object_new_object();
1655 n
= (zebra_neigh_t
*)bucket
->data
;
1658 vty_out(vty
, "%-15s %-17s\n",
1659 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1660 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1662 json_object_string_add(json_nh
, "nexthopIp",
1663 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1664 json_object_string_add(
1665 json_nh
, "routerMac",
1666 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1667 json_object_object_add(json_vni
,
1668 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1673 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1676 struct vty
*vty
= NULL
;
1677 json_object
*json
= NULL
;
1678 json_object
*json_vni
= NULL
;
1679 zebra_l3vni_t
*zl3vni
= NULL
;
1680 uint32_t num_nh
= 0;
1681 struct nh_walk_ctx wctx
;
1682 char vni_str
[VNI_STR_LEN
];
1684 vty
= (struct vty
*)args
[0];
1685 json
= (struct json_object
*)args
[1];
1687 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1689 num_nh
= hashcount(zl3vni
->nh_table
);
1694 json_vni
= json_object_new_object();
1695 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1699 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1700 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1702 json_object_int_add(json_vni
, "numNextHops", num_nh
);
1704 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1706 wctx
.json
= json_vni
;
1707 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1709 json_object_object_add(json
, vni_str
, json_vni
);
1712 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1715 struct vty
*vty
= NULL
;
1716 json_object
*json
= NULL
;
1717 json_object
*json_vni
= NULL
;
1718 zebra_l3vni_t
*zl3vni
= NULL
;
1720 struct rmac_walk_ctx wctx
;
1721 char vni_str
[VNI_STR_LEN
];
1723 vty
= (struct vty
*)args
[0];
1724 json
= (struct json_object
*)args
[1];
1726 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1728 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1733 json_vni
= json_object_new_object();
1734 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1738 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1739 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1741 json_object_int_add(json_vni
, "numRmacs", num_rmacs
);
1743 /* assign per-vni to wctx->json object to fill macs
1744 * under the vni. Re-assign primary json object to fill
1745 * next vni information.
1747 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1749 wctx
.json
= json_vni
;
1750 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1752 json_object_object_add(json
, vni_str
, json_vni
);
1755 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1757 zebra_mac_t
*zrmac
= NULL
;
1758 struct rmac_walk_ctx
*wctx
= NULL
;
1759 struct vty
*vty
= NULL
;
1760 struct json_object
*json
= NULL
;
1761 struct json_object
*json_rmac
= NULL
;
1762 char buf
[ETHER_ADDR_STRLEN
];
1764 wctx
= (struct rmac_walk_ctx
*)ctx
;
1768 json_rmac
= json_object_new_object();
1769 zrmac
= (zebra_mac_t
*)bucket
->data
;
1772 vty_out(vty
, "%-17s %-21s\n",
1773 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1774 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1776 json_object_string_add(
1777 json_rmac
, "routerMac",
1778 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1779 json_object_string_add(json_rmac
, "vtepIp",
1780 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1781 json_object_object_add(
1782 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1787 /* print a specific L3 VNI entry */
1788 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1790 char buf
[ETHER_ADDR_STRLEN
];
1791 struct vty
*vty
= NULL
;
1792 json_object
*json
= NULL
;
1793 zebra_vni_t
*zvni
= NULL
;
1794 json_object
*json_vni_list
= NULL
;
1795 struct listnode
*node
= NULL
, *nnode
= NULL
;
1801 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1802 vty_out(vty
, " Type: %s\n", "L3");
1803 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
1804 vty_out(vty
, " Local Vtep Ip: %s\n",
1805 inet_ntoa(zl3vni
->local_vtep_ip
));
1806 vty_out(vty
, " Vxlan-Intf: %s\n",
1807 zl3vni_vxlan_if_name(zl3vni
));
1808 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
1809 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
1810 vty_out(vty
, " VNI Filter: %s\n",
1811 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1812 ? "prefix-routes-only"
1814 vty_out(vty
, " Router MAC: %s\n",
1815 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1816 vty_out(vty
, " L2 VNIs: ");
1817 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
))
1818 vty_out(vty
, "%u ", zvni
->vni
);
1821 json_vni_list
= json_object_new_array();
1822 json_object_int_add(json
, "vni", zl3vni
->vni
);
1823 json_object_string_add(json
, "type", "L3");
1824 json_object_string_add(json
, "localVtepIp",
1825 inet_ntoa(zl3vni
->local_vtep_ip
));
1826 json_object_string_add(json
, "vxlanIntf",
1827 zl3vni_vxlan_if_name(zl3vni
));
1828 json_object_string_add(json
, "sviIntf",
1829 zl3vni_svi_if_name(zl3vni
));
1830 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
1831 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
1832 json_object_string_add(
1834 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
1835 json_object_string_add(
1837 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
1838 ? "prefix-routes-only"
1840 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zvni
)) {
1841 json_object_array_add(json_vni_list
,
1842 json_object_new_int(zvni
->vni
));
1844 json_object_object_add(json
, "l2Vnis", json_vni_list
);
1849 * Print a specific VNI entry.
1851 static void zvni_print(zebra_vni_t
*zvni
, void **ctxt
)
1854 zebra_vtep_t
*zvtep
;
1857 json_object
*json
= NULL
;
1858 json_object
*json_vtep_list
= NULL
;
1859 json_object
*json_ip_str
= NULL
;
1865 vty_out(vty
, "VNI: %u\n", zvni
->vni
);
1866 vty_out(vty
, " Type: %s\n", "L2");
1867 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zvni
->vrf_id
));
1869 json_object_int_add(json
, "vni", zvni
->vni
);
1870 json_object_string_add(json
, "type", "L2");
1871 json_object_string_add(json
, "vrf",
1872 vrf_id_to_name(zvni
->vrf_id
));
1875 if (!zvni
->vxlan_if
) { // unexpected
1877 vty_out(vty
, " VxLAN interface: unknown\n");
1880 num_macs
= num_valid_macs(zvni
);
1881 num_neigh
= hashcount(zvni
->neigh_table
);
1883 vty_out(vty
, " VxLAN interface: %s\n", zvni
->vxlan_if
->name
);
1884 vty_out(vty
, " VxLAN ifIndex: %u\n", zvni
->vxlan_if
->ifindex
);
1885 vty_out(vty
, " Local VTEP IP: %s\n",
1886 inet_ntoa(zvni
->local_vtep_ip
));
1887 vty_out(vty
, " Mcast group: %s\n",
1888 inet_ntoa(zvni
->mcast_grp
));
1890 json_object_string_add(json
, "vxlanInterface",
1891 zvni
->vxlan_if
->name
);
1892 json_object_int_add(json
, "ifindex", zvni
->vxlan_if
->ifindex
);
1893 json_object_string_add(json
, "vtepIp",
1894 inet_ntoa(zvni
->local_vtep_ip
));
1895 json_object_string_add(json
, "mcastGroup",
1896 inet_ntoa(zvni
->mcast_grp
));
1897 json_object_string_add(json
, "advertiseGatewayMacip",
1898 zvni
->advertise_gw_macip
? "Yes" : "No");
1899 json_object_int_add(json
, "numMacs", num_macs
);
1900 json_object_int_add(json
, "numArpNd", num_neigh
);
1904 vty_out(vty
, " No remote VTEPs known for this VNI\n");
1907 vty_out(vty
, " Remote VTEPs for this VNI:\n");
1909 json_vtep_list
= json_object_new_array();
1910 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
1911 const char *flood_str
= lookup_msg(zvtep_flood_str
,
1912 zvtep
->flood_control
,
1913 VXLAN_FLOOD_STR_DEFAULT
);
1916 vty_out(vty
, " %s flood: %s\n",
1917 inet_ntoa(zvtep
->vtep_ip
),
1920 json_ip_str
= json_object_new_string(
1921 inet_ntoa(zvtep
->vtep_ip
));
1922 json_object_array_add(json_vtep_list
,
1927 json_object_object_add(json
, "numRemoteVteps",
1932 " Number of MACs (local and remote) known for this VNI: %u\n",
1935 " Number of ARPs (IPv4 and IPv6, local and remote) "
1936 "known for this VNI: %u\n",
1938 vty_out(vty
, " Advertise-gw-macip: %s\n",
1939 zvni
->advertise_gw_macip
? "Yes" : "No");
1943 /* print a L3 VNI hash entry */
1944 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
1946 struct vty
*vty
= NULL
;
1947 json_object
*json
= NULL
;
1948 json_object
*json_vni
= NULL
;
1949 zebra_l3vni_t
*zl3vni
= NULL
;
1951 vty
= (struct vty
*)ctx
[0];
1952 json
= (json_object
*)ctx
[1];
1954 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1957 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1958 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
1959 hashcount(zl3vni
->rmac_table
),
1960 hashcount(zl3vni
->nh_table
), "n/a",
1961 zl3vni_vrf_name(zl3vni
));
1963 char vni_str
[VNI_STR_LEN
];
1965 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1966 json_vni
= json_object_new_object();
1967 json_object_int_add(json_vni
, "vni", zl3vni
->vni
);
1968 json_object_string_add(json_vni
, "vxlanIf",
1969 zl3vni_vxlan_if_name(zl3vni
));
1970 json_object_int_add(json_vni
, "numMacs",
1971 hashcount(zl3vni
->rmac_table
));
1972 json_object_int_add(json_vni
, "numArpNd",
1973 hashcount(zl3vni
->nh_table
));
1974 json_object_string_add(json_vni
, "numRemoteVteps", "n/a");
1975 json_object_string_add(json_vni
, "type", "L3");
1976 json_object_string_add(json_vni
, "tenantVrf",
1977 zl3vni_vrf_name(zl3vni
));
1978 json_object_object_add(json
, vni_str
, json_vni
);
1982 /* Private Structure to pass callback data for hash iterator */
1983 struct zvni_evpn_show
{
1986 struct zebra_vrf
*zvrf
;
1989 /* print a L3 VNI hash entry in detail*/
1990 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
1992 struct vty
*vty
= NULL
;
1993 zebra_l3vni_t
*zl3vni
= NULL
;
1994 json_object
*json
= NULL
;
1995 bool use_json
= false;
1996 struct zvni_evpn_show
*zes
= data
;
2004 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2006 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
, use_json
);
2012 * Print a VNI hash entry - called for display of all VNIs.
2014 static void zvni_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2018 zebra_vtep_t
*zvtep
;
2019 uint32_t num_vteps
= 0;
2020 uint32_t num_macs
= 0;
2021 uint32_t num_neigh
= 0;
2022 json_object
*json
= NULL
;
2023 json_object
*json_vni
= NULL
;
2024 json_object
*json_ip_str
= NULL
;
2025 json_object
*json_vtep_list
= NULL
;
2030 zvni
= (zebra_vni_t
*)bucket
->data
;
2032 zvtep
= zvni
->vteps
;
2035 zvtep
= zvtep
->next
;
2038 num_macs
= num_valid_macs(zvni
);
2039 num_neigh
= hashcount(zvni
->neigh_table
);
2041 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2043 zvni
->vxlan_if
? zvni
->vxlan_if
->name
: "unknown",
2044 num_macs
, num_neigh
, num_vteps
,
2045 vrf_id_to_name(zvni
->vrf_id
));
2047 char vni_str
[VNI_STR_LEN
];
2048 snprintf(vni_str
, VNI_STR_LEN
, "%u", zvni
->vni
);
2049 json_vni
= json_object_new_object();
2050 json_object_int_add(json_vni
, "vni", zvni
->vni
);
2051 json_object_string_add(json_vni
, "type", "L2");
2052 json_object_string_add(json_vni
, "vxlanIf",
2053 zvni
->vxlan_if
? zvni
->vxlan_if
->name
2055 json_object_int_add(json_vni
, "numMacs", num_macs
);
2056 json_object_int_add(json_vni
, "numArpNd", num_neigh
);
2057 json_object_int_add(json_vni
, "numRemoteVteps", num_vteps
);
2058 json_object_string_add(json_vni
, "tenantVrf",
2059 vrf_id_to_name(zvni
->vrf_id
));
2061 json_vtep_list
= json_object_new_array();
2062 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2063 json_ip_str
= json_object_new_string(
2064 inet_ntoa(zvtep
->vtep_ip
));
2065 json_object_array_add(json_vtep_list
,
2068 json_object_object_add(json_vni
, "remoteVteps",
2071 json_object_object_add(json
, vni_str
, json_vni
);
2076 * Print a VNI hash entry in detail - called for display of all VNIs.
2078 static void zvni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2082 json_object
*json
= NULL
;
2083 bool use_json
= false;
2084 struct zvni_evpn_show
*zes
= data
;
2092 zvni
= (zebra_vni_t
*)bucket
->data
;
2094 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zvni
->vni
, use_json
);
2099 * Inform BGP about local MACIP.
2101 static int zvni_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2102 struct ipaddr
*ip
, uint8_t flags
,
2103 uint32_t seq
, int state
, uint16_t cmd
)
2105 char buf
[ETHER_ADDR_STRLEN
];
2106 char buf2
[INET6_ADDRSTRLEN
];
2108 struct zserv
*client
= NULL
;
2109 struct stream
*s
= NULL
;
2111 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2112 /* BGP may not be running. */
2116 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2118 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2119 stream_putl(s
, vni
);
2120 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2123 if (IS_IPADDR_V4(ip
))
2124 ipa_len
= IPV4_MAX_BYTELEN
;
2125 else if (IS_IPADDR_V6(ip
))
2126 ipa_len
= IPV6_MAX_BYTELEN
;
2128 stream_putl(s
, ipa_len
); /* IP address length */
2130 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2132 stream_putl(s
, 0); /* Just MAC. */
2134 if (cmd
== ZEBRA_MACIP_ADD
) {
2135 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2136 stream_putl(s
, seq
); /* sequence number */
2138 stream_putl(s
, state
); /* state - active/inactive */
2142 /* Write packet size. */
2143 stream_putw_at(s
, 0, stream_get_endp(s
));
2145 if (IS_ZEBRA_DEBUG_VXLAN
)
2147 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2148 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2149 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2150 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2151 zebra_route_string(client
->proto
));
2153 if (cmd
== ZEBRA_MACIP_ADD
)
2154 client
->macipadd_cnt
++;
2156 client
->macipdel_cnt
++;
2158 return zserv_send_message(client
, s
);
2162 * Make hash key for neighbors.
2164 static unsigned int neigh_hash_keymake(const void *p
)
2166 const zebra_neigh_t
*n
= p
;
2167 const struct ipaddr
*ip
= &n
->ip
;
2169 if (IS_IPADDR_V4(ip
))
2170 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2172 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2173 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2177 * Compare two neighbor hash structures.
2179 static bool neigh_cmp(const void *p1
, const void *p2
)
2181 const zebra_neigh_t
*n1
= p1
;
2182 const zebra_neigh_t
*n2
= p2
;
2184 if (n1
== NULL
&& n2
== NULL
)
2187 if (n1
== NULL
|| n2
== NULL
)
2190 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2193 static int neigh_list_cmp(void *p1
, void *p2
)
2195 const zebra_neigh_t
*n1
= p1
;
2196 const zebra_neigh_t
*n2
= p2
;
2198 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2202 * Callback to allocate neighbor hash entry.
2204 static void *zvni_neigh_alloc(void *p
)
2206 const zebra_neigh_t
*tmp_n
= p
;
2209 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2216 * Add neighbor entry.
2218 static zebra_neigh_t
*zvni_neigh_add(zebra_vni_t
*zvni
, struct ipaddr
*ip
,
2219 struct ethaddr
*mac
)
2221 zebra_neigh_t tmp_n
;
2222 zebra_neigh_t
*n
= NULL
;
2223 zebra_mac_t
*zmac
= NULL
;
2225 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2226 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2227 n
= hash_get(zvni
->neigh_table
, &tmp_n
, zvni_neigh_alloc
);
2230 memcpy(&n
->emac
, mac
, ETH_ALEN
);
2231 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2233 n
->dad_ip_auto_recovery_timer
= NULL
;
2235 /* Associate the neigh to mac */
2236 zmac
= zvni_mac_lookup(zvni
, mac
);
2238 listnode_add_sort(zmac
->neigh_list
, n
);
2244 * Delete neighbor entry.
2246 static int zvni_neigh_del(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2248 zebra_neigh_t
*tmp_n
;
2249 zebra_mac_t
*zmac
= NULL
;
2251 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
2253 listnode_delete(zmac
->neigh_list
, n
);
2255 /* Cancel auto recovery */
2256 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2258 /* Free the VNI hash entry and allocated memory. */
2259 tmp_n
= hash_release(zvni
->neigh_table
, n
);
2260 XFREE(MTYPE_NEIGH
, tmp_n
);
2266 * Free neighbor hash entry (callback)
2268 static void zvni_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2270 struct neigh_walk_ctx
*wctx
= arg
;
2271 zebra_neigh_t
*n
= bucket
->data
;
2273 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2274 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2275 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2276 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2277 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2278 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2279 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2280 zvni_neigh_send_del_to_client(wctx
->zvni
->vni
, &n
->ip
,
2281 &n
->emac
, 0, n
->state
);
2283 if (wctx
->uninstall
)
2284 zvni_neigh_uninstall(wctx
->zvni
, n
);
2286 zvni_neigh_del(wctx
->zvni
, n
);
2293 * Delete all neighbor entries from specific VTEP for a particular VNI.
2295 static void zvni_neigh_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
2296 struct in_addr
*r_vtep_ip
)
2298 struct neigh_walk_ctx wctx
;
2300 if (!zvni
->neigh_table
)
2303 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2305 wctx
.uninstall
= uninstall
;
2306 wctx
.flags
= DEL_REMOTE_NEIGH_FROM_VTEP
;
2307 wctx
.r_vtep_ip
= *r_vtep_ip
;
2309 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2313 * Delete all neighbor entries for this VNI.
2315 static void zvni_neigh_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
2318 struct neigh_walk_ctx wctx
;
2320 if (!zvni
->neigh_table
)
2323 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2325 wctx
.uninstall
= uninstall
;
2326 wctx
.upd_client
= upd_client
;
2329 hash_iterate(zvni
->neigh_table
, zvni_neigh_del_hash_entry
, &wctx
);
2333 * Look up neighbor hash entry.
2335 static zebra_neigh_t
*zvni_neigh_lookup(zebra_vni_t
*zvni
, struct ipaddr
*ip
)
2340 memset(&tmp
, 0, sizeof(tmp
));
2341 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2342 n
= hash_lookup(zvni
->neigh_table
, &tmp
);
2348 * Process all neighbors associated with a MAC upon the MAC being learnt
2349 * locally or undergoing any other change (such as sequence number).
2351 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t
*zvni
,
2355 zebra_neigh_t
*n
= NULL
;
2356 struct listnode
*node
= NULL
;
2357 struct zebra_vrf
*zvrf
= NULL
;
2358 char buf
[ETHER_ADDR_STRLEN
];
2360 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
2362 if (IS_ZEBRA_DEBUG_VXLAN
)
2363 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2364 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2365 seq_change
? "CHANGE" : "ADD", zvni
->vni
);
2367 /* Walk all neighbors and mark any inactive local neighbors as
2368 * active and/or update sequence number upon a move, and inform BGP.
2369 * The action for remote neighbors is TBD.
2370 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2371 * accidentally end up deleting a just-learnt local neighbor.
2373 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2374 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2375 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
) {
2376 ZEBRA_NEIGH_SET_ACTIVE(n
);
2377 n
->loc_seq
= zmac
->loc_seq
;
2378 if (!(zvrf
->dup_addr_detect
&&
2379 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2380 ZEBRA_NEIGH_DUPLICATE
)))
2381 zvni_neigh_send_add_to_client(
2382 zvni
->vni
, &n
->ip
, &n
->emac
,
2383 n
->flags
, n
->loc_seq
);
2390 * Process all neighbors associated with a local MAC upon the MAC being
2393 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t
*zvni
,
2396 zebra_neigh_t
*n
= NULL
;
2397 struct listnode
*node
= NULL
;
2398 char buf
[ETHER_ADDR_STRLEN
];
2400 if (IS_ZEBRA_DEBUG_VXLAN
)
2401 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2402 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2405 /* Walk all local neighbors and mark as inactive and inform
2407 * TBD: There is currently no handling for remote neighbors. We
2408 * don't expect them to exist, if they do, do we install the MAC
2409 * as a remote MAC and the neighbor as remote?
2411 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2412 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2413 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2414 ZEBRA_NEIGH_SET_INACTIVE(n
);
2416 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2417 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2424 * Process all neighbors associated with a MAC upon the MAC being remotely
2427 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t
*zvni
,
2430 zebra_neigh_t
*n
= NULL
;
2431 struct listnode
*node
= NULL
;
2432 char buf
[ETHER_ADDR_STRLEN
];
2434 if (IS_ZEBRA_DEBUG_VXLAN
)
2435 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2436 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2439 /* Walk all local neighbors and mark as inactive and inform
2442 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2443 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2444 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2445 ZEBRA_NEIGH_SET_INACTIVE(n
);
2447 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
2448 &n
->emac
, 0, ZEBRA_NEIGH_ACTIVE
);
2455 * Process all neighbors associated with a remote MAC upon the MAC being
2458 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t
*zvni
,
2461 /* NOTE: Currently a NO-OP. */
2464 static void zvni_probe_neigh_on_mac_add(zebra_vni_t
*zvni
, zebra_mac_t
*zmac
)
2466 zebra_neigh_t
*nbr
= NULL
;
2467 struct listnode
*node
= NULL
;
2469 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2470 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2471 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2472 zvni_neigh_probe(zvni
, nbr
);
2477 * Inform BGP about local neighbor addition.
2479 static int zvni_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2480 struct ethaddr
*macaddr
,
2481 uint8_t neigh_flags
,
2486 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2487 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2488 /* Set router flag (R-bit) based on local neigh entry add */
2489 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2490 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2492 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2493 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
2497 * Inform BGP about local neighbor deletion.
2499 static int zvni_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2500 struct ethaddr
*macaddr
, uint8_t flags
,
2503 return zvni_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2504 0, state
, ZEBRA_MACIP_DEL
);
2508 * Install remote neighbor into the kernel.
2510 static int zvni_neigh_install(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2512 struct zebra_if
*zif
;
2513 struct zebra_l2info_vxlan
*vxl
;
2514 struct interface
*vlan_if
;
2520 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2523 zif
= zvni
->vxlan_if
->info
;
2526 vxl
= &zif
->l2info
.vxl
;
2528 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2532 flags
= NTF_EXT_LEARNED
;
2533 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2534 flags
|= NTF_ROUTER
;
2535 ZEBRA_NEIGH_SET_ACTIVE(n
);
2536 ret
= kernel_add_neigh(vlan_if
, &n
->ip
, &n
->emac
, flags
);
2542 * Uninstall remote neighbor from the kernel.
2544 static int zvni_neigh_uninstall(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2546 struct zebra_if
*zif
;
2547 struct zebra_l2info_vxlan
*vxl
;
2548 struct interface
*vlan_if
;
2550 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2553 if (!zvni
->vxlan_if
) {
2554 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2559 zif
= zvni
->vxlan_if
->info
;
2562 vxl
= &zif
->l2info
.vxl
;
2563 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2567 ZEBRA_NEIGH_SET_INACTIVE(n
);
2569 return kernel_del_neigh(vlan_if
, &n
->ip
);
2573 * Probe neighbor from the kernel.
2575 static int zvni_neigh_probe(zebra_vni_t
*zvni
, zebra_neigh_t
*n
)
2577 struct zebra_if
*zif
;
2578 struct zebra_l2info_vxlan
*vxl
;
2579 struct interface
*vlan_if
;
2581 zif
= zvni
->vxlan_if
->info
;
2584 vxl
= &zif
->l2info
.vxl
;
2586 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2591 return kernel_upd_neigh(vlan_if
, &n
->ip
, &n
->emac
,
2599 * Install neighbor hash entry - called upon access VLAN change.
2601 static void zvni_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2604 struct neigh_walk_ctx
*wctx
= ctxt
;
2606 n
= (zebra_neigh_t
*)bucket
->data
;
2608 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2609 zvni_neigh_install(wctx
->zvni
, n
);
2612 /* Get the VRR interface for SVI if any */
2613 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2615 struct zebra_vrf
*zvrf
= NULL
;
2616 struct interface
*tmp_if
= NULL
;
2617 struct zebra_if
*zif
= NULL
;
2619 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2622 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2627 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2630 if (zif
->link
== ifp
)
2637 static int zvni_del_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2639 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2640 struct connected
*c
= NULL
;
2641 struct ethaddr macaddr
;
2643 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2645 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2648 memset(&ip
, 0, sizeof(struct ipaddr
));
2649 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2652 if (c
->address
->family
== AF_INET
) {
2653 ip
.ipa_type
= IPADDR_V4
;
2654 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2655 sizeof(struct in_addr
));
2656 } else if (c
->address
->family
== AF_INET6
) {
2657 ip
.ipa_type
= IPADDR_V6
;
2658 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2659 sizeof(struct in6_addr
));
2664 zvni_gw_macip_del(ifp
, zvni
, &ip
);
2670 static int zvni_add_macip_for_intf(struct interface
*ifp
, zebra_vni_t
*zvni
)
2672 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2673 struct connected
*c
= NULL
;
2674 struct ethaddr macaddr
;
2676 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2678 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2681 memset(&ip
, 0, sizeof(struct ipaddr
));
2682 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2685 if (c
->address
->family
== AF_INET
) {
2686 ip
.ipa_type
= IPADDR_V4
;
2687 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2688 sizeof(struct in_addr
));
2689 } else if (c
->address
->family
== AF_INET6
) {
2690 ip
.ipa_type
= IPADDR_V6
;
2691 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2692 sizeof(struct in6_addr
));
2697 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
2703 static int zvni_advertise_subnet(zebra_vni_t
*zvni
, struct interface
*ifp
,
2706 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2707 struct connected
*c
= NULL
;
2708 struct ethaddr macaddr
;
2710 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2712 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2715 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2717 /* skip link local address */
2718 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2723 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2724 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2726 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2727 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2733 * zvni_gw_macip_add_to_client
2735 static int zvni_gw_macip_add(struct interface
*ifp
, zebra_vni_t
*zvni
,
2736 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2738 char buf
[ETHER_ADDR_STRLEN
];
2739 char buf2
[INET6_ADDRSTRLEN
];
2740 zebra_neigh_t
*n
= NULL
;
2741 zebra_mac_t
*mac
= NULL
;
2742 struct zebra_if
*zif
= NULL
;
2743 struct zebra_l2info_vxlan
*vxl
= NULL
;
2745 zif
= zvni
->vxlan_if
->info
;
2749 vxl
= &zif
->l2info
.vxl
;
2751 mac
= zvni_mac_lookup(zvni
, macaddr
);
2753 mac
= zvni_mac_add(zvni
, macaddr
);
2755 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2756 "Failed to add MAC %s intf %s(%u) VID %u",
2757 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2758 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2763 /* Set "local" forwarding info. */
2764 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2765 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2766 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2767 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2768 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2769 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2771 n
= zvni_neigh_lookup(zvni
, ip
);
2773 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
2776 EC_ZEBRA_MAC_ADD_FAILED
,
2777 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2778 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
2779 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2780 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
2785 /* Set "local" forwarding info. */
2786 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
2787 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
2788 ZEBRA_NEIGH_SET_ACTIVE(n
);
2789 /* Set Router flag (R-bit) */
2790 if (ip
->ipa_type
== IPADDR_V6
)
2791 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
2792 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
2793 n
->ifindex
= ifp
->ifindex
;
2795 /* Only advertise in BGP if the knob is enabled */
2796 if (!advertise_gw_macip_enabled(zvni
))
2799 if (IS_ZEBRA_DEBUG_VXLAN
)
2801 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2802 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2803 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2804 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
2806 zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
2807 n
->flags
, n
->loc_seq
);
2813 * zvni_gw_macip_del_from_client
2815 static int zvni_gw_macip_del(struct interface
*ifp
, zebra_vni_t
*zvni
,
2818 char buf1
[ETHER_ADDR_STRLEN
];
2819 char buf2
[INET6_ADDRSTRLEN
];
2820 zebra_neigh_t
*n
= NULL
;
2821 zebra_mac_t
*mac
= NULL
;
2823 /* If the neigh entry is not present nothing to do*/
2824 n
= zvni_neigh_lookup(zvni
, ip
);
2828 /* mac entry should be present */
2829 mac
= zvni_mac_lookup(zvni
, &n
->emac
);
2831 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2832 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)),
2833 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
2837 /* If the entry is not local nothing to do*/
2838 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
2841 /* only need to delete the entry from bgp if we sent it before */
2842 if (IS_ZEBRA_DEBUG_VXLAN
)
2844 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2845 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zvni
->vni
,
2846 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
2847 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
2849 /* Remove neighbor from BGP. */
2850 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
,
2851 ZEBRA_MACIP_TYPE_GW
, ZEBRA_NEIGH_ACTIVE
);
2853 /* Delete this neighbor entry. */
2854 zvni_neigh_del(zvni
, n
);
2856 /* see if the mac needs to be deleted as well*/
2858 zvni_deref_ip2mac(zvni
, mac
);
2863 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2866 zebra_vni_t
*zvni
= NULL
;
2867 struct zebra_if
*zif
= NULL
;
2868 struct zebra_l2info_vxlan zl2_info
;
2869 struct interface
*vlan_if
= NULL
;
2870 struct interface
*vrr_if
= NULL
;
2871 struct interface
*ifp
;
2873 /* Add primary SVI MAC*/
2874 zvni
= (zebra_vni_t
*)bucket
->data
;
2876 ifp
= zvni
->vxlan_if
;
2881 /* If down or not mapped to a bridge, we're done. */
2882 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2885 zl2_info
= zif
->l2info
.vxl
;
2888 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2892 /* Del primary MAC-IP */
2893 zvni_del_macip_for_intf(vlan_if
, zvni
);
2895 /* Del VRR MAC-IP - if any*/
2896 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2898 zvni_del_macip_for_intf(vrr_if
, zvni
);
2903 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket
*bucket
,
2906 zebra_vni_t
*zvni
= NULL
;
2907 struct zebra_if
*zif
= NULL
;
2908 struct zebra_l2info_vxlan zl2_info
;
2909 struct interface
*vlan_if
= NULL
;
2910 struct interface
*vrr_if
= NULL
;
2911 struct interface
*ifp
= NULL
;
2913 zvni
= (zebra_vni_t
*)bucket
->data
;
2915 ifp
= zvni
->vxlan_if
;
2920 /* If down or not mapped to a bridge, we're done. */
2921 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2923 zl2_info
= zif
->l2info
.vxl
;
2926 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
2930 /* Add primary SVI MAC-IP */
2931 zvni_add_macip_for_intf(vlan_if
, zvni
);
2933 if (advertise_gw_macip_enabled(zvni
)) {
2934 /* Add VRR MAC-IP - if any*/
2935 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
2937 zvni_add_macip_for_intf(vrr_if
, zvni
);
2943 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket
*bucket
,
2946 zebra_vni_t
*zvni
= NULL
;
2947 struct zebra_if
*zif
= NULL
;
2948 struct zebra_l2info_vxlan zl2_info
;
2949 struct interface
*vlan_if
= NULL
;
2950 struct interface
*ifp
;
2952 /* Add primary SVI MAC*/
2953 zvni
= (zebra_vni_t
*)bucket
->data
;
2957 ifp
= zvni
->vxlan_if
;
2962 /* If down or not mapped to a bridge, we're done. */
2963 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
2966 zl2_info
= zif
->l2info
.vxl
;
2968 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
2969 zif
->brslave_info
.br_if
);
2973 /* Del primary MAC-IP */
2974 zvni_del_macip_for_intf(vlan_if
, zvni
);
2979 static int zvni_local_neigh_update(zebra_vni_t
*zvni
,
2980 struct interface
*ifp
,
2982 struct ethaddr
*macaddr
,
2985 char buf
[ETHER_ADDR_STRLEN
];
2986 char buf2
[INET6_ADDRSTRLEN
];
2987 struct zebra_vrf
*zvrf
;
2988 zebra_neigh_t
*n
= NULL
;
2989 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
2990 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
2991 bool upd_mac_seq
= false;
2992 bool neigh_mac_change
= false;
2993 bool neigh_on_hold
= false;
2994 bool neigh_was_remote
= false;
2995 bool do_dad
= false;
2996 struct in_addr vtep_ip
= {.s_addr
= 0};
2998 /* Check if the MAC exists. */
2999 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3001 /* create a dummy MAC if the MAC is not already present */
3002 if (IS_ZEBRA_DEBUG_VXLAN
)
3004 "AUTO MAC %s created for neigh %s on VNI %u",
3005 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3006 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zvni
->vni
);
3008 zmac
= zvni_mac_add(zvni
, macaddr
);
3010 zlog_debug("Failed to add MAC %s VNI %u",
3011 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3016 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3017 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3018 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3020 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3022 * We don't change the MAC to local upon a neighbor
3023 * learn event, we wait for the explicit local MAC
3024 * learn. However, we have to compute its sequence
3025 * number in preparation for when it actually turns
3032 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
3034 if (IS_ZEBRA_DEBUG_VXLAN
)
3035 zlog_debug("\tUnable to find vrf for: %d",
3036 zvni
->vxlan_if
->vrf_id
);
3040 /* Check if the neighbor exists. */
3041 n
= zvni_neigh_lookup(zvni
, ip
);
3043 /* New neighbor - create */
3044 n
= zvni_neigh_add(zvni
, ip
, macaddr
);
3047 EC_ZEBRA_MAC_ADD_FAILED
,
3048 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3049 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3050 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3051 ifp
->name
, ifp
->ifindex
, zvni
->vni
);
3054 /* Set "local" forwarding info. */
3055 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3056 n
->ifindex
= ifp
->ifindex
;
3058 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3062 /* Note any changes and see if of interest to BGP. */
3063 mac_different
= (memcmp(n
->emac
.octet
,
3064 macaddr
->octet
, ETH_ALEN
) != 0) ? 1 : 0;
3065 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3066 ZEBRA_NEIGH_ROUTER_FLAG
);
3067 if (!mac_different
&& is_router
== cur_is_router
) {
3068 if (IS_ZEBRA_DEBUG_VXLAN
)
3070 "\tIgnoring entry mac is the same and is_router == cur_is_router");
3071 n
->ifindex
= ifp
->ifindex
;
3075 if (!mac_different
) {
3076 bool is_neigh_freezed
= false;
3078 /* Only the router flag has changed. */
3081 ZEBRA_NEIGH_ROUTER_FLAG
);
3083 UNSET_FLAG(n
->flags
,
3084 ZEBRA_NEIGH_ROUTER_FLAG
);
3086 /* Neigh is in freeze state and freeze action
3087 * is enabled, do not send update to client.
3089 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3091 CHECK_FLAG(n
->flags
,
3092 ZEBRA_NEIGH_DUPLICATE
));
3094 if (IS_ZEBRA_NEIGH_ACTIVE(n
) &&
3096 return zvni_neigh_send_add_to_client(
3097 zvni
->vni
, ip
, macaddr
,
3098 n
->flags
, n
->loc_seq
);
3100 if (IS_ZEBRA_DEBUG_VXLAN
)
3102 "\tNeighbor active and frozen");
3107 /* The MAC has changed, need to issue a delete
3108 * first as this means a different MACIP route.
3109 * Also, need to do some unlinking/relinking.
3110 * We also need to update the MAC's sequence number
3111 * in different situations.
3113 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
3114 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
,
3115 &n
->emac
, 0, n
->state
);
3116 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3118 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3120 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3121 neigh_mac_change
= upd_mac_seq
= true;
3122 listnode_delete(old_zmac
->neigh_list
, n
);
3123 zvni_deref_ip2mac(zvni
, old_zmac
);
3126 /* Update the forwarding info. */
3127 n
->ifindex
= ifp
->ifindex
;
3128 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3130 /* Link to new MAC */
3131 listnode_add_sort(zmac
->neigh_list
, n
);
3132 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3134 * Neighbor has moved from remote to local. Its
3135 * MAC could have also changed as part of the move.
3137 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3139 old_zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
3141 old_mac_seq
= CHECK_FLAG(
3146 neigh_mac_change
= upd_mac_seq
= true;
3147 listnode_delete(old_zmac
->neigh_list
,
3149 zvni_deref_ip2mac(zvni
, old_zmac
);
3152 /* Link to new MAC */
3153 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3154 listnode_add_sort(zmac
->neigh_list
, n
);
3156 /* Based on Mobility event Scenario-B from the
3157 * draft, neigh's previous state was remote treat this
3160 neigh_was_remote
= true;
3161 vtep_ip
= n
->r_vtep_ip
;
3162 /* Mark appropriately */
3163 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3164 n
->r_vtep_ip
.s_addr
= 0;
3165 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3166 n
->ifindex
= ifp
->ifindex
;
3170 /* If MAC was previously remote, or the neighbor had a different
3171 * MAC earlier, recompute the sequence number.
3174 uint32_t seq1
, seq2
;
3176 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3177 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3178 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3179 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3180 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3183 /* Mark Router flag (R-bit) */
3185 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3187 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3189 /* Check old and/or new MAC detected as duplicate mark
3190 * the neigh as duplicate
3192 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3193 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3194 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3196 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3197 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3200 /* For IP Duplicate Address Detection (DAD) is trigger,
3201 * when the event is extended mobility based on scenario-B
3202 * from the draft, IP/Neigh's MAC binding changed and
3203 * neigh's previous state was remote.
3205 if (neigh_mac_change
&& neigh_was_remote
)
3208 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3209 &neigh_on_hold
, true);
3211 /* Before we program this in BGP, we need to check if MAC is locally
3212 * learnt. If not, force neighbor to be inactive and reset its seq.
3214 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3215 ZEBRA_NEIGH_SET_INACTIVE(n
);
3217 zmac
->loc_seq
= mac_new_seq
;
3221 /* If the MAC's sequence number has changed, inform the MAC and all
3222 * neighbors associated with the MAC to BGP, else just inform this
3225 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3226 if (IS_ZEBRA_DEBUG_VXLAN
)
3227 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3228 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3229 zvni
->vni
, zmac
->loc_seq
, mac_new_seq
);
3230 zmac
->loc_seq
= mac_new_seq
;
3231 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
3232 zmac
->flags
, zmac
->loc_seq
))
3234 zvni_process_neigh_on_local_mac_change(zvni
, zmac
, 1);
3238 n
->loc_seq
= zmac
->loc_seq
;
3240 if (!neigh_on_hold
) {
3241 ZEBRA_NEIGH_SET_ACTIVE(n
);
3243 return zvni_neigh_send_add_to_client(zvni
->vni
, ip
, macaddr
,
3244 n
->flags
, n
->loc_seq
);
3246 if (IS_ZEBRA_DEBUG_VXLAN
)
3247 zlog_debug("\tNeighbor on hold not sending");
3252 static int zvni_remote_neigh_update(zebra_vni_t
*zvni
,
3253 struct interface
*ifp
,
3255 struct ethaddr
*macaddr
,
3258 char buf
[ETHER_ADDR_STRLEN
];
3259 char buf2
[INET6_ADDRSTRLEN
];
3260 zebra_neigh_t
*n
= NULL
;
3261 zebra_mac_t
*zmac
= NULL
;
3263 /* If the neighbor is unknown, there is no further action. */
3264 n
= zvni_neigh_lookup(zvni
, ip
);
3268 /* If a remote entry, see if it needs to be refreshed */
3269 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3271 if (state
& NUD_STALE
)
3272 zvni_neigh_install(zvni
, n
);
3275 /* We got a "remote" neighbor notification for an entry
3276 * we think is local. This can happen in a multihoming
3277 * scenario - but only if the MAC is already "remote".
3278 * Just mark our entry as "remote".
3280 zmac
= zvni_mac_lookup(zvni
, macaddr
);
3281 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3283 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3284 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3285 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3290 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3291 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3292 ZEBRA_NEIGH_SET_ACTIVE(n
);
3293 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3300 * Make hash key for MAC.
3302 static unsigned int mac_hash_keymake(const void *p
)
3304 const zebra_mac_t
*pmac
= p
;
3305 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3307 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3311 * Compare two MAC addresses.
3313 static bool mac_cmp(const void *p1
, const void *p2
)
3315 const zebra_mac_t
*pmac1
= p1
;
3316 const zebra_mac_t
*pmac2
= p2
;
3318 if (pmac1
== NULL
&& pmac2
== NULL
)
3321 if (pmac1
== NULL
|| pmac2
== NULL
)
3324 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3329 * Callback to allocate MAC hash entry.
3331 static void *zvni_mac_alloc(void *p
)
3333 const zebra_mac_t
*tmp_mac
= p
;
3336 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3339 return ((void *)mac
);
3345 static zebra_mac_t
*zvni_mac_add(zebra_vni_t
*zvni
, struct ethaddr
*macaddr
)
3347 zebra_mac_t tmp_mac
;
3348 zebra_mac_t
*mac
= NULL
;
3350 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3351 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3352 mac
= hash_get(zvni
->mac_table
, &tmp_mac
, zvni_mac_alloc
);
3356 mac
->dad_mac_auto_recovery_timer
= NULL
;
3358 mac
->neigh_list
= list_new();
3359 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3367 static int zvni_mac_del(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3369 zebra_mac_t
*tmp_mac
;
3371 /* Cancel auto recovery */
3372 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3374 list_delete(&mac
->neigh_list
);
3376 /* Free the VNI hash entry and allocated memory. */
3377 tmp_mac
= hash_release(zvni
->mac_table
, mac
);
3378 XFREE(MTYPE_MAC
, tmp_mac
);
3384 * Free MAC hash entry (callback)
3386 static void zvni_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3388 struct mac_walk_ctx
*wctx
= arg
;
3389 zebra_mac_t
*mac
= bucket
->data
;
3391 if (((wctx
->flags
& DEL_LOCAL_MAC
) && (mac
->flags
& ZEBRA_MAC_LOCAL
))
3392 || ((wctx
->flags
& DEL_REMOTE_MAC
)
3393 && (mac
->flags
& ZEBRA_MAC_REMOTE
))
3394 || ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
)
3395 && (mac
->flags
& ZEBRA_MAC_REMOTE
)
3396 && IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
3397 &wctx
->r_vtep_ip
))) {
3398 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3399 zvni_mac_send_del_to_client(wctx
->zvni
->vni
,
3403 if (wctx
->uninstall
)
3404 zvni_mac_uninstall(wctx
->zvni
, mac
);
3406 zvni_mac_del(wctx
->zvni
, mac
);
3413 * Delete all MAC entries from specific VTEP for a particular VNI.
3415 static void zvni_mac_del_from_vtep(zebra_vni_t
*zvni
, int uninstall
,
3416 struct in_addr
*r_vtep_ip
)
3418 struct mac_walk_ctx wctx
;
3420 if (!zvni
->mac_table
)
3423 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3425 wctx
.uninstall
= uninstall
;
3426 wctx
.flags
= DEL_REMOTE_MAC_FROM_VTEP
;
3427 wctx
.r_vtep_ip
= *r_vtep_ip
;
3429 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3433 * Delete all MAC entries for this VNI.
3435 static void zvni_mac_del_all(zebra_vni_t
*zvni
, int uninstall
, int upd_client
,
3438 struct mac_walk_ctx wctx
;
3440 if (!zvni
->mac_table
)
3443 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3445 wctx
.uninstall
= uninstall
;
3446 wctx
.upd_client
= upd_client
;
3449 hash_iterate(zvni
->mac_table
, zvni_mac_del_hash_entry
, &wctx
);
3453 * Look up MAC hash entry.
3455 static zebra_mac_t
*zvni_mac_lookup(zebra_vni_t
*zvni
, struct ethaddr
*mac
)
3460 memset(&tmp
, 0, sizeof(tmp
));
3461 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3462 pmac
= hash_lookup(zvni
->mac_table
, &tmp
);
3468 * Inform BGP about local MAC addition.
3470 static int zvni_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3471 uint8_t mac_flags
, uint32_t seq
)
3475 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3476 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3477 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3478 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3480 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3481 seq
, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_ADD
);
3485 * Inform BGP about local MAC deletion.
3487 static int zvni_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
)
3489 return zvni_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3490 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, ZEBRA_MACIP_DEL
);
3494 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3495 * notifications, to see if they are of interest.
3497 static zebra_vni_t
*zvni_map_vlan(struct interface
*ifp
,
3498 struct interface
*br_if
, vlanid_t vid
)
3500 struct zebra_ns
*zns
;
3501 struct route_node
*rn
;
3502 struct interface
*tmp_if
= NULL
;
3503 struct zebra_if
*zif
;
3504 struct zebra_l2info_bridge
*br
;
3505 struct zebra_l2info_vxlan
*vxl
= NULL
;
3506 uint8_t bridge_vlan_aware
;
3510 /* Determine if bridge is VLAN-aware or not */
3513 br
= &zif
->l2info
.br
;
3514 bridge_vlan_aware
= br
->vlan_aware
;
3516 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3517 /* TODO: Optimize with a hash. */
3518 zns
= zebra_ns_lookup(NS_DEFAULT
);
3519 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3520 tmp_if
= (struct interface
*)rn
->info
;
3524 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3526 if (!if_is_operative(tmp_if
))
3528 vxl
= &zif
->l2info
.vxl
;
3530 if (zif
->brslave_info
.br_if
!= br_if
)
3533 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3542 zvni
= zvni_lookup(vxl
->vni
);
3547 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3548 * neighbor notifications, to see if they are of interest.
3550 static zebra_vni_t
*zvni_from_svi(struct interface
*ifp
,
3551 struct interface
*br_if
)
3553 struct zebra_ns
*zns
;
3554 struct route_node
*rn
;
3555 struct interface
*tmp_if
= NULL
;
3556 struct zebra_if
*zif
;
3557 struct zebra_l2info_bridge
*br
;
3558 struct zebra_l2info_vxlan
*vxl
= NULL
;
3559 uint8_t bridge_vlan_aware
;
3567 /* Make sure the linked interface is a bridge. */
3568 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3571 /* Determine if bridge is VLAN-aware or not */
3574 br
= &zif
->l2info
.br
;
3575 bridge_vlan_aware
= br
->vlan_aware
;
3576 if (bridge_vlan_aware
) {
3577 struct zebra_l2info_vlan
*vl
;
3579 if (!IS_ZEBRA_IF_VLAN(ifp
))
3584 vl
= &zif
->l2info
.vl
;
3588 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3589 /* TODO: Optimize with a hash. */
3590 zns
= zebra_ns_lookup(NS_DEFAULT
);
3591 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3592 tmp_if
= (struct interface
*)rn
->info
;
3596 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3598 if (!if_is_operative(tmp_if
))
3600 vxl
= &zif
->l2info
.vxl
;
3602 if (zif
->brslave_info
.br_if
!= br_if
)
3605 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3614 zvni
= zvni_lookup(vxl
->vni
);
3618 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3620 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3621 * linked to the bridge
3622 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3625 static struct interface
*zvni_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
3627 struct zebra_ns
*zns
;
3628 struct route_node
*rn
;
3629 struct interface
*tmp_if
= NULL
;
3630 struct zebra_if
*zif
;
3631 struct zebra_l2info_bridge
*br
;
3632 struct zebra_l2info_vlan
*vl
;
3633 uint8_t bridge_vlan_aware
;
3636 /* Defensive check, caller expected to invoke only with valid bridge. */
3640 /* Determine if bridge is VLAN-aware or not */
3643 br
= &zif
->l2info
.br
;
3644 bridge_vlan_aware
= br
->vlan_aware
;
3646 /* Check oper status of the SVI. */
3647 if (!bridge_vlan_aware
)
3648 return if_is_operative(br_if
) ? br_if
: NULL
;
3650 /* Identify corresponding VLAN interface. */
3651 /* TODO: Optimize with a hash. */
3652 zns
= zebra_ns_lookup(NS_DEFAULT
);
3653 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3654 tmp_if
= (struct interface
*)rn
->info
;
3655 /* Check oper status of the SVI. */
3656 if (!tmp_if
|| !if_is_operative(tmp_if
))
3659 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
3660 || zif
->link
!= br_if
)
3662 vl
= (struct zebra_l2info_vlan
*)&zif
->l2info
.vl
;
3664 if (vl
->vid
== vid
) {
3670 return found
? tmp_if
: NULL
;
3674 * Install remote MAC into the kernel.
3676 static int zvni_mac_install(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3678 struct zebra_if
*zif
;
3679 struct zebra_l2info_vxlan
*vxl
;
3682 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3685 zif
= zvni
->vxlan_if
->info
;
3688 vxl
= &zif
->l2info
.vxl
;
3690 sticky
= !!CHECK_FLAG(mac
->flags
,
3691 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
3693 return kernel_add_mac(zvni
->vxlan_if
, vxl
->access_vlan
, &mac
->macaddr
,
3694 mac
->fwd_info
.r_vtep_ip
, sticky
);
3698 * Uninstall remote MAC from the kernel.
3700 static int zvni_mac_uninstall(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3702 struct zebra_if
*zif
;
3703 struct zebra_l2info_vxlan
*vxl
;
3704 struct in_addr vtep_ip
;
3705 struct interface
*ifp
;
3707 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
3710 if (!zvni
->vxlan_if
) {
3711 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3716 zif
= zvni
->vxlan_if
->info
;
3719 vxl
= &zif
->l2info
.vxl
;
3721 ifp
= zvni
->vxlan_if
;
3722 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
3724 return kernel_del_mac(ifp
, vxl
->access_vlan
, &mac
->macaddr
, vtep_ip
);
3728 * Install MAC hash entry - called upon access VLAN change.
3730 static void zvni_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
3733 struct mac_walk_ctx
*wctx
= ctxt
;
3735 mac
= (zebra_mac_t
*)bucket
->data
;
3737 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
3738 zvni_mac_install(wctx
->zvni
, mac
);
3742 * Count of remote neighbors referencing this MAC.
3744 static int remote_neigh_count(zebra_mac_t
*zmac
)
3746 zebra_neigh_t
*n
= NULL
;
3747 struct listnode
*node
= NULL
;
3750 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
3751 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
3759 * Decrement neighbor refcount of MAC; uninstall and free it if
3762 static void zvni_deref_ip2mac(zebra_vni_t
*zvni
, zebra_mac_t
*mac
)
3764 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
3767 /* If all remote neighbors referencing a remote MAC go away,
3768 * we need to uninstall the MAC.
3770 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
3771 remote_neigh_count(mac
) == 0) {
3772 zvni_mac_uninstall(zvni
, mac
);
3773 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
3776 /* If no neighbors, delete the MAC. */
3777 if (list_isempty(mac
->neigh_list
))
3778 zvni_mac_del(zvni
, mac
);
3782 * Read and populate local MACs and neighbors corresponding to this VNI.
3784 static void zvni_read_mac_neigh(zebra_vni_t
*zvni
, struct interface
*ifp
)
3786 struct zebra_ns
*zns
;
3787 struct zebra_if
*zif
;
3788 struct interface
*vlan_if
;
3789 struct zebra_l2info_vxlan
*vxl
;
3790 struct interface
*vrr_if
;
3793 vxl
= &zif
->l2info
.vxl
;
3794 zns
= zebra_ns_lookup(NS_DEFAULT
);
3796 if (IS_ZEBRA_DEBUG_VXLAN
)
3798 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3799 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
3800 zif
->brslave_info
.bridge_ifindex
);
3802 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
3803 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
3806 /* Add SVI MAC-IP */
3807 zvni_add_macip_for_intf(vlan_if
, zvni
);
3809 /* Add VRR MAC-IP - if any*/
3810 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3812 zvni_add_macip_for_intf(vrr_if
, zvni
);
3814 neigh_read_for_vlan(zns
, vlan_if
);
3819 * Hash function for VNI.
3821 static unsigned int vni_hash_keymake(const void *p
)
3823 const zebra_vni_t
*zvni
= p
;
3825 return (jhash_1word(zvni
->vni
, 0));
3829 * Compare 2 VNI hash entries.
3831 static bool vni_hash_cmp(const void *p1
, const void *p2
)
3833 const zebra_vni_t
*zvni1
= p1
;
3834 const zebra_vni_t
*zvni2
= p2
;
3836 return (zvni1
->vni
== zvni2
->vni
);
3839 static int vni_list_cmp(void *p1
, void *p2
)
3841 const zebra_vni_t
*zvni1
= p1
;
3842 const zebra_vni_t
*zvni2
= p2
;
3844 if (zvni1
->vni
== zvni2
->vni
)
3846 return (zvni1
->vni
< zvni2
->vni
) ? -1 : 1;
3850 * Callback to allocate VNI hash entry.
3852 static void *zvni_alloc(void *p
)
3854 const zebra_vni_t
*tmp_vni
= p
;
3857 zvni
= XCALLOC(MTYPE_ZVNI
, sizeof(zebra_vni_t
));
3858 zvni
->vni
= tmp_vni
->vni
;
3859 return ((void *)zvni
);
3863 * Look up VNI hash entry.
3865 static zebra_vni_t
*zvni_lookup(vni_t vni
)
3867 struct zebra_vrf
*zvrf
;
3868 zebra_vni_t tmp_vni
;
3869 zebra_vni_t
*zvni
= NULL
;
3871 zvrf
= zebra_vrf_get_evpn();
3873 memset(&tmp_vni
, 0, sizeof(zebra_vni_t
));
3875 zvni
= hash_lookup(zvrf
->vni_table
, &tmp_vni
);
3881 * Add VNI hash entry.
3883 static zebra_vni_t
*zvni_add(vni_t vni
)
3885 struct zebra_vrf
*zvrf
;
3886 zebra_vni_t tmp_zvni
;
3887 zebra_vni_t
*zvni
= NULL
;
3889 zvrf
= zebra_vrf_get_evpn();
3891 memset(&tmp_zvni
, 0, sizeof(zebra_vni_t
));
3893 zvni
= hash_get(zvrf
->vni_table
, &tmp_zvni
, zvni_alloc
);
3896 /* Create hash table for MAC */
3898 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra VNI MAC Table");
3900 /* Create hash table for neighbors */
3901 zvni
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
3902 "Zebra VNI Neighbor Table");
3908 * Delete VNI hash entry.
3910 static int zvni_del(zebra_vni_t
*zvni
)
3912 struct zebra_vrf
*zvrf
;
3913 zebra_vni_t
*tmp_zvni
;
3915 zvrf
= zebra_vrf_get_evpn();
3918 zvni
->vxlan_if
= NULL
;
3920 /* Remove references to the BUM mcast grp */
3921 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
, zvni
->mcast_grp
);
3923 /* Free the neighbor hash table. */
3924 hash_free(zvni
->neigh_table
);
3925 zvni
->neigh_table
= NULL
;
3927 /* Free the MAC hash table. */
3928 hash_free(zvni
->mac_table
);
3929 zvni
->mac_table
= NULL
;
3931 /* Free the VNI hash entry and allocated memory. */
3932 tmp_zvni
= hash_release(zvrf
->vni_table
, zvni
);
3933 XFREE(MTYPE_ZVNI
, tmp_zvni
);
3939 * Inform BGP about local VNI addition.
3941 static int zvni_send_add_to_client(zebra_vni_t
*zvni
)
3943 struct zserv
*client
;
3946 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3947 /* BGP may not be running. */
3951 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3953 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
3954 stream_putl(s
, zvni
->vni
);
3955 stream_put_in_addr(s
, &zvni
->local_vtep_ip
);
3956 stream_put(s
, &zvni
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
3957 stream_put_in_addr(s
, &zvni
->mcast_grp
);
3959 /* Write packet size. */
3960 stream_putw_at(s
, 0, stream_get_endp(s
));
3962 if (IS_ZEBRA_DEBUG_VXLAN
)
3963 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni
->vni
,
3964 inet_ntoa(zvni
->local_vtep_ip
),
3965 vrf_id_to_name(zvni
->vrf_id
),
3966 zebra_route_string(client
->proto
));
3968 client
->vniadd_cnt
++;
3969 return zserv_send_message(client
, s
);
3973 * Inform BGP about local VNI deletion.
3975 static int zvni_send_del_to_client(vni_t vni
)
3977 struct zserv
*client
;
3980 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
3981 /* BGP may not be running. */
3985 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
3988 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
3989 stream_putl(s
, vni
);
3991 /* Write packet size. */
3992 stream_putw_at(s
, 0, stream_get_endp(s
));
3994 if (IS_ZEBRA_DEBUG_VXLAN
)
3995 zlog_debug("Send VNI_DEL %u to %s", vni
,
3996 zebra_route_string(client
->proto
));
3998 client
->vnidel_cnt
++;
3999 return zserv_send_message(client
, s
);
4003 * Build the VNI hash table by going over the VxLAN interfaces. This
4004 * is called when EVPN (advertise-all-vni) is enabled.
4006 static void zvni_build_hash_table(void)
4008 struct zebra_ns
*zns
;
4009 struct route_node
*rn
;
4010 struct interface
*ifp
;
4012 /* Walk VxLAN interfaces and create VNI hash. */
4013 zns
= zebra_ns_lookup(NS_DEFAULT
);
4014 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4016 zebra_vni_t
*zvni
= NULL
;
4017 zebra_l3vni_t
*zl3vni
= NULL
;
4018 struct zebra_if
*zif
;
4019 struct zebra_l2info_vxlan
*vxl
;
4021 ifp
= (struct interface
*)rn
->info
;
4025 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4028 vxl
= &zif
->l2info
.vxl
;
4031 /* L3-VNI and L2-VNI are handled seperately */
4032 zl3vni
= zl3vni_lookup(vni
);
4035 if (IS_ZEBRA_DEBUG_VXLAN
)
4037 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4038 ifp
->name
, ifp
->ifindex
, vni
);
4040 /* associate with vxlan_if */
4041 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4042 zl3vni
->vxlan_if
= ifp
;
4045 * we need to associate with SVI.
4046 * we can associate with svi-if only after association
4047 * with vxlan-intf is complete
4049 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4051 if (is_l3vni_oper_up(zl3vni
))
4052 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4055 struct interface
*vlan_if
= NULL
;
4057 if (IS_ZEBRA_DEBUG_VXLAN
)
4059 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4060 ifp
->name
, ifp
->ifindex
, vni
,
4061 inet_ntoa(vxl
->vtep_ip
));
4063 /* VNI hash entry is not expected to exist. */
4064 zvni
= zvni_lookup(vni
);
4067 "VNI hash already present for IF %s(%u) L2-VNI %u",
4068 ifp
->name
, ifp
->ifindex
, vni
);
4072 zvni
= zvni_add(vni
);
4075 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4076 ifp
->name
, ifp
->ifindex
, vni
);
4080 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
4081 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
4082 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
4084 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4086 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
4087 zvni
->mcast_grp
= vxl
->mcast_grp
;
4089 zvni
->vxlan_if
= ifp
;
4090 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
4091 zif
->brslave_info
.br_if
);
4093 zvni
->vrf_id
= vlan_if
->vrf_id
;
4094 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
4096 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
4100 /* Inform BGP if intf is up and mapped to bridge. */
4101 if (if_is_operative(ifp
) && zif
->brslave_info
.br_if
)
4102 zvni_send_add_to_client(zvni
);
4108 * See if remote VTEP matches with prefix.
4110 static int zvni_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4112 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4116 * Locate remote VTEP in VNI hash table.
4118 static zebra_vtep_t
*zvni_vtep_find(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4120 zebra_vtep_t
*zvtep
;
4125 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4126 if (zvni_vtep_match(vtep_ip
, zvtep
))
4134 * Add remote VTEP to VNI hash table.
4136 static zebra_vtep_t
*zvni_vtep_add(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
,
4140 zebra_vtep_t
*zvtep
;
4142 zvtep
= XCALLOC(MTYPE_ZVNI_VTEP
, sizeof(zebra_vtep_t
));
4144 zvtep
->vtep_ip
= *vtep_ip
;
4145 zvtep
->flood_control
= flood_control
;
4148 zvni
->vteps
->prev
= zvtep
;
4149 zvtep
->next
= zvni
->vteps
;
4150 zvni
->vteps
= zvtep
;
4156 * Remove remote VTEP from VNI hash table.
4158 static int zvni_vtep_del(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4161 zvtep
->next
->prev
= zvtep
->prev
;
4163 zvtep
->prev
->next
= zvtep
->next
;
4165 zvni
->vteps
= zvtep
->next
;
4167 zvtep
->prev
= zvtep
->next
= NULL
;
4168 XFREE(MTYPE_ZVNI_VTEP
, zvtep
);
4174 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4175 * uninstall from kernel if asked to.
4177 static int zvni_vtep_del_all(zebra_vni_t
*zvni
, int uninstall
)
4179 zebra_vtep_t
*zvtep
, *zvtep_next
;
4184 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4185 zvtep_next
= zvtep
->next
;
4187 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4188 zvni_vtep_del(zvni
, zvtep
);
4195 * Install remote VTEP into the kernel if the remote VTEP has asked
4196 * for head-end-replication.
4198 static int zvni_vtep_install(zebra_vni_t
*zvni
, zebra_vtep_t
*zvtep
)
4200 if (is_vxlan_flooding_head_end() &&
4201 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
))
4202 return kernel_add_vtep(zvni
->vni
, zvni
->vxlan_if
,
4208 * Uninstall remote VTEP from the kernel.
4210 static int zvni_vtep_uninstall(zebra_vni_t
*zvni
, struct in_addr
*vtep_ip
)
4212 if (!zvni
->vxlan_if
) {
4213 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4218 return kernel_del_vtep(zvni
->vni
, zvni
->vxlan_if
, vtep_ip
);
4222 * Install or uninstall flood entries in the kernel corresponding to
4223 * remote VTEPs. This is invoked upon change to BUM handling.
4225 static void zvni_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4229 zebra_vtep_t
*zvtep
;
4231 zvni
= (zebra_vni_t
*)bucket
->data
;
4235 for (zvtep
= zvni
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4236 if (is_vxlan_flooding_head_end())
4237 zvni_vtep_install(zvni
, zvtep
);
4239 zvni_vtep_uninstall(zvni
, &zvtep
->vtep_ip
);
4244 * Cleanup VNI/VTEP and update kernel
4246 static void zvni_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4248 zebra_vni_t
*zvni
= NULL
;
4249 zebra_l3vni_t
*zl3vni
= NULL
;
4250 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4252 zvni
= (zebra_vni_t
*)bucket
->data
;
4254 /* remove from l3-vni list */
4256 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4258 listnode_delete(zl3vni
->l2vnis
, zvni
);
4260 /* Free up all neighbors and MACs, if any. */
4261 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
4262 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
4264 /* Free up all remote VTEPs, if any. */
4265 zvni_vtep_del_all(zvni
, 1);
4267 /* Delete the hash entry. */
4272 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4274 zebra_l3vni_t
*zl3vni
= NULL
;
4276 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4278 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4281 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4282 struct prefix
*host
)
4284 struct host_rb_entry lookup
;
4285 struct host_rb_entry
*hle
;
4287 memset(&lookup
, 0, sizeof(lookup
));
4288 memcpy(&lookup
.p
, host
, sizeof(*host
));
4290 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4294 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4295 memcpy(hle
, &lookup
, sizeof(lookup
));
4297 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4300 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4302 struct host_rb_entry lookup
;
4303 struct host_rb_entry
*hle
;
4305 memset(&lookup
, 0, sizeof(lookup
));
4306 memcpy(&lookup
.p
, host
, sizeof(*host
));
4308 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4310 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4311 XFREE(MTYPE_HOST_PREFIX
, hle
);
4318 * Look up MAC hash entry.
4320 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4321 struct ethaddr
*rmac
)
4326 memset(&tmp
, 0, sizeof(tmp
));
4327 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4328 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4334 * Callback to allocate RMAC hash entry.
4336 static void *zl3vni_rmac_alloc(void *p
)
4338 const zebra_mac_t
*tmp_rmac
= p
;
4341 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4344 return ((void *)zrmac
);
4348 * Add RMAC entry to l3-vni
4350 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
)
4352 zebra_mac_t tmp_rmac
;
4353 zebra_mac_t
*zrmac
= NULL
;
4355 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4356 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4357 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4360 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4362 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4363 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4371 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4373 zebra_mac_t
*tmp_rmac
;
4374 struct host_rb_entry
*hle
;
4376 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4377 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4379 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4380 XFREE(MTYPE_HOST_PREFIX
, hle
);
4383 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4384 XFREE(MTYPE_MAC
, tmp_rmac
);
4390 * Install remote RMAC into the kernel.
4392 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4394 struct zebra_if
*zif
= NULL
;
4395 struct zebra_l2info_vxlan
*vxl
= NULL
;
4397 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4398 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4401 zif
= zl3vni
->vxlan_if
->info
;
4405 vxl
= &zif
->l2info
.vxl
;
4407 return kernel_add_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4408 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0);
4412 * Uninstall remote RMAC from the kernel.
4414 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4416 char buf
[ETHER_ADDR_STRLEN
];
4417 struct zebra_if
*zif
= NULL
;
4418 struct zebra_l2info_vxlan
*vxl
= NULL
;
4420 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
4421 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
4424 if (!zl3vni
->vxlan_if
) {
4426 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4427 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
4428 zl3vni
->vni
, zl3vni
);
4432 zif
= zl3vni
->vxlan_if
->info
;
4436 vxl
= &zif
->l2info
.vxl
;
4438 return kernel_del_mac(zl3vni
->vxlan_if
, vxl
->access_vlan
,
4439 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
4442 /* handle rmac add */
4443 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
, struct ethaddr
*rmac
,
4444 struct ipaddr
*vtep_ip
,
4445 struct prefix
*host_prefix
)
4447 char buf
[ETHER_ADDR_STRLEN
];
4448 char buf1
[INET6_ADDRSTRLEN
];
4449 zebra_mac_t
*zrmac
= NULL
;
4451 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
4454 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
4457 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4458 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4460 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)));
4463 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
4464 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
4466 /* install rmac in kernel */
4467 zl3vni_rmac_install(zl3vni
, zrmac
);
4470 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
4476 /* handle rmac delete */
4477 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
4478 struct prefix
*host_prefix
)
4480 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
4482 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4483 /* uninstall from kernel */
4484 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
4486 /* del the rmac entry */
4487 zl3vni_rmac_del(zl3vni
, zrmac
);
4492 * Look up nh hash entry on a l3-vni.
4494 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4499 memset(&tmp
, 0, sizeof(tmp
));
4500 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
4501 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
4508 * Callback to allocate NH hash entry on L3-VNI.
4510 static void *zl3vni_nh_alloc(void *p
)
4512 const zebra_neigh_t
*tmp_n
= p
;
4515 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
4522 * Add neighbor entry.
4524 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4525 struct ethaddr
*mac
)
4527 zebra_neigh_t tmp_n
;
4528 zebra_neigh_t
*n
= NULL
;
4530 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
4531 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
4532 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
4535 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
4537 memcpy(&n
->emac
, mac
, ETH_ALEN
);
4538 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
4539 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
4545 * Delete neighbor entry.
4547 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4549 zebra_neigh_t
*tmp_n
;
4550 struct host_rb_entry
*hle
;
4552 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
4553 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
4555 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
4556 XFREE(MTYPE_HOST_PREFIX
, hle
);
4559 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
4560 XFREE(MTYPE_NEIGH
, tmp_n
);
4566 * Install remote nh as neigh into the kernel.
4568 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4575 if (!is_l3vni_oper_up(zl3vni
))
4578 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4579 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4582 flags
= NTF_EXT_LEARNED
;
4583 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
4584 flags
|= NTF_ROUTER
;
4585 ret
= kernel_add_neigh(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
);
4591 * Uninstall remote nh from the kernel.
4593 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
4595 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
4596 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
4599 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
4602 return kernel_del_neigh(zl3vni
->svi_if
, &n
->ip
);
4605 /* add remote vtep as a neigh entry */
4606 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
, struct ipaddr
*vtep_ip
,
4607 struct ethaddr
*rmac
,
4608 struct prefix
*host_prefix
)
4610 char buf
[ETHER_ADDR_STRLEN
];
4611 char buf1
[INET6_ADDRSTRLEN
];
4612 zebra_neigh_t
*nh
= NULL
;
4614 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
4616 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
4620 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4621 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
4622 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
4627 /* install the nh neigh in kernel */
4628 zl3vni_nh_install(zl3vni
, nh
);
4631 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
4636 /* handle nh neigh delete */
4637 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
4638 struct prefix
*host_prefix
)
4640 rb_delete_host(&nh
->host_rb
, host_prefix
);
4642 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
4643 /* uninstall from kernel */
4644 zl3vni_nh_uninstall(zl3vni
, nh
);
4646 /* delete the nh entry */
4647 zl3vni_nh_del(zl3vni
, nh
);
4651 /* handle neigh update from kernel - the only thing of interest is to
4652 * readd stale entries.
4654 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
4658 zebra_neigh_t
*n
= NULL
;
4660 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4664 /* all next hop neigh are remote and installed by frr.
4665 * If the kernel has aged this entry, re-install.
4667 if (state
& NUD_STALE
)
4668 zl3vni_nh_install(zl3vni
, n
);
4673 /* handle neigh delete from kernel */
4674 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
4676 zebra_neigh_t
*n
= NULL
;
4678 n
= zl3vni_nh_lookup(zl3vni
, ip
);
4682 /* all next hop neigh are remote and installed by frr.
4683 * If we get an age out notification for these neigh entries, we have to
4686 zl3vni_nh_install(zl3vni
, n
);
4692 * Hash function for L3 VNI.
4694 static unsigned int l3vni_hash_keymake(const void *p
)
4696 const zebra_l3vni_t
*zl3vni
= p
;
4698 return jhash_1word(zl3vni
->vni
, 0);
4702 * Compare 2 L3 VNI hash entries.
4704 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
4706 const zebra_l3vni_t
*zl3vni1
= p1
;
4707 const zebra_l3vni_t
*zl3vni2
= p2
;
4709 return (zl3vni1
->vni
== zl3vni2
->vni
);
4713 * Callback to allocate L3 VNI hash entry.
4715 static void *zl3vni_alloc(void *p
)
4717 zebra_l3vni_t
*zl3vni
= NULL
;
4718 const zebra_l3vni_t
*tmp_l3vni
= p
;
4720 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
4721 zl3vni
->vni
= tmp_l3vni
->vni
;
4722 return ((void *)zl3vni
);
4726 * Look up L3 VNI hash entry.
4728 static zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
4730 zebra_l3vni_t tmp_l3vni
;
4731 zebra_l3vni_t
*zl3vni
= NULL
;
4733 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
4734 tmp_l3vni
.vni
= vni
;
4735 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
4741 * Add L3 VNI hash entry.
4743 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
4745 zebra_l3vni_t tmp_zl3vni
;
4746 zebra_l3vni_t
*zl3vni
= NULL
;
4748 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
4749 tmp_zl3vni
.vni
= vni
;
4751 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
4754 zl3vni
->vrf_id
= vrf_id
;
4755 zl3vni
->svi_if
= NULL
;
4756 zl3vni
->vxlan_if
= NULL
;
4757 zl3vni
->l2vnis
= list_new();
4758 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
4760 /* Create hash table for remote RMAC */
4761 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
4762 "Zebra L3-VNI RMAC-Table");
4764 /* Create hash table for neighbors */
4765 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4766 "Zebra L3-VNI next-hop table");
4772 * Delete L3 VNI hash entry.
4774 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
4776 zebra_l3vni_t
*tmp_zl3vni
;
4778 /* free the list of l2vnis */
4779 list_delete(&zl3vni
->l2vnis
);
4780 zl3vni
->l2vnis
= NULL
;
4782 /* Free the rmac table */
4783 hash_free(zl3vni
->rmac_table
);
4784 zl3vni
->rmac_table
= NULL
;
4786 /* Free the nh table */
4787 hash_free(zl3vni
->nh_table
);
4788 zl3vni
->nh_table
= NULL
;
4790 /* Free the VNI hash entry and allocated memory. */
4791 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
4792 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
4797 static struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
4799 struct zebra_ns
*zns
= NULL
;
4800 struct route_node
*rn
= NULL
;
4801 struct interface
*ifp
= NULL
;
4803 /* loop through all vxlan-interface */
4804 zns
= zebra_ns_lookup(NS_DEFAULT
);
4805 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4807 struct zebra_if
*zif
= NULL
;
4808 struct zebra_l2info_vxlan
*vxl
= NULL
;
4810 ifp
= (struct interface
*)rn
->info
;
4815 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4818 vxl
= &zif
->l2info
.vxl
;
4819 if (vxl
->vni
== zl3vni
->vni
) {
4820 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4828 static struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
4830 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
4831 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
4836 if (!zl3vni
->vxlan_if
)
4839 zif
= zl3vni
->vxlan_if
->info
;
4843 vxl
= &zif
->l2info
.vxl
;
4845 return zvni_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4848 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
4850 struct zebra_vrf
*zvrf
= NULL
;
4852 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
4856 return zl3vni_lookup(zvrf
->l3vni
);
4860 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4861 * neighbor notifications, to see if they are of interest.
4863 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
4864 struct interface
*br_if
)
4868 uint8_t bridge_vlan_aware
= 0;
4869 zebra_l3vni_t
*zl3vni
= NULL
;
4870 struct zebra_ns
*zns
= NULL
;
4871 struct route_node
*rn
= NULL
;
4872 struct zebra_if
*zif
= NULL
;
4873 struct interface
*tmp_if
= NULL
;
4874 struct zebra_l2info_bridge
*br
= NULL
;
4875 struct zebra_l2info_vxlan
*vxl
= NULL
;
4880 /* Make sure the linked interface is a bridge. */
4881 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
4884 /* Determine if bridge is VLAN-aware or not */
4887 br
= &zif
->l2info
.br
;
4888 bridge_vlan_aware
= br
->vlan_aware
;
4889 if (bridge_vlan_aware
) {
4890 struct zebra_l2info_vlan
*vl
;
4892 if (!IS_ZEBRA_IF_VLAN(ifp
))
4897 vl
= &zif
->l2info
.vl
;
4901 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4902 /* TODO: Optimize with a hash. */
4903 zns
= zebra_ns_lookup(NS_DEFAULT
);
4904 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4905 tmp_if
= (struct interface
*)rn
->info
;
4909 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4911 if (!if_is_operative(tmp_if
))
4913 vxl
= &zif
->l2info
.vxl
;
4915 if (zif
->brslave_info
.br_if
!= br_if
)
4918 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4927 zl3vni
= zl3vni_lookup(vxl
->vni
);
4932 * Inform BGP about l3-vni.
4934 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
4936 struct stream
*s
= NULL
;
4937 struct zserv
*client
= NULL
;
4938 struct ethaddr rmac
;
4939 char buf
[ETHER_ADDR_STRLEN
];
4941 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4942 /* BGP may not be running. */
4947 memset(&rmac
, 0, sizeof(struct ethaddr
));
4948 zl3vni_get_rmac(zl3vni
, &rmac
);
4950 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4952 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
4953 stream_putl(s
, zl3vni
->vni
);
4954 stream_put(s
, &rmac
, sizeof(struct ethaddr
));
4955 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
4956 stream_put(s
, &zl3vni
->filter
, sizeof(int));
4957 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
4959 /* Write packet size. */
4960 stream_putw_at(s
, 0, stream_get_endp(s
));
4962 if (IS_ZEBRA_DEBUG_VXLAN
)
4964 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4965 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
4966 prefix_mac2str(&rmac
, buf
, sizeof(buf
)),
4967 inet_ntoa(zl3vni
->local_vtep_ip
),
4968 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
4969 ? "prefix-routes-only"
4971 zebra_route_string(client
->proto
));
4973 client
->l3vniadd_cnt
++;
4974 return zserv_send_message(client
, s
);
4978 * Inform BGP about local l3-VNI deletion.
4980 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
4982 struct stream
*s
= NULL
;
4983 struct zserv
*client
= NULL
;
4985 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4986 /* BGP may not be running. */
4990 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4992 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
4993 stream_putl(s
, zl3vni
->vni
);
4995 /* Write packet size. */
4996 stream_putw_at(s
, 0, stream_get_endp(s
));
4998 if (IS_ZEBRA_DEBUG_VXLAN
)
4999 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5000 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5001 zebra_route_string(client
->proto
));
5003 client
->l3vnidel_cnt
++;
5004 return zserv_send_message(client
, s
);
5007 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5012 /* send l3vni add to BGP */
5013 zl3vni_send_add_to_client(zl3vni
);
5016 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5021 /* send l3-vni del to BGP*/
5022 zl3vni_send_del_to_client(zl3vni
);
5025 static void zvni_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5027 zebra_vni_t
*zvni
= (zebra_vni_t
*)bucket
->data
;
5028 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5030 if (zvni
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5031 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
5035 * handle transition of vni from l2 to l3 and vice versa
5037 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5040 zebra_vni_t
*zvni
= NULL
;
5042 /* There is a possibility that VNI notification was already received
5043 * from kernel and we programmed it as L2-VNI
5044 * In such a case we need to delete this L2-VNI first, so
5045 * that it can be reprogrammed as L3-VNI in the system. It is also
5046 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5047 * interface is still present in kernel. In this case to keep it
5048 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5051 /* Locate hash entry */
5052 zvni
= zvni_lookup(vni
);
5056 if (IS_ZEBRA_DEBUG_VXLAN
)
5057 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5059 /* Delete VNI from BGP. */
5060 zvni_send_del_to_client(zvni
->vni
);
5062 /* Free up all neighbors and MAC, if any. */
5063 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
5064 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
5066 /* Free up all remote VTEPs, if any. */
5067 zvni_vtep_del_all(zvni
, 0);
5069 /* Delete the hash entry. */
5070 if (zvni_del(zvni
)) {
5071 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5072 "Failed to del VNI hash %p, VNI %u", zvni
,
5077 /* TODO_MITESH: This needs to be thought through. We don't have
5078 * enough information at this point to reprogram the vni as
5079 * l2-vni. One way is to store the required info in l3-vni and
5080 * used it solely for this purpose
5087 /* delete and uninstall rmac hash entry */
5088 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5090 zebra_mac_t
*zrmac
= NULL
;
5091 zebra_l3vni_t
*zl3vni
= NULL
;
5093 zrmac
= (zebra_mac_t
*)bucket
->data
;
5094 zl3vni
= (zebra_l3vni_t
*)ctx
;
5095 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5096 zl3vni_rmac_del(zl3vni
, zrmac
);
5099 /* delete and uninstall nh hash entry */
5100 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5102 zebra_neigh_t
*n
= NULL
;
5103 zebra_l3vni_t
*zl3vni
= NULL
;
5105 n
= (zebra_neigh_t
*)bucket
->data
;
5106 zl3vni
= (zebra_l3vni_t
*)ctx
;
5107 zl3vni_nh_uninstall(zl3vni
, n
);
5108 zl3vni_nh_del(zl3vni
, n
);
5111 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5114 struct zserv
*client
= NULL
;
5115 struct stream
*s
= NULL
;
5116 char buf
[PREFIX_STRLEN
];
5118 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5119 /* BGP may not be running. */
5123 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5125 zclient_create_header(s
, cmd
, vrf_id
);
5126 stream_put(s
, p
, sizeof(struct prefix
));
5128 /* Write packet size. */
5129 stream_putw_at(s
, 0, stream_get_endp(s
));
5131 if (IS_ZEBRA_DEBUG_VXLAN
)
5132 zlog_debug("Send ip prefix %s %s on vrf %s",
5133 prefix2str(p
, buf
, sizeof(buf
)),
5134 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5135 vrf_id_to_name(vrf_id
));
5137 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5138 client
->prefixadd_cnt
++;
5140 client
->prefixdel_cnt
++;
5142 return zserv_send_message(client
, s
);
5145 /* re-add remote rmac if needed */
5146 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5147 struct ethaddr
*rmac
)
5149 char buf
[ETHER_ADDR_STRLEN
];
5150 zebra_mac_t
*zrmac
= NULL
;
5152 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5156 if (IS_ZEBRA_DEBUG_VXLAN
)
5157 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5158 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5160 zl3vni_rmac_install(zl3vni
, zrmac
);
5164 /* Process a remote MACIP add from BGP. */
5165 static void process_remote_macip_add(vni_t vni
,
5166 struct ethaddr
*macaddr
,
5168 struct ipaddr
*ipaddr
,
5171 struct in_addr vtep_ip
)
5174 zebra_vtep_t
*zvtep
;
5175 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
5176 zebra_neigh_t
*n
= NULL
;
5177 int update_mac
= 0, update_neigh
= 0;
5178 char buf
[ETHER_ADDR_STRLEN
];
5179 char buf1
[INET6_ADDRSTRLEN
];
5180 struct interface
*ifp
= NULL
;
5181 struct zebra_if
*zif
= NULL
;
5182 struct zebra_vrf
*zvrf
;
5187 bool do_dad
= false;
5188 bool is_dup_detect
= false;
5190 /* Locate VNI hash entry - expected to exist. */
5191 zvni
= zvni_lookup(vni
);
5193 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
5197 ifp
= zvni
->vxlan_if
;
5201 !if_is_operative(ifp
) ||
5203 !zif
->brslave_info
.br_if
) {
5204 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5209 /* The remote VTEP specified should normally exist, but it is
5210 * possible that when peering comes up, peer may advertise MACIP
5211 * routes before advertising type-3 routes.
5213 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
5215 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, VXLAN_FLOOD_DISABLED
);
5218 EC_ZEBRA_VTEP_ADD_FAILED
,
5219 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5224 zvni_vtep_install(zvni
, zvtep
);
5227 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
5228 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
5229 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
5231 mac
= zvni_mac_lookup(zvni
, macaddr
);
5233 /* Ignore if the mac is already present as a gateway mac */
5235 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
5236 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
5237 if (IS_ZEBRA_DEBUG_VXLAN
)
5238 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5240 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5241 ipa_len
? " IP " : "",
5243 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5247 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5251 /* check if the remote MAC is unknown or has a change.
5252 * If so, that needs to be updated first. Note that client could
5253 * install MAC and MACIP separately or just install the latter.
5256 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
5257 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
5258 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
5259 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
5260 || seq
!= mac
->rem_seq
)
5265 mac
= zvni_mac_add(zvni
, macaddr
);
5268 "Failed to add MAC %s VNI %u Remote VTEP %s",
5269 prefix_mac2str(macaddr
, buf
,
5271 vni
, inet_ntoa(vtep_ip
));
5275 /* Is this MAC created for a MACIP? */
5277 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5279 const char *mac_type
;
5281 /* When host moves but changes its (MAC,IP)
5282 * binding, BGP may install a MACIP entry that
5283 * corresponds to "older" location of the host
5284 * in transient situations (because {IP1,M1}
5285 * is a different route from {IP1,M2}). Check
5286 * the sequence number and ignore this update
5289 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
5290 tmp_seq
= mac
->loc_seq
;
5293 tmp_seq
= mac
->rem_seq
;
5294 mac_type
= "remote";
5296 if (seq
< tmp_seq
) {
5297 if (IS_ZEBRA_DEBUG_VXLAN
)
5298 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5300 prefix_mac2str(macaddr
,
5302 ipa_len
? " IP " : "",
5305 buf1
, sizeof(buf1
)) : "",
5312 /* Check MAC's curent state is local (this is the case
5313 * where MAC has moved from L->R) and check previous
5314 * detection started via local learning.
5315 * RFC-7432: A PE/VTEP that detects a MAC mobility
5316 * event via local learning starts an M-second timer.
5318 * VTEP-IP or seq. change alone is not considered
5319 * for dup. detection.
5321 * MAC is already marked duplicate set dad, then
5322 * is_dup_detect will be set to not install the entry.
5324 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
5326 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
5329 /* Remove local MAC from BGP. */
5330 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
5331 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
5333 /* Set "auto" and "remote" forwarding info. */
5334 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
5335 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
5336 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5337 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
5340 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5342 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5345 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5347 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
5349 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
5350 mac
->fwd_info
.r_vtep_ip
,
5351 do_dad
, &is_dup_detect
,
5354 if (!is_dup_detect
) {
5355 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
5356 /* Install the entry. */
5357 zvni_mac_install(zvni
, mac
);
5361 /* Update seq number. */
5364 /* If there is no IP, return after clearing AUTO flag of MAC. */
5366 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5373 /* Check if the remote neighbor itself is unknown or has a
5374 * change. If so, create or update and then install the entry.
5376 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5378 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5379 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
5380 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
5381 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
5382 || seq
!= n
->rem_seq
)
5387 n
= zvni_neigh_add(zvni
, ipaddr
, macaddr
);
5390 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5391 ipaddr2str(ipaddr
, buf1
,
5393 prefix_mac2str(macaddr
, buf
,
5395 vni
, inet_ntoa(vtep_ip
));
5402 /* When host moves but changes its (MAC,IP)
5403 * binding, BGP may install a MACIP entry that
5404 * corresponds to "older" location of the host
5405 * in transient situations (because {IP1,M1}
5406 * is a different route from {IP1,M2}). Check
5407 * the sequence number and ignore this update
5410 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
5411 tmp_seq
= n
->loc_seq
;
5414 tmp_seq
= n
->rem_seq
;
5417 if (seq
< tmp_seq
) {
5418 if (IS_ZEBRA_DEBUG_VXLAN
)
5419 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5421 prefix_mac2str(macaddr
,
5424 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
5429 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
5430 /* MAC change, send a delete for old
5431 * neigh if learnt locally.
5433 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
5434 IS_ZEBRA_NEIGH_ACTIVE(n
))
5435 zvni_neigh_send_del_to_client(
5437 &n
->emac
, 0, n
->state
);
5439 /* update neigh list for macs */
5440 old_mac
= zvni_mac_lookup(zvni
, &n
->emac
);
5442 listnode_delete(old_mac
->neigh_list
, n
);
5443 zvni_deref_ip2mac(zvni
, old_mac
);
5445 listnode_add_sort(mac
->neigh_list
, n
);
5446 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
5448 /* Check Neigh's curent state is local
5449 * (this is the case where neigh/host has moved
5450 * from L->R) and check previous detction
5451 * started via local learning.
5453 * RFC-7432: A PE/VTEP that detects a MAC
5454 * mobilit event via local learning starts
5455 * an M-second timer.
5456 * VTEP-IP or seq. change along is not
5457 * considered for dup. detection.
5459 * Mobilty event scenario-B IP-MAC binding
5462 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
5469 /* Set "remote" forwarding info. */
5470 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
5471 n
->r_vtep_ip
= vtep_ip
;
5472 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5474 /* Set router flag (R-bit) to this Neighbor entry */
5475 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
5476 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5478 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
5480 /* Check old or new MAC detected as duplicate,
5481 * inherit duplicate flag to this neigh.
5483 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
5485 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
5486 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5488 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
5489 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
5492 /* Check duplicate address detection for IP */
5493 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
5498 /* Install the entry. */
5500 zvni_neigh_install(zvni
, n
);
5503 zvni_probe_neigh_on_mac_add(zvni
, mac
);
5505 /* Update seq number. */
5509 /* Process a remote MACIP delete from BGP. */
5510 static void process_remote_macip_del(vni_t vni
,
5511 struct ethaddr
*macaddr
,
5513 struct ipaddr
*ipaddr
,
5514 struct in_addr vtep_ip
)
5517 zebra_mac_t
*mac
= NULL
;
5518 zebra_neigh_t
*n
= NULL
;
5519 struct interface
*ifp
= NULL
;
5520 struct zebra_if
*zif
= NULL
;
5521 struct zebra_ns
*zns
;
5522 struct zebra_l2info_vxlan
*vxl
;
5523 struct zebra_vrf
*zvrf
;
5524 char buf
[ETHER_ADDR_STRLEN
];
5525 char buf1
[INET6_ADDRSTRLEN
];
5527 /* Locate VNI hash entry - expected to exist. */
5528 zvni
= zvni_lookup(vni
);
5530 if (IS_ZEBRA_DEBUG_VXLAN
)
5531 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
5535 ifp
= zvni
->vxlan_if
;
5539 !if_is_operative(ifp
) ||
5541 !zif
->brslave_info
.br_if
) {
5542 if (IS_ZEBRA_DEBUG_VXLAN
)
5543 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5547 zns
= zebra_ns_lookup(NS_DEFAULT
);
5548 vxl
= &zif
->l2info
.vxl
;
5550 /* The remote VTEP specified is normally expected to exist, but
5551 * it is possible that the peer may delete the VTEP before deleting
5552 * any MACs referring to the VTEP, in which case the handler (see
5553 * remote_vtep_del) would have already deleted the MACs.
5555 if (!zvni_vtep_find(zvni
, &vtep_ip
))
5558 mac
= zvni_mac_lookup(zvni
, macaddr
);
5560 n
= zvni_neigh_lookup(zvni
, ipaddr
);
5563 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5564 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5565 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
5569 /* If the remote mac or neighbor doesn't exist there is nothing
5570 * more to do. Otherwise, uninstall the entry and then remove it.
5575 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
5577 /* Ignore the delete if this mac is a gateway mac-ip */
5578 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
5579 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
5581 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5583 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
5584 ipa_len
? " IP " : "",
5586 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
5590 /* Uninstall remote neighbor or MAC. */
5592 if (zvrf
->dad_freeze
&&
5593 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
5594 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
5595 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5596 struct interface
*vlan_if
;
5598 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
5599 zif
->brslave_info
.br_if
);
5600 if (IS_ZEBRA_DEBUG_VXLAN
)
5601 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5602 __PRETTY_FUNCTION__
,
5603 ipaddr2str(ipaddr
, buf1
,
5604 sizeof(buf1
)), n
->flags
,
5606 neigh_read_specific_ip(ipaddr
, vlan_if
);
5609 /* When the MAC changes for an IP, it is possible the
5610 * client may update the new MAC before trying to delete the
5611 * "old" neighbor (as these are two different MACIP routes).
5612 * Do the delete only if the MAC matches.
5614 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
5615 && (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
5616 zvni_neigh_uninstall(zvni
, n
);
5617 zvni_neigh_del(zvni
, n
);
5618 zvni_deref_ip2mac(zvni
, mac
);
5621 /* DAD: when MAC is freeze state as remote learn event,
5622 * remote mac-ip delete event is received will result in freeze
5623 * entry removal, first fetch kernel for the same entry present
5624 * as LOCAL and reachable, avoid deleting this entry instead
5625 * use kerenel local entry to update during unfreeze time.
5627 if (zvrf
->dad_freeze
&&
5628 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
5629 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5630 if (IS_ZEBRA_DEBUG_VXLAN
)
5631 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5632 __PRETTY_FUNCTION__
,
5633 prefix_mac2str(macaddr
, buf
,
5636 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
5637 macaddr
, vxl
->access_vlan
);
5640 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
5641 zvni_process_neigh_on_remote_mac_del(zvni
, mac
);
5643 * the remote sequence number in the auto mac entry
5644 * needs to be reset to 0 as the mac entry may have
5645 * been removed on all VTEPs (including
5646 * the originating one)
5650 /* If all remote neighbors referencing a remote MAC
5651 * go away, we need to uninstall the MAC.
5653 if (remote_neigh_count(mac
) == 0) {
5654 zvni_mac_uninstall(zvni
, mac
);
5655 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
5657 if (list_isempty(mac
->neigh_list
))
5658 zvni_mac_del(zvni
, mac
);
5660 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
5666 /* Public functions */
5668 int is_l3vni_for_prefix_routes_only(vni_t vni
)
5670 zebra_l3vni_t
*zl3vni
= NULL
;
5672 zl3vni
= zl3vni_lookup(vni
);
5676 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
5679 /* handle evpn route in vrf table */
5680 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, struct ethaddr
*rmac
,
5681 struct ipaddr
*vtep_ip
,
5682 struct prefix
*host_prefix
)
5684 zebra_l3vni_t
*zl3vni
= NULL
;
5685 struct ipaddr ipv4_vtep
;
5687 zl3vni
= zl3vni_from_vrf(vrf_id
);
5688 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
5692 * add the next hop neighbor -
5693 * neigh to be installed is the ipv6 nexthop neigh
5695 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
5698 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5699 * address. Rmac is programmed against the ipv4 vtep because we only
5700 * support ipv4 tunnels in the h/w right now
5702 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
5703 ipv4_vtep
.ipa_type
= IPADDR_V4
;
5704 if (vtep_ip
->ipa_type
== IPADDR_V6
)
5705 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
5706 &(ipv4_vtep
.ipaddr_v4
));
5708 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
5709 sizeof(struct in_addr
));
5712 * add the rmac - remote rmac to be installed is against the ipv4
5715 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
5718 /* handle evpn vrf route delete */
5719 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
5720 struct ipaddr
*vtep_ip
,
5721 struct prefix
*host_prefix
)
5723 zebra_l3vni_t
*zl3vni
= NULL
;
5724 zebra_neigh_t
*nh
= NULL
;
5725 zebra_mac_t
*zrmac
= NULL
;
5727 zl3vni
= zl3vni_from_vrf(vrf_id
);
5731 /* find the next hop entry and rmac entry */
5732 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5735 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
5737 /* delete the next hop entry */
5738 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
5740 /* delete the rmac entry */
5742 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
5746 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
5747 struct ethaddr
*rmac
, bool use_json
)
5749 zebra_l3vni_t
*zl3vni
= NULL
;
5750 zebra_mac_t
*zrmac
= NULL
;
5751 json_object
*json
= NULL
;
5753 if (!is_evpn_enabled()) {
5755 vty_out(vty
, "{}\n");
5760 json
= json_object_new_object();
5762 zl3vni
= zl3vni_lookup(l3vni
);
5765 vty_out(vty
, "{}\n");
5767 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
5771 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5774 vty_out(vty
, "{}\n");
5777 "%% Requested RMAC doesn't exist in L3-VNI %u",
5782 zl3vni_print_rmac(zrmac
, vty
, json
);
5785 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5786 json
, JSON_C_TO_STRING_PRETTY
));
5787 json_object_free(json
);
5791 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5793 zebra_l3vni_t
*zl3vni
;
5795 struct rmac_walk_ctx wctx
;
5796 json_object
*json
= NULL
;
5798 if (!is_evpn_enabled())
5801 zl3vni
= zl3vni_lookup(l3vni
);
5804 vty_out(vty
, "{}\n");
5806 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5809 num_rmacs
= hashcount(zl3vni
->rmac_table
);
5814 json
= json_object_new_object();
5816 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
5820 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
5822 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
5824 json_object_int_add(json
, "numRmacs", num_rmacs
);
5826 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
5829 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5830 json
, JSON_C_TO_STRING_PRETTY
));
5831 json_object_free(json
);
5835 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
5837 json_object
*json
= NULL
;
5840 if (!is_evpn_enabled()) {
5842 vty_out(vty
, "{}\n");
5847 json
= json_object_new_object();
5851 hash_iterate(zrouter
.l3vni_table
,
5852 (void (*)(struct hash_bucket
*,
5853 void *))zl3vni_print_rmac_hash_all_vni
,
5857 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5858 json
, JSON_C_TO_STRING_PRETTY
));
5859 json_object_free(json
);
5863 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
5864 struct ipaddr
*ip
, bool use_json
)
5866 zebra_l3vni_t
*zl3vni
= NULL
;
5867 zebra_neigh_t
*n
= NULL
;
5868 json_object
*json
= NULL
;
5870 if (!is_evpn_enabled()) {
5872 vty_out(vty
, "{}\n");
5877 json
= json_object_new_object();
5879 zl3vni
= zl3vni_lookup(l3vni
);
5882 vty_out(vty
, "{}\n");
5884 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5888 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5891 vty_out(vty
, "{}\n");
5894 "%% Requested next-hop not present for L3-VNI %u",
5899 zl3vni_print_nh(n
, vty
, json
);
5902 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5903 json
, JSON_C_TO_STRING_PRETTY
));
5904 json_object_free(json
);
5908 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
5911 struct nh_walk_ctx wctx
;
5912 json_object
*json
= NULL
;
5913 zebra_l3vni_t
*zl3vni
= NULL
;
5915 if (!is_evpn_enabled())
5918 zl3vni
= zl3vni_lookup(l3vni
);
5921 vty_out(vty
, "{}\n");
5923 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
5927 num_nh
= hashcount(zl3vni
->nh_table
);
5932 json
= json_object_new_object();
5937 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
5939 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
5941 json_object_int_add(json
, "numNextHops", num_nh
);
5943 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
5946 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5947 json
, JSON_C_TO_STRING_PRETTY
));
5948 json_object_free(json
);
5952 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
5954 json_object
*json
= NULL
;
5957 if (!is_evpn_enabled()) {
5959 vty_out(vty
, "{}\n");
5964 json
= json_object_new_object();
5968 hash_iterate(zrouter
.l3vni_table
,
5969 (void (*)(struct hash_bucket
*,
5970 void *))zl3vni_print_nh_hash_all_vni
,
5974 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5975 json
, JSON_C_TO_STRING_PRETTY
));
5976 json_object_free(json
);
5981 * Display L3 VNI information (VTY command handler).
5983 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
5986 json_object
*json
= NULL
;
5987 zebra_l3vni_t
*zl3vni
= NULL
;
5989 if (!is_evpn_enabled()) {
5991 vty_out(vty
, "{}\n");
5995 zl3vni
= zl3vni_lookup(vni
);
5998 vty_out(vty
, "{}\n");
6000 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6005 json
= json_object_new_object();
6009 zl3vni_print(zl3vni
, (void *)args
);
6012 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6013 json
, JSON_C_TO_STRING_PRETTY
));
6014 json_object_free(json
);
6018 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6019 json_object
*json_vrfs
)
6021 char buf
[ETHER_ADDR_STRLEN
];
6022 zebra_l3vni_t
*zl3vni
= NULL
;
6024 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
6029 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
6030 zvrf_name(zvrf
), zl3vni
->vni
,
6031 zl3vni_vxlan_if_name(zl3vni
),
6032 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
6033 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6035 json_object
*json_vrf
= NULL
;
6037 json_vrf
= json_object_new_object();
6038 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
6039 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
6040 json_object_string_add(json_vrf
, "vxlanIntf",
6041 zl3vni_vxlan_if_name(zl3vni
));
6042 json_object_string_add(json_vrf
, "sviIntf",
6043 zl3vni_svi_if_name(zl3vni
));
6044 json_object_string_add(json_vrf
, "state",
6045 zl3vni_state2str(zl3vni
));
6046 json_object_string_add(
6047 json_vrf
, "routerMac",
6048 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
6049 json_object_array_add(json_vrfs
, json_vrf
);
6054 * Display Neighbors for a VNI (VTY command handler).
6056 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6057 vni_t vni
, bool use_json
)
6061 struct neigh_walk_ctx wctx
;
6062 json_object
*json
= NULL
;
6064 if (!is_evpn_enabled())
6066 zvni
= zvni_lookup(vni
);
6069 vty_out(vty
, "{}\n");
6071 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6074 num_neigh
= hashcount(zvni
->neigh_table
);
6079 json
= json_object_new_object();
6081 /* Since we have IPv6 addresses to deal with which can vary widely in
6082 * size, we try to be a bit more elegant in display by first computing
6083 * the maximum width.
6085 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6088 wctx
.addr_width
= 15;
6090 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6094 "Number of ARPs (local and remote) known for this VNI: %u\n",
6096 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6097 -wctx
.addr_width
, "IP", "Type",
6098 "State", "MAC", "Remote VTEP");
6100 json_object_int_add(json
, "numArpNd", num_neigh
);
6102 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6104 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6105 json
, JSON_C_TO_STRING_PRETTY
));
6106 json_object_free(json
);
6111 * Display neighbors across all VNIs (VTY command handler).
6113 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6114 bool print_dup
, bool use_json
)
6116 json_object
*json
= NULL
;
6119 if (!is_evpn_enabled())
6123 json
= json_object_new_object();
6127 args
[2] = (void *)(ptrdiff_t)print_dup
;
6129 hash_iterate(zvrf
->vni_table
,
6130 (void (*)(struct hash_bucket
*,
6131 void *))zvni_print_neigh_hash_all_vni
,
6134 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6135 json
, JSON_C_TO_STRING_PRETTY
));
6136 json_object_free(json
);
6141 * Display neighbors across all VNIs in detail(VTY command handler).
6143 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
6144 struct zebra_vrf
*zvrf
,
6145 bool print_dup
, bool use_json
)
6147 json_object
*json
= NULL
;
6150 if (!is_evpn_enabled())
6154 json
= json_object_new_object();
6158 args
[2] = (void *)(ptrdiff_t)print_dup
;
6160 hash_iterate(zvrf
->vni_table
,
6161 (void (*)(struct hash_bucket
*,
6162 void *))zvni_print_neigh_hash_all_vni_detail
,
6165 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6166 json
, JSON_C_TO_STRING_PRETTY
));
6167 json_object_free(json
);
6172 * Display specific neighbor for a VNI, if present (VTY command handler).
6174 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
6175 struct zebra_vrf
*zvrf
, vni_t vni
,
6176 struct ipaddr
*ip
, bool use_json
)
6180 json_object
*json
= NULL
;
6182 if (!is_evpn_enabled())
6184 zvni
= zvni_lookup(vni
);
6187 vty_out(vty
, "{}\n");
6189 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6192 n
= zvni_neigh_lookup(zvni
, ip
);
6196 "%% Requested neighbor does not exist in VNI %u\n",
6201 json
= json_object_new_object();
6203 zvni_print_neigh(n
, vty
, json
);
6206 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6207 json
, JSON_C_TO_STRING_PRETTY
));
6208 json_object_free(json
);
6213 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6214 * By definition, these are remote neighbors.
6216 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6217 vni_t vni
, struct in_addr vtep_ip
,
6222 struct neigh_walk_ctx wctx
;
6223 json_object
*json
= NULL
;
6225 if (!is_evpn_enabled())
6227 zvni
= zvni_lookup(vni
);
6230 vty_out(vty
, "{}\n");
6232 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6235 num_neigh
= hashcount(zvni
->neigh_table
);
6239 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6242 wctx
.addr_width
= 15;
6243 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
6244 wctx
.r_vtep_ip
= vtep_ip
;
6246 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6247 hash_iterate(zvni
->neigh_table
, zvni_print_neigh_hash
, &wctx
);
6250 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6251 json
, JSON_C_TO_STRING_PRETTY
));
6252 json_object_free(json
);
6257 * Display Duplicate detected Neighbors for a VNI
6258 * (VTY command handler).
6260 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
6261 struct zebra_vrf
*zvrf
,
6267 struct neigh_walk_ctx wctx
;
6268 json_object
*json
= NULL
;
6270 if (!is_evpn_enabled())
6273 zvni
= zvni_lookup(vni
);
6275 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6279 num_neigh
= hashcount(zvni
->neigh_table
);
6283 num_neigh
= num_dup_detected_neighs(zvni
);
6288 json
= json_object_new_object();
6290 /* Since we have IPv6 addresses to deal with which can vary widely in
6291 * size, we try to be a bit more elegant in display by first computing
6292 * the maximum width.
6294 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
6297 wctx
.addr_width
= 15;
6299 hash_iterate(zvni
->neigh_table
, zvni_find_neigh_addr_width
, &wctx
);
6303 "Number of ARPs (local and remote) known for this VNI: %u\n",
6305 vty_out(vty
, "%*s %-6s %-8s %-17s %-21s\n",
6306 -wctx
.addr_width
, "IP", "Type",
6307 "State", "MAC", "Remote VTEP");
6309 json_object_int_add(json
, "numArpNd", num_neigh
);
6311 hash_iterate(zvni
->neigh_table
, zvni_print_dad_neigh_hash
, &wctx
);
6314 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6315 json
, JSON_C_TO_STRING_PRETTY
));
6316 json_object_free(json
);
6321 * Display MACs for a VNI (VTY command handler).
6323 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6324 vni_t vni
, bool use_json
)
6328 struct mac_walk_ctx wctx
;
6329 json_object
*json
= NULL
;
6330 json_object
*json_mac
= NULL
;
6332 if (!is_evpn_enabled())
6334 zvni
= zvni_lookup(vni
);
6337 vty_out(vty
, "{}\n");
6339 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6342 num_macs
= num_valid_macs(zvni
);
6347 json
= json_object_new_object();
6348 json_mac
= json_object_new_object();
6351 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6354 wctx
.json
= json_mac
;
6358 "Number of MACs (local and remote) known for this VNI: %u\n",
6360 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6361 "Intf/Remote VTEP", "VLAN");
6363 json_object_int_add(json
, "numMacs", num_macs
);
6365 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6368 json_object_object_add(json
, "macs", json_mac
);
6369 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6370 json
, JSON_C_TO_STRING_PRETTY
));
6371 json_object_free(json
);
6376 * Display MACs for all VNIs (VTY command handler).
6378 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6379 bool print_dup
, bool use_json
)
6381 struct mac_walk_ctx wctx
;
6382 json_object
*json
= NULL
;
6384 if (!is_evpn_enabled()) {
6386 vty_out(vty
, "{}\n");
6390 json
= json_object_new_object();
6392 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6395 wctx
.print_dup
= print_dup
;
6396 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6399 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6400 json
, JSON_C_TO_STRING_PRETTY
));
6401 json_object_free(json
);
6406 * Display MACs in detail for all VNIs (VTY command handler).
6408 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
6409 struct zebra_vrf
*zvrf
,
6410 bool print_dup
, bool use_json
)
6412 struct mac_walk_ctx wctx
;
6413 json_object
*json
= NULL
;
6415 if (!is_evpn_enabled()) {
6417 vty_out(vty
, "{}\n");
6421 json
= json_object_new_object();
6423 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6426 wctx
.print_dup
= print_dup
;
6427 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni_detail
,
6431 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6432 json
, JSON_C_TO_STRING_PRETTY
));
6433 json_object_free(json
);
6438 * Display MACs for all VNIs (VTY command handler).
6440 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
6441 struct zebra_vrf
*zvrf
,
6442 struct in_addr vtep_ip
, bool use_json
)
6444 struct mac_walk_ctx wctx
;
6445 json_object
*json
= NULL
;
6447 if (!is_evpn_enabled())
6451 json
= json_object_new_object();
6453 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6455 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6456 wctx
.r_vtep_ip
= vtep_ip
;
6458 hash_iterate(zvrf
->vni_table
, zvni_print_mac_hash_all_vni
, &wctx
);
6461 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6462 json
, JSON_C_TO_STRING_PRETTY
));
6463 json_object_free(json
);
6468 * Display specific MAC for a VNI, if present (VTY command handler).
6470 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6471 vni_t vni
, struct ethaddr
*macaddr
,
6476 json_object
*json
= NULL
;
6478 if (!is_evpn_enabled())
6481 zvni
= zvni_lookup(vni
);
6484 vty_out(vty
, "{}\n");
6486 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6489 mac
= zvni_mac_lookup(zvni
, macaddr
);
6492 vty_out(vty
, "{}\n");
6495 "%% Requested MAC does not exist in VNI %u\n",
6501 json
= json_object_new_object();
6503 zvni_print_mac(mac
, vty
, json
);
6505 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6506 json
, JSON_C_TO_STRING_PRETTY
));
6507 json_object_free(json
);
6511 /* Print Duplicate MACs per VNI */
6512 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
6513 struct zebra_vrf
*zvrf
,
6514 vni_t vni
, bool use_json
)
6517 struct mac_walk_ctx wctx
;
6519 json_object
*json
= NULL
;
6520 json_object
*json_mac
= NULL
;
6522 if (!is_evpn_enabled())
6525 zvni
= zvni_lookup(vni
);
6527 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6531 num_macs
= num_valid_macs(zvni
);
6535 num_macs
= num_dup_detected_macs(zvni
);
6540 json
= json_object_new_object();
6541 json_mac
= json_object_new_object();
6544 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6547 wctx
.json
= json_mac
;
6551 "Number of MACs (local and remote) known for this VNI: %u\n",
6553 vty_out(vty
, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6554 "Intf/Remote VTEP", "VLAN");
6556 json_object_int_add(json
, "numMacs", num_macs
);
6558 hash_iterate(zvni
->mac_table
, zvni_print_dad_mac_hash
, &wctx
);
6561 json_object_object_add(json
, "macs", json_mac
);
6562 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6563 json
, JSON_C_TO_STRING_PRETTY
));
6564 json_object_free(json
);
6569 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty
*vty
,
6570 struct zebra_vrf
*zvrf
,
6571 vni_t vni
, struct ethaddr
*macaddr
)
6575 struct listnode
*node
= NULL
;
6576 zebra_neigh_t
*nbr
= NULL
;
6578 if (!is_evpn_enabled())
6581 zvni
= zvni_lookup(vni
);
6583 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6587 mac
= zvni_mac_lookup(zvni
, macaddr
);
6589 vty_out(vty
, "%% Requested MAC does not exist in VNI %u\n",
6594 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6595 vty_out(vty
, "%% Requested MAC is not duplicate detected\n");
6599 /* Remove all IPs as duplicate associcated with this MAC */
6600 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6601 /* For local neigh mark inactive so MACIP update is generated
6602 * to BGP. This is a scenario where MAC update received
6603 * and detected as duplicate which marked neigh as duplicate.
6604 * Later local neigh update did not get a chance to relay
6605 * to BGP. Similarly remote macip update, neigh needs to be
6606 * installed locally.
6608 if (zvrf
->dad_freeze
&&
6609 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6610 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
6611 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6612 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
6613 zvni_neigh_install(zvni
, nbr
);
6616 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6618 nbr
->detect_start_time
.tv_sec
= 0;
6619 nbr
->dad_dup_detect_time
= 0;
6622 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6624 mac
->detect_start_time
.tv_sec
= 0;
6625 mac
->detect_start_time
.tv_usec
= 0;
6626 mac
->dad_dup_detect_time
= 0;
6627 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6629 /* warn-only action return */
6630 if (!zvrf
->dad_freeze
)
6633 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6634 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6636 if (zvni_mac_send_add_to_client(zvni
->vni
,
6642 /* Process all neighbors associated with this MAC. */
6643 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6645 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6646 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6648 /* Install the entry. */
6649 zvni_mac_install(zvni
, mac
);
6655 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty
*vty
,
6656 struct zebra_vrf
*zvrf
,
6657 vni_t vni
, struct ipaddr
*ip
)
6662 char buf
[INET6_ADDRSTRLEN
];
6663 char buf2
[ETHER_ADDR_STRLEN
];
6665 if (!is_evpn_enabled())
6668 zvni
= zvni_lookup(vni
);
6670 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6674 nbr
= zvni_neigh_lookup(zvni
, ip
);
6677 "%% Requested host IP does not exist in VNI %u\n",
6682 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6684 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
6686 "%% Requsted host IP %s is not duplicate detected\n",
6691 mac
= zvni_mac_lookup(zvni
, &nbr
->emac
);
6693 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
6695 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6696 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
6697 return CMD_WARNING_CONFIG_FAILED
;
6700 if (IS_ZEBRA_DEBUG_VXLAN
)
6701 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6702 __PRETTY_FUNCTION__
, buf
, nbr
->flags
,
6705 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6707 nbr
->detect_start_time
.tv_sec
= 0;
6708 nbr
->detect_start_time
.tv_usec
= 0;
6709 nbr
->dad_dup_detect_time
= 0;
6710 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6712 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6713 zvni_neigh_send_add_to_client(zvni
->vni
, ip
,
6715 nbr
->flags
, nbr
->loc_seq
);
6716 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6717 zvni_neigh_install(zvni
, nbr
);
6723 static void zvni_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
6725 struct mac_walk_ctx
*wctx
= ctxt
;
6728 struct listnode
*node
= NULL
;
6729 zebra_neigh_t
*nbr
= NULL
;
6731 mac
= (zebra_mac_t
*)bucket
->data
;
6737 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
6740 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
6742 mac
->detect_start_time
.tv_sec
= 0;
6743 mac
->detect_start_time
.tv_usec
= 0;
6744 mac
->dad_dup_detect_time
= 0;
6745 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
6747 /* Remove all IPs as duplicate associcated with this MAC */
6748 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
6749 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
6751 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
6753 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6755 nbr
->detect_start_time
.tv_sec
= 0;
6756 nbr
->dad_dup_detect_time
= 0;
6759 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6760 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
6762 if (zvni_mac_send_add_to_client(zvni
->vni
,
6764 mac
->flags
, mac
->loc_seq
))
6767 /* Process all neighbors associated with this MAC. */
6768 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
6770 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
6771 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
6773 /* Install the entry. */
6774 zvni_mac_install(zvni
, mac
);
6778 static void zvni_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
6780 struct neigh_walk_ctx
*wctx
= ctxt
;
6783 char buf
[INET6_ADDRSTRLEN
];
6785 nbr
= (zebra_neigh_t
*)bucket
->data
;
6791 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
6794 if (IS_ZEBRA_DEBUG_VXLAN
) {
6795 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
6797 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6798 __PRETTY_FUNCTION__
, buf
,
6799 nbr
->flags
, nbr
->loc_seq
);
6802 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
6804 nbr
->detect_start_time
.tv_sec
= 0;
6805 nbr
->detect_start_time
.tv_usec
= 0;
6806 nbr
->dad_dup_detect_time
= 0;
6807 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
6809 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
6810 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
,
6812 nbr
->flags
, nbr
->loc_seq
);
6813 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
6814 zvni_neigh_install(zvni
, nbr
);
6818 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
6823 struct zebra_vrf
*zvrf
;
6824 struct mac_walk_ctx m_wctx
;
6825 struct neigh_walk_ctx n_wctx
;
6827 zvni
= (zebra_vni_t
*)bucket
->data
;
6831 vty
= (struct vty
*)args
[0];
6832 zvrf
= (struct zebra_vrf
*)args
[1];
6834 if (hashcount(zvni
->neigh_table
)) {
6835 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6839 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6843 if (num_valid_macs(zvni
)) {
6844 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6848 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6853 int zebra_vxlan_clear_dup_detect_vni_all(struct vty
*vty
,
6854 struct zebra_vrf
*zvrf
)
6858 if (!is_evpn_enabled())
6864 hash_iterate(zvrf
->vni_table
,
6865 (void (*)(struct hash_bucket
*, void *))
6866 zvni_clear_dup_detect_hash_vni_all
, args
);
6871 int zebra_vxlan_clear_dup_detect_vni(struct vty
*vty
,
6872 struct zebra_vrf
*zvrf
,
6876 struct mac_walk_ctx m_wctx
;
6877 struct neigh_walk_ctx n_wctx
;
6879 if (!is_evpn_enabled())
6882 zvni
= zvni_lookup(vni
);
6884 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6888 if (hashcount(zvni
->neigh_table
)) {
6889 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
6893 hash_iterate(zvni
->neigh_table
, zvni_clear_dup_neigh_hash
,
6897 if (num_valid_macs(zvni
)) {
6898 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
6902 hash_iterate(zvni
->mac_table
, zvni_clear_dup_mac_hash
, &m_wctx
);
6909 * Display MACs for a VNI from specific VTEP (VTY command handler).
6911 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
6912 vni_t vni
, struct in_addr vtep_ip
,
6917 struct mac_walk_ctx wctx
;
6918 json_object
*json
= NULL
;
6919 json_object
*json_mac
= NULL
;
6921 if (!is_evpn_enabled())
6923 zvni
= zvni_lookup(vni
);
6926 vty_out(vty
, "{}\n");
6928 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6931 num_macs
= num_valid_macs(zvni
);
6936 json
= json_object_new_object();
6937 json_mac
= json_object_new_object();
6940 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
6943 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
6944 wctx
.r_vtep_ip
= vtep_ip
;
6945 wctx
.json
= json_mac
;
6946 hash_iterate(zvni
->mac_table
, zvni_print_mac_hash
, &wctx
);
6949 json_object_int_add(json
, "numMacs", wctx
.count
);
6951 json_object_object_add(json
, "macs", json_mac
);
6952 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6953 json
, JSON_C_TO_STRING_PRETTY
));
6954 json_object_free(json
);
6960 * Display VNI information (VTY command handler).
6962 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
6965 json_object
*json
= NULL
;
6967 zebra_l3vni_t
*zl3vni
= NULL
;
6968 zebra_vni_t
*zvni
= NULL
;
6970 if (!is_evpn_enabled())
6974 json
= json_object_new_object();
6978 zl3vni
= zl3vni_lookup(vni
);
6980 zl3vni_print(zl3vni
, (void *)args
);
6982 zvni
= zvni_lookup(vni
);
6985 vty_out(vty
, "{}\n");
6987 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
6991 zvni_print(zvni
, (void *)args
);
6995 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
6996 json
, JSON_C_TO_STRING_PRETTY
));
6997 json_object_free(json
);
7001 /* Display all global details for EVPN */
7002 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
7007 json_object
*json
= NULL
;
7008 struct zebra_vrf
*zvrf
= NULL
;
7010 if (!is_evpn_enabled())
7013 zvrf
= zebra_vrf_get_evpn();
7017 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
7018 num_l2vnis
= hashcount(zvrf
->vni_table
);
7019 num_vnis
= num_l2vnis
+ num_l3vnis
;
7022 json
= json_object_new_object();
7023 json_object_string_add(json
, "advertiseGatewayMacip",
7024 zvrf
->advertise_gw_macip
? "Yes" : "No");
7025 json_object_int_add(json
, "numVnis", num_vnis
);
7026 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
7027 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
7028 if (zvrf
->dup_addr_detect
)
7029 json_object_boolean_true_add(json
,
7030 "isDuplicateAddrDetection");
7032 json_object_boolean_false_add(json
,
7033 "isDuplicateAddrDetection");
7034 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
7035 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
7036 json_object_int_add(json
, "detectionFreezeTime",
7037 zvrf
->dad_freeze_time
);
7040 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
7041 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
7042 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
7043 zvrf
->advertise_gw_macip
? "Yes" : "No");
7044 vty_out(vty
, "Advertise svi mac-ip: %s\n",
7045 zvrf
->advertise_svi_macip
? "Yes" : "No");
7046 vty_out(vty
, "Duplicate address detection: %s\n",
7047 zvrf
->dup_addr_detect
? "Enable" : "Disable");
7048 vty_out(vty
, " Detection max-moves %u, time %d\n",
7049 zvrf
->dad_max_moves
, zvrf
->dad_time
);
7050 if (zvrf
->dad_freeze
) {
7051 if (zvrf
->dad_freeze_time
)
7052 vty_out(vty
, " Detection freeze %u\n",
7053 zvrf
->dad_freeze_time
);
7055 vty_out(vty
, " Detection freeze %s\n",
7061 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7062 json
, JSON_C_TO_STRING_PRETTY
));
7063 json_object_free(json
);
7068 * Display VNI hash table (VTY command handler).
7070 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7073 json_object
*json
= NULL
;
7076 if (!is_evpn_enabled())
7080 json
= json_object_new_object();
7082 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7083 "Type", "VxLAN IF", "# MACs", "# ARPs",
7084 "# Remote VTEPs", "Tenant VRF");
7089 /* Display all L2-VNIs */
7090 hash_iterate(zvrf
->vni_table
,
7091 (void (*)(struct hash_bucket
*, void *))zvni_print_hash
,
7094 /* Display all L3-VNIs */
7095 hash_iterate(zrouter
.l3vni_table
,
7096 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
7100 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7101 json
, JSON_C_TO_STRING_PRETTY
));
7102 json_object_free(json
);
7106 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
7110 uint32_t max_moves
= 0;
7111 uint32_t freeze_time
= 0;
7112 bool dup_addr_detect
= false;
7113 bool freeze
= false;
7116 STREAM_GETL(s
, dup_addr_detect
);
7117 STREAM_GETL(s
, time
);
7118 STREAM_GETL(s
, max_moves
);
7119 STREAM_GETL(s
, freeze
);
7120 STREAM_GETL(s
, freeze_time
);
7122 /* DAD previous state was enabled, and new state is disable,
7123 * clear all duplicate detected addresses.
7125 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
7126 zebra_vxlan_clear_dup_detect_vni_all(NULL
, zvrf
);
7128 zvrf
->dup_addr_detect
= dup_addr_detect
;
7129 zvrf
->dad_time
= time
;
7130 zvrf
->dad_max_moves
= max_moves
;
7131 zvrf
->dad_freeze
= freeze
;
7132 zvrf
->dad_freeze_time
= freeze_time
;
7134 if (IS_ZEBRA_DEBUG_VXLAN
)
7136 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7137 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
7138 zvrf
->dup_addr_detect
? "enable" : "disable",
7139 zvrf
->dad_max_moves
,
7141 zvrf
->dad_freeze
? "enable" : "disable",
7142 zvrf
->dad_freeze_time
);
7149 * Display VNI hash table in detail(VTY command handler).
7151 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7154 json_object
*json
= NULL
;
7155 struct zebra_ns
*zns
= NULL
;
7156 struct zvni_evpn_show zes
;
7158 if (!is_evpn_enabled())
7161 zns
= zebra_ns_lookup(NS_DEFAULT
);
7167 json
= json_object_new_object();
7173 /* Display all L2-VNIs */
7176 (void (*)(struct hash_bucket
*, void *))zvni_print_hash_detail
,
7179 /* Display all L3-VNIs */
7180 hash_iterate(zrouter
.l3vni_table
,
7181 (void (*)(struct hash_bucket
*,
7182 void *))zl3vni_print_hash_detail
,
7186 vty_out(vty
, "%s\n",
7187 json_object_to_json_string_ext(
7188 json
, JSON_C_TO_STRING_PRETTY
));
7189 json_object_free(json
);
7194 * Handle neighbor delete notification from the kernel (on a VLAN device
7195 * / L3 interface). This may result in either the neighbor getting deleted
7196 * from our database or being re-added to the kernel (if it is a valid
7199 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
7200 struct interface
*link_if
,
7203 char buf
[INET6_ADDRSTRLEN
];
7204 char buf2
[ETHER_ADDR_STRLEN
];
7205 zebra_neigh_t
*n
= NULL
;
7206 zebra_vni_t
*zvni
= NULL
;
7207 zebra_mac_t
*zmac
= NULL
;
7208 zebra_l3vni_t
*zl3vni
= NULL
;
7209 struct zebra_vrf
*zvrf
;
7211 /* check if this is a remote neigh entry corresponding to remote
7214 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7216 return zl3vni_local_nh_del(zl3vni
, ip
);
7218 /* We are only interested in neighbors on an SVI that resides on top
7219 * of a VxLAN bridge.
7221 zvni
= zvni_from_svi(ifp
, link_if
);
7225 if (!zvni
->vxlan_if
) {
7227 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7232 if (IS_ZEBRA_DEBUG_VXLAN
)
7233 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7234 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
7235 ifp
->ifindex
, zvni
->vni
);
7237 /* If entry doesn't exist, nothing to do. */
7238 n
= zvni_neigh_lookup(zvni
, ip
);
7242 zmac
= zvni_mac_lookup(zvni
, &n
->emac
);
7244 if (IS_ZEBRA_DEBUG_VXLAN
)
7246 "Trying to del a neigh %s without a mac %s on VNI %u",
7247 ipaddr2str(ip
, buf
, sizeof(buf
)),
7248 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
7254 /* If it is a remote entry, the kernel has aged this out or someone has
7255 * deleted it, it needs to be re-installed as Quagga is the owner.
7257 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7258 zvni_neigh_install(zvni
, n
);
7262 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7264 zlog_debug("%s: VNI %u vrf lookup failed.",
7265 __PRETTY_FUNCTION__
, zvni
->vni
);
7269 /* In case of feeze action, if local neigh is in duplicate state,
7270 * Mark the Neigh as inactive before sending delete request to BGPd,
7271 * If BGPd has remote entry, it will re-install
7273 if (zvrf
->dad_freeze
&&
7274 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
7275 ZEBRA_NEIGH_SET_INACTIVE(n
);
7277 /* Remove neighbor from BGP. */
7278 zvni_neigh_send_del_to_client(zvni
->vni
, &n
->ip
, &n
->emac
, 0, n
->state
);
7280 /* Delete this neighbor entry. */
7281 zvni_neigh_del(zvni
, n
);
7283 /* see if the AUTO mac needs to be deleted */
7284 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
7285 && !listcount(zmac
->neigh_list
))
7286 zvni_mac_del(zvni
, zmac
);
7292 * Handle neighbor add or update notification from the kernel (on a VLAN
7293 * device / L3 interface). This is typically for a local neighbor but can
7294 * also be for a remote neighbor (e.g., ageout notification). It could
7295 * also be a "move" scenario.
7297 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
7298 struct interface
*link_if
,
7300 struct ethaddr
*macaddr
,
7305 char buf
[ETHER_ADDR_STRLEN
];
7306 char buf2
[INET6_ADDRSTRLEN
];
7307 zebra_vni_t
*zvni
= NULL
;
7308 zebra_l3vni_t
*zl3vni
= NULL
;
7310 /* check if this is a remote neigh entry corresponding to remote
7313 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
7315 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
7317 /* We are only interested in neighbors on an SVI that resides on top
7318 * of a VxLAN bridge.
7320 zvni
= zvni_from_svi(ifp
, link_if
);
7324 if (IS_ZEBRA_DEBUG_VXLAN
)
7326 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7327 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
7328 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7329 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
7330 is_router
? "router " : "",
7333 /* Is this about a local neighbor or a remote one? */
7335 return zvni_local_neigh_update(zvni
, ifp
, ip
, macaddr
,
7338 return zvni_remote_neigh_update(zvni
, ifp
, ip
, macaddr
, state
);
7343 * Handle message from client to delete a remote MACIP for a VNI.
7345 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
7349 struct ethaddr macaddr
;
7351 struct in_addr vtep_ip
;
7352 uint16_t l
= 0, ipa_len
;
7353 char buf
[ETHER_ADDR_STRLEN
];
7354 char buf1
[INET6_ADDRSTRLEN
];
7356 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7357 memset(&ip
, 0, sizeof(struct ipaddr
));
7358 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7362 while (l
< hdr
->length
) {
7363 /* Obtain each remote MACIP and process. */
7364 /* Message contains VNI, followed by MAC followed by IP (if any)
7365 * followed by remote VTEP IP.
7367 memset(&ip
, 0, sizeof(ip
));
7368 STREAM_GETL(s
, vni
);
7369 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7370 STREAM_GETL(s
, ipa_len
);
7372 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7374 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7376 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7377 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7378 l
+= IPV4_MAX_BYTELEN
;
7380 if (IS_ZEBRA_DEBUG_VXLAN
)
7382 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7384 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7385 ipa_len
? " IP " : "",
7387 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7389 zebra_route_string(client
->proto
));
7391 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
7399 * Handle message from client to add a remote MACIP for a VNI. This
7400 * could be just the add of a MAC address or the add of a neighbor
7403 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
7407 struct ethaddr macaddr
;
7409 struct in_addr vtep_ip
;
7410 uint16_t l
= 0, ipa_len
;
7413 char buf
[ETHER_ADDR_STRLEN
];
7414 char buf1
[INET6_ADDRSTRLEN
];
7416 memset(&macaddr
, 0, sizeof(struct ethaddr
));
7417 memset(&ip
, 0, sizeof(struct ipaddr
));
7418 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
7420 if (!EVPN_ENABLED(zvrf
)) {
7421 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7427 while (l
< hdr
->length
) {
7428 /* Obtain each remote MACIP and process. */
7429 /* Message contains VNI, followed by MAC followed by IP (if any)
7430 * followed by remote VTEP IP.
7432 memset(&ip
, 0, sizeof(ip
));
7433 STREAM_GETL(s
, vni
);
7434 STREAM_GET(&macaddr
.octet
, s
, ETH_ALEN
);
7435 STREAM_GETL(s
, ipa_len
);
7437 ip
.ipa_type
= (ipa_len
== IPV4_MAX_BYTELEN
) ? IPADDR_V4
7439 STREAM_GET(&ip
.ip
.addr
, s
, ipa_len
);
7441 l
+= 4 + ETH_ALEN
+ 4 + ipa_len
;
7442 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7443 l
+= IPV4_MAX_BYTELEN
;
7445 /* Get flags - sticky mac and/or gateway mac */
7446 STREAM_GETC(s
, flags
);
7448 STREAM_GETL(s
, seq
);
7451 if (IS_ZEBRA_DEBUG_VXLAN
)
7453 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7455 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
7456 ipa_len
? " IP " : "",
7458 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
7459 flags
, seq
, inet_ntoa(vtep_ip
),
7460 zebra_route_string(client
->proto
));
7462 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
7463 flags
, seq
, vtep_ip
);
7471 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7472 * us, this must involve a multihoming scenario. Treat this as implicit delete
7473 * of any prior local MAC.
7475 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
7476 struct interface
*br_if
,
7477 struct ethaddr
*macaddr
, vlanid_t vid
)
7479 struct zebra_if
*zif
;
7480 struct zebra_l2info_vxlan
*vxl
;
7484 char buf
[ETHER_ADDR_STRLEN
];
7488 vxl
= &zif
->l2info
.vxl
;
7491 /* Check if EVPN is enabled. */
7492 if (!is_evpn_enabled())
7495 /* Locate hash entry; it is expected to exist. */
7496 zvni
= zvni_lookup(vni
);
7500 /* If entry doesn't exist, nothing to do. */
7501 mac
= zvni_mac_lookup(zvni
, macaddr
);
7505 /* Is it a local entry? */
7506 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7509 if (IS_ZEBRA_DEBUG_VXLAN
)
7511 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
7512 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7513 ifp
->ifindex
, vni
, mac
->flags
);
7515 /* Remove MAC from BGP. */
7516 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7519 * If there are no neigh associated with the mac delete the mac
7520 * else mark it as AUTO for forward reference
7522 if (!listcount(mac
->neigh_list
)) {
7523 zvni_mac_del(zvni
, mac
);
7525 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7526 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7527 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7534 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7535 * This can happen because the remote MAC entries are also added as "dynamic",
7536 * so the kernel can ageout the entry.
7538 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
7539 struct interface
*br_if
,
7540 struct ethaddr
*macaddr
, vlanid_t vid
)
7542 struct zebra_if
*zif
= NULL
;
7543 struct zebra_l2info_vxlan
*vxl
= NULL
;
7545 zebra_vni_t
*zvni
= NULL
;
7546 zebra_l3vni_t
*zl3vni
= NULL
;
7547 zebra_mac_t
*mac
= NULL
;
7548 char buf
[ETHER_ADDR_STRLEN
];
7552 vxl
= &zif
->l2info
.vxl
;
7555 /* Check if EVPN is enabled. */
7556 if (!is_evpn_enabled())
7559 /* check if this is a remote RMAC and readd simillar to remote macs */
7560 zl3vni
= zl3vni_lookup(vni
);
7562 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
7564 /* Locate hash entry; it is expected to exist. */
7565 zvni
= zvni_lookup(vni
);
7569 /* If entry doesn't exist, nothing to do. */
7570 mac
= zvni_mac_lookup(zvni
, macaddr
);
7574 /* Is it a remote entry? */
7575 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
7578 if (IS_ZEBRA_DEBUG_VXLAN
)
7579 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7580 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7583 zvni_mac_install(zvni
, mac
);
7588 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7590 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
7591 struct ethaddr
*macaddr
, vlanid_t vid
)
7595 char buf
[ETHER_ADDR_STRLEN
];
7597 /* We are interested in MACs only on ports or (port, VLAN) that
7600 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7603 if (!zvni
->vxlan_if
) {
7605 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7610 /* If entry doesn't exist, nothing to do. */
7611 mac
= zvni_mac_lookup(zvni
, macaddr
);
7615 /* Is it a local entry? */
7616 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7619 if (IS_ZEBRA_DEBUG_VXLAN
)
7620 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
7621 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
7622 ifp
->ifindex
, vid
, zvni
->vni
, mac
->flags
);
7624 /* Update all the neigh entries associated with this mac */
7625 zvni_process_neigh_on_local_mac_del(zvni
, mac
);
7627 /* Remove MAC from BGP. */
7628 zvni_mac_send_del_to_client(zvni
->vni
, macaddr
);
7631 * If there are no neigh associated with the mac delete the mac
7632 * else mark it as AUTO for forward reference
7634 if (!listcount(mac
->neigh_list
)) {
7635 zvni_mac_del(zvni
, mac
);
7637 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7638 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7639 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7646 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7648 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
7649 struct interface
*br_if
,
7650 struct ethaddr
*macaddr
, vlanid_t vid
,
7655 struct zebra_vrf
*zvrf
;
7656 char buf
[ETHER_ADDR_STRLEN
];
7657 bool mac_sticky
= false;
7658 bool inform_client
= false;
7659 bool upd_neigh
= false;
7660 bool is_dup_detect
= false;
7661 struct in_addr vtep_ip
= {.s_addr
= 0};
7663 /* We are interested in MACs only on ports or (port, VLAN) that
7666 zvni
= zvni_map_vlan(ifp
, br_if
, vid
);
7668 if (IS_ZEBRA_DEBUG_VXLAN
)
7670 "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7671 sticky
? "sticky " : "",
7672 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7673 ifp
->name
, ifp
->ifindex
, vid
);
7677 if (!zvni
->vxlan_if
) {
7678 if (IS_ZEBRA_DEBUG_VXLAN
)
7680 "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
7685 zvrf
= vrf_info_lookup(zvni
->vxlan_if
->vrf_id
);
7687 if (IS_ZEBRA_DEBUG_VXLAN
)
7688 zlog_debug("\tNo Vrf found for vrf_id: %d",
7689 zvni
->vxlan_if
->vrf_id
);
7693 /* Check if we need to create or update or it is a NO-OP. */
7694 mac
= zvni_mac_lookup(zvni
, macaddr
);
7696 if (IS_ZEBRA_DEBUG_VXLAN
)
7698 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7699 sticky
? "sticky " : "",
7700 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7701 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7703 mac
= zvni_mac_add(zvni
, macaddr
);
7706 EC_ZEBRA_MAC_ADD_FAILED
,
7707 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7708 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7709 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
);
7712 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7713 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7714 mac
->fwd_info
.local
.vid
= vid
;
7716 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7717 inform_client
= true;
7720 if (IS_ZEBRA_DEBUG_VXLAN
)
7722 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7723 sticky
? "sticky " : "",
7724 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7725 ifp
->name
, ifp
->ifindex
, vid
, zvni
->vni
,
7728 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7729 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
7733 * Update any changes and if changes are relevant to
7736 if (mac_sticky
== sticky
7737 && mac
->fwd_info
.local
.ifindex
== ifp
->ifindex
7738 && mac
->fwd_info
.local
.vid
== vid
) {
7739 if (IS_ZEBRA_DEBUG_VXLAN
)
7741 "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7742 "entry exists and has not changed ",
7743 sticky
? "sticky " : "",
7744 prefix_mac2str(macaddr
, buf
,
7746 ifp
->name
, ifp
->ifindex
, vid
,
7750 if (mac_sticky
!= sticky
) {
7752 SET_FLAG(mac
->flags
,
7755 UNSET_FLAG(mac
->flags
,
7757 inform_client
= true;
7760 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7761 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7762 mac
->fwd_info
.local
.vid
= vid
;
7764 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
7765 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
7766 bool do_dad
= false;
7769 * MAC has either moved or was "internally" created due
7770 * to a neighbor learn and is now actually learnt. If
7771 * it was learnt as a remote sticky MAC, this is an
7774 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
7776 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
7777 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7778 prefix_mac2str(macaddr
, buf
,
7780 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
7785 /* If an actual move, compute MAC's seq number */
7786 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7787 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
7789 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
7790 /* Trigger DAD for remote MAC */
7794 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7795 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7796 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
7797 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7798 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
7799 mac
->fwd_info
.local
.vid
= vid
;
7801 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7803 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7805 * We have to inform BGP of this MAC as well as process
7808 inform_client
= true;
7811 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
7815 if (is_dup_detect
) {
7816 inform_client
= false;
7822 /* Inform BGP if required. */
7823 if (inform_client
) {
7824 if (zvni_mac_send_add_to_client(zvni
->vni
, macaddr
,
7825 mac
->flags
, mac
->loc_seq
))
7829 /* Process all neighbors associated with this MAC, if required. */
7831 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
7837 * Handle message from client to delete a remote VTEP for a VNI.
7839 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
7842 unsigned short l
= 0;
7844 struct in_addr vtep_ip
;
7846 zebra_vtep_t
*zvtep
;
7847 struct interface
*ifp
;
7848 struct zebra_if
*zif
;
7850 if (!is_evpn_enabled()) {
7852 "%s: EVPN is not enabled yet we have received a vtep del command",
7853 __PRETTY_FUNCTION__
);
7857 if (!EVPN_ENABLED(zvrf
)) {
7858 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
7865 while (l
< hdr
->length
) {
7866 int flood_control
__attribute__((unused
));
7868 /* Obtain each remote VTEP and process. */
7869 STREAM_GETL(s
, vni
);
7871 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7872 l
+= IPV4_MAX_BYTELEN
;
7874 /* Flood control is intentionally ignored right now */
7875 STREAM_GETL(s
, flood_control
);
7878 if (IS_ZEBRA_DEBUG_VXLAN
)
7879 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7880 inet_ntoa(vtep_ip
), vni
,
7881 zebra_route_string(client
->proto
));
7883 /* Locate VNI hash entry - expected to exist. */
7884 zvni
= zvni_lookup(vni
);
7886 if (IS_ZEBRA_DEBUG_VXLAN
)
7888 "Failed to locate VNI hash upon remote VTEP DEL, "
7894 ifp
= zvni
->vxlan_if
;
7897 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7903 /* If down or not mapped to a bridge, we're done. */
7904 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7907 /* If the remote VTEP does not exist, there's nothing more to
7909 * Otherwise, uninstall any remote MACs pointing to this VTEP
7911 * then, the VTEP entry itself and remove it.
7913 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7917 zvni_neigh_del_from_vtep(zvni
, 1, &vtep_ip
);
7918 zvni_mac_del_from_vtep(zvni
, 1, &vtep_ip
);
7919 zvni_vtep_uninstall(zvni
, &vtep_ip
);
7920 zvni_vtep_del(zvni
, zvtep
);
7928 * Handle message from client to add a remote VTEP for a VNI.
7930 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
7933 unsigned short l
= 0;
7935 struct in_addr vtep_ip
;
7937 struct interface
*ifp
;
7938 struct zebra_if
*zif
;
7940 zebra_vtep_t
*zvtep
;
7942 if (!is_evpn_enabled()) {
7944 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7945 __PRETTY_FUNCTION__
);
7949 if (!EVPN_ENABLED(zvrf
)) {
7950 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
7957 while (l
< hdr
->length
) {
7958 /* Obtain each remote VTEP and process. */
7959 STREAM_GETL(s
, vni
);
7961 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
7962 STREAM_GETL(s
, flood_control
);
7963 l
+= IPV4_MAX_BYTELEN
+ 4;
7965 if (IS_ZEBRA_DEBUG_VXLAN
)
7966 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
7967 inet_ntoa(vtep_ip
), vni
, flood_control
,
7968 zebra_route_string(client
->proto
));
7970 /* Locate VNI hash entry - expected to exist. */
7971 zvni
= zvni_lookup(vni
);
7974 EC_ZEBRA_VTEP_ADD_FAILED
,
7975 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7980 ifp
= zvni
->vxlan_if
;
7983 EC_ZEBRA_VTEP_ADD_FAILED
,
7984 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7991 /* If down or not mapped to a bridge, we're done. */
7992 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
7995 zvtep
= zvni_vtep_find(zvni
, &vtep_ip
);
7997 /* If the remote VTEP already exists check if
7998 * the flood mode has changed
8000 if (zvtep
->flood_control
!= flood_control
) {
8001 if (zvtep
->flood_control
8002 == VXLAN_FLOOD_DISABLED
)
8003 /* old mode was head-end-replication but
8004 * is no longer; get rid of the HER fdb
8005 * entry installed before
8007 zvni_vtep_uninstall(zvni
, &vtep_ip
);
8008 zvtep
->flood_control
= flood_control
;
8009 zvni_vtep_install(zvni
, zvtep
);
8012 zvtep
= zvni_vtep_add(zvni
, &vtep_ip
, flood_control
);
8014 zvni_vtep_install(zvni
, zvtep
);
8016 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
8017 "Failed to add remote VTEP, VNI %u zvni %p",
8027 * Add/Del gateway macip to evpn
8029 * 1. SVI interface on a vlan aware bridge
8030 * 2. SVI interface on a vlan unaware bridge
8031 * 3. vrr interface (MACVLAN) associated to a SVI
8032 * We advertise macip routes for an interface if it is associated to VxLan vlan
8034 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
8038 struct ethaddr macaddr
;
8039 zebra_vni_t
*zvni
= NULL
;
8041 memset(&ip
, 0, sizeof(struct ipaddr
));
8042 memset(&macaddr
, 0, sizeof(struct ethaddr
));
8044 /* Check if EVPN is enabled. */
8045 if (!is_evpn_enabled())
8048 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
8049 struct interface
*svi_if
=
8050 NULL
; /* SVI corresponding to the MACVLAN */
8051 struct zebra_if
*ifp_zif
=
8052 NULL
; /* Zebra daemon specific info for MACVLAN */
8053 struct zebra_if
*svi_if_zif
=
8054 NULL
; /* Zebra daemon specific info for SVI*/
8056 ifp_zif
= ifp
->info
;
8061 * for a MACVLAN interface the link represents the svi_if
8063 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
8064 ifp_zif
->link_ifindex
);
8066 zlog_debug("MACVLAN %s(%u) without link information",
8067 ifp
->name
, ifp
->ifindex
);
8071 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
8073 * If it is a vlan aware bridge then the link gives the
8074 * bridge information
8076 struct interface
*svi_if_link
= NULL
;
8078 svi_if_zif
= svi_if
->info
;
8080 svi_if_link
= if_lookup_by_index_per_ns(
8081 zebra_ns_lookup(NS_DEFAULT
),
8082 svi_if_zif
->link_ifindex
);
8083 zvni
= zvni_from_svi(svi_if
, svi_if_link
);
8085 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
8087 * If it is a vlan unaware bridge then svi is the bridge
8090 zvni
= zvni_from_svi(svi_if
, svi_if
);
8092 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
8093 struct zebra_if
*svi_if_zif
=
8094 NULL
; /* Zebra daemon specific info for SVI */
8095 struct interface
*svi_if_link
=
8096 NULL
; /* link info for the SVI = bridge info */
8098 svi_if_zif
= ifp
->info
;
8100 svi_if_link
= if_lookup_by_index_per_ns(
8101 zebra_ns_lookup(NS_DEFAULT
),
8102 svi_if_zif
->link_ifindex
);
8104 zvni
= zvni_from_svi(ifp
, svi_if_link
);
8106 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
8107 zvni
= zvni_from_svi(ifp
, ifp
);
8113 if (!zvni
->vxlan_if
) {
8114 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8120 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
8122 if (p
->family
== AF_INET
) {
8123 ip
.ipa_type
= IPADDR_V4
;
8124 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
8125 sizeof(struct in_addr
));
8126 } else if (p
->family
== AF_INET6
) {
8127 ip
.ipa_type
= IPADDR_V6
;
8128 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
8129 sizeof(struct in6_addr
));
8134 zvni_gw_macip_add(ifp
, zvni
, &macaddr
, &ip
);
8136 zvni_gw_macip_del(ifp
, zvni
, &ip
);
8142 * Handle SVI interface going down.
8143 * SVI can be associated to either L3-VNI or L2-VNI.
8144 * For L2-VNI: At this point, this is a NOP since
8145 * the kernel deletes the neighbor entries on this SVI (if any).
8146 * We only need to update the vrf corresponding to zvni.
8147 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8150 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
8152 zebra_l3vni_t
*zl3vni
= NULL
;
8154 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8157 /* process l3-vni down */
8158 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8160 /* remove association with svi-if */
8161 zl3vni
->svi_if
= NULL
;
8163 zebra_vni_t
*zvni
= NULL
;
8165 /* since we dont have svi corresponding to zvni, we associate it
8166 * to default vrf. Note: the corresponding neigh entries on the
8167 * SVI would have already been deleted */
8168 zvni
= zvni_from_svi(ifp
, link_if
);
8170 zvni
->vrf_id
= VRF_DEFAULT
;
8172 /* update the tenant vrf in BGP */
8173 zvni_send_add_to_client(zvni
);
8180 * Handle SVI interface coming up.
8181 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8183 * For L2-VNI: we need to install any remote neighbors entried (used for
8185 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8187 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
8189 zebra_vni_t
*zvni
= NULL
;
8190 zebra_l3vni_t
*zl3vni
= NULL
;
8192 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
8195 /* associate with svi */
8196 zl3vni
->svi_if
= ifp
;
8198 /* process oper-up */
8199 if (is_l3vni_oper_up(zl3vni
))
8200 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8203 /* process SVI up for l2-vni */
8204 struct neigh_walk_ctx n_wctx
;
8206 zvni
= zvni_from_svi(ifp
, link_if
);
8210 if (!zvni
->vxlan_if
) {
8212 "VNI %u hash %p doesn't have intf upon SVI up",
8217 if (IS_ZEBRA_DEBUG_VXLAN
)
8219 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8220 ifp
->name
, ifp
->ifindex
, zvni
->vni
,
8221 vrf_id_to_name(ifp
->vrf_id
));
8223 /* update the vrf information for l2-vni and inform bgp */
8224 zvni
->vrf_id
= ifp
->vrf_id
;
8225 zvni_send_add_to_client(zvni
);
8227 /* Install any remote neighbors for this VNI. */
8228 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8230 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8238 * Handle VxLAN interface down
8240 int zebra_vxlan_if_down(struct interface
*ifp
)
8243 struct zebra_if
*zif
= NULL
;
8244 struct zebra_l2info_vxlan
*vxl
= NULL
;
8245 zebra_l3vni_t
*zl3vni
= NULL
;
8248 /* Check if EVPN is enabled. */
8249 if (!is_evpn_enabled())
8254 vxl
= &zif
->l2info
.vxl
;
8257 zl3vni
= zl3vni_lookup(vni
);
8259 /* process-if-down for l3-vni */
8260 if (IS_ZEBRA_DEBUG_VXLAN
)
8261 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
8264 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8266 /* process if-down for l2-vni */
8267 if (IS_ZEBRA_DEBUG_VXLAN
)
8268 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
8271 /* Locate hash entry; it is expected to exist. */
8272 zvni
= zvni_lookup(vni
);
8275 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8276 ifp
->name
, ifp
->ifindex
, vni
);
8280 assert(zvni
->vxlan_if
== ifp
);
8282 /* Delete this VNI from BGP. */
8283 zvni_send_del_to_client(zvni
->vni
);
8285 /* Free up all neighbors and MACs, if any. */
8286 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8287 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8289 /* Free up all remote VTEPs, if any. */
8290 zvni_vtep_del_all(zvni
, 1);
8296 * Handle VxLAN interface up - update BGP if required.
8298 int zebra_vxlan_if_up(struct interface
*ifp
)
8301 struct zebra_if
*zif
= NULL
;
8302 struct zebra_l2info_vxlan
*vxl
= NULL
;
8303 zebra_vni_t
*zvni
= NULL
;
8304 zebra_l3vni_t
*zl3vni
= NULL
;
8306 /* Check if EVPN is enabled. */
8307 if (!is_evpn_enabled())
8312 vxl
= &zif
->l2info
.vxl
;
8315 zl3vni
= zl3vni_lookup(vni
);
8318 if (IS_ZEBRA_DEBUG_VXLAN
)
8319 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp
->name
,
8322 /* we need to associate with SVI, if any, we can associate with
8323 * svi-if only after association with vxlan-intf is complete
8325 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8327 if (is_l3vni_oper_up(zl3vni
))
8328 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8330 /* Handle L2-VNI add */
8331 struct interface
*vlan_if
= NULL
;
8333 if (IS_ZEBRA_DEBUG_VXLAN
)
8334 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
8337 /* Locate hash entry; it is expected to exist. */
8338 zvni
= zvni_lookup(vni
);
8341 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8342 ifp
->name
, ifp
->ifindex
, vni
);
8346 assert(zvni
->vxlan_if
== ifp
);
8347 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8348 zif
->brslave_info
.br_if
);
8350 zvni
->vrf_id
= vlan_if
->vrf_id
;
8351 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8353 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8356 /* If part of a bridge, inform BGP about this VNI. */
8357 /* Also, read and populate local MACs and neighbors. */
8358 if (zif
->brslave_info
.br_if
) {
8359 zvni_send_add_to_client(zvni
);
8360 zvni_read_mac_neigh(zvni
, ifp
);
8368 * Handle VxLAN interface delete. Locate and remove entry in hash table
8369 * and update BGP, if required.
8371 int zebra_vxlan_if_del(struct interface
*ifp
)
8374 struct zebra_if
*zif
= NULL
;
8375 struct zebra_l2info_vxlan
*vxl
= NULL
;
8376 zebra_vni_t
*zvni
= NULL
;
8377 zebra_l3vni_t
*zl3vni
= NULL
;
8379 /* Check if EVPN is enabled. */
8380 if (!is_evpn_enabled())
8385 vxl
= &zif
->l2info
.vxl
;
8388 zl3vni
= zl3vni_lookup(vni
);
8391 if (IS_ZEBRA_DEBUG_VXLAN
)
8392 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
8395 /* process oper-down for l3-vni */
8396 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8398 /* remove the association with vxlan_if */
8399 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
8400 zl3vni
->vxlan_if
= NULL
;
8403 /* process if-del for l2-vni*/
8404 if (IS_ZEBRA_DEBUG_VXLAN
)
8405 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
8408 /* Locate hash entry; it is expected to exist. */
8409 zvni
= zvni_lookup(vni
);
8412 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8413 ifp
->name
, ifp
->ifindex
, vni
);
8417 /* remove from l3-vni list */
8418 zl3vni
= zl3vni_from_vrf(zvni
->vrf_id
);
8420 listnode_delete(zl3vni
->l2vnis
, zvni
);
8422 /* Delete VNI from BGP. */
8423 zvni_send_del_to_client(zvni
->vni
);
8425 /* Free up all neighbors and MAC, if any. */
8426 zvni_neigh_del_all(zvni
, 0, 0, DEL_ALL_NEIGH
);
8427 zvni_mac_del_all(zvni
, 0, 0, DEL_ALL_MAC
);
8429 /* Free up all remote VTEPs, if any. */
8430 zvni_vtep_del_all(zvni
, 0);
8432 /* Delete the hash entry. */
8433 if (zvni_del(zvni
)) {
8434 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
8435 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8436 zvni
, ifp
->name
, ifp
->ifindex
, zvni
->vni
);
8444 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8446 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
8449 struct zebra_if
*zif
= NULL
;
8450 struct zebra_l2info_vxlan
*vxl
= NULL
;
8451 zebra_vni_t
*zvni
= NULL
;
8452 zebra_l3vni_t
*zl3vni
= NULL
;
8454 /* Check if EVPN is enabled. */
8455 if (!is_evpn_enabled())
8460 vxl
= &zif
->l2info
.vxl
;
8463 zl3vni
= zl3vni_lookup(vni
);
8466 if (IS_ZEBRA_DEBUG_VXLAN
)
8468 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8469 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8470 inet_ntoa(vxl
->vtep_ip
),
8471 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8473 /* Removed from bridge? Cleanup and return */
8474 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8475 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8476 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8480 /* access-vlan change - process oper down, associate with new
8481 * svi_if and then process oper up again
8483 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8484 if (if_is_operative(ifp
)) {
8485 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8486 zl3vni
->svi_if
= NULL
;
8487 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8488 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8489 if (is_l3vni_oper_up(zl3vni
))
8490 zebra_vxlan_process_l3vni_oper_up(
8496 * local-ip change - process oper down, associate with new
8497 * local-ip and then process oper up again
8499 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
8500 if (if_is_operative(ifp
)) {
8501 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8502 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8503 if (is_l3vni_oper_up(zl3vni
))
8504 zebra_vxlan_process_l3vni_oper_up(
8509 /* Update local tunnel IP. */
8510 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8512 /* if we have a valid new master, process l3-vni oper up */
8513 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
8514 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
8515 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8519 /* Update VNI hash. */
8520 zvni
= zvni_lookup(vni
);
8523 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8524 ifp
->name
, ifp
->ifindex
, vni
);
8528 if (IS_ZEBRA_DEBUG_VXLAN
)
8530 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8531 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8532 inet_ntoa(vxl
->vtep_ip
),
8533 zif
->brslave_info
.bridge_ifindex
, chgflags
);
8535 /* Removed from bridge? Cleanup and return */
8536 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8537 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
8538 /* Delete from client, remove all remote VTEPs */
8539 /* Also, free up all MACs and neighbors. */
8540 zvni_send_del_to_client(zvni
->vni
);
8541 zvni_neigh_del_all(zvni
, 1, 0, DEL_ALL_NEIGH
);
8542 zvni_mac_del_all(zvni
, 1, 0, DEL_ALL_MAC
);
8543 zvni_vtep_del_all(zvni
, 1);
8547 /* Handle other changes. */
8548 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8549 /* Remove all existing local neigh and MACs for this VNI
8550 * (including from BGP)
8552 zvni_neigh_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8553 zvni_mac_del_all(zvni
, 0, 1, DEL_LOCAL_MAC
);
8556 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8557 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8558 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8560 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8561 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8562 zvni
->mcast_grp
= vxl
->mcast_grp
;
8564 zvni
->vxlan_if
= ifp
;
8566 /* Take further actions needed.
8567 * Note that if we are here, there is a change of interest.
8569 /* If down or not mapped to a bridge, we're done. */
8570 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8573 /* Inform BGP, if there is a change of interest. */
8575 & (ZEBRA_VXLIF_MASTER_CHANGE
|
8576 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
8577 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
8578 zvni_send_add_to_client(zvni
);
8580 /* If there is a valid new master or a VLAN mapping change,
8581 * read and populate local MACs and neighbors.
8582 * Also, reinstall any remote MACs and neighbors
8583 * for this VNI (based on new VLAN).
8585 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
8586 zvni_read_mac_neigh(zvni
, ifp
);
8587 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
8588 struct mac_walk_ctx m_wctx
;
8589 struct neigh_walk_ctx n_wctx
;
8591 zvni_read_mac_neigh(zvni
, ifp
);
8593 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8595 hash_iterate(zvni
->mac_table
, zvni_install_mac_hash
,
8598 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8600 hash_iterate(zvni
->neigh_table
, zvni_install_neigh_hash
,
8609 * Handle VxLAN interface add.
8611 int zebra_vxlan_if_add(struct interface
*ifp
)
8614 struct zebra_if
*zif
= NULL
;
8615 struct zebra_l2info_vxlan
*vxl
= NULL
;
8616 zebra_vni_t
*zvni
= NULL
;
8617 zebra_l3vni_t
*zl3vni
= NULL
;
8619 /* Check if EVPN is enabled. */
8620 if (!is_evpn_enabled())
8625 vxl
= &zif
->l2info
.vxl
;
8628 zl3vni
= zl3vni_lookup(vni
);
8631 /* process if-add for l3-vni*/
8632 if (IS_ZEBRA_DEBUG_VXLAN
)
8634 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8635 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8636 inet_ntoa(vxl
->vtep_ip
),
8637 zif
->brslave_info
.bridge_ifindex
);
8639 /* associate with vxlan_if */
8640 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
8641 zl3vni
->vxlan_if
= ifp
;
8643 /* Associate with SVI, if any. We can associate with svi-if only
8644 * after association with vxlan_if is complete */
8645 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8647 if (is_l3vni_oper_up(zl3vni
))
8648 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8651 /* process if-add for l2-vni */
8652 struct interface
*vlan_if
= NULL
;
8654 /* Create or update VNI hash. */
8655 zvni
= zvni_lookup(vni
);
8657 zvni
= zvni_add(vni
);
8660 EC_ZEBRA_VNI_ADD_FAILED
,
8661 "Failed to add VNI hash, IF %s(%u) VNI %u",
8662 ifp
->name
, ifp
->ifindex
, vni
);
8667 if (zvni
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
8668 zvni
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
8669 zebra_vxlan_sg_deref(zvni
->local_vtep_ip
,
8671 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
8672 zvni
->local_vtep_ip
= vxl
->vtep_ip
;
8673 zvni
->mcast_grp
= vxl
->mcast_grp
;
8675 zvni
->vxlan_if
= ifp
;
8676 vlan_if
= zvni_map_to_svi(vxl
->access_vlan
,
8677 zif
->brslave_info
.br_if
);
8679 zvni
->vrf_id
= vlan_if
->vrf_id
;
8680 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
8682 listnode_add_sort(zl3vni
->l2vnis
, zvni
);
8685 if (IS_ZEBRA_DEBUG_VXLAN
) {
8686 char addr_buf1
[INET_ADDRSTRLEN
];
8687 char addr_buf2
[INET_ADDRSTRLEN
];
8689 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
8690 addr_buf1
, INET_ADDRSTRLEN
);
8691 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
8692 addr_buf2
, INET_ADDRSTRLEN
);
8695 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
8697 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
8699 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
8700 addr_buf1
, addr_buf2
,
8701 zif
->brslave_info
.bridge_ifindex
);
8704 /* If down or not mapped to a bridge, we're done. */
8705 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8709 zvni_send_add_to_client(zvni
);
8711 /* Read and populate local MACs and neighbors */
8712 zvni_read_mac_neigh(zvni
, ifp
);
8718 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
8719 char *err
, int err_str_sz
, int filter
,
8722 zebra_l3vni_t
*zl3vni
= NULL
;
8723 struct zebra_vrf
*zvrf_evpn
= NULL
;
8725 zvrf_evpn
= zebra_vrf_get_evpn();
8729 if (IS_ZEBRA_DEBUG_VXLAN
)
8730 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
8731 add
? "ADD" : "DEL");
8735 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8737 /* check if the vni is already present under zvrf */
8739 snprintf(err
, err_str_sz
,
8740 "VNI is already configured under the vrf");
8744 /* check if this VNI is already present in the system */
8745 zl3vni
= zl3vni_lookup(vni
);
8747 snprintf(err
, err_str_sz
,
8748 "VNI is already configured as L3-VNI");
8752 /* add the L3-VNI to the global table */
8753 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
8755 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
8759 /* associate the vrf with vni */
8762 /* set the filter in l3vni to denote if we are using l3vni only
8766 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
8768 /* associate with vxlan-intf;
8769 * we need to associate with the vxlan-intf first
8771 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
8773 /* associate with corresponding SVI interface, we can associate
8774 * with svi-if only after vxlan interface association is
8777 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
8779 /* formulate l2vni list */
8780 hash_iterate(zvrf_evpn
->vni_table
, zvni_add_to_l3vni_list
,
8783 if (is_l3vni_oper_up(zl3vni
))
8784 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8787 zl3vni
= zl3vni_lookup(vni
);
8789 snprintf(err
, err_str_sz
, "VNI doesn't exist");
8793 if (zvrf
->l3vni
!= vni
) {
8794 snprintf(err
, err_str_sz
,
8795 "VNI %d doesn't exist in VRF: %s",
8796 vni
, zvrf
->vrf
->name
);
8800 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
8801 snprintf(err
, ERR_STR_SZ
,
8802 "prefix-routes-only is not set for the vni");
8806 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8808 /* delete and uninstall all rmacs */
8809 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
8812 /* delete and uninstall all next-hops */
8813 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
8819 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
8824 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
8826 zebra_l3vni_t
*zl3vni
= NULL
;
8829 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8833 zl3vni
->vrf_id
= zvrf_id(zvrf
);
8834 if (is_l3vni_oper_up(zl3vni
))
8835 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
8839 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
8841 zebra_l3vni_t
*zl3vni
= NULL
;
8844 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8848 zl3vni
->vrf_id
= VRF_UNKNOWN
;
8849 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
8853 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
8855 zebra_l3vni_t
*zl3vni
= NULL
;
8859 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
8865 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
8871 * Handle message from client to specify the flooding mechanism for
8872 * BUM packets. The default is to do head-end (ingress) replication
8873 * and the other supported option is to disable it. This applies to
8874 * all BUM traffic and disabling it applies to both the transmit and
8875 * receive direction.
8877 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
8880 enum vxlan_flood_control flood_ctrl
;
8882 if (!EVPN_ENABLED(zvrf
)) {
8883 zlog_err("EVPN flood control for non-EVPN VRF %u",
8889 STREAM_GETC(s
, flood_ctrl
);
8891 if (IS_ZEBRA_DEBUG_VXLAN
)
8892 zlog_debug("EVPN flood control %u, currently %u",
8893 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
8895 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
8898 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
8900 /* Install or uninstall flood entries corresponding to
8903 hash_iterate(zvrf
->vni_table
, zvni_handle_flooding_remote_vteps
,
8911 * Handle message from client to enable/disable advertisement of svi macip
8914 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
8919 zebra_vni_t
*zvni
= NULL
;
8920 struct interface
*ifp
= NULL
;
8922 if (!EVPN_ENABLED(zvrf
)) {
8923 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
8929 STREAM_GETC(s
, advertise
);
8930 STREAM_GETL(s
, vni
);
8933 if (IS_ZEBRA_DEBUG_VXLAN
)
8934 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8935 advertise
? "enabled" : "disabled",
8936 advertise_gw_macip_enabled(NULL
)
8940 if (zvrf
->advertise_svi_macip
== advertise
)
8945 zvrf
->advertise_svi_macip
= advertise
;
8946 hash_iterate(zvrf
->vni_table
,
8947 zvni_gw_macip_add_for_vni_hash
, NULL
);
8949 hash_iterate(zvrf
->vni_table
,
8950 zvni_svi_macip_del_for_vni_hash
, NULL
);
8951 zvrf
->advertise_svi_macip
= advertise
;
8955 struct zebra_if
*zif
= NULL
;
8956 struct zebra_l2info_vxlan zl2_info
;
8957 struct interface
*vlan_if
= NULL
;
8959 zvni
= zvni_lookup(vni
);
8963 if (IS_ZEBRA_DEBUG_VXLAN
)
8965 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8966 advertise
? "enabled" : "disabled", vni
,
8967 advertise_svi_macip_enabled(zvni
)
8971 if (zvni
->advertise_svi_macip
== advertise
)
8974 ifp
= zvni
->vxlan_if
;
8980 /* If down or not mapped to a bridge, we're done. */
8981 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
8984 zl2_info
= zif
->l2info
.vxl
;
8986 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
8987 zif
->brslave_info
.br_if
);
8992 zvni
->advertise_svi_macip
= advertise
;
8993 /* Add primary SVI MAC-IP */
8994 zvni_add_macip_for_intf(vlan_if
, zvni
);
8996 /* Del primary MAC-IP */
8997 zvni_del_macip_for_intf(vlan_if
, zvni
);
8998 zvni
->advertise_svi_macip
= advertise
;
9007 * Handle message from client to enable/disable advertisement of g/w macip
9010 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
9015 zebra_vni_t
*zvni
= NULL
;
9016 struct interface
*ifp
= NULL
;
9017 struct zebra_if
*zif
= NULL
;
9018 struct zebra_l2info_vxlan zl2_info
;
9019 struct interface
*vlan_if
= NULL
;
9021 if (!EVPN_ENABLED(zvrf
)) {
9022 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9028 STREAM_GETC(s
, advertise
);
9029 vni
= stream_get3(s
);
9031 zvni
= zvni_lookup(vni
);
9035 if (zvni
->advertise_subnet
== advertise
)
9038 if (IS_ZEBRA_DEBUG_VXLAN
)
9039 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
9040 advertise
? "enabled" : "disabled", vni
,
9041 zvni
->advertise_subnet
? "enabled" : "disabled");
9044 zvni
->advertise_subnet
= advertise
;
9046 ifp
= zvni
->vxlan_if
;
9052 /* If down or not mapped to a bridge, we're done. */
9053 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9056 zl2_info
= zif
->l2info
.vxl
;
9059 zvni_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
9063 if (zvni
->advertise_subnet
)
9064 zvni_advertise_subnet(zvni
, vlan_if
, 1);
9066 zvni_advertise_subnet(zvni
, vlan_if
, 0);
9073 * Handle message from client to enable/disable advertisement of g/w macip
9076 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
9081 zebra_vni_t
*zvni
= NULL
;
9082 struct interface
*ifp
= NULL
;
9084 if (!EVPN_ENABLED(zvrf
)) {
9085 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
9091 STREAM_GETC(s
, advertise
);
9092 STREAM_GETL(s
, vni
);
9095 if (IS_ZEBRA_DEBUG_VXLAN
)
9096 zlog_debug("EVPN gateway macip Adv %s, currently %s",
9097 advertise
? "enabled" : "disabled",
9098 advertise_gw_macip_enabled(NULL
)
9102 if (zvrf
->advertise_gw_macip
== advertise
)
9105 zvrf
->advertise_gw_macip
= advertise
;
9107 if (advertise_gw_macip_enabled(zvni
))
9108 hash_iterate(zvrf
->vni_table
,
9109 zvni_gw_macip_add_for_vni_hash
, NULL
);
9111 hash_iterate(zvrf
->vni_table
,
9112 zvni_gw_macip_del_for_vni_hash
, NULL
);
9115 struct zebra_if
*zif
= NULL
;
9116 struct zebra_l2info_vxlan zl2_info
;
9117 struct interface
*vlan_if
= NULL
;
9118 struct interface
*vrr_if
= NULL
;
9120 zvni
= zvni_lookup(vni
);
9124 if (IS_ZEBRA_DEBUG_VXLAN
)
9126 "EVPN gateway macip Adv %s on VNI %d , currently %s",
9127 advertise
? "enabled" : "disabled", vni
,
9128 advertise_gw_macip_enabled(zvni
) ? "enabled"
9131 if (zvni
->advertise_gw_macip
== advertise
)
9134 zvni
->advertise_gw_macip
= advertise
;
9136 ifp
= zvni
->vxlan_if
;
9142 /* If down or not mapped to a bridge, we're done. */
9143 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
9146 zl2_info
= zif
->l2info
.vxl
;
9148 vlan_if
= zvni_map_to_svi(zl2_info
.access_vlan
,
9149 zif
->brslave_info
.br_if
);
9153 if (advertise_gw_macip_enabled(zvni
)) {
9154 /* Add primary SVI MAC-IP */
9155 zvni_add_macip_for_intf(vlan_if
, zvni
);
9157 /* Add VRR MAC-IP - if any*/
9158 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9160 zvni_add_macip_for_intf(vrr_if
, zvni
);
9162 /* Del primary MAC-IP */
9163 zvni_del_macip_for_intf(vlan_if
, zvni
);
9165 /* Del VRR MAC-IP - if any*/
9166 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
9168 zvni_del_macip_for_intf(vrr_if
, zvni
);
9178 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9179 * When enabled, the VNI hash table will be built and MAC FDB table read;
9180 * when disabled, the entries should be deleted and remote VTEPs and MACs
9181 * uninstalled from the kernel.
9182 * This also informs the setting for BUM handling at the time this change
9183 * occurs; it is relevant only when specifying "learn".
9185 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
9187 struct stream
*s
= NULL
;
9189 enum vxlan_flood_control flood_ctrl
;
9191 /* Mismatch between EVPN VRF and current VRF (should be prevented by
9193 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
9197 STREAM_GETC(s
, advertise
);
9198 STREAM_GETC(s
, flood_ctrl
);
9200 if (IS_ZEBRA_DEBUG_VXLAN
)
9201 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
9202 zvrf_name(zvrf
), zvrf_id(zvrf
),
9203 advertise
? "enabled" : "disabled",
9204 is_evpn_enabled() ? "enabled" : "disabled",
9207 if (zvrf
->advertise_all_vni
== advertise
)
9210 zvrf
->advertise_all_vni
= advertise
;
9211 if (EVPN_ENABLED(zvrf
)) {
9212 zrouter
.evpn_vrf
= zvrf
;
9214 /* Note BUM handling */
9215 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
9217 /* Build VNI hash table and inform BGP. */
9218 zvni_build_hash_table();
9220 /* Add all SVI (L3 GW) MACs to BGP*/
9221 hash_iterate(zvrf
->vni_table
, zvni_gw_macip_add_for_vni_hash
,
9224 /* Read the MAC FDB */
9225 macfdb_read(zvrf
->zns
);
9227 /* Read neighbors */
9228 neigh_read(zvrf
->zns
);
9230 /* Cleanup VTEPs for all VNIs - uninstall from
9231 * kernel and free entries.
9233 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9235 /* cleanup all l3vnis */
9236 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
9238 /* Mark as "no EVPN VRF" */
9239 zrouter
.evpn_vrf
= NULL
;
9247 * Allocate VNI hash table for this VRF and do other initialization.
9248 * NOTE: Currently supported only for default VRF.
9250 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
9254 zvrf
->vni_table
= hash_create(vni_hash_keymake
, vni_hash_cmp
,
9255 "Zebra VRF VNI Table");
9256 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
9257 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
9260 /* Cleanup VNI info, but don't free the table. */
9261 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
9265 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9266 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
9269 /* Close all VNI handling */
9270 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
9274 hash_iterate(zvrf
->vni_table
, zvni_cleanup_all
, zvrf
);
9275 hash_free(zvrf
->vni_table
);
9278 /* init the l3vni table */
9279 void zebra_vxlan_init(void)
9281 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
9282 "Zebra VRF L3 VNI table");
9283 zrouter
.evpn_vrf
= NULL
;
9286 /* free l3vni table */
9287 void zebra_vxlan_disable(void)
9289 hash_free(zrouter
.l3vni_table
);
9292 /* get the l3vni svi ifindex */
9293 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
9295 zebra_l3vni_t
*zl3vni
= NULL
;
9297 zl3vni
= zl3vni_from_vrf(vrf_id
);
9298 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
9301 return zl3vni
->svi_if
->ifindex
;
9304 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
9306 struct zebra_vrf
*zvrf
= NULL
;
9307 zebra_neigh_t
*nbr
= NULL
;
9308 zebra_vni_t
*zvni
= NULL
;
9309 char buf1
[INET6_ADDRSTRLEN
];
9310 char buf2
[ETHER_ADDR_STRLEN
];
9312 nbr
= THREAD_ARG(t
);
9314 /* since this is asynchronous we need sanity checks*/
9315 zvrf
= vrf_info_lookup(nbr
->zvni
->vrf_id
);
9319 zvni
= zvni_lookup(nbr
->zvni
->vni
);
9323 nbr
= zvni_neigh_lookup(zvni
, &nbr
->ip
);
9327 if (IS_ZEBRA_DEBUG_VXLAN
)
9328 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9329 __PRETTY_FUNCTION__
,
9330 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
9331 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
9333 nbr
->dad_count
, zvni
->vni
);
9335 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9337 nbr
->detect_start_time
.tv_sec
= 0;
9338 nbr
->detect_start_time
.tv_usec
= 0;
9339 nbr
->dad_dup_detect_time
= 0;
9340 nbr
->dad_ip_auto_recovery_timer
= NULL
;
9341 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
9344 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
9345 zvni_neigh_send_add_to_client(zvni
->vni
, &nbr
->ip
, &nbr
->emac
,
9346 nbr
->flags
, nbr
->loc_seq
);
9347 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9348 zvni_neigh_install(zvni
, nbr
);
9354 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
9356 struct zebra_vrf
*zvrf
= NULL
;
9357 zebra_mac_t
*mac
= NULL
;
9358 zebra_vni_t
*zvni
= NULL
;
9359 struct listnode
*node
= NULL
;
9360 zebra_neigh_t
*nbr
= NULL
;
9361 char buf
[ETHER_ADDR_STRLEN
];
9363 mac
= THREAD_ARG(t
);
9365 /* since this is asynchronous we need sanity checks*/
9366 zvrf
= vrf_info_lookup(mac
->zvni
->vrf_id
);
9370 zvni
= zvni_lookup(mac
->zvni
->vni
);
9374 mac
= zvni_mac_lookup(zvni
, &mac
->macaddr
);
9378 if (IS_ZEBRA_DEBUG_VXLAN
)
9379 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9380 __PRETTY_FUNCTION__
,
9381 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
9384 listcount(mac
->neigh_list
));
9386 /* Remove all IPs as duplicate associcated with this MAC */
9387 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
9388 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
9389 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
9390 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
9391 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
9392 zvni_neigh_install(zvni
, nbr
);
9395 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
9397 nbr
->detect_start_time
.tv_sec
= 0;
9398 nbr
->dad_dup_detect_time
= 0;
9401 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
9403 mac
->detect_start_time
.tv_sec
= 0;
9404 mac
->detect_start_time
.tv_usec
= 0;
9405 mac
->dad_dup_detect_time
= 0;
9406 mac
->dad_mac_auto_recovery_timer
= NULL
;
9408 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9410 if (zvni_mac_send_add_to_client(zvni
->vni
, &mac
->macaddr
,
9411 mac
->flags
, mac
->loc_seq
))
9414 /* Process all neighbors associated with this MAC. */
9415 zvni_process_neigh_on_local_mac_change(zvni
, mac
, 0);
9417 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9418 zvni_process_neigh_on_remote_mac_add(zvni
, mac
);
9420 /* Install the entry. */
9421 zvni_mac_install(zvni
, mac
);
9427 /************************** vxlan SG cache management ************************/
9428 /* Inform PIM about the mcast group */
9429 static int zebra_vxlan_sg_send(struct prefix_sg
*sg
,
9430 char *sg_str
, uint16_t cmd
)
9432 struct zserv
*client
= NULL
;
9433 struct stream
*s
= NULL
;
9435 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
9439 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
9441 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
9442 stream_putl(s
, IPV4_MAX_BYTELEN
);
9443 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
9444 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
9446 /* Write packet size. */
9447 stream_putw_at(s
, 0, stream_get_endp(s
));
9449 if (IS_ZEBRA_DEBUG_VXLAN
)
9452 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
9453 zebra_route_string(client
->proto
));
9455 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
9456 client
->vxlan_sg_add_cnt
++;
9458 client
->vxlan_sg_del_cnt
++;
9460 return zserv_send_message(client
, s
);
9463 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
9465 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
9467 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
9468 vxlan_sg
->sg
.grp
.s_addr
, 0));
9471 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
9473 const zebra_vxlan_sg_t
*sg1
= p1
;
9474 const zebra_vxlan_sg_t
*sg2
= p2
;
9476 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
9477 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
9480 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
9481 struct prefix_sg
*sg
)
9483 zebra_vxlan_sg_t
*vxlan_sg
;
9485 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
9487 vxlan_sg
->zvrf
= zvrf
;
9489 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
9491 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
9493 if (IS_ZEBRA_DEBUG_VXLAN
)
9494 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
9499 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
9500 struct prefix_sg
*sg
)
9502 zebra_vxlan_sg_t lookup
;
9505 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
9508 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
9509 struct prefix_sg
*sg
)
9511 zebra_vxlan_sg_t
*vxlan_sg
;
9512 zebra_vxlan_sg_t
*parent
= NULL
;
9515 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
9519 /* create a *G entry for every BUM group implicitly -
9520 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
9521 * 2. the XG entry is used by pimd to setup the
9522 * vxlan-termination-mroute
9524 if (sg
->src
.s_addr
) {
9525 memset(&sip
, 0, sizeof(sip
));
9526 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
9531 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
9534 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
9538 zebra_vxlan_sg_send(sg
, vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
9543 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
9546 struct zebra_vrf
*zvrf
;
9548 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9552 /* On SG entry deletion remove the reference to its parent XG
9555 if (vxlan_sg
->sg
.src
.s_addr
) {
9556 memset(&sip
, 0, sizeof(sip
));
9557 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
9560 zebra_vxlan_sg_send(&vxlan_sg
->sg
, vxlan_sg
->sg_str
,
9561 ZEBRA_VXLAN_SG_DEL
);
9563 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
9565 if (IS_ZEBRA_DEBUG_VXLAN
)
9566 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
9568 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
9571 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
9572 struct in_addr sip
, struct in_addr mcast_grp
)
9574 zebra_vxlan_sg_t
*vxlan_sg
;
9575 struct prefix_sg sg
;
9577 sg
.family
= AF_INET
;
9578 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9581 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
9585 if (vxlan_sg
->ref_cnt
)
9586 --vxlan_sg
->ref_cnt
;
9588 if (!vxlan_sg
->ref_cnt
)
9589 zebra_vxlan_sg_del(vxlan_sg
);
9592 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
9593 struct in_addr sip
, struct in_addr mcast_grp
)
9595 zebra_vxlan_sg_t
*vxlan_sg
;
9596 struct prefix_sg sg
;
9598 sg
.family
= AF_INET
;
9599 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
9602 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
9604 ++vxlan_sg
->ref_cnt
;
9609 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
9610 struct in_addr mcast_grp
)
9612 struct zebra_vrf
*zvrf
;
9614 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9617 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9621 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
9624 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
9625 struct in_addr mcast_grp
)
9627 struct zebra_vrf
*zvrf
;
9629 if (!local_vtep_ip
.s_addr
|| !mcast_grp
.s_addr
)
9632 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
9635 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
9638 static void zebra_vxlan_sg_cleanup(struct hash_backet
*backet
, void *arg
)
9640 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
9642 zebra_vxlan_sg_del(vxlan_sg
);