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_evpn_mh.h"
54 #include "zebra/zebra_router.h"
55 //commment for cloning
57 DEFINE_MTYPE_STATIC(ZEBRA
, HOST_PREFIX
, "host prefix");
58 DEFINE_MTYPE_STATIC(ZEBRA
, ZEVPN
, "EVPN hash");
59 DEFINE_MTYPE_STATIC(ZEBRA
, ZL3VNI
, "L3 VNI hash");
60 DEFINE_MTYPE_STATIC(ZEBRA
, ZEVPN_VTEP
, "EVPN remote VTEP/PTUN");
61 DEFINE_MTYPE_STATIC(ZEBRA
, MAC
, "EVPN MAC");
62 DEFINE_MTYPE_STATIC(ZEBRA
, NEIGH
, "EVPN Neighbor");
63 DEFINE_MTYPE_STATIC(ZEBRA
, ZVXLAN_SG
, "zebra VxLAN multicast group");
65 DEFINE_HOOK(zebra_rmac_update
, (zebra_mac_t
*rmac
, zebra_l3vni_t
*zl3vni
,
66 bool delete, const char *reason
), (rmac
, zl3vni
, delete, reason
))
70 #define VXLAN_FLOOD_STR_NO_INFO "-"
71 #define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO
72 static const struct message zvtep_flood_str
[] = {
73 {VXLAN_FLOOD_DISABLED
, VXLAN_FLOOD_STR_NO_INFO
},
74 {VXLAN_FLOOD_PIM_SM
, "PIM-SM"},
75 {VXLAN_FLOOD_HEAD_END_REPL
, "HER"},
79 /* static function declarations */
80 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
82 static void zevpn_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
);
83 static void zevpn_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
84 static void zevpn_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
);
85 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
87 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
89 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
91 static void zevpn_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
);
92 static void zevpn_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
93 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
);
94 static void zevpn_print(zebra_evpn_t
*zevpn
, void **ctxt
);
95 static void zevpn_print_hash(struct hash_bucket
*bucket
, void *ctxt
[]);
97 static int zevpn_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
98 struct ipaddr
*ip
, uint8_t flags
,
99 uint32_t seq
, int state
,
100 struct zebra_evpn_es
*es
,
102 static unsigned int neigh_hash_keymake(const void *p
);
103 static void *zevpn_neigh_alloc(void *p
);
104 static zebra_neigh_t
*zevpn_neigh_add(zebra_evpn_t
*zevpn
, struct ipaddr
*ip
,
105 struct ethaddr
*mac
, zebra_mac_t
*zmac
,
107 static int zevpn_neigh_del(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
);
108 static void zevpn_neigh_del_all(zebra_evpn_t
*zevpn
, int uninstall
, int upd_client
,
110 static zebra_neigh_t
*zevpn_neigh_lookup(zebra_evpn_t
*zevpn
, struct ipaddr
*ip
);
111 static int zevpn_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
112 struct ethaddr
*mac
, zebra_mac_t
*zmac
,
113 uint32_t flags
, uint32_t seq
);
114 static int zevpn_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
116 uint32_t flags
, int state
, bool force
);
117 static int zevpn_rem_neigh_install(zebra_evpn_t
*zevpn
,
118 zebra_neigh_t
*n
, bool was_static
);
119 static int zevpn_neigh_uninstall(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
);
120 static int zevpn_neigh_probe(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
);
121 static zebra_evpn_t
*zevpn_from_svi(struct interface
*ifp
,
122 struct interface
*br_if
);
123 static struct interface
*zevpn_map_to_svi(vlanid_t vid
, struct interface
*br_if
);
124 static struct interface
*zevpn_map_to_macvlan(struct interface
*br_if
,
125 struct interface
*svi_if
);
127 /* l3-vni next-hop neigh related APIs */
128 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
129 const struct ipaddr
*ip
);
130 static void *zl3vni_nh_alloc(void *p
);
131 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
132 const struct ipaddr
*vtep_ip
,
133 const struct ethaddr
*rmac
);
134 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
135 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
136 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
);
138 /* l3-vni rmac related APIs */
139 static void zl3vni_print_rmac_hash(struct hash_bucket
*, void *);
140 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
141 const struct ethaddr
*rmac
);
142 static void *zl3vni_rmac_alloc(void *p
);
143 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
144 const struct ethaddr
*rmac
);
145 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
146 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
147 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
);
149 /* l3-vni related APIs*/
150 static void *zl3vni_alloc(void *p
);
151 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
);
152 static int zl3vni_del(zebra_l3vni_t
*zl3vni
);
153 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
);
154 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
);
156 static unsigned int mac_hash_keymake(const void *p
);
157 static bool mac_cmp(const void *p1
, const void *p2
);
158 static void *zevpn_mac_alloc(void *p
);
159 static zebra_mac_t
*zevpn_mac_add(zebra_evpn_t
*zevpn
, struct ethaddr
*macaddr
);
160 static int zevpn_mac_del(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
);
161 static void zevpn_mac_del_all(zebra_evpn_t
*zevpn
, int uninstall
, int upd_client
,
163 static zebra_mac_t
*zevpn_mac_lookup(zebra_evpn_t
*zevpn
, struct ethaddr
*macaddr
);
164 static int zevpn_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
165 uint32_t flags
, uint32_t seq
, struct zebra_evpn_es
*es
);
166 static int zevpn_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
167 uint32_t flags
, bool force
);
168 static zebra_evpn_t
*zevpn_map_vlan(struct interface
*ifp
,
169 struct interface
*br_if
, vlanid_t vid
);
170 static int zevpn_rem_mac_install(zebra_evpn_t
*zevpn
,
171 zebra_mac_t
*mac
, bool was_static
);
172 static int zevpn_rem_mac_uninstall(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
);
173 static void zevpn_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
);
175 static unsigned int evpn_hash_keymake(const void *p
);
176 static void *zevpn_alloc(void *p
);
177 static zebra_evpn_t
*zevpn_add(vni_t vni
);
178 static int zevpn_del(zebra_evpn_t
*zevpn
);
179 static int zevpn_send_add_to_client(zebra_evpn_t
*zevpn
);
180 static int zevpn_send_del_to_client(zebra_evpn_t
*zevpn
);
181 static void zevpn_build_hash_table(void);
182 static int zevpn_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
);
183 static zebra_vtep_t
*zevpn_vtep_find(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
);
184 static zebra_vtep_t
*zevpn_vtep_add(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
,
186 static int zevpn_vtep_del(zebra_evpn_t
*zevpn
, zebra_vtep_t
*zvtep
);
187 static int zevpn_vtep_del_all(zebra_evpn_t
*zevpn
, int uninstall
);
188 static int zevpn_vtep_install(zebra_evpn_t
*zevpn
, zebra_vtep_t
*zvtep
);
189 static int zevpn_vtep_uninstall(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
);
190 static int zevpn_del_macip_for_intf(struct interface
*ifp
, zebra_evpn_t
*zevpn
);
191 static int zevpn_add_macip_for_intf(struct interface
*ifp
, zebra_evpn_t
*zevpn
);
192 static int zevpn_gw_macip_add(struct interface
*ifp
, zebra_evpn_t
*zevpn
,
193 struct ethaddr
*macaddr
, struct ipaddr
*ip
);
194 static int zevpn_gw_macip_del(struct interface
*ifp
, zebra_evpn_t
*zevpn
,
196 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
);
197 static int advertise_gw_macip_enabled(zebra_evpn_t
*zevpn
);
198 static int advertise_svi_macip_enabled(zebra_evpn_t
*zevpn
);
199 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
200 zebra_mac_t
*old_zmac
,
201 zebra_mac_t
*new_zmac
,
203 static int remote_neigh_count(zebra_mac_t
*zmac
);
204 static void zevpn_deref_ip2mac(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
);
205 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
);
206 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
);
207 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
209 struct in_addr vtep_ip
,
213 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
215 struct in_addr vtep_ip
,
219 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
);
220 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
);
221 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
222 struct in_addr sip
, struct in_addr mcast_grp
);
223 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*vrf
,
224 struct in_addr sip
, struct in_addr mcast_grp
);
225 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
226 struct in_addr mcast_grp
);
227 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
228 struct in_addr mcast_grp
);
229 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*bucket
, void *arg
);
231 static void zevpn_send_mac_to_client(zebra_evpn_t
*zvn
);
232 static void zevpn_send_neigh_to_client(zebra_evpn_t
*zevpn
);
233 static void zebra_vxlan_rem_mac_del(zebra_evpn_t
*zevpn
,
235 static inline void zebra_vxlan_mac_stop_hold_timer(zebra_mac_t
*mac
);
236 static inline bool zebra_vxlan_mac_is_static(zebra_mac_t
*mac
);
237 static void zebra_vxlan_local_neigh_ref_mac(zebra_neigh_t
*n
,
238 struct ethaddr
*macaddr
, zebra_mac_t
*mac
,
239 bool send_mac_update
);
240 static void zebra_vxlan_local_neigh_deref_mac(zebra_neigh_t
*n
,
241 bool send_mac_update
);
242 static inline bool zebra_vxlan_neigh_is_ready_for_bgp(zebra_neigh_t
*n
);
243 static inline bool zebra_vxlan_neigh_clear_sync_info(zebra_neigh_t
*n
);
244 static void zebra_vxlan_sync_neigh_dp_install(zebra_neigh_t
*n
,
245 bool set_inactive
, bool force_clear_static
, const char *caller
);
246 static inline bool zebra_vxlan_neigh_is_static(zebra_neigh_t
*neigh
);
247 static void zebra_vxlan_neigh_send_add_del_to_client(zebra_neigh_t
*n
,
248 bool old_bgp_ready
, bool new_bgp_ready
);
250 /* Private functions */
251 static int host_rb_entry_compare(const struct host_rb_entry
*hle1
,
252 const struct host_rb_entry
*hle2
)
254 if (hle1
->p
.family
< hle2
->p
.family
)
257 if (hle1
->p
.family
> hle2
->p
.family
)
260 if (hle1
->p
.prefixlen
< hle2
->p
.prefixlen
)
263 if (hle1
->p
.prefixlen
> hle2
->p
.prefixlen
)
266 if (hle1
->p
.family
== AF_INET
) {
267 if (hle1
->p
.u
.prefix4
.s_addr
< hle2
->p
.u
.prefix4
.s_addr
)
270 if (hle1
->p
.u
.prefix4
.s_addr
> hle2
->p
.u
.prefix4
.s_addr
)
274 } else if (hle1
->p
.family
== AF_INET6
) {
275 return memcmp(&hle1
->p
.u
.prefix6
, &hle2
->p
.u
.prefix6
,
278 zlog_debug("%s: Unexpected family type: %d", __func__
,
283 RB_GENERATE(host_rb_tree_entry
, host_rb_entry
, hl_entry
, host_rb_entry_compare
);
285 static uint32_t rb_host_count(struct host_rb_tree_entry
*hrbe
)
287 struct host_rb_entry
*hle
;
290 RB_FOREACH (hle
, host_rb_tree_entry
, hrbe
)
297 * Return number of valid MACs in an EVPN's MAC hash table - all
298 * remote MACs and non-internal (auto) local MACs count.
300 static uint32_t num_valid_macs(zebra_evpn_t
*zevpn
)
303 uint32_t num_macs
= 0;
305 struct hash_bucket
*hb
;
308 hash
= zevpn
->mac_table
;
311 for (i
= 0; i
< hash
->size
; i
++) {
312 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
313 mac
= (zebra_mac_t
*)hb
->data
;
314 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
315 || CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
316 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
324 static uint32_t num_dup_detected_macs(zebra_evpn_t
*zevpn
)
327 uint32_t num_macs
= 0;
329 struct hash_bucket
*hb
;
332 hash
= zevpn
->mac_table
;
335 for (i
= 0; i
< hash
->size
; i
++) {
336 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
337 mac
= (zebra_mac_t
*)hb
->data
;
338 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
346 static uint32_t num_dup_detected_neighs(zebra_evpn_t
*zevpn
)
349 uint32_t num_neighs
= 0;
351 struct hash_bucket
*hb
;
354 hash
= zevpn
->neigh_table
;
357 for (i
= 0; i
< hash
->size
; i
++) {
358 for (hb
= hash
->index
[i
]; hb
; hb
= hb
->next
) {
359 nbr
= (zebra_neigh_t
*)hb
->data
;
360 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
368 static int advertise_gw_macip_enabled(zebra_evpn_t
*zevpn
)
370 struct zebra_vrf
*zvrf
;
372 zvrf
= zebra_vrf_get_evpn();
373 if (zvrf
&& zvrf
->advertise_gw_macip
)
376 if (zevpn
&& zevpn
->advertise_gw_macip
)
382 static int advertise_svi_macip_enabled(zebra_evpn_t
*zevpn
)
384 struct zebra_vrf
*zvrf
;
386 zvrf
= zebra_vrf_get_evpn();
387 if (zvrf
&& zvrf
->advertise_svi_macip
)
390 if (zevpn
&& zevpn
->advertise_svi_macip
)
396 /* As part Duplicate Address Detection (DAD) for IP mobility
397 * MAC binding changes, ensure to inherit duplicate flag
400 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf
*zvrf
,
401 zebra_mac_t
*old_zmac
,
402 zebra_mac_t
*new_zmac
,
405 bool is_old_mac_dup
= false;
406 bool is_new_mac_dup
= false;
408 if (!zvrf
->dup_addr_detect
)
410 /* Check old or new MAC is detected as duplicate
411 * mark this neigh as duplicate
414 is_old_mac_dup
= CHECK_FLAG(old_zmac
->flags
,
415 ZEBRA_MAC_DUPLICATE
);
417 is_new_mac_dup
= CHECK_FLAG(new_zmac
->flags
,
418 ZEBRA_MAC_DUPLICATE
);
419 /* Old and/or new MAC can be in duplicate state,
420 * based on that IP/Neigh Inherits the flag.
421 * If New MAC is marked duplicate, inherit to the IP.
422 * If old MAC is duplicate but new MAC is not, clear
423 * duplicate flag for IP and reset detection params
424 * and let IP DAD retrigger.
426 if (is_new_mac_dup
&& !CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
427 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
428 /* Capture Duplicate detection time */
429 nbr
->dad_dup_detect_time
= monotime(NULL
);
430 /* Mark neigh inactive */
431 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
434 } else if (is_old_mac_dup
&& !is_new_mac_dup
) {
435 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
437 nbr
->detect_start_time
.tv_sec
= 0;
438 nbr
->detect_start_time
.tv_usec
= 0;
443 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf
*zvrf
,
445 struct in_addr vtep_ip
,
451 struct listnode
*node
= NULL
;
452 struct timeval elapsed
= {0, 0};
453 char buf
[ETHER_ADDR_STRLEN
];
454 char buf1
[INET6_ADDRSTRLEN
];
455 bool reset_params
= false;
457 if (!(zvrf
->dup_addr_detect
&& do_dad
))
460 /* MAC is detected as duplicate,
461 * Local MAC event -> hold on advertising to BGP.
462 * Remote MAC event -> hold on installing it.
464 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
465 if (IS_ZEBRA_DEBUG_VXLAN
)
467 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
469 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
470 mac
->flags
, mac
->dad_count
,
471 zvrf
->dad_freeze_time
);
473 /* For duplicate MAC do not update
474 * client but update neigh due to
477 if (zvrf
->dad_freeze
)
478 *is_dup_detect
= true;
483 /* Check if detection time (M-secs) expired.
484 * Reset learn count and detection start time.
486 monotime_since(&mac
->detect_start_time
, &elapsed
);
487 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
488 if (is_local
&& !reset_params
) {
489 /* RFC-7432: A PE/VTEP that detects a MAC mobility
490 * event via LOCAL learning starts an M-second timer.
492 * NOTE: This is the START of the probe with count is
493 * 0 during LOCAL learn event.
494 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
496 reset_params
= !mac
->dad_count
;
500 if (IS_ZEBRA_DEBUG_VXLAN
)
502 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u",
504 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
505 mac
->flags
, mac
->dad_count
);
508 /* Start dup. addr detection (DAD) start time,
509 * ONLY during LOCAL learn.
512 monotime(&mac
->detect_start_time
);
514 } else if (!is_local
) {
515 /* For REMOTE MAC, increment detection count
516 * ONLY while in probe window, once window passed,
517 * next local learn event should trigger DAD.
522 /* For LOCAL MAC learn event, once count is reset above via either
523 * initial/start detection time or passed the probe time, the count
524 * needs to be incremented.
529 if (mac
->dad_count
>= zvrf
->dad_max_moves
) {
530 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED
,
531 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
533 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
534 is_local
? "local update, last" :
535 "remote update, from", inet_ntoa(vtep_ip
));
537 SET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
539 /* Capture Duplicate detection time */
540 mac
->dad_dup_detect_time
= monotime(NULL
);
542 /* Mark all IPs/Neighs as duplicate
543 * associcated with this MAC
545 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
547 /* Ony Mark IPs which are Local */
548 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
551 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
553 nbr
->dad_dup_detect_time
= monotime(NULL
);
555 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
556 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
558 prefix_mac2str(&mac
->macaddr
,
560 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
561 is_local
? "local" : "remote");
564 /* Start auto recovery timer for this MAC */
565 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
566 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
567 if (IS_ZEBRA_DEBUG_VXLAN
)
569 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start",
571 prefix_mac2str(&mac
->macaddr
, buf
,
573 mac
->flags
, zvrf
->dad_freeze_time
);
575 thread_add_timer(zrouter
.master
,
576 zebra_vxlan_dad_mac_auto_recovery_exp
,
577 mac
, zvrf
->dad_freeze_time
,
578 &mac
->dad_mac_auto_recovery_timer
);
581 /* In case of local update, do not inform to client (BGPd),
582 * upd_neigh for neigh sequence change.
584 if (zvrf
->dad_freeze
)
585 *is_dup_detect
= true;
589 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf
*zvrf
,
591 struct in_addr vtep_ip
,
597 struct timeval elapsed
= {0, 0};
598 char buf
[ETHER_ADDR_STRLEN
];
599 char buf1
[INET6_ADDRSTRLEN
];
600 bool reset_params
= false;
602 if (!zvrf
->dup_addr_detect
)
605 /* IP is detected as duplicate or inherit dup
606 * state, hold on to install as remote entry
607 * only if freeze is enabled.
609 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
610 if (IS_ZEBRA_DEBUG_VXLAN
)
612 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
614 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
615 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
616 nbr
->flags
, nbr
->dad_count
,
617 zvrf
->dad_freeze_time
);
619 if (zvrf
->dad_freeze
)
620 *is_dup_detect
= true;
622 /* warn-only action, neigh will be installed.
623 * freeze action, it wil not be installed.
631 /* Check if detection time (M-secs) expired.
632 * Reset learn count and detection start time.
633 * During remote mac add, count should already be 1
634 * via local learning.
636 monotime_since(&nbr
->detect_start_time
, &elapsed
);
637 reset_params
= (elapsed
.tv_sec
> zvrf
->dad_time
);
639 if (is_local
&& !reset_params
) {
640 /* RFC-7432: A PE/VTEP that detects a MAC mobility
641 * event via LOCAL learning starts an M-second timer.
643 * NOTE: This is the START of the probe with count is
644 * 0 during LOCAL learn event.
646 reset_params
= !nbr
->dad_count
;
650 if (IS_ZEBRA_DEBUG_VXLAN
)
652 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
654 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
655 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
656 nbr
->flags
, nbr
->dad_count
);
657 /* Reset learn count but do not start detection
658 * during REMOTE learn event.
661 /* Start dup. addr detection (DAD) start time,
662 * ONLY during LOCAL learn.
665 monotime(&nbr
->detect_start_time
);
667 } else if (!is_local
) {
668 /* For REMOTE IP/Neigh, increment detection count
669 * ONLY while in probe window, once window passed,
670 * next local learn event should trigger DAD.
675 /* For LOCAL IP/Neigh learn event, once count is reset above via either
676 * initial/start detection time or passed the probe time, the count
677 * needs to be incremented.
682 if (nbr
->dad_count
>= zvrf
->dad_max_moves
) {
683 flog_warn(EC_ZEBRA_DUP_IP_DETECTED
,
684 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
686 prefix_mac2str(&nbr
->emac
, buf
, sizeof(buf
)),
687 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)),
688 is_local
? "local update, last" :
689 "remote update, from",
692 SET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
694 /* Capture Duplicate detection time */
695 nbr
->dad_dup_detect_time
= monotime(NULL
);
697 /* Start auto recovery timer for this IP */
698 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
699 if (zvrf
->dad_freeze
&& zvrf
->dad_freeze_time
) {
700 if (IS_ZEBRA_DEBUG_VXLAN
)
702 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
704 prefix_mac2str(&nbr
->emac
, buf
,
706 ipaddr2str(&nbr
->ip
, buf1
,
708 nbr
->flags
, zvrf
->dad_freeze_time
);
710 thread_add_timer(zrouter
.master
,
711 zebra_vxlan_dad_ip_auto_recovery_exp
,
712 nbr
, zvrf
->dad_freeze_time
,
713 &nbr
->dad_ip_auto_recovery_timer
);
715 if (zvrf
->dad_freeze
)
716 *is_dup_detect
= true;
721 * Helper function to determine maximum width of neighbor IP address for
722 * display - just because we're dealing with IPv6 addresses that can
725 static void zevpn_find_neigh_addr_width(struct hash_bucket
*bucket
, void *ctxt
)
728 char buf
[INET6_ADDRSTRLEN
];
729 struct neigh_walk_ctx
*wctx
= ctxt
;
732 n
= (zebra_neigh_t
*)bucket
->data
;
734 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
736 if (width
> wctx
->addr_width
)
737 wctx
->addr_width
= width
;
742 * Print a specific neighbor entry.
744 static void zevpn_print_neigh(zebra_neigh_t
*n
, void *ctxt
, json_object
*json
)
747 char buf1
[ETHER_ADDR_STRLEN
];
748 char buf2
[INET6_ADDRSTRLEN
];
749 const char *type_str
;
750 const char *state_str
;
751 bool flags_present
= false;
752 struct zebra_vrf
*zvrf
= NULL
;
753 struct timeval detect_start_time
= {0, 0};
754 char timebuf
[MONOTIME_STRLEN
];
755 char thread_buf
[THREAD_TIMER_STRLEN
];
757 zvrf
= zebra_vrf_get_evpn();
761 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
762 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
763 type_str
= CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) ?
765 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
766 vty
= (struct vty
*)ctxt
;
768 bool sync_info
= false;
770 vty_out(vty
, "IP: %s\n",
771 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
772 vty_out(vty
, " Type: %s\n", type_str
);
773 vty_out(vty
, " State: %s\n", state_str
);
774 vty_out(vty
, " MAC: %s\n",
775 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
776 vty_out(vty
, " Sync-info:");
777 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
)) {
778 vty_out(vty
, " local-inactive");
781 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_PROXY
)) {
782 vty_out(vty
, " peer-proxy");
785 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
)) {
786 vty_out(vty
, " peer-active");
790 vty_out(vty
, " (ht: %s)",
791 thread_timer_to_hhmmss(
801 json_object_string_add(json
, "ip", buf2
);
802 json_object_string_add(json
, "type", type_str
);
803 json_object_string_add(json
, "state", state_str
);
804 json_object_string_add(json
, "mac", buf1
);
805 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
))
806 json_object_boolean_true_add(json
,
808 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_PROXY
))
809 json_object_boolean_true_add(json
,
811 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
))
812 json_object_boolean_true_add(json
,
815 json_object_string_add(json
, "peerActiveHold",
816 thread_timer_to_hhmmss(
821 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
824 json_object_string_add(json
, "remoteEs",
825 n
->mac
->es
->esi_str
);
827 vty_out(vty
, " Remote ES: %s\n",
828 n
->mac
->es
->esi_str
);
831 json_object_string_add(json
, "remoteVtep",
832 inet_ntoa(n
->r_vtep_ip
));
834 vty_out(vty
, " Remote VTEP: %s\n",
835 inet_ntoa(n
->r_vtep_ip
));
838 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
)) {
840 vty_out(vty
, " Flags: Default-gateway");
841 flags_present
= true;
843 json_object_boolean_true_add(json
, "defaultGateway");
845 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)) {
848 flags_present
? " ,Router" : " Flags: Router");
849 flags_present
= true;
855 vty_out(vty
, " Local Seq: %u Remote Seq: %u\n",
856 n
->loc_seq
, n
->rem_seq
);
858 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
859 vty_out(vty
, " Duplicate, detected at %s",
860 time_to_string(n
->dad_dup_detect_time
,
862 } else if (n
->dad_count
) {
863 monotime_since(&n
->detect_start_time
,
865 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
866 time_to_string(n
->detect_start_time
.tv_sec
,
869 " Duplicate detection started at %s, detection count %u\n",
870 timebuf
, n
->dad_count
);
874 json_object_int_add(json
, "localSequence", n
->loc_seq
);
875 json_object_int_add(json
, "remoteSequence", n
->rem_seq
);
876 json_object_int_add(json
, "detectionCount",
878 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
879 json_object_boolean_true_add(json
, "isDuplicate");
881 json_object_boolean_false_add(json
, "isDuplicate");
887 static void zevpn_print_neigh_hdr(struct vty
*vty
,
888 struct neigh_walk_ctx
*wctx
)
891 "Flags: I=local-inactive, P=peer-active, X=peer-proxy\n");
892 vty_out(vty
, "%*s %-6s %-5s %-8s %-17s %-30s %s\n",
893 -wctx
->addr_width
, "Neighbor", "Type", "Flags",
894 "State", "MAC", "Remote ES/VTEP", "Seq #'s");
897 static char *zevpn_print_neigh_flags(zebra_neigh_t
*n
, char *flags_buf
,
898 uint32_t flags_buf_sz
)
900 snprintf(flags_buf
, flags_buf_sz
, "%s%s%s",
901 (n
->flags
& ZEBRA_NEIGH_ES_PEER_ACTIVE
) ?
903 (n
->flags
& ZEBRA_NEIGH_ES_PEER_PROXY
) ?
905 (n
->flags
& ZEBRA_NEIGH_LOCAL_INACTIVE
) ?
912 * Print neighbor hash entry - called for display of all neighbors.
914 static void zevpn_print_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
917 json_object
*json_evpn
= NULL
, *json_row
= NULL
;
919 char buf1
[ETHER_ADDR_STRLEN
];
920 char buf2
[INET6_ADDRSTRLEN
];
921 struct neigh_walk_ctx
*wctx
= ctxt
;
922 const char *state_str
;
926 json_evpn
= wctx
->json
;
927 n
= (zebra_neigh_t
*)bucket
->data
;
930 json_row
= json_object_new_object();
932 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
));
933 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
));
934 state_str
= IS_ZEBRA_NEIGH_ACTIVE(n
) ? "active" : "inactive";
935 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
936 if (wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
)
939 if (json_vni
== NULL
) {
940 vty_out(vty
, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
941 -wctx
->addr_width
, buf2
, "local",
942 zevpn_print_neigh_flags(n
, flags_buf
,
943 sizeof(flags_buf
)), state_str
,
944 buf1
, "", n
->loc_seq
, n
->rem_seq
);
946 json_object_string_add(json_row
, "type", "local");
947 json_object_string_add(json_row
, "state", state_str
);
948 json_object_string_add(json_row
, "mac", buf1
);
949 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
950 json_object_boolean_true_add(
951 json_row
, "defaultGateway");
952 json_object_int_add(json_row
, "localSequence",
954 json_object_int_add(json_row
, "remoteSequence",
956 json_object_int_add(json_row
, "detectionCount",
958 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
959 json_object_boolean_true_add(json_row
,
962 json_object_boolean_false_add(json_row
,
966 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
967 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
968 !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))
971 if (json_vni
== NULL
) {
972 if ((wctx
->flags
& SHOW_REMOTE_NEIGH_FROM_VTEP
) &&
974 zevpn_print_neigh_hdr(vty
, wctx
);
975 vty_out(vty
, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
976 -wctx
->addr_width
, buf2
, "remote",
977 zevpn_print_neigh_flags(n
, flags_buf
,
980 n
->mac
->es
? n
->mac
->es
->esi_str
:
981 inet_ntoa(n
->r_vtep_ip
),
982 n
->loc_seq
, n
->rem_seq
);
984 json_object_string_add(json_row
, "type", "remote");
985 json_object_string_add(json_row
, "state", state_str
);
986 json_object_string_add(json_row
, "mac", buf1
);
988 json_object_string_add(json_row
, "remoteEs",
989 n
->mac
->es
->esi_str
);
991 json_object_string_add(json_row
, "remoteVtep",
992 inet_ntoa(n
->r_vtep_ip
));
993 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
))
994 json_object_boolean_true_add(json_row
,
996 json_object_int_add(json_row
, "localSequence",
998 json_object_int_add(json_row
, "remoteSequence",
1000 json_object_int_add(json_row
, "detectionCount",
1002 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1003 json_object_boolean_true_add(json_row
,
1006 json_object_boolean_false_add(json_row
,
1013 json_object_object_add(json_evpn
, buf2
, json_row
);
1017 * Print neighbor hash entry in detail - called for display of all neighbors.
1019 static void zevpn_print_neigh_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1022 json_object
*json_evpn
= NULL
, *json_row
= NULL
;
1024 char buf
[INET6_ADDRSTRLEN
];
1025 struct neigh_walk_ctx
*wctx
= ctxt
;
1028 json_evpn
= wctx
->json
;
1029 n
= (zebra_neigh_t
*)bucket
->data
;
1033 ipaddr2str(&n
->ip
, buf
, sizeof(buf
));
1035 json_row
= json_object_new_object();
1037 zevpn_print_neigh(n
, vty
, json_row
);
1040 json_object_object_add(json_evpn
, buf
, json_row
);
1044 * Print neighbors for all EVPN.
1046 static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket
*bucket
,
1050 json_object
*json
= NULL
, *json_evpn
= NULL
;
1051 zebra_evpn_t
*zevpn
;
1053 struct neigh_walk_ctx wctx
;
1054 char vni_str
[VNI_STR_LEN
];
1057 vty
= (struct vty
*)args
[0];
1058 json
= (json_object
*)args
[1];
1059 print_dup
= (uint32_t)(uintptr_t)args
[2];
1061 zevpn
= (zebra_evpn_t
*)bucket
->data
;
1063 num_neigh
= hashcount(zevpn
->neigh_table
);
1066 num_neigh
= num_dup_detected_neighs(zevpn
);
1070 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1071 zevpn
->vni
, num_neigh
);
1073 json_evpn
= json_object_new_object();
1074 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
1075 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
1080 json_object_object_add(json
, vni_str
, json_evpn
);
1084 /* Since we have IPv6 addresses to deal with which can vary widely in
1085 * size, we try to be a bit more elegant in display by first computing
1086 * the maximum width.
1088 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1091 wctx
.addr_width
= 15;
1092 wctx
.json
= json_evpn
;
1093 hash_iterate(zevpn
->neigh_table
, zevpn_find_neigh_addr_width
, &wctx
);
1096 zevpn_print_neigh_hdr(vty
, &wctx
);
1099 hash_iterate(zevpn
->neigh_table
, zevpn_print_dad_neigh_hash
,
1102 hash_iterate(zevpn
->neigh_table
, zevpn_print_neigh_hash
, &wctx
);
1105 json_object_object_add(json
, vni_str
, json_evpn
);
1108 static void zevpn_print_dad_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
1112 nbr
= (zebra_neigh_t
*)bucket
->data
;
1116 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1117 zevpn_print_neigh_hash(bucket
, ctxt
);
1120 static void zevpn_print_dad_neigh_hash_detail(struct hash_bucket
*bucket
,
1125 nbr
= (zebra_neigh_t
*)bucket
->data
;
1129 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
1130 zevpn_print_neigh_hash_detail(bucket
, ctxt
);
1134 * Print neighbors for all EVPNs in detail.
1136 static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket
*bucket
,
1140 json_object
*json
= NULL
, *json_evpn
= NULL
;
1141 zebra_evpn_t
*zevpn
;
1143 struct neigh_walk_ctx wctx
;
1144 char vni_str
[VNI_STR_LEN
];
1147 vty
= (struct vty
*)args
[0];
1148 json
= (json_object
*)args
[1];
1149 print_dup
= (uint32_t)(uintptr_t)args
[2];
1151 zevpn
= (zebra_evpn_t
*)bucket
->data
;
1154 vty_out(vty
, "{}\n");
1157 num_neigh
= hashcount(zevpn
->neigh_table
);
1159 if (print_dup
&& num_dup_detected_neighs(zevpn
) == 0)
1164 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1165 zevpn
->vni
, num_neigh
);
1167 json_evpn
= json_object_new_object();
1168 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
1169 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
1173 json_object_object_add(json
, vni_str
, json_evpn
);
1177 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
1180 wctx
.addr_width
= 15;
1181 wctx
.json
= json_evpn
;
1184 hash_iterate(zevpn
->neigh_table
,
1185 zevpn_print_dad_neigh_hash_detail
, &wctx
);
1187 hash_iterate(zevpn
->neigh_table
, zevpn_print_neigh_hash_detail
,
1191 json_object_object_add(json
, vni_str
, json_evpn
);
1194 /* print a specific next hop for an l3vni */
1195 static void zl3vni_print_nh(zebra_neigh_t
*n
, struct vty
*vty
,
1198 char buf1
[ETHER_ADDR_STRLEN
];
1199 char buf2
[INET6_ADDRSTRLEN
];
1200 json_object
*json_hosts
= NULL
;
1201 struct host_rb_entry
*hle
;
1204 vty_out(vty
, "Ip: %s\n",
1205 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1206 vty_out(vty
, " RMAC: %s\n",
1207 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1208 vty_out(vty
, " Refcount: %d\n",
1209 rb_host_count(&n
->host_rb
));
1210 vty_out(vty
, " Prefixes:\n");
1211 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1212 vty_out(vty
, " %s\n",
1213 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1215 json_hosts
= json_object_new_array();
1216 json_object_string_add(
1217 json
, "ip", ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)));
1218 json_object_string_add(
1220 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)));
1221 json_object_int_add(json
, "refCount",
1222 rb_host_count(&n
->host_rb
));
1223 RB_FOREACH (hle
, host_rb_tree_entry
, &n
->host_rb
)
1224 json_object_array_add(json_hosts
,
1225 json_object_new_string(prefix2str(
1226 &hle
->p
, buf2
, sizeof(buf2
))));
1227 json_object_object_add(json
, "prefixList", json_hosts
);
1231 /* Print a specific RMAC entry */
1232 static void zl3vni_print_rmac(zebra_mac_t
*zrmac
, struct vty
*vty
,
1235 char buf1
[ETHER_ADDR_STRLEN
];
1236 char buf2
[PREFIX_STRLEN
];
1237 json_object
*json_hosts
= NULL
;
1238 struct host_rb_entry
*hle
;
1241 vty_out(vty
, "MAC: %s\n",
1242 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1243 vty_out(vty
, " Remote VTEP: %s\n",
1244 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1245 vty_out(vty
, " Refcount: %d\n", rb_host_count(&zrmac
->host_rb
));
1246 vty_out(vty
, " Prefixes:\n");
1247 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1248 vty_out(vty
, " %s\n",
1249 prefix2str(&hle
->p
, buf2
, sizeof(buf2
)));
1251 json_hosts
= json_object_new_array();
1252 json_object_string_add(
1254 prefix_mac2str(&zrmac
->macaddr
, buf1
, sizeof(buf1
)));
1255 json_object_string_add(json
, "vtepIp",
1256 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1257 json_object_int_add(json
, "refCount",
1258 rb_host_count(&zrmac
->host_rb
));
1259 json_object_int_add(json
, "localSequence", zrmac
->loc_seq
);
1260 json_object_int_add(json
, "remoteSequence", zrmac
->rem_seq
);
1261 RB_FOREACH (hle
, host_rb_tree_entry
, &zrmac
->host_rb
)
1262 json_object_array_add(
1264 json_object_new_string(prefix2str(
1265 &hle
->p
, buf2
, sizeof(buf2
))));
1266 json_object_object_add(json
, "prefixList", json_hosts
);
1271 zebra_vxlan_mac_get_access_info(zebra_mac_t
*mac
,
1272 struct interface
**ifpP
, vlanid_t
*vid
)
1274 /* if the mac is associated with an ES we must get the access
1278 struct zebra_if
*zif
;
1280 /* get the access port from the es */
1281 *ifpP
= mac
->es
->zif
? mac
->es
->zif
->ifp
: NULL
;
1282 /* get the vlan from the EVPN */
1283 if (mac
->zevpn
->vxlan_if
) {
1284 zif
= mac
->zevpn
->vxlan_if
->info
;
1285 *vid
= zif
->l2info
.vxl
.access_vlan
;
1290 struct zebra_ns
*zns
;
1292 *vid
= mac
->fwd_info
.local
.vid
;
1293 zns
= zebra_ns_lookup(NS_DEFAULT
);
1294 *ifpP
= if_lookup_by_index_per_ns(zns
,
1295 mac
->fwd_info
.local
.ifindex
);
1300 * Print a specific MAC entry.
1302 static void zevpn_print_mac(zebra_mac_t
*mac
, void *ctxt
, json_object
*json
)
1305 zebra_neigh_t
*n
= NULL
;
1306 struct listnode
*node
= NULL
;
1307 char buf1
[ETHER_ADDR_STRLEN
];
1308 char buf2
[INET6_ADDRSTRLEN
];
1309 struct zebra_vrf
*zvrf
;
1310 struct timeval detect_start_time
= {0, 0};
1311 char timebuf
[MONOTIME_STRLEN
];
1312 char thread_buf
[THREAD_TIMER_STRLEN
];
1314 zvrf
= zebra_vrf_get_evpn();
1318 vty
= (struct vty
*)ctxt
;
1319 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1322 json_object
*json_mac
= json_object_new_object();
1324 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1325 struct interface
*ifp
;
1328 zebra_vxlan_mac_get_access_info(mac
,
1330 json_object_string_add(json_mac
, "type", "local");
1332 json_object_string_add(json_mac
,
1334 json_object_int_add(json_mac
,
1335 "ifindex", ifp
->ifindex
);
1338 json_object_int_add(json_mac
, "vlan",
1340 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1341 json_object_string_add(json_mac
, "type", "remote");
1342 json_object_string_add(
1343 json_mac
, "remoteVtep",
1344 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1345 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
1346 json_object_string_add(json_mac
, "type", "auto");
1348 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1349 json_object_boolean_true_add(json_mac
, "stickyMac");
1351 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1352 json_object_boolean_true_add(json_mac
,
1355 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1356 json_object_boolean_true_add(json_mac
,
1357 "remoteGatewayMac");
1359 json_object_int_add(json_mac
, "localSequence", mac
->loc_seq
);
1360 json_object_int_add(json_mac
, "remoteSequence", mac
->rem_seq
);
1362 json_object_int_add(json_mac
, "detectionCount", mac
->dad_count
);
1363 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1364 json_object_boolean_true_add(json_mac
, "isDuplicate");
1366 json_object_boolean_false_add(json_mac
, "isDuplicate");
1368 json_object_int_add(json_mac
, "syncNeighCount", mac
->sync_neigh_cnt
);
1369 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
))
1370 json_object_boolean_true_add(json_mac
,
1372 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_PROXY
))
1373 json_object_boolean_true_add(json_mac
,
1375 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
1376 json_object_boolean_true_add(json_mac
,
1378 if (mac
->hold_timer
)
1379 json_object_string_add(json_mac
, "peerActiveHold",
1380 thread_timer_to_hhmmss(
1385 json_object_string_add(json_mac
, "esi",
1387 /* print all the associated neigh */
1388 if (!listcount(mac
->neigh_list
))
1389 json_object_string_add(json_mac
, "neighbors", "none");
1391 json_object
*json_active_nbrs
= json_object_new_array();
1392 json_object
*json_inactive_nbrs
=
1393 json_object_new_array();
1394 json_object
*json_nbrs
= json_object_new_object();
1396 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1397 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
1398 json_object_array_add(
1400 json_object_new_string(
1405 json_object_array_add(
1407 json_object_new_string(
1413 json_object_object_add(json_nbrs
, "active",
1415 json_object_object_add(json_nbrs
, "inactive",
1416 json_inactive_nbrs
);
1417 json_object_object_add(json_mac
, "neighbors",
1421 json_object_object_add(json
, buf1
, json_mac
);
1423 vty_out(vty
, "MAC: %s\n", buf1
);
1425 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1426 struct interface
*ifp
;
1429 zebra_vxlan_mac_get_access_info(mac
,
1433 vty_out(vty
, " ESI: %s\n", mac
->es
->esi_str
);
1436 vty_out(vty
, " Intf: %s(%u)",
1437 ifp
->name
, ifp
->ifindex
);
1439 vty_out(vty
, " Intf: -");
1440 vty_out(vty
, " VLAN: %u", vid
);
1441 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1443 vty_out(vty
, " Remote ES: %s",
1446 vty_out(vty
, " Remote VTEP: %s",
1447 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1448 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
1449 vty_out(vty
, " Auto Mac ");
1452 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
1453 vty_out(vty
, " Sticky Mac ");
1455 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
))
1456 vty_out(vty
, " Default-gateway Mac ");
1458 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
))
1459 vty_out(vty
, " Remote-gateway Mac ");
1462 vty_out(vty
, " Sync-info: neigh#: %u", mac
->sync_neigh_cnt
);
1463 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
))
1464 vty_out(vty
, " local-inactive");
1465 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_PROXY
))
1466 vty_out(vty
, " peer-proxy");
1467 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
1468 vty_out(vty
, " peer-active");
1469 if (mac
->hold_timer
)
1470 vty_out(vty
, " (ht: %s)",
1471 thread_timer_to_hhmmss(
1476 vty_out(vty
, " Local Seq: %u Remote Seq: %u",
1477 mac
->loc_seq
, mac
->rem_seq
);
1480 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
1481 vty_out(vty
, " Duplicate, detected at %s",
1482 time_to_string(mac
->dad_dup_detect_time
,
1484 } else if (mac
->dad_count
) {
1485 monotime_since(&mac
->detect_start_time
,
1486 &detect_start_time
);
1487 if (detect_start_time
.tv_sec
<= zvrf
->dad_time
) {
1488 time_to_string(mac
->detect_start_time
.tv_sec
,
1491 " Duplicate detection started at %s, detection count %u\n",
1492 timebuf
, mac
->dad_count
);
1496 /* print all the associated neigh */
1497 vty_out(vty
, " Neighbors:\n");
1498 if (!listcount(mac
->neigh_list
))
1499 vty_out(vty
, " No Neighbors\n");
1501 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, n
)) {
1502 vty_out(vty
, " %s %s\n",
1503 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
1504 (IS_ZEBRA_NEIGH_ACTIVE(n
)
1514 static char *zevpn_print_mac_flags(zebra_mac_t
*mac
, char *flags_buf
,
1515 uint32_t flags_buf_sz
)
1517 snprintf(flags_buf
, flags_buf_sz
, "%s%s%s%s",
1518 mac
->sync_neigh_cnt
?
1520 (mac
->flags
& ZEBRA_MAC_ES_PEER_ACTIVE
) ?
1522 (mac
->flags
& ZEBRA_MAC_ES_PEER_PROXY
) ?
1524 (mac
->flags
& ZEBRA_MAC_LOCAL_INACTIVE
) ?
1531 * Print MAC hash entry - called for display of all MACs.
1533 static void zevpn_print_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1536 json_object
*json_mac_hdr
= NULL
, *json_mac
= NULL
;
1538 char buf1
[ETHER_ADDR_STRLEN
];
1539 struct mac_walk_ctx
*wctx
= ctxt
;
1543 json_mac_hdr
= wctx
->json
;
1544 mac
= (zebra_mac_t
*)bucket
->data
;
1546 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1549 json_mac
= json_object_new_object();
1551 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
1552 struct interface
*ifp
;
1555 if (wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
)
1558 zebra_vxlan_mac_get_access_info(mac
,
1560 if (json_mac_hdr
== NULL
) {
1561 vty_out(vty
, "%-17s %-6s %-5s %-30s", buf1
, "local",
1562 zevpn_print_mac_flags(mac
, flags_buf
,
1564 ifp
? ifp
->name
: "-");
1566 json_object_string_add(json_mac
, "type", "local");
1568 json_object_string_add(json_mac
,
1572 if (json_mac_hdr
== NULL
)
1573 vty_out(vty
, " %-5u", vid
);
1575 json_object_int_add(json_mac
, "vlan", vid
);
1576 } else /* No vid? fill out the space */
1577 if (json_mac_hdr
== NULL
)
1578 vty_out(vty
, " %-5s", "");
1579 if (json_mac_hdr
== NULL
) {
1580 vty_out(vty
, " %u/%u", mac
->loc_seq
, mac
->rem_seq
);
1583 json_object_int_add(json_mac
, "localSequence",
1585 json_object_int_add(json_mac
, "remoteSequence",
1587 json_object_int_add(json_mac
, "detectionCount",
1589 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1590 json_object_boolean_true_add(json_mac
,
1593 json_object_boolean_false_add(json_mac
,
1595 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1600 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
1602 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1603 !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
,
1607 if (json_mac_hdr
== NULL
) {
1608 if ((wctx
->flags
& SHOW_REMOTE_MAC_FROM_VTEP
) &&
1609 (wctx
->count
== 0)) {
1610 vty_out(vty
, "\nVNI %u\n\n", wctx
->zevpn
->vni
);
1611 vty_out(vty
, "%-17s %-6s %-5s%-30s %-5s %s\n",
1612 "MAC", "Type", "Flags",
1613 "Intf/Remote ES/VTEP",
1616 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1
,
1618 zevpn_print_mac_flags(mac
, flags_buf
,
1620 mac
->es
? mac
->es
->esi_str
:
1621 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
1622 "", mac
->loc_seq
, mac
->rem_seq
);
1624 json_object_string_add(json_mac
, "type", "remote");
1625 json_object_string_add(json_mac
, "remoteVtep",
1626 inet_ntoa(mac
->fwd_info
.r_vtep_ip
));
1627 json_object_object_add(json_mac_hdr
, buf1
, json_mac
);
1628 json_object_int_add(json_mac
, "localSequence",
1630 json_object_int_add(json_mac
, "remoteSequence",
1632 json_object_int_add(json_mac
, "detectionCount",
1634 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1635 json_object_boolean_true_add(json_mac
,
1638 json_object_boolean_false_add(json_mac
,
1647 /* Print Duplicate MAC */
1648 static void zevpn_print_dad_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
1652 mac
= (zebra_mac_t
*)bucket
->data
;
1656 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1657 zevpn_print_mac_hash(bucket
, ctxt
);
1661 * Print MAC hash entry in detail - called for display of all MACs.
1663 static void zevpn_print_mac_hash_detail(struct hash_bucket
*bucket
, void *ctxt
)
1666 json_object
*json_mac_hdr
= NULL
;
1668 struct mac_walk_ctx
*wctx
= ctxt
;
1669 char buf1
[ETHER_ADDR_STRLEN
];
1672 json_mac_hdr
= wctx
->json
;
1673 mac
= (zebra_mac_t
*)bucket
->data
;
1678 prefix_mac2str(&mac
->macaddr
, buf1
, sizeof(buf1
));
1680 zevpn_print_mac(mac
, vty
, json_mac_hdr
);
1683 /* Print Duplicate MAC in detail */
1684 static void zevpn_print_dad_mac_hash_detail(struct hash_bucket
*bucket
,
1689 mac
= (zebra_mac_t
*)bucket
->data
;
1693 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
1694 zevpn_print_mac_hash_detail(bucket
, ctxt
);
1698 * Print MACs for all EVPNs.
1700 static void zevpn_print_mac_hash_all_evpn(struct hash_bucket
*bucket
, void *ctxt
)
1703 json_object
*json
= NULL
, *json_evpn
= NULL
;
1704 json_object
*json_mac
= NULL
;
1705 zebra_evpn_t
*zevpn
;
1707 struct mac_walk_ctx
*wctx
= ctxt
;
1708 char vni_str
[VNI_STR_LEN
];
1713 zevpn
= (zebra_evpn_t
*)bucket
->data
;
1714 wctx
->zevpn
= zevpn
;
1716 /*We are iterating over a new VNI, set the count to 0*/
1719 num_macs
= num_valid_macs(zevpn
);
1723 if (wctx
->print_dup
)
1724 num_macs
= num_dup_detected_macs(zevpn
);
1727 json_evpn
= json_object_new_object();
1728 json_mac
= json_object_new_object();
1729 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
1732 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1734 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1735 zevpn
->vni
, num_macs
);
1737 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
1738 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
1739 "Type", "Flags", "Intf/Remote ES/VTEP",
1742 json_object_int_add(json_evpn
, "numMacs", num_macs
);
1747 json_object_int_add(json_evpn
, "numMacs", num_macs
);
1748 json_object_object_add(json
, vni_str
, json_evpn
);
1753 /* assign per-evpn to wctx->json object to fill macs
1754 * under the evpn. Re-assign primary json object to fill
1755 * next evpn information.
1757 wctx
->json
= json_mac
;
1758 if (wctx
->print_dup
)
1759 hash_iterate(zevpn
->mac_table
, zevpn_print_dad_mac_hash
, wctx
);
1761 hash_iterate(zevpn
->mac_table
, zevpn_print_mac_hash
, wctx
);
1765 json_object_object_add(json_evpn
, "macs", json_mac
);
1766 json_object_object_add(json
, vni_str
, json_evpn
);
1771 * Print MACs in detail for all EVPNs.
1773 static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket
*bucket
,
1777 json_object
*json
= NULL
, *json_evpn
= NULL
;
1778 json_object
*json_mac
= NULL
;
1779 zebra_evpn_t
*zevpn
;
1781 struct mac_walk_ctx
*wctx
= ctxt
;
1782 char vni_str
[VNI_STR_LEN
];
1787 zevpn
= (zebra_evpn_t
*)bucket
->data
;
1790 vty_out(vty
, "{}\n");
1793 wctx
->zevpn
= zevpn
;
1795 /*We are iterating over a new EVPN, set the count to 0*/
1798 num_macs
= num_valid_macs(zevpn
);
1802 if (wctx
->print_dup
&& (num_dup_detected_macs(zevpn
) == 0))
1806 json_evpn
= json_object_new_object();
1807 json_mac
= json_object_new_object();
1808 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
1811 if (!CHECK_FLAG(wctx
->flags
, SHOW_REMOTE_MAC_FROM_VTEP
)) {
1813 vty_out(vty
, "\nVNI %u #MACs (local and remote) %u\n\n",
1814 zevpn
->vni
, num_macs
);
1816 json_object_int_add(json_evpn
, "numMacs", num_macs
);
1818 /* assign per-evpn to wctx->json object to fill macs
1819 * under the evpn. Re-assign primary json object to fill
1820 * next evpn information.
1822 wctx
->json
= json_mac
;
1823 if (wctx
->print_dup
)
1824 hash_iterate(zevpn
->mac_table
, zevpn_print_dad_mac_hash_detail
,
1827 hash_iterate(zevpn
->mac_table
, zevpn_print_mac_hash_detail
, wctx
);
1831 json_object_object_add(json_evpn
, "macs", json_mac
);
1832 json_object_object_add(json
, vni_str
, json_evpn
);
1836 static void zl3vni_print_nh_hash(struct hash_bucket
*bucket
, void *ctx
)
1838 struct nh_walk_ctx
*wctx
= NULL
;
1839 struct vty
*vty
= NULL
;
1840 struct json_object
*json_evpn
= NULL
;
1841 struct json_object
*json_nh
= NULL
;
1842 zebra_neigh_t
*n
= NULL
;
1843 char buf1
[ETHER_ADDR_STRLEN
];
1844 char buf2
[INET6_ADDRSTRLEN
];
1846 wctx
= (struct nh_walk_ctx
*)ctx
;
1848 json_evpn
= wctx
->json
;
1850 json_nh
= json_object_new_object();
1851 n
= (zebra_neigh_t
*)bucket
->data
;
1854 vty_out(vty
, "%-15s %-17s\n",
1855 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1856 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1858 json_object_string_add(json_nh
, "nexthopIp",
1859 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
1860 json_object_string_add(
1861 json_nh
, "routerMac",
1862 prefix_mac2str(&n
->emac
, buf1
, sizeof(buf1
)));
1863 json_object_object_add(json_evpn
,
1864 ipaddr2str(&(n
->ip
), buf2
, sizeof(buf2
)),
1869 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket
*bucket
,
1872 struct vty
*vty
= NULL
;
1873 json_object
*json
= NULL
;
1874 json_object
*json_evpn
= NULL
;
1875 zebra_l3vni_t
*zl3vni
= NULL
;
1876 uint32_t num_nh
= 0;
1877 struct nh_walk_ctx wctx
;
1878 char vni_str
[VNI_STR_LEN
];
1880 vty
= (struct vty
*)args
[0];
1881 json
= (struct json_object
*)args
[1];
1883 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1885 num_nh
= hashcount(zl3vni
->nh_table
);
1890 json_evpn
= json_object_new_object();
1891 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1895 vty_out(vty
, "\nVNI %u #Next-Hops %u\n\n", zl3vni
->vni
, num_nh
);
1896 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
1898 json_object_int_add(json_evpn
, "numNextHops", num_nh
);
1900 memset(&wctx
, 0, sizeof(struct nh_walk_ctx
));
1902 wctx
.json
= json_evpn
;
1903 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
1905 json_object_object_add(json
, vni_str
, json_evpn
);
1908 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket
*bucket
,
1911 struct vty
*vty
= NULL
;
1912 json_object
*json
= NULL
;
1913 json_object
*json_evpn
= NULL
;
1914 zebra_l3vni_t
*zl3vni
= NULL
;
1916 struct rmac_walk_ctx wctx
;
1917 char vni_str
[VNI_STR_LEN
];
1919 vty
= (struct vty
*)args
[0];
1920 json
= (struct json_object
*)args
[1];
1922 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
1924 num_rmacs
= hashcount(zl3vni
->rmac_table
);
1929 json_evpn
= json_object_new_object();
1930 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
1934 vty_out(vty
, "\nVNI %u #RMACs %u\n\n", zl3vni
->vni
, num_rmacs
);
1935 vty_out(vty
, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1937 json_object_int_add(json_evpn
, "numRmacs", num_rmacs
);
1939 /* assign per-vni to wctx->json object to fill macs
1940 * under the vni. Re-assign primary json object to fill
1941 * next vni information.
1943 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
1945 wctx
.json
= json_evpn
;
1946 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
1948 json_object_object_add(json
, vni_str
, json_evpn
);
1951 static void zl3vni_print_rmac_hash(struct hash_bucket
*bucket
, void *ctx
)
1953 zebra_mac_t
*zrmac
= NULL
;
1954 struct rmac_walk_ctx
*wctx
= NULL
;
1955 struct vty
*vty
= NULL
;
1956 struct json_object
*json
= NULL
;
1957 struct json_object
*json_rmac
= NULL
;
1958 char buf
[ETHER_ADDR_STRLEN
];
1960 wctx
= (struct rmac_walk_ctx
*)ctx
;
1964 json_rmac
= json_object_new_object();
1965 zrmac
= (zebra_mac_t
*)bucket
->data
;
1968 vty_out(vty
, "%-17s %-21s\n",
1969 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1970 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1972 json_object_string_add(
1973 json_rmac
, "routerMac",
1974 prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)));
1975 json_object_string_add(json_rmac
, "vtepIp",
1976 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
));
1977 json_object_object_add(
1978 json
, prefix_mac2str(&zrmac
->macaddr
, buf
, sizeof(buf
)),
1983 /* print a specific L3 VNI entry */
1984 static void zl3vni_print(zebra_l3vni_t
*zl3vni
, void **ctx
)
1986 char buf
[ETHER_ADDR_STRLEN
];
1987 struct vty
*vty
= NULL
;
1988 json_object
*json
= NULL
;
1989 zebra_evpn_t
*zevpn
= NULL
;
1990 json_object
*json_evpn_list
= NULL
;
1991 struct listnode
*node
= NULL
, *nnode
= NULL
;
1997 vty_out(vty
, "VNI: %u\n", zl3vni
->vni
);
1998 vty_out(vty
, " Type: %s\n", "L3");
1999 vty_out(vty
, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni
));
2000 vty_out(vty
, " Local Vtep Ip: %s\n",
2001 inet_ntoa(zl3vni
->local_vtep_ip
));
2002 vty_out(vty
, " Vxlan-Intf: %s\n",
2003 zl3vni_vxlan_if_name(zl3vni
));
2004 vty_out(vty
, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni
));
2005 vty_out(vty
, " State: %s\n", zl3vni_state2str(zl3vni
));
2006 vty_out(vty
, " VNI Filter: %s\n",
2007 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
2008 ? "prefix-routes-only"
2010 vty_out(vty
, " System MAC: %s\n",
2011 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
2012 vty_out(vty
, " Router MAC: %s\n",
2013 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2014 vty_out(vty
, " L2 VNIs: ");
2015 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
))
2016 vty_out(vty
, "%u ", zevpn
->vni
);
2019 json_evpn_list
= json_object_new_array();
2020 json_object_int_add(json
, "vni", zl3vni
->vni
);
2021 json_object_string_add(json
, "type", "L3");
2022 json_object_string_add(json
, "localVtepIp",
2023 inet_ntoa(zl3vni
->local_vtep_ip
));
2024 json_object_string_add(json
, "vxlanIntf",
2025 zl3vni_vxlan_if_name(zl3vni
));
2026 json_object_string_add(json
, "sviIntf",
2027 zl3vni_svi_if_name(zl3vni
));
2028 json_object_string_add(json
, "state", zl3vni_state2str(zl3vni
));
2029 json_object_string_add(json
, "vrf", zl3vni_vrf_name(zl3vni
));
2030 json_object_string_add(
2032 zl3vni_sysmac2str(zl3vni
, buf
, sizeof(buf
)));
2033 json_object_string_add(
2035 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
2036 json_object_string_add(
2038 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
2039 ? "prefix-routes-only"
2041 for (ALL_LIST_ELEMENTS(zl3vni
->l2vnis
, node
, nnode
, zevpn
)) {
2042 json_object_array_add(json_evpn_list
,
2043 json_object_new_int(zevpn
->vni
));
2045 json_object_object_add(json
, "l2Vnis", json_evpn_list
);
2050 * Print a specific EVPN entry.
2052 static void zevpn_print(zebra_evpn_t
*zevpn
, void **ctxt
)
2055 zebra_vtep_t
*zvtep
;
2058 json_object
*json
= NULL
;
2059 json_object
*json_vtep_list
= NULL
;
2060 json_object
*json_ip_str
= NULL
;
2066 vty_out(vty
, "VNI: %u\n", zevpn
->vni
);
2067 vty_out(vty
, " Type: %s\n", "L2");
2068 vty_out(vty
, " Tenant VRF: %s\n", vrf_id_to_name(zevpn
->vrf_id
));
2070 json_object_int_add(json
, "vni", zevpn
->vni
);
2071 json_object_string_add(json
, "type", "L2");
2072 json_object_string_add(json
, "vrf",
2073 vrf_id_to_name(zevpn
->vrf_id
));
2076 if (!zevpn
->vxlan_if
) { // unexpected
2078 vty_out(vty
, " VxLAN interface: unknown\n");
2081 num_macs
= num_valid_macs(zevpn
);
2082 num_neigh
= hashcount(zevpn
->neigh_table
);
2084 vty_out(vty
, " VxLAN interface: %s\n", zevpn
->vxlan_if
->name
);
2085 vty_out(vty
, " VxLAN ifIndex: %u\n", zevpn
->vxlan_if
->ifindex
);
2086 vty_out(vty
, " Local VTEP IP: %s\n",
2087 inet_ntoa(zevpn
->local_vtep_ip
));
2088 vty_out(vty
, " Mcast group: %s\n",
2089 inet_ntoa(zevpn
->mcast_grp
));
2091 json_object_string_add(json
, "vxlanInterface",
2092 zevpn
->vxlan_if
->name
);
2093 json_object_int_add(json
, "ifindex", zevpn
->vxlan_if
->ifindex
);
2094 json_object_string_add(json
, "vtepIp",
2095 inet_ntoa(zevpn
->local_vtep_ip
));
2096 json_object_string_add(json
, "mcastGroup",
2097 inet_ntoa(zevpn
->mcast_grp
));
2098 json_object_string_add(json
, "advertiseGatewayMacip",
2099 zevpn
->advertise_gw_macip
? "Yes" : "No");
2100 json_object_int_add(json
, "numMacs", num_macs
);
2101 json_object_int_add(json
, "numArpNd", num_neigh
);
2103 if (!zevpn
->vteps
) {
2105 vty_out(vty
, " No remote VTEPs known for this VNI\n");
2108 vty_out(vty
, " Remote VTEPs for this VNI:\n");
2110 json_vtep_list
= json_object_new_array();
2111 for (zvtep
= zevpn
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2112 const char *flood_str
= lookup_msg(zvtep_flood_str
,
2113 zvtep
->flood_control
,
2114 VXLAN_FLOOD_STR_DEFAULT
);
2117 vty_out(vty
, " %s flood: %s\n",
2118 inet_ntoa(zvtep
->vtep_ip
),
2121 json_ip_str
= json_object_new_string(
2122 inet_ntoa(zvtep
->vtep_ip
));
2123 json_object_array_add(json_vtep_list
,
2128 json_object_object_add(json
, "numRemoteVteps",
2133 " Number of MACs (local and remote) known for this VNI: %u\n",
2136 " Number of ARPs (IPv4 and IPv6, local and remote) known for this VNI: %u\n",
2138 vty_out(vty
, " Advertise-gw-macip: %s\n",
2139 zevpn
->advertise_gw_macip
? "Yes" : "No");
2143 /* print a L3 VNI hash entry */
2144 static void zl3vni_print_hash(struct hash_bucket
*bucket
, void *ctx
[])
2146 struct vty
*vty
= NULL
;
2147 json_object
*json
= NULL
;
2148 json_object
*json_evpn
= NULL
;
2149 zebra_l3vni_t
*zl3vni
= NULL
;
2151 vty
= (struct vty
*)ctx
[0];
2152 json
= (json_object
*)ctx
[1];
2154 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2157 vty_out(vty
, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
2158 zl3vni
->vni
, "L3", zl3vni_vxlan_if_name(zl3vni
),
2159 hashcount(zl3vni
->rmac_table
),
2160 hashcount(zl3vni
->nh_table
), "n/a",
2161 zl3vni_vrf_name(zl3vni
));
2163 char vni_str
[VNI_STR_LEN
];
2165 snprintf(vni_str
, VNI_STR_LEN
, "%u", zl3vni
->vni
);
2166 json_evpn
= json_object_new_object();
2167 json_object_int_add(json_evpn
, "vni", zl3vni
->vni
);
2168 json_object_string_add(json_evpn
, "vxlanIf",
2169 zl3vni_vxlan_if_name(zl3vni
));
2170 json_object_int_add(json_evpn
, "numMacs",
2171 hashcount(zl3vni
->rmac_table
));
2172 json_object_int_add(json_evpn
, "numArpNd",
2173 hashcount(zl3vni
->nh_table
));
2174 json_object_string_add(json_evpn
, "numRemoteVteps", "n/a");
2175 json_object_string_add(json_evpn
, "type", "L3");
2176 json_object_string_add(json_evpn
, "tenantVrf",
2177 zl3vni_vrf_name(zl3vni
));
2178 json_object_object_add(json
, vni_str
, json_evpn
);
2182 /* Private Structure to pass callback data for hash iterator */
2186 struct zebra_vrf
*zvrf
;
2190 /* print a L3 VNI hash entry in detail*/
2191 static void zl3vni_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2193 struct vty
*vty
= NULL
;
2194 zebra_l3vni_t
*zl3vni
= NULL
;
2195 json_object
*json_array
= NULL
;
2196 bool use_json
= false;
2197 struct zevpn_show
*zes
= data
;
2200 json_array
= zes
->json
;
2201 use_json
= zes
->use_json
;
2203 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
2205 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zl3vni
->vni
,
2206 use_json
, json_array
);
2214 * Print an EVPN hash entry - called for display of all VNIs.
2216 static void zevpn_print_hash(struct hash_bucket
*bucket
, void *ctxt
[])
2219 zebra_evpn_t
*zevpn
;
2220 zebra_vtep_t
*zvtep
;
2221 uint32_t num_vteps
= 0;
2222 uint32_t num_macs
= 0;
2223 uint32_t num_neigh
= 0;
2224 json_object
*json
= NULL
;
2225 json_object
*json_evpn
= NULL
;
2226 json_object
*json_ip_str
= NULL
;
2227 json_object
*json_vtep_list
= NULL
;
2232 zevpn
= (zebra_evpn_t
*)bucket
->data
;
2234 zvtep
= zevpn
->vteps
;
2237 zvtep
= zvtep
->next
;
2240 num_macs
= num_valid_macs(zevpn
);
2241 num_neigh
= hashcount(zevpn
->neigh_table
);
2243 vty_out(vty
, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2245 zevpn
->vxlan_if
? zevpn
->vxlan_if
->name
: "unknown",
2246 num_macs
, num_neigh
, num_vteps
,
2247 vrf_id_to_name(zevpn
->vrf_id
));
2249 char vni_str
[VNI_STR_LEN
];
2250 snprintf(vni_str
, VNI_STR_LEN
, "%u", zevpn
->vni
);
2251 json_evpn
= json_object_new_object();
2252 json_object_int_add(json_evpn
, "vni", zevpn
->vni
);
2253 json_object_string_add(json_evpn
, "type", "L2");
2254 json_object_string_add(json_evpn
, "vxlanIf",
2255 zevpn
->vxlan_if
? zevpn
->vxlan_if
->name
2257 json_object_int_add(json_evpn
, "numMacs", num_macs
);
2258 json_object_int_add(json_evpn
, "numArpNd", num_neigh
);
2259 json_object_int_add(json_evpn
, "numRemoteVteps", num_vteps
);
2260 json_object_string_add(json_evpn
, "tenantVrf",
2261 vrf_id_to_name(zevpn
->vrf_id
));
2263 json_vtep_list
= json_object_new_array();
2264 for (zvtep
= zevpn
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
2265 json_ip_str
= json_object_new_string(
2266 inet_ntoa(zvtep
->vtep_ip
));
2267 json_object_array_add(json_vtep_list
,
2270 json_object_object_add(json_evpn
, "remoteVteps",
2273 json_object_object_add(json
, vni_str
, json_evpn
);
2278 * Print an EVPN hash entry in detail - called for display of all EVPNs.
2280 static void zevpn_print_hash_detail(struct hash_bucket
*bucket
, void *data
)
2283 zebra_evpn_t
*zevpn
;
2284 json_object
*json_array
= NULL
;
2285 bool use_json
= false;
2286 struct zevpn_show
*zes
= data
;
2289 json_array
= zes
->json
;
2290 use_json
= zes
->use_json
;
2292 zevpn
= (zebra_evpn_t
*)bucket
->data
;
2294 zebra_vxlan_print_vni(vty
, zes
->zvrf
, zevpn
->vni
, use_json
, json_array
);
2301 * Inform BGP about local MACIP.
2303 static int zevpn_macip_send_msg_to_client(vni_t vni
, struct ethaddr
*macaddr
,
2304 struct ipaddr
*ip
, uint8_t flags
,
2305 uint32_t seq
, int state
,
2306 struct zebra_evpn_es
*es
,
2309 char buf
[ETHER_ADDR_STRLEN
];
2310 char buf2
[INET6_ADDRSTRLEN
];
2312 struct zserv
*client
= NULL
;
2313 struct stream
*s
= NULL
;
2314 esi_t
*esi
= es
? &es
->esi
: zero_esi
;
2316 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
2317 /* BGP may not be running. */
2321 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
2323 zclient_create_header(s
, cmd
, zebra_vrf_get_evpn_id());
2324 stream_putl(s
, vni
);
2325 stream_put(s
, macaddr
->octet
, ETH_ALEN
);
2328 if (IS_IPADDR_V4(ip
))
2329 ipa_len
= IPV4_MAX_BYTELEN
;
2330 else if (IS_IPADDR_V6(ip
))
2331 ipa_len
= IPV6_MAX_BYTELEN
;
2333 stream_putl(s
, ipa_len
); /* IP address length */
2335 stream_put(s
, &ip
->ip
.addr
, ipa_len
); /* IP address */
2337 stream_putl(s
, 0); /* Just MAC. */
2339 if (cmd
== ZEBRA_MACIP_ADD
) {
2340 stream_putc(s
, flags
); /* sticky mac/gateway mac */
2341 stream_putl(s
, seq
); /* sequence number */
2342 stream_put(s
, esi
, sizeof(esi_t
));
2344 stream_putl(s
, state
); /* state - active/inactive */
2348 /* Write packet size. */
2349 stream_putw_at(s
, 0, stream_get_endp(s
));
2351 if (IS_ZEBRA_DEBUG_VXLAN
)
2353 "Send MACIP %s f 0x%x MAC %s IP %s seq %u L2-VNI %u ESI %s to %s",
2354 (cmd
== ZEBRA_MACIP_ADD
) ? "Add" : "Del", flags
,
2355 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2356 ipaddr2str(ip
, buf2
, sizeof(buf2
)), seq
, vni
,
2357 es
? es
->esi_str
: "-",
2358 zebra_route_string(client
->proto
));
2360 if (cmd
== ZEBRA_MACIP_ADD
)
2361 client
->macipadd_cnt
++;
2363 client
->macipdel_cnt
++;
2365 return zserv_send_message(client
, s
);
2369 * Make hash key for neighbors.
2371 static unsigned int neigh_hash_keymake(const void *p
)
2373 const zebra_neigh_t
*n
= p
;
2374 const struct ipaddr
*ip
= &n
->ip
;
2376 if (IS_IPADDR_V4(ip
))
2377 return jhash_1word(ip
->ipaddr_v4
.s_addr
, 0);
2379 return jhash2(ip
->ipaddr_v6
.s6_addr32
,
2380 array_size(ip
->ipaddr_v6
.s6_addr32
), 0);
2384 * Compare two neighbor hash structures.
2386 static bool neigh_cmp(const void *p1
, const void *p2
)
2388 const zebra_neigh_t
*n1
= p1
;
2389 const zebra_neigh_t
*n2
= p2
;
2391 if (n1
== NULL
&& n2
== NULL
)
2394 if (n1
== NULL
|| n2
== NULL
)
2397 return (memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
)) == 0);
2400 static int neigh_list_cmp(void *p1
, void *p2
)
2402 const zebra_neigh_t
*n1
= p1
;
2403 const zebra_neigh_t
*n2
= p2
;
2405 return memcmp(&n1
->ip
, &n2
->ip
, sizeof(struct ipaddr
));
2409 * Callback to allocate neighbor hash entry.
2411 static void *zevpn_neigh_alloc(void *p
)
2413 const zebra_neigh_t
*tmp_n
= p
;
2416 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
2423 * Add neighbor entry.
2425 static zebra_neigh_t
*zevpn_neigh_add(zebra_evpn_t
*zevpn
, struct ipaddr
*ip
,
2426 struct ethaddr
*mac
, zebra_mac_t
*zmac
,
2429 zebra_neigh_t tmp_n
;
2430 zebra_neigh_t
*n
= NULL
;
2432 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
2433 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
2434 n
= hash_get(zevpn
->neigh_table
, &tmp_n
, zevpn_neigh_alloc
);
2437 n
->state
= ZEBRA_NEIGH_INACTIVE
;
2439 n
->dad_ip_auto_recovery_timer
= NULL
;
2443 zmac
= zevpn_mac_lookup(zevpn
, mac
);
2444 zebra_vxlan_local_neigh_ref_mac(n
, mac
,
2445 zmac
, false /* send_mac_update */);
2451 * Delete neighbor entry.
2453 static int zevpn_neigh_del(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
)
2455 zebra_neigh_t
*tmp_n
;
2458 listnode_delete(n
->mac
->neigh_list
, n
);
2460 /* Cancel auto recovery */
2461 THREAD_OFF(n
->dad_ip_auto_recovery_timer
);
2463 /* Free the VNI hash entry and allocated memory. */
2464 tmp_n
= hash_release(zevpn
->neigh_table
, n
);
2465 XFREE(MTYPE_NEIGH
, tmp_n
);
2471 * Free neighbor hash entry (callback)
2473 static void zevpn_neigh_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
2475 struct neigh_walk_ctx
*wctx
= arg
;
2476 zebra_neigh_t
*n
= bucket
->data
;
2478 if (((wctx
->flags
& DEL_LOCAL_NEIGH
) && (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2479 || ((wctx
->flags
& DEL_REMOTE_NEIGH
)
2480 && (n
->flags
& ZEBRA_NEIGH_REMOTE
))
2481 || ((wctx
->flags
& DEL_REMOTE_NEIGH_FROM_VTEP
)
2482 && (n
->flags
& ZEBRA_NEIGH_REMOTE
)
2483 && IPV4_ADDR_SAME(&n
->r_vtep_ip
, &wctx
->r_vtep_ip
))) {
2484 if (wctx
->upd_client
&& (n
->flags
& ZEBRA_NEIGH_LOCAL
))
2485 zevpn_neigh_send_del_to_client(wctx
->zevpn
->vni
, &n
->ip
,
2486 &n
->emac
, n
->flags
, n
->state
,
2489 if (wctx
->uninstall
) {
2490 if (zebra_vxlan_neigh_is_static(n
))
2491 zebra_vxlan_sync_neigh_dp_install(n
,
2492 false /* set_inactive */,
2493 true /* force_clear_static */,
2495 if ((n
->flags
& ZEBRA_NEIGH_REMOTE
))
2496 zevpn_neigh_uninstall(wctx
->zevpn
, n
);
2499 zevpn_neigh_del(wctx
->zevpn
, n
);
2506 * Delete all neighbor entries for this EVPN.
2508 static void zevpn_neigh_del_all(zebra_evpn_t
*zevpn
, int uninstall
, int upd_client
,
2511 struct neigh_walk_ctx wctx
;
2513 if (!zevpn
->neigh_table
)
2516 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
2518 wctx
.uninstall
= uninstall
;
2519 wctx
.upd_client
= upd_client
;
2522 hash_iterate(zevpn
->neigh_table
, zevpn_neigh_del_hash_entry
, &wctx
);
2526 * Look up neighbor hash entry.
2528 static zebra_neigh_t
*zevpn_neigh_lookup(zebra_evpn_t
*zevpn
, struct ipaddr
*ip
)
2533 memset(&tmp
, 0, sizeof(tmp
));
2534 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
2535 n
= hash_lookup(zevpn
->neigh_table
, &tmp
);
2541 * Process all neighbors associated with a MAC upon the MAC being learnt
2542 * locally or undergoing any other change (such as sequence number).
2544 static void zevpn_process_neigh_on_local_mac_change(zebra_evpn_t
*zevpn
,
2545 zebra_mac_t
*zmac
, bool seq_change
, bool es_change
)
2547 zebra_neigh_t
*n
= NULL
;
2548 struct listnode
*node
= NULL
;
2549 struct zebra_vrf
*zvrf
= NULL
;
2550 char buf
[ETHER_ADDR_STRLEN
];
2552 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
2554 if (IS_ZEBRA_DEBUG_VXLAN
)
2555 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2556 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2557 seq_change
? "CHANGE" : "ADD", zevpn
->vni
);
2559 /* Walk all neighbors and mark any inactive local neighbors as
2560 * active and/or update sequence number upon a move, and inform BGP.
2561 * The action for remote neighbors is TBD.
2562 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2563 * accidentally end up deleting a just-learnt local neighbor.
2565 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2566 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2567 if (IS_ZEBRA_NEIGH_INACTIVE(n
) || seq_change
||
2569 ZEBRA_NEIGH_SET_ACTIVE(n
);
2570 n
->loc_seq
= zmac
->loc_seq
;
2571 if (!(zvrf
->dup_addr_detect
&&
2572 zvrf
->dad_freeze
&& !!CHECK_FLAG(n
->flags
,
2573 ZEBRA_NEIGH_DUPLICATE
)))
2574 zevpn_neigh_send_add_to_client(
2575 zevpn
->vni
, &n
->ip
, &n
->emac
,
2576 n
->mac
, n
->flags
, n
->loc_seq
);
2583 * Process all neighbors associated with a local MAC upon the MAC being
2586 static void zevpn_process_neigh_on_local_mac_del(zebra_evpn_t
*zevpn
,
2589 zebra_neigh_t
*n
= NULL
;
2590 struct listnode
*node
= NULL
;
2591 char buf
[ETHER_ADDR_STRLEN
];
2593 if (IS_ZEBRA_DEBUG_VXLAN
)
2594 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2595 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2598 /* Walk all local neighbors and mark as inactive and inform
2600 * TBD: There is currently no handling for remote neighbors. We
2601 * don't expect them to exist, if they do, do we install the MAC
2602 * as a remote MAC and the neighbor as remote?
2604 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2605 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2606 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2607 ZEBRA_NEIGH_SET_INACTIVE(n
);
2609 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
,
2619 * Process all neighbors associated with a MAC upon the MAC being remotely
2622 static void zevpn_process_neigh_on_remote_mac_add(zebra_evpn_t
*zevpn
,
2625 zebra_neigh_t
*n
= NULL
;
2626 struct listnode
*node
= NULL
;
2627 char buf
[ETHER_ADDR_STRLEN
];
2629 if (IS_ZEBRA_DEBUG_VXLAN
)
2630 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2631 prefix_mac2str(&zmac
->macaddr
, buf
, sizeof(buf
)),
2634 /* Walk all local neighbors and mark as inactive and inform
2637 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
2638 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
2639 if (IS_ZEBRA_NEIGH_ACTIVE(n
)) {
2640 ZEBRA_NEIGH_SET_INACTIVE(n
);
2642 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
,
2652 * Process all neighbors associated with a remote MAC upon the MAC being
2655 static void zevpn_process_neigh_on_remote_mac_del(zebra_evpn_t
*zevpn
,
2658 /* NOTE: Currently a NO-OP. */
2661 static void zevpn_probe_neigh_on_mac_add(zebra_evpn_t
*zevpn
, zebra_mac_t
*zmac
)
2663 zebra_neigh_t
*nbr
= NULL
;
2664 struct listnode
*node
= NULL
;
2666 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, nbr
)) {
2667 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
) &&
2668 IS_ZEBRA_NEIGH_INACTIVE(nbr
))
2669 zevpn_neigh_probe(zevpn
, nbr
);
2674 * Inform BGP about local neighbor addition.
2676 static int zevpn_neigh_send_add_to_client(vni_t vni
, struct ipaddr
*ip
,
2677 struct ethaddr
*macaddr
,
2679 uint32_t neigh_flags
,
2684 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
)) {
2685 /* host reachability has not been verified locally */
2687 /* if no ES peer is claiming reachability we can't advertise
2690 if (!CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
))
2693 /* ES peers are claiming reachability; we will
2694 * advertise the entry but with a proxy flag
2696 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
);
2699 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_DEF_GW
))
2700 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
2701 /* Set router flag (R-bit) based on local neigh entry add */
2702 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_ROUTER_FLAG
))
2703 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
2704 if (CHECK_FLAG(neigh_flags
, ZEBRA_NEIGH_SVI_IP
))
2705 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_SVI_IP
);
2707 return zevpn_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2708 seq
, ZEBRA_NEIGH_ACTIVE
,
2709 zmac
? zmac
->es
: NULL
,
2714 * Inform BGP about local neighbor deletion.
2716 static int zevpn_neigh_send_del_to_client(vni_t vni
, struct ipaddr
*ip
,
2717 struct ethaddr
*macaddr
, uint32_t flags
,
2718 int state
, bool force
)
2721 if (CHECK_FLAG(flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
) &&
2722 !CHECK_FLAG(flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
))
2723 /* the neigh was not advertised - nothing to delete */
2727 return zevpn_macip_send_msg_to_client(vni
, macaddr
, ip
, flags
,
2728 0, state
, NULL
, ZEBRA_MACIP_DEL
);
2732 * Install remote neighbor into the kernel.
2734 static int zevpn_rem_neigh_install(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
,
2737 struct zebra_if
*zif
;
2738 struct zebra_l2info_vxlan
*vxl
;
2739 struct interface
*vlan_if
;
2743 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2746 zif
= zevpn
->vxlan_if
->info
;
2749 vxl
= &zif
->l2info
.vxl
;
2751 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2755 flags
= DPLANE_NTF_EXT_LEARNED
;
2756 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
2757 flags
|= DPLANE_NTF_ROUTER
;
2758 ZEBRA_NEIGH_SET_ACTIVE(n
);
2760 dplane_rem_neigh_add(vlan_if
, &n
->ip
, &n
->emac
, flags
,
2767 * Uninstall remote neighbor from the kernel.
2769 static int zevpn_neigh_uninstall(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
)
2771 struct zebra_if
*zif
;
2772 struct zebra_l2info_vxlan
*vxl
;
2773 struct interface
*vlan_if
;
2775 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
))
2778 if (!zevpn
->vxlan_if
) {
2779 if (IS_ZEBRA_DEBUG_VXLAN
)
2780 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2785 zif
= zevpn
->vxlan_if
->info
;
2788 vxl
= &zif
->l2info
.vxl
;
2789 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2793 ZEBRA_NEIGH_SET_INACTIVE(n
);
2796 dplane_rem_neigh_delete(vlan_if
, &n
->ip
);
2802 * Probe neighbor from the kernel.
2804 static int zevpn_neigh_probe(zebra_evpn_t
*zevpn
, zebra_neigh_t
*n
)
2806 struct zebra_if
*zif
;
2807 struct zebra_l2info_vxlan
*vxl
;
2808 struct interface
*vlan_if
;
2810 zif
= zevpn
->vxlan_if
->info
;
2813 vxl
= &zif
->l2info
.vxl
;
2815 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
2819 dplane_rem_neigh_update(vlan_if
, &n
->ip
, &n
->emac
);
2825 * Install neighbor hash entry - called upon access VLAN change.
2827 static void zevpn_install_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
2830 struct neigh_walk_ctx
*wctx
= ctxt
;
2832 n
= (zebra_neigh_t
*)bucket
->data
;
2834 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
2835 zevpn_rem_neigh_install(wctx
->zevpn
, n
, false /*was_static*/);
2838 /* Get the VRR interface for SVI if any */
2839 struct interface
*zebra_get_vrr_intf_for_svi(struct interface
*ifp
)
2841 struct zebra_vrf
*zvrf
= NULL
;
2842 struct interface
*tmp_if
= NULL
;
2843 struct zebra_if
*zif
= NULL
;
2845 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
2848 FOR_ALL_INTERFACES (zvrf
->vrf
, tmp_if
) {
2853 if (!IS_ZEBRA_IF_MACVLAN(tmp_if
))
2856 if (zif
->link
== ifp
)
2863 static int zevpn_del_macip_for_intf(struct interface
*ifp
, zebra_evpn_t
*zevpn
)
2865 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2866 struct connected
*c
= NULL
;
2867 struct ethaddr macaddr
;
2869 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2871 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2874 memset(&ip
, 0, sizeof(struct ipaddr
));
2875 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2878 if (c
->address
->family
== AF_INET
) {
2879 ip
.ipa_type
= IPADDR_V4
;
2880 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2881 sizeof(struct in_addr
));
2882 } else if (c
->address
->family
== AF_INET6
) {
2883 ip
.ipa_type
= IPADDR_V6
;
2884 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2885 sizeof(struct in6_addr
));
2890 zevpn_gw_macip_del(ifp
, zevpn
, &ip
);
2896 static int zevpn_add_macip_for_intf(struct interface
*ifp
, zebra_evpn_t
*zevpn
)
2898 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2899 struct connected
*c
= NULL
;
2900 struct ethaddr macaddr
;
2902 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2904 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2907 memset(&ip
, 0, sizeof(struct ipaddr
));
2908 if (!CHECK_FLAG(c
->conf
, ZEBRA_IFC_REAL
))
2911 if (c
->address
->family
== AF_INET
) {
2912 ip
.ipa_type
= IPADDR_V4
;
2913 memcpy(&(ip
.ipaddr_v4
), &(c
->address
->u
.prefix4
),
2914 sizeof(struct in_addr
));
2915 } else if (c
->address
->family
== AF_INET6
) {
2916 ip
.ipa_type
= IPADDR_V6
;
2917 memcpy(&(ip
.ipaddr_v6
), &(c
->address
->u
.prefix6
),
2918 sizeof(struct in6_addr
));
2923 zevpn_gw_macip_add(ifp
, zevpn
, &macaddr
, &ip
);
2929 static int zevpn_advertise_subnet(zebra_evpn_t
*zevpn
, struct interface
*ifp
,
2932 struct listnode
*cnode
= NULL
, *cnnode
= NULL
;
2933 struct connected
*c
= NULL
;
2934 struct ethaddr macaddr
;
2936 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
2938 for (ALL_LIST_ELEMENTS(ifp
->connected
, cnode
, cnnode
, c
)) {
2941 memcpy(&p
, c
->address
, sizeof(struct prefix
));
2943 /* skip link local address */
2944 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
2949 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2950 ZEBRA_IP_PREFIX_ROUTE_ADD
);
2952 ip_prefix_send_to_client(ifp
->vrf_id
, &p
,
2953 ZEBRA_IP_PREFIX_ROUTE_DEL
);
2959 * zevpn_gw_macip_add_to_client
2961 static int zevpn_gw_macip_add(struct interface
*ifp
, zebra_evpn_t
*zevpn
,
2962 struct ethaddr
*macaddr
, struct ipaddr
*ip
)
2964 char buf
[ETHER_ADDR_STRLEN
];
2965 char buf2
[INET6_ADDRSTRLEN
];
2966 zebra_neigh_t
*n
= NULL
;
2967 zebra_mac_t
*mac
= NULL
;
2968 struct zebra_if
*zif
= NULL
;
2969 struct zebra_l2info_vxlan
*vxl
= NULL
;
2971 zif
= zevpn
->vxlan_if
->info
;
2975 vxl
= &zif
->l2info
.vxl
;
2977 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
2979 mac
= zevpn_mac_add(zevpn
, macaddr
);
2981 flog_err(EC_ZEBRA_MAC_ADD_FAILED
,
2982 "Failed to add MAC %s intf %s(%u) VID %u",
2983 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
2984 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
);
2989 /* Set "local" forwarding info. */
2990 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
2991 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
2992 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
2993 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
2994 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
2995 mac
->fwd_info
.local
.vid
= vxl
->access_vlan
;
2997 n
= zevpn_neigh_lookup(zevpn
, ip
);
2999 n
= zevpn_neigh_add(zevpn
, ip
, macaddr
, mac
, 0);
3002 EC_ZEBRA_MAC_ADD_FAILED
,
3003 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3004 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3005 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3006 ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
3011 /* Set "local" forwarding info. */
3012 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3013 ZEBRA_NEIGH_SET_ACTIVE(n
);
3014 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
3015 n
->ifindex
= ifp
->ifindex
;
3017 /* Only advertise in BGP if the knob is enabled */
3018 if (advertise_gw_macip_enabled(zevpn
)) {
3020 SET_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
);
3021 SET_FLAG(n
->flags
, ZEBRA_NEIGH_DEF_GW
);
3022 /* Set Router flag (R-bit) */
3023 if (ip
->ipa_type
== IPADDR_V6
)
3024 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3026 if (IS_ZEBRA_DEBUG_VXLAN
)
3028 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
3029 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
3030 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3031 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
3033 zevpn_neigh_send_add_to_client(zevpn
->vni
, ip
, &n
->emac
, n
->mac
,
3034 n
->flags
, n
->loc_seq
);
3035 } else if (advertise_svi_macip_enabled(zevpn
)) {
3037 SET_FLAG(n
->flags
, ZEBRA_NEIGH_SVI_IP
);
3038 if (IS_ZEBRA_DEBUG_VXLAN
)
3040 "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
3041 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
3042 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3043 ipaddr2str(ip
, buf2
, sizeof(buf2
)), n
->flags
);
3045 zevpn_neigh_send_add_to_client(zevpn
->vni
, ip
, &n
->emac
, n
->mac
,
3046 n
->flags
, n
->loc_seq
);
3053 * zevpn_gw_macip_del_from_client
3055 static int zevpn_gw_macip_del(struct interface
*ifp
, zebra_evpn_t
*zevpn
,
3058 char buf1
[ETHER_ADDR_STRLEN
];
3059 char buf2
[INET6_ADDRSTRLEN
];
3060 zebra_neigh_t
*n
= NULL
;
3061 zebra_mac_t
*mac
= NULL
;
3063 /* If the neigh entry is not present nothing to do*/
3064 n
= zevpn_neigh_lookup(zevpn
, ip
);
3068 /* mac entry should be present */
3069 mac
= zevpn_mac_lookup(zevpn
, &n
->emac
);
3071 if (IS_ZEBRA_DEBUG_VXLAN
)
3072 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
3073 prefix_mac2str(&n
->emac
,
3074 buf1
, sizeof(buf1
)),
3075 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3080 /* If the entry is not local nothing to do*/
3081 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
3084 /* only need to delete the entry from bgp if we sent it before */
3085 if (IS_ZEBRA_DEBUG_VXLAN
)
3087 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
3088 ifp
->vrf_id
, ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
3089 prefix_mac2str(&(n
->emac
), buf1
, sizeof(buf1
)),
3090 ipaddr2str(ip
, buf2
, sizeof(buf2
)));
3092 /* Remove neighbor from BGP. */
3093 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
, &n
->emac
,
3094 n
->flags
, ZEBRA_NEIGH_ACTIVE
,
3097 /* Delete this neighbor entry. */
3098 zevpn_neigh_del(zevpn
, n
);
3100 /* see if the mac needs to be deleted as well*/
3102 zevpn_deref_ip2mac(zevpn
, mac
);
3107 static void zevpn_gw_macip_del_for_evpn_hash(struct hash_bucket
*bucket
,
3110 zebra_evpn_t
*zevpn
= NULL
;
3111 struct zebra_if
*zif
= NULL
;
3112 struct zebra_l2info_vxlan zl2_info
;
3113 struct interface
*vlan_if
= NULL
;
3114 struct interface
*vrr_if
= NULL
;
3115 struct interface
*ifp
;
3117 /* Add primary SVI MAC*/
3118 zevpn
= (zebra_evpn_t
*)bucket
->data
;
3120 /* Global (Zvrf) advertise-default-gw is disabled,
3121 * but zevpn advertise-default-gw is enabled
3123 if (zevpn
->advertise_gw_macip
) {
3124 if (IS_ZEBRA_DEBUG_VXLAN
)
3125 zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
3130 ifp
= zevpn
->vxlan_if
;
3135 /* If down or not mapped to a bridge, we're done. */
3136 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3139 zl2_info
= zif
->l2info
.vxl
;
3142 zevpn_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
3146 /* Del primary MAC-IP */
3147 zevpn_del_macip_for_intf(vlan_if
, zevpn
);
3149 /* Del VRR MAC-IP - if any*/
3150 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3152 zevpn_del_macip_for_intf(vrr_if
, zevpn
);
3157 static void zevpn_gw_macip_add_for_evpn_hash(struct hash_bucket
*bucket
,
3160 zebra_evpn_t
*zevpn
= NULL
;
3161 struct zebra_if
*zif
= NULL
;
3162 struct zebra_l2info_vxlan zl2_info
;
3163 struct interface
*vlan_if
= NULL
;
3164 struct interface
*vrr_if
= NULL
;
3165 struct interface
*ifp
= NULL
;
3167 zevpn
= (zebra_evpn_t
*)bucket
->data
;
3169 ifp
= zevpn
->vxlan_if
;
3174 /* If down or not mapped to a bridge, we're done. */
3175 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3177 zl2_info
= zif
->l2info
.vxl
;
3180 zevpn_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
3184 /* Add primary SVI MAC-IP */
3185 zevpn_add_macip_for_intf(vlan_if
, zevpn
);
3187 if (advertise_gw_macip_enabled(zevpn
)) {
3188 /* Add VRR MAC-IP - if any*/
3189 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
3191 zevpn_add_macip_for_intf(vrr_if
, zevpn
);
3197 static void zevpn_svi_macip_del_for_evpn_hash(struct hash_bucket
*bucket
,
3200 zebra_evpn_t
*zevpn
= NULL
;
3201 struct zebra_if
*zif
= NULL
;
3202 struct zebra_l2info_vxlan zl2_info
;
3203 struct interface
*vlan_if
= NULL
;
3204 struct interface
*ifp
;
3206 /* Add primary SVI MAC*/
3207 zevpn
= (zebra_evpn_t
*)bucket
->data
;
3211 /* Global(vrf) advertise-svi-ip disabled, but zevpn advertise-svi-ip
3214 if (zevpn
->advertise_svi_macip
) {
3215 if (IS_ZEBRA_DEBUG_VXLAN
)
3216 zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
3221 ifp
= zevpn
->vxlan_if
;
3226 /* If down or not mapped to a bridge, we're done. */
3227 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
3230 zl2_info
= zif
->l2info
.vxl
;
3232 vlan_if
= zevpn_map_to_svi(zl2_info
.access_vlan
,
3233 zif
->brslave_info
.br_if
);
3237 /* Del primary MAC-IP */
3238 zevpn_del_macip_for_intf(vlan_if
, zevpn
);
3243 static inline void zevpn_local_neigh_update_log(const char *pfx
,
3244 zebra_neigh_t
*n
, bool is_router
, bool local_inactive
,
3245 bool old_bgp_ready
, bool new_bgp_ready
,
3246 bool inform_dataplane
, bool inform_bgp
, const char *sfx
)
3248 char macbuf
[ETHER_ADDR_STRLEN
];
3249 char ipbuf
[INET6_ADDRSTRLEN
];
3251 if (!IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
3254 zlog_debug("%s neigh vni %u ip %s mac %s f 0x%x%s%s%s%s%s%s %s",
3256 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
3257 prefix_mac2str(&n
->emac
, macbuf
, sizeof(macbuf
)),
3258 n
->flags
, is_router
? " router" : "",
3259 local_inactive
? " local-inactive" : "",
3260 old_bgp_ready
? " old_bgp_ready" : "",
3261 new_bgp_ready
? " new_bgp_ready" : "",
3262 inform_dataplane
? " inform_dp" : "",
3263 inform_bgp
? " inform_bgp" : "",
3267 static int zevpn_local_neigh_update(zebra_evpn_t
*zevpn
,
3268 struct interface
*ifp
,
3270 struct ethaddr
*macaddr
,
3272 bool local_inactive
, bool dp_static
)
3274 char buf
[ETHER_ADDR_STRLEN
];
3275 char buf2
[INET6_ADDRSTRLEN
];
3276 struct zebra_vrf
*zvrf
;
3277 zebra_neigh_t
*n
= NULL
;
3278 zebra_mac_t
*zmac
= NULL
, *old_zmac
= NULL
;
3279 uint32_t old_mac_seq
= 0, mac_new_seq
= 0;
3280 bool upd_mac_seq
= false;
3281 bool neigh_mac_change
= false;
3282 bool neigh_on_hold
= false;
3283 bool neigh_was_remote
= false;
3284 bool do_dad
= false;
3285 struct in_addr vtep_ip
= {.s_addr
= 0};
3286 bool inform_dataplane
= false;
3287 bool created
= false;
3288 bool new_static
= false;
3289 bool old_bgp_ready
= false;
3292 /* Check if the MAC exists. */
3293 zmac
= zevpn_mac_lookup(zevpn
, macaddr
);
3295 /* create a dummy MAC if the MAC is not already present */
3296 if (IS_ZEBRA_DEBUG_VXLAN
)
3298 "AUTO MAC %s created for neigh %s on VNI %u",
3299 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3300 ipaddr2str(ip
, buf2
, sizeof(buf2
)), zevpn
->vni
);
3302 zmac
= zevpn_mac_add(zevpn
, macaddr
);
3304 zlog_debug("Failed to add MAC %s VNI %u",
3305 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3310 memset(&zmac
->fwd_info
, 0, sizeof(zmac
->fwd_info
));
3311 memset(&zmac
->flags
, 0, sizeof(uint32_t));
3312 SET_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
);
3314 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3316 * We don't change the MAC to local upon a neighbor
3317 * learn event, we wait for the explicit local MAC
3318 * learn. However, we have to compute its sequence
3319 * number in preparation for when it actually turns
3326 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
3328 if (IS_ZEBRA_DEBUG_VXLAN
)
3329 zlog_debug(" Unable to find vrf for: %d",
3330 zevpn
->vxlan_if
->vrf_id
);
3334 /* Check if the neighbor exists. */
3335 n
= zevpn_neigh_lookup(zevpn
, ip
);
3337 /* New neighbor - create */
3338 n
= zevpn_neigh_add(zevpn
, ip
, macaddr
, zmac
, 0);
3341 EC_ZEBRA_MAC_ADD_FAILED
,
3342 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
3343 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
3344 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3345 ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
3348 /* Set "local" forwarding info. */
3349 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3350 n
->ifindex
= ifp
->ifindex
;
3353 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
3356 bool old_local_inactive
;
3358 old_local_inactive
= !!CHECK_FLAG(n
->flags
,
3359 ZEBRA_NEIGH_LOCAL_INACTIVE
);
3362 zebra_vxlan_neigh_is_ready_for_bgp(n
);
3364 /* Note any changes and see if of interest to BGP. */
3365 mac_different
= !!memcmp(&n
->emac
,
3367 cur_is_router
= !!CHECK_FLAG(n
->flags
,
3368 ZEBRA_NEIGH_ROUTER_FLAG
);
3369 new_static
= zebra_vxlan_neigh_is_static(n
);
3370 if (!mac_different
&& is_router
== cur_is_router
&&
3371 old_local_inactive
== local_inactive
&&
3372 dp_static
!= new_static
) {
3373 if (IS_ZEBRA_DEBUG_VXLAN
)
3375 " Ignoring entry mac is the same and is_router == cur_is_router");
3376 n
->ifindex
= ifp
->ifindex
;
3381 if (!mac_different
) {
3382 /* XXX - cleanup this code duplication */
3383 bool is_neigh_freezed
= false;
3385 /* Only the router flag has changed. */
3388 ZEBRA_NEIGH_ROUTER_FLAG
);
3390 UNSET_FLAG(n
->flags
,
3391 ZEBRA_NEIGH_ROUTER_FLAG
);
3395 ZEBRA_NEIGH_LOCAL_INACTIVE
);
3397 UNSET_FLAG(n
->flags
,
3398 ZEBRA_NEIGH_LOCAL_INACTIVE
);
3400 zebra_vxlan_neigh_is_ready_for_bgp(n
);
3402 /* Neigh is in freeze state and freeze action
3403 * is enabled, do not send update to client.
3405 is_neigh_freezed
= (zvrf
->dup_addr_detect
&&
3407 CHECK_FLAG(n
->flags
,
3408 ZEBRA_NEIGH_DUPLICATE
));
3410 zevpn_local_neigh_update_log("local", n
,
3411 is_router
, local_inactive
,
3412 old_bgp_ready
, new_bgp_ready
,
3413 false, false, "flag-update");
3415 /* if the neigh can no longer be advertised
3416 * remove it from bgp
3418 if (!is_neigh_freezed
) {
3419 zebra_vxlan_neigh_send_add_del_to_client(
3420 n
, old_bgp_ready
, new_bgp_ready
);
3422 if (IS_ZEBRA_DEBUG_VXLAN
&&
3423 IS_ZEBRA_NEIGH_ACTIVE(n
))
3425 " Neighbor active and frozen");
3430 /* The MAC has changed, need to issue a delete
3431 * first as this means a different MACIP route.
3432 * Also, need to do some unlinking/relinking.
3433 * We also need to update the MAC's sequence number
3434 * in different situations.
3436 if (old_bgp_ready
) {
3437 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
,
3438 &n
->emac
, n
->flags
, n
->state
,
3440 old_bgp_ready
= false;
3443 old_mac_seq
= CHECK_FLAG(old_zmac
->flags
,
3445 old_zmac
->rem_seq
: old_zmac
->loc_seq
;
3446 neigh_mac_change
= upd_mac_seq
= true;
3447 zebra_vxlan_local_neigh_deref_mac(n
,
3448 true /* send_mac_update */);
3451 /* if mac changes abandon peer flags and tell
3452 * dataplane to clear the static flag
3454 if (zebra_vxlan_neigh_clear_sync_info(n
))
3455 inform_dataplane
= true;
3456 /* Update the forwarding info. */
3457 n
->ifindex
= ifp
->ifindex
;
3459 /* Link to new MAC */
3460 zebra_vxlan_local_neigh_ref_mac(n
, macaddr
, zmac
,
3461 true /* send_mac_update */);
3462 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3464 * Neighbor has moved from remote to local. Its
3465 * MAC could have also changed as part of the move.
3467 if (memcmp(n
->emac
.octet
, macaddr
->octet
,
3471 old_mac_seq
= CHECK_FLAG(
3476 neigh_mac_change
= upd_mac_seq
= true;
3477 zebra_vxlan_local_neigh_deref_mac(n
,
3478 true /* send_update */);
3481 /* Link to new MAC */
3482 zebra_vxlan_local_neigh_ref_mac(n
, macaddr
,
3483 zmac
, true /*send_update*/);
3485 /* Based on Mobility event Scenario-B from the
3486 * draft, neigh's previous state was remote treat this
3489 neigh_was_remote
= true;
3490 vtep_ip
= n
->r_vtep_ip
;
3491 /* Mark appropriately */
3492 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3493 n
->r_vtep_ip
.s_addr
= INADDR_ANY
;
3494 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
3495 n
->ifindex
= ifp
->ifindex
;
3499 /* If MAC was previously remote, or the neighbor had a different
3500 * MAC earlier, recompute the sequence number.
3503 uint32_t seq1
, seq2
;
3505 seq1
= CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
) ?
3506 zmac
->rem_seq
+ 1 : zmac
->loc_seq
;
3507 seq2
= neigh_mac_change
? old_mac_seq
+ 1 : 0;
3508 mac_new_seq
= zmac
->loc_seq
< MAX(seq1
, seq2
) ?
3509 MAX(seq1
, seq2
) : zmac
->loc_seq
;
3513 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
);
3515 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
);
3517 /* Mark Router flag (R-bit) */
3519 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3521 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
3523 /* if the dataplane thinks that this is a sync entry but
3524 * zebra doesn't we need to re-concile the diff
3525 * by re-installing the dataplane entry
3528 new_static
= zebra_vxlan_neigh_is_static(n
);
3530 inform_dataplane
= true;
3533 /* Check old and/or new MAC detected as duplicate mark
3534 * the neigh as duplicate
3536 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_zmac
, zmac
, n
)) {
3537 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
3538 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3540 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3541 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)));
3544 /* For IP Duplicate Address Detection (DAD) is trigger,
3545 * when the event is extended mobility based on scenario-B
3546 * from the draft, IP/Neigh's MAC binding changed and
3547 * neigh's previous state was remote.
3549 if (neigh_mac_change
&& neigh_was_remote
)
3552 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
, vtep_ip
, do_dad
,
3553 &neigh_on_hold
, true);
3555 if (inform_dataplane
)
3556 zebra_vxlan_sync_neigh_dp_install(n
, false /* set_inactive */,
3557 false /* force_clear_static */, __func__
);
3559 /* Before we program this in BGP, we need to check if MAC is locally
3560 * learnt. If not, force neighbor to be inactive and reset its seq.
3562 if (!CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
)) {
3563 zevpn_local_neigh_update_log("local",
3564 n
, is_router
, local_inactive
,
3565 false, false, inform_dataplane
, false,
3567 ZEBRA_NEIGH_SET_INACTIVE(n
);
3569 zmac
->loc_seq
= mac_new_seq
;
3573 zevpn_local_neigh_update_log("local",
3574 n
, is_router
, local_inactive
, false, false, inform_dataplane
,
3575 true, created
? "created" : "updated");
3577 /* If the MAC's sequence number has changed, inform the MAC and all
3578 * neighbors associated with the MAC to BGP, else just inform this
3581 if (upd_mac_seq
&& zmac
->loc_seq
!= mac_new_seq
) {
3582 if (IS_ZEBRA_DEBUG_VXLAN
)
3583 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3584 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3585 zevpn
->vni
, zmac
->loc_seq
, mac_new_seq
);
3586 zmac
->loc_seq
= mac_new_seq
;
3587 if (zevpn_mac_send_add_to_client(zevpn
->vni
, macaddr
,
3588 zmac
->flags
, zmac
->loc_seq
, zmac
->es
))
3590 zevpn_process_neigh_on_local_mac_change(zevpn
, zmac
, 1,
3595 n
->loc_seq
= zmac
->loc_seq
;
3597 if (!neigh_on_hold
) {
3598 ZEBRA_NEIGH_SET_ACTIVE(n
);
3600 zebra_vxlan_neigh_is_ready_for_bgp(n
);
3601 zebra_vxlan_neigh_send_add_del_to_client(n
,
3602 old_bgp_ready
, new_bgp_ready
);
3604 if (IS_ZEBRA_DEBUG_VXLAN
)
3605 zlog_debug(" Neighbor on hold not sending");
3610 static int zevpn_remote_neigh_update(zebra_evpn_t
*zevpn
,
3611 struct interface
*ifp
,
3613 struct ethaddr
*macaddr
,
3616 char buf
[ETHER_ADDR_STRLEN
];
3617 char buf2
[INET6_ADDRSTRLEN
];
3618 zebra_neigh_t
*n
= NULL
;
3619 zebra_mac_t
*zmac
= NULL
;
3621 /* If the neighbor is unknown, there is no further action. */
3622 n
= zevpn_neigh_lookup(zevpn
, ip
);
3626 /* If a remote entry, see if it needs to be refreshed */
3627 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
3629 if (state
& NUD_STALE
)
3630 zevpn_rem_neigh_install(zevpn
, n
, false /*was_static*/);
3633 /* We got a "remote" neighbor notification for an entry
3634 * we think is local. This can happen in a multihoming
3635 * scenario - but only if the MAC is already "remote".
3636 * Just mark our entry as "remote".
3638 zmac
= zevpn_mac_lookup(zevpn
, macaddr
);
3639 if (!zmac
|| !CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_REMOTE
)) {
3641 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3642 ipaddr2str(&n
->ip
, buf2
, sizeof(buf2
)),
3643 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
3648 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ALL_LOCAL_FLAGS
);
3649 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
3650 ZEBRA_NEIGH_SET_ACTIVE(n
);
3651 n
->r_vtep_ip
= zmac
->fwd_info
.r_vtep_ip
;
3658 * Make hash key for MAC.
3660 static unsigned int mac_hash_keymake(const void *p
)
3662 const zebra_mac_t
*pmac
= p
;
3663 const void *pnt
= (void *)pmac
->macaddr
.octet
;
3665 return jhash(pnt
, ETH_ALEN
, 0xa5a5a55a);
3669 * Compare two MAC addresses.
3671 static bool mac_cmp(const void *p1
, const void *p2
)
3673 const zebra_mac_t
*pmac1
= p1
;
3674 const zebra_mac_t
*pmac2
= p2
;
3676 if (pmac1
== NULL
&& pmac2
== NULL
)
3679 if (pmac1
== NULL
|| pmac2
== NULL
)
3682 return (memcmp(pmac1
->macaddr
.octet
, pmac2
->macaddr
.octet
, ETH_ALEN
)
3687 * Callback to allocate MAC hash entry.
3689 static void *zevpn_mac_alloc(void *p
)
3691 const zebra_mac_t
*tmp_mac
= p
;
3694 mac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
3697 return ((void *)mac
);
3703 static zebra_mac_t
*zevpn_mac_add(zebra_evpn_t
*zevpn
, struct ethaddr
*macaddr
)
3705 zebra_mac_t tmp_mac
;
3706 zebra_mac_t
*mac
= NULL
;
3708 memset(&tmp_mac
, 0, sizeof(zebra_mac_t
));
3709 memcpy(&tmp_mac
.macaddr
, macaddr
, ETH_ALEN
);
3710 mac
= hash_get(zevpn
->mac_table
, &tmp_mac
, zevpn_mac_alloc
);
3714 mac
->dad_mac_auto_recovery_timer
= NULL
;
3716 mac
->neigh_list
= list_new();
3717 mac
->neigh_list
->cmp
= neigh_list_cmp
;
3719 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
) {
3720 char buf
[ETHER_ADDR_STRLEN
];
3722 zlog_debug("%s: MAC %s flags 0x%x",
3724 prefix_mac2str(&mac
->macaddr
,
3734 static int zevpn_mac_del(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
)
3736 zebra_mac_t
*tmp_mac
;
3738 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
) {
3739 char buf
[ETHER_ADDR_STRLEN
];
3741 zlog_debug("%s: MAC %s flags 0x%x",
3743 prefix_mac2str(&mac
->macaddr
,
3748 /* force de-ref any ES entry linked to the MAC */
3749 zebra_evpn_es_mac_deref_entry(mac
);
3751 /* Cancel proxy hold timer */
3752 zebra_vxlan_mac_stop_hold_timer(mac
);
3754 /* Cancel auto recovery */
3755 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
3757 list_delete(&mac
->neigh_list
);
3759 /* Free the VNI hash entry and allocated memory. */
3760 tmp_mac
= hash_release(zevpn
->mac_table
, mac
);
3761 XFREE(MTYPE_MAC
, tmp_mac
);
3766 static bool zevpn_check_mac_del_from_db(struct mac_walk_ctx
*wctx
,
3769 if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3770 (mac
->flags
& ZEBRA_MAC_LOCAL
))
3772 else if ((wctx
->flags
& DEL_REMOTE_MAC
) &&
3773 (mac
->flags
& ZEBRA_MAC_REMOTE
))
3775 else if ((wctx
->flags
& DEL_REMOTE_MAC_FROM_VTEP
) &&
3776 (mac
->flags
& ZEBRA_MAC_REMOTE
) &&
3777 IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &wctx
->r_vtep_ip
))
3779 else if ((wctx
->flags
& DEL_LOCAL_MAC
) &&
3780 (mac
->flags
& ZEBRA_MAC_AUTO
) &&
3781 !listcount(mac
->neigh_list
)) {
3782 if (IS_ZEBRA_DEBUG_VXLAN
) {
3783 char buf
[ETHER_ADDR_STRLEN
];
3786 "%s: Del MAC %s flags 0x%x", __func__
,
3787 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
3790 wctx
->uninstall
= 0;
3799 * Free MAC hash entry (callback)
3801 static void zevpn_mac_del_hash_entry(struct hash_bucket
*bucket
, void *arg
)
3803 struct mac_walk_ctx
*wctx
= arg
;
3804 zebra_mac_t
*mac
= bucket
->data
;
3806 if (zevpn_check_mac_del_from_db(wctx
, mac
)) {
3807 if (wctx
->upd_client
&& (mac
->flags
& ZEBRA_MAC_LOCAL
)) {
3808 zevpn_mac_send_del_to_client(wctx
->zevpn
->vni
,
3809 &mac
->macaddr
, mac
->flags
, false);
3811 if (wctx
->uninstall
) {
3812 if (zebra_vxlan_mac_is_static(mac
))
3813 zebra_vxlan_sync_mac_dp_install(mac
,
3814 false /* set_inactive */,
3815 true /* force_clear_static */,
3818 if (mac
->flags
& ZEBRA_MAC_REMOTE
)
3819 zevpn_rem_mac_uninstall(wctx
->zevpn
, mac
);
3822 zevpn_mac_del(wctx
->zevpn
, mac
);
3829 * Delete all MAC entries for this EVPN.
3831 static void zevpn_mac_del_all(zebra_evpn_t
*zevpn
, int uninstall
, int upd_client
,
3834 struct mac_walk_ctx wctx
;
3836 if (!zevpn
->mac_table
)
3839 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
3841 wctx
.uninstall
= uninstall
;
3842 wctx
.upd_client
= upd_client
;
3845 hash_iterate(zevpn
->mac_table
, zevpn_mac_del_hash_entry
, &wctx
);
3849 * Look up MAC hash entry.
3851 static zebra_mac_t
*zevpn_mac_lookup(zebra_evpn_t
*zevpn
, struct ethaddr
*mac
)
3856 memset(&tmp
, 0, sizeof(tmp
));
3857 memcpy(&tmp
.macaddr
, mac
, ETH_ALEN
);
3858 pmac
= hash_lookup(zevpn
->mac_table
, &tmp
);
3864 * Inform BGP about local MAC addition.
3866 static int zevpn_mac_send_add_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3867 uint32_t mac_flags
, uint32_t seq
, struct zebra_evpn_es
*es
)
3871 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_LOCAL_INACTIVE
)) {
3872 /* host reachability has not been verified locally */
3874 /* if no ES peer is claiming reachability we can't advertise the
3877 if (!CHECK_FLAG(mac_flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
3880 /* ES peers are claiming reachability; we will
3881 * advertise the entry but with a proxy flag
3883 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
);
3886 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_STICKY
))
3887 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
3888 if (CHECK_FLAG(mac_flags
, ZEBRA_MAC_DEF_GW
))
3889 SET_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
3891 return zevpn_macip_send_msg_to_client(vni
, macaddr
, NULL
, flags
,
3892 seq
, ZEBRA_NEIGH_ACTIVE
, es
,
3897 * Inform BGP about local MAC deletion.
3899 static int zevpn_mac_send_del_to_client(vni_t vni
, struct ethaddr
*macaddr
,
3900 uint32_t flags
, bool force
)
3903 if (CHECK_FLAG(flags
, ZEBRA_MAC_LOCAL_INACTIVE
) &&
3904 !CHECK_FLAG(flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
3905 /* the host was not advertised - nothing to delete */
3909 return zevpn_macip_send_msg_to_client(vni
, macaddr
, NULL
, 0 /* flags */,
3910 0 /* seq */, ZEBRA_NEIGH_ACTIVE
, NULL
,
3915 * Map port or (port, VLAN) to an EVPN. This is invoked upon getting MAC
3916 * notifications, to see if they are of interest.
3918 static zebra_evpn_t
*zevpn_map_vlan(struct interface
*ifp
,
3919 struct interface
*br_if
, vlanid_t vid
)
3921 struct zebra_ns
*zns
;
3922 struct route_node
*rn
;
3923 struct interface
*tmp_if
= NULL
;
3924 struct zebra_if
*zif
;
3925 struct zebra_l2info_bridge
*br
;
3926 struct zebra_l2info_vxlan
*vxl
= NULL
;
3927 uint8_t bridge_vlan_aware
;
3928 zebra_evpn_t
*zevpn
;
3931 /* Determine if bridge is VLAN-aware or not */
3934 br
= &zif
->l2info
.br
;
3935 bridge_vlan_aware
= br
->vlan_aware
;
3937 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3938 /* TODO: Optimize with a hash. */
3939 zns
= zebra_ns_lookup(NS_DEFAULT
);
3940 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
3941 tmp_if
= (struct interface
*)rn
->info
;
3945 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
3947 if (!if_is_operative(tmp_if
))
3949 vxl
= &zif
->l2info
.vxl
;
3951 if (zif
->brslave_info
.br_if
!= br_if
)
3954 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
3963 zevpn
= zevpn_lookup(vxl
->vni
);
3968 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3969 * neighbor notifications, to see if they are of interest.
3971 static zebra_evpn_t
*zevpn_from_svi(struct interface
*ifp
,
3972 struct interface
*br_if
)
3974 struct zebra_ns
*zns
;
3975 struct route_node
*rn
;
3976 struct interface
*tmp_if
= NULL
;
3977 struct zebra_if
*zif
;
3978 struct zebra_l2info_bridge
*br
;
3979 struct zebra_l2info_vxlan
*vxl
= NULL
;
3980 uint8_t bridge_vlan_aware
;
3982 zebra_evpn_t
*zevpn
;
3988 /* Make sure the linked interface is a bridge. */
3989 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
3992 /* Determine if bridge is VLAN-aware or not */
3995 br
= &zif
->l2info
.br
;
3996 bridge_vlan_aware
= br
->vlan_aware
;
3997 if (bridge_vlan_aware
) {
3998 struct zebra_l2info_vlan
*vl
;
4000 if (!IS_ZEBRA_IF_VLAN(ifp
))
4005 vl
= &zif
->l2info
.vl
;
4009 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4010 /* TODO: Optimize with a hash. */
4011 zns
= zebra_ns_lookup(NS_DEFAULT
);
4012 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4013 tmp_if
= (struct interface
*)rn
->info
;
4017 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4019 if (!if_is_operative(tmp_if
))
4021 vxl
= &zif
->l2info
.vxl
;
4023 if (zif
->brslave_info
.br_if
!= br_if
)
4026 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
4035 zevpn
= zevpn_lookup(vxl
->vni
);
4039 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
4041 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
4042 * linked to the bridge
4043 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
4046 static struct interface
*zevpn_map_to_svi(vlanid_t vid
, struct interface
*br_if
)
4048 struct zebra_ns
*zns
;
4049 struct route_node
*rn
;
4050 struct interface
*tmp_if
= NULL
;
4051 struct zebra_if
*zif
;
4052 struct zebra_l2info_bridge
*br
;
4053 struct zebra_l2info_vlan
*vl
;
4054 uint8_t bridge_vlan_aware
;
4057 /* Defensive check, caller expected to invoke only with valid bridge. */
4061 /* Determine if bridge is VLAN-aware or not */
4064 br
= &zif
->l2info
.br
;
4065 bridge_vlan_aware
= br
->vlan_aware
;
4067 /* Check oper status of the SVI. */
4068 if (!bridge_vlan_aware
)
4069 return if_is_operative(br_if
) ? br_if
: NULL
;
4071 /* Identify corresponding VLAN interface. */
4072 /* TODO: Optimize with a hash. */
4073 zns
= zebra_ns_lookup(NS_DEFAULT
);
4074 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4075 tmp_if
= (struct interface
*)rn
->info
;
4076 /* Check oper status of the SVI. */
4077 if (!tmp_if
|| !if_is_operative(tmp_if
))
4080 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VLAN
4081 || zif
->link
!= br_if
)
4083 vl
= &zif
->l2info
.vl
;
4085 if (vl
->vid
== vid
) {
4091 return found
? tmp_if
: NULL
;
4094 /* Map to MAC-VLAN interface corresponding to specified SVI interface.
4096 static struct interface
*zevpn_map_to_macvlan(struct interface
*br_if
,
4097 struct interface
*svi_if
)
4099 struct zebra_ns
*zns
;
4100 struct route_node
*rn
;
4101 struct interface
*tmp_if
= NULL
;
4102 struct zebra_if
*zif
;
4105 /* Defensive check, caller expected to invoke only with valid bridge. */
4110 zlog_debug("svi_if is not passed.");
4114 /* Determine if bridge is VLAN-aware or not */
4118 /* Identify corresponding VLAN interface. */
4119 zns
= zebra_ns_lookup(NS_DEFAULT
);
4120 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4121 tmp_if
= (struct interface
*)rn
->info
;
4122 /* Check oper status of the SVI. */
4123 if (!tmp_if
|| !if_is_operative(tmp_if
))
4127 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_MACVLAN
)
4130 if (zif
->link
== svi_if
) {
4136 return found
? tmp_if
: NULL
;
4141 * Install remote MAC into the forwarding plane.
4143 static int zevpn_rem_mac_install(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
,
4146 const struct zebra_if
*zif
, *br_zif
;
4147 const struct zebra_l2info_vxlan
*vxl
;
4149 enum zebra_dplane_result res
;
4150 const struct interface
*br_ifp
;
4153 struct in_addr vtep_ip
;
4155 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
4158 zif
= zevpn
->vxlan_if
->info
;
4162 br_ifp
= zif
->brslave_info
.br_if
;
4166 vxl
= &zif
->l2info
.vxl
;
4168 sticky
= !!CHECK_FLAG(mac
->flags
,
4169 (ZEBRA_MAC_STICKY
| ZEBRA_MAC_REMOTE_DEF_GW
));
4171 /* If nexthop group for the FDB entry is inactive (not programmed in
4172 * the dataplane) the MAC entry cannot be installed
4175 if (!(mac
->es
->flags
& ZEBRA_EVPNES_NHG_ACTIVE
))
4177 nhg_id
= mac
->es
->nhg_id
;
4181 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
4184 br_zif
= (const struct zebra_if
*)(br_ifp
->info
);
4186 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4187 vid
= vxl
->access_vlan
;
4191 res
= dplane_rem_mac_add(zevpn
->vxlan_if
, br_ifp
, vid
,
4192 &mac
->macaddr
, vtep_ip
, sticky
,
4193 nhg_id
, was_static
);
4194 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4201 * Uninstall remote MAC from the forwarding plane.
4203 static int zevpn_rem_mac_uninstall(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
)
4205 const struct zebra_if
*zif
, *br_zif
;
4206 const struct zebra_l2info_vxlan
*vxl
;
4207 struct in_addr vtep_ip
;
4208 const struct interface
*ifp
, *br_ifp
;
4210 enum zebra_dplane_result res
;
4212 if (!(mac
->flags
& ZEBRA_MAC_REMOTE
))
4215 if (!zevpn
->vxlan_if
) {
4216 if (IS_ZEBRA_DEBUG_VXLAN
)
4217 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4222 zif
= zevpn
->vxlan_if
->info
;
4226 br_ifp
= zif
->brslave_info
.br_if
;
4230 vxl
= &zif
->l2info
.vxl
;
4232 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
4234 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
4235 vid
= vxl
->access_vlan
;
4239 ifp
= zevpn
->vxlan_if
;
4240 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
4242 res
= dplane_rem_mac_del(ifp
, br_ifp
, vid
, &mac
->macaddr
, vtep_ip
);
4243 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
4250 * Install MAC hash entry - called upon access VLAN change.
4252 static void zevpn_install_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
4255 struct mac_walk_ctx
*wctx
= ctxt
;
4257 mac
= (zebra_mac_t
*)bucket
->data
;
4259 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
4260 zevpn_rem_mac_install(wctx
->zevpn
, mac
, false);
4264 * Count of remote neighbors referencing this MAC.
4266 static int remote_neigh_count(zebra_mac_t
*zmac
)
4268 zebra_neigh_t
*n
= NULL
;
4269 struct listnode
*node
= NULL
;
4272 for (ALL_LIST_ELEMENTS_RO(zmac
->neigh_list
, node
, n
)) {
4273 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
4281 * Decrement neighbor refcount of MAC; uninstall and free it if
4284 static void zevpn_deref_ip2mac(zebra_evpn_t
*zevpn
, zebra_mac_t
*mac
)
4286 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
))
4289 /* If all remote neighbors referencing a remote MAC go away,
4290 * we need to uninstall the MAC.
4292 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
4293 remote_neigh_count(mac
) == 0) {
4294 zevpn_rem_mac_uninstall(zevpn
, mac
);
4295 zebra_evpn_es_mac_deref_entry(mac
);
4296 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
4299 /* If no neighbors, delete the MAC. */
4300 if (list_isempty(mac
->neigh_list
))
4301 zevpn_mac_del(zevpn
, mac
);
4305 * Read and populate local MACs and neighbors corresponding to this EVPN.
4307 static void zevpn_read_mac_neigh(zebra_evpn_t
*zevpn
, struct interface
*ifp
)
4309 struct zebra_ns
*zns
;
4310 struct zebra_if
*zif
;
4311 struct interface
*vlan_if
;
4312 struct zebra_l2info_vxlan
*vxl
;
4313 struct interface
*vrr_if
;
4316 vxl
= &zif
->l2info
.vxl
;
4317 zns
= zebra_ns_lookup(NS_DEFAULT
);
4319 if (IS_ZEBRA_DEBUG_VXLAN
)
4321 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
4322 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
4323 zif
->brslave_info
.bridge_ifindex
);
4325 macfdb_read_for_bridge(zns
, ifp
, zif
->brslave_info
.br_if
);
4326 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
4329 /* Add SVI MAC-IP */
4330 zevpn_add_macip_for_intf(vlan_if
, zevpn
);
4332 /* Add VRR MAC-IP - if any*/
4333 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
4335 zevpn_add_macip_for_intf(vrr_if
, zevpn
);
4337 neigh_read_for_vlan(zns
, vlan_if
);
4342 * Hash function for VNI.
4344 static unsigned int evpn_hash_keymake(const void *p
)
4346 const zebra_evpn_t
*zevpn
= p
;
4348 return (jhash_1word(zevpn
->vni
, 0));
4352 * Compare 2 VNI hash entries.
4354 static bool vni_hash_cmp(const void *p1
, const void *p2
)
4356 const zebra_evpn_t
*zevpn1
= p1
;
4357 const zebra_evpn_t
*zevpn2
= p2
;
4359 return (zevpn1
->vni
== zevpn2
->vni
);
4362 int vni_list_cmp(void *p1
, void *p2
)
4364 const zebra_evpn_t
*zevpn1
= p1
;
4365 const zebra_evpn_t
*zevpn2
= p2
;
4367 if (zevpn1
->vni
== zevpn2
->vni
)
4369 return (zevpn1
->vni
< zevpn2
->vni
) ? -1 : 1;
4373 * Callback to allocate VNI hash entry.
4375 static void *zevpn_alloc(void *p
)
4377 const zebra_evpn_t
*tmp_vni
= p
;
4378 zebra_evpn_t
*zevpn
;
4380 zevpn
= XCALLOC(MTYPE_ZEVPN
, sizeof(zebra_evpn_t
));
4381 zevpn
->vni
= tmp_vni
->vni
;
4382 return ((void *)zevpn
);
4386 * Look up EVPN hash entry.
4388 zebra_evpn_t
*zevpn_lookup(vni_t vni
)
4390 struct zebra_vrf
*zvrf
;
4391 zebra_evpn_t tmp_vni
;
4392 zebra_evpn_t
*zevpn
= NULL
;
4394 zvrf
= zebra_vrf_get_evpn();
4396 memset(&tmp_vni
, 0, sizeof(zebra_evpn_t
));
4398 zevpn
= hash_lookup(zvrf
->evpn_table
, &tmp_vni
);
4404 * Add EVPN hash entry.
4406 static zebra_evpn_t
*zevpn_add(vni_t vni
)
4408 struct zebra_vrf
*zvrf
;
4409 zebra_evpn_t tmp_zevpn
;
4410 zebra_evpn_t
*zevpn
= NULL
;
4412 zvrf
= zebra_vrf_get_evpn();
4414 memset(&tmp_zevpn
, 0, sizeof(zebra_evpn_t
));
4415 tmp_zevpn
.vni
= vni
;
4416 zevpn
= hash_get(zvrf
->evpn_table
, &tmp_zevpn
, zevpn_alloc
);
4419 zebra_evpn_evpn_es_init(zevpn
);
4421 /* Create hash table for MAC */
4423 hash_create(mac_hash_keymake
, mac_cmp
, "Zebra EVPN MAC Table");
4425 /* Create hash table for neighbors */
4426 zevpn
->neigh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
4427 "Zebra EVPN Neighbor Table");
4432 /* EVPN<=>vxlan_zif association */
4433 static void zevpn_vxlan_if_set(zebra_evpn_t
*zevpn
, struct interface
*ifp
,
4436 struct zebra_if
*zif
;
4439 if (zevpn
->vxlan_if
== ifp
)
4441 zevpn
->vxlan_if
= ifp
;
4443 if (!zevpn
->vxlan_if
)
4445 zevpn
->vxlan_if
= NULL
;
4453 zebra_evpn_vxl_evpn_set(zif
, zevpn
, set
);
4457 * Delete EVPN hash entry.
4459 static int zevpn_del(zebra_evpn_t
*zevpn
)
4461 struct zebra_vrf
*zvrf
;
4462 zebra_evpn_t
*tmp_zevpn
;
4464 zvrf
= zebra_vrf_get_evpn();
4467 zevpn_vxlan_if_set(zevpn
, zevpn
->vxlan_if
, false /* set */);
4469 /* Remove references to the BUM mcast grp */
4470 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
, zevpn
->mcast_grp
);
4472 /* Free the neighbor hash table. */
4473 hash_free(zevpn
->neigh_table
);
4474 zevpn
->neigh_table
= NULL
;
4476 /* Free the MAC hash table. */
4477 hash_free(zevpn
->mac_table
);
4478 zevpn
->mac_table
= NULL
;
4480 zebra_evpn_evpn_es_cleanup(zevpn
);
4482 /* Free the EVPN hash entry and allocated memory. */
4483 tmp_zevpn
= hash_release(zvrf
->evpn_table
, zevpn
);
4484 XFREE(MTYPE_ZEVPN
, tmp_zevpn
);
4490 * Inform BGP about local EVPN addition.
4492 static int zevpn_send_add_to_client(zebra_evpn_t
*zevpn
)
4494 struct zserv
*client
;
4498 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4499 /* BGP may not be running. */
4503 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4505 zclient_create_header(s
, ZEBRA_VNI_ADD
, zebra_vrf_get_evpn_id());
4506 stream_putl(s
, zevpn
->vni
);
4507 stream_put_in_addr(s
, &zevpn
->local_vtep_ip
);
4508 stream_put(s
, &zevpn
->vrf_id
, sizeof(vrf_id_t
)); /* tenant vrf */
4509 stream_put_in_addr(s
, &zevpn
->mcast_grp
);
4511 /* Write packet size. */
4512 stream_putw_at(s
, 0, stream_get_endp(s
));
4514 if (IS_ZEBRA_DEBUG_VXLAN
)
4515 zlog_debug("Send EVPN_ADD %u %s tenant vrf %s to %s", zevpn
->vni
,
4516 inet_ntoa(zevpn
->local_vtep_ip
),
4517 vrf_id_to_name(zevpn
->vrf_id
),
4518 zebra_route_string(client
->proto
));
4520 client
->vniadd_cnt
++;
4521 rc
= zserv_send_message(client
, s
);
4523 if (!(zevpn
->flags
& ZEVPN_READY_FOR_BGP
)) {
4524 zevpn
->flags
|= ZEVPN_READY_FOR_BGP
;
4525 /* once the EVPN is sent the ES-EVIs can also be replayed
4528 zebra_evpn_update_all_es(zevpn
);
4534 * Inform BGP about local EVPN deletion.
4536 static int zevpn_send_del_to_client(zebra_evpn_t
*zevpn
)
4538 struct zserv
*client
;
4541 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
4542 /* BGP may not be running. */
4546 if (zevpn
->flags
& ZEVPN_READY_FOR_BGP
) {
4547 zevpn
->flags
&= ~ZEVPN_READY_FOR_BGP
;
4548 /* the ES-EVIs must be removed from BGP before the EVPN is */
4549 zebra_evpn_update_all_es(zevpn
);
4552 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
4555 zclient_create_header(s
, ZEBRA_VNI_DEL
, zebra_vrf_get_evpn_id());
4556 stream_putl(s
, zevpn
->vni
);
4558 /* Write packet size. */
4559 stream_putw_at(s
, 0, stream_get_endp(s
));
4561 if (IS_ZEBRA_DEBUG_VXLAN
)
4562 zlog_debug("Send EVPN_DEL %u to %s", zevpn
->vni
,
4563 zebra_route_string(client
->proto
));
4565 client
->vnidel_cnt
++;
4566 return zserv_send_message(client
, s
);
4570 * Build the VNI hash table by going over the VxLAN interfaces. This
4571 * is called when EVPN (advertise-all-vni) is enabled.
4573 static void zevpn_build_hash_table(void)
4575 struct zebra_ns
*zns
;
4576 struct route_node
*rn
;
4577 struct interface
*ifp
;
4579 /* Walk VxLAN interfaces and create EVPN hash. */
4580 zns
= zebra_ns_lookup(NS_DEFAULT
);
4581 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
4583 zebra_evpn_t
*zevpn
= NULL
;
4584 zebra_l3vni_t
*zl3vni
= NULL
;
4585 struct zebra_if
*zif
;
4586 struct zebra_l2info_vxlan
*vxl
;
4588 ifp
= (struct interface
*)rn
->info
;
4592 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
4595 vxl
= &zif
->l2info
.vxl
;
4598 /* L3-VNI and L2-VNI are handled seperately */
4599 zl3vni
= zl3vni_lookup(vni
);
4602 if (IS_ZEBRA_DEBUG_VXLAN
)
4604 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
4605 ifp
->name
, ifp
->ifindex
, vni
);
4607 /* associate with vxlan_if */
4608 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
4609 zl3vni
->vxlan_if
= ifp
;
4612 * we need to associate with SVI.
4613 * we can associate with svi-if only after association
4614 * with vxlan-intf is complete
4616 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
4618 /* Associate l3vni to mac-vlan and extract VRR MAC */
4619 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
4621 if (IS_ZEBRA_DEBUG_VXLAN
)
4622 zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
4623 vni
, zl3vni
->svi_if
? zl3vni
->svi_if
->name
4625 zl3vni
->mac_vlan_if
?
4626 zl3vni
->mac_vlan_if
->name
: "NIL");
4628 if (is_l3vni_oper_up(zl3vni
))
4629 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
4632 struct interface
*vlan_if
= NULL
;
4634 if (IS_ZEBRA_DEBUG_VXLAN
)
4636 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
4637 ifp
->name
, ifp
->ifindex
, vni
,
4638 inet_ntoa(vxl
->vtep_ip
));
4640 /* EVPN hash entry is expected to exist, if the BGP process is killed */
4641 zevpn
= zevpn_lookup(vni
);
4644 "EVPN hash already present for IF %s(%u) L2-VNI %u",
4645 ifp
->name
, ifp
->ifindex
, vni
);
4648 * Inform BGP if intf is up and mapped to
4651 if (if_is_operative(ifp
) &&
4652 zif
->brslave_info
.br_if
)
4653 zevpn_send_add_to_client(zevpn
);
4655 /* Send Local MAC-entries to client */
4656 zevpn_send_mac_to_client(zevpn
);
4658 /* Send Loval Neighbor entries to client */
4659 zevpn_send_neigh_to_client(zevpn
);
4661 zevpn
= zevpn_add(vni
);
4664 "Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
4665 ifp
->name
, ifp
->ifindex
, vni
);
4669 if (zevpn
->local_vtep_ip
.s_addr
!=
4670 vxl
->vtep_ip
.s_addr
||
4671 zevpn
->mcast_grp
.s_addr
!=
4672 vxl
->mcast_grp
.s_addr
) {
4673 zebra_vxlan_sg_deref(
4674 zevpn
->local_vtep_ip
,
4676 zebra_vxlan_sg_ref(vxl
->vtep_ip
,
4678 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
4679 zevpn
->mcast_grp
= vxl
->mcast_grp
;
4680 /* on local vtep-ip check if ES
4681 * orig-ip needs to be updated
4683 zebra_evpn_es_set_base_evpn(zevpn
);
4685 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
4686 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
,
4687 zif
->brslave_info
.br_if
);
4689 zevpn
->vrf_id
= vlan_if
->vrf_id
;
4690 zl3vni
= zl3vni_from_vrf(
4694 zl3vni
->l2vnis
, zevpn
);
4698 * Inform BGP if intf is up and mapped to
4701 if (if_is_operative(ifp
) &&
4702 zif
->brslave_info
.br_if
)
4703 zevpn_send_add_to_client(zevpn
);
4710 * See if remote VTEP matches with prefix.
4712 static int zevpn_vtep_match(struct in_addr
*vtep_ip
, zebra_vtep_t
*zvtep
)
4714 return (IPV4_ADDR_SAME(vtep_ip
, &zvtep
->vtep_ip
));
4718 * Locate remote VTEP in EVPN hash table.
4720 static zebra_vtep_t
*zevpn_vtep_find(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
)
4722 zebra_vtep_t
*zvtep
;
4727 for (zvtep
= zevpn
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4728 if (zevpn_vtep_match(vtep_ip
, zvtep
))
4736 * Add remote VTEP to EVPN hash table.
4738 static zebra_vtep_t
*zevpn_vtep_add(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
,
4742 zebra_vtep_t
*zvtep
;
4744 zvtep
= XCALLOC(MTYPE_ZEVPN_VTEP
, sizeof(zebra_vtep_t
));
4746 zvtep
->vtep_ip
= *vtep_ip
;
4747 zvtep
->flood_control
= flood_control
;
4750 zevpn
->vteps
->prev
= zvtep
;
4751 zvtep
->next
= zevpn
->vteps
;
4752 zevpn
->vteps
= zvtep
;
4758 * Remove remote VTEP from EVPN hash table.
4760 static int zevpn_vtep_del(zebra_evpn_t
*zevpn
, zebra_vtep_t
*zvtep
)
4763 zvtep
->next
->prev
= zvtep
->prev
;
4765 zvtep
->prev
->next
= zvtep
->next
;
4767 zevpn
->vteps
= zvtep
->next
;
4769 zvtep
->prev
= zvtep
->next
= NULL
;
4770 XFREE(MTYPE_ZEVPN_VTEP
, zvtep
);
4776 * Delete all remote VTEPs for this EVPN (upon VNI delete). Also
4777 * uninstall from kernel if asked to.
4779 static int zevpn_vtep_del_all(zebra_evpn_t
*zevpn
, int uninstall
)
4781 zebra_vtep_t
*zvtep
, *zvtep_next
;
4786 for (zvtep
= zevpn
->vteps
; zvtep
; zvtep
= zvtep_next
) {
4787 zvtep_next
= zvtep
->next
;
4789 zevpn_vtep_uninstall(zevpn
, &zvtep
->vtep_ip
);
4790 zevpn_vtep_del(zevpn
, zvtep
);
4797 * Install remote VTEP into the kernel if the remote VTEP has asked
4798 * for head-end-replication.
4800 static int zevpn_vtep_install(zebra_evpn_t
*zevpn
, zebra_vtep_t
*zvtep
)
4802 if (is_vxlan_flooding_head_end() &&
4803 (zvtep
->flood_control
== VXLAN_FLOOD_HEAD_END_REPL
)) {
4804 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4805 dplane_vtep_add(zevpn
->vxlan_if
,
4806 &zvtep
->vtep_ip
, zevpn
->vni
))
4814 * Uninstall remote VTEP from the kernel.
4816 static int zevpn_vtep_uninstall(zebra_evpn_t
*zevpn
, struct in_addr
*vtep_ip
)
4818 if (!zevpn
->vxlan_if
) {
4819 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4824 if (ZEBRA_DPLANE_REQUEST_FAILURE
==
4825 dplane_vtep_delete(zevpn
->vxlan_if
, vtep_ip
, zevpn
->vni
))
4832 * Install or uninstall flood entries in the kernel corresponding to
4833 * remote VTEPs. This is invoked upon change to BUM handling.
4835 static void zevpn_handle_flooding_remote_vteps(struct hash_bucket
*bucket
,
4838 zebra_evpn_t
*zevpn
;
4839 zebra_vtep_t
*zvtep
;
4841 zevpn
= (zebra_evpn_t
*)bucket
->data
;
4845 for (zvtep
= zevpn
->vteps
; zvtep
; zvtep
= zvtep
->next
) {
4846 if (is_vxlan_flooding_head_end())
4847 zevpn_vtep_install(zevpn
, zvtep
);
4849 zevpn_vtep_uninstall(zevpn
, &zvtep
->vtep_ip
);
4854 * Cleanup EVPN/VTEP and update kernel
4856 static void zevpn_cleanup_all(struct hash_bucket
*bucket
, void *arg
)
4858 zebra_evpn_t
*zevpn
= NULL
;
4859 zebra_l3vni_t
*zl3vni
= NULL
;
4860 struct zebra_vrf
*zvrf
= (struct zebra_vrf
*)arg
;
4862 zevpn
= (zebra_evpn_t
*)bucket
->data
;
4864 /* remove from l3-vni list */
4866 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
4868 listnode_delete(zl3vni
->l2vnis
, zevpn
);
4870 /* Free up all neighbors and MACs, if any. */
4871 zevpn_neigh_del_all(zevpn
, 1, 0, DEL_ALL_NEIGH
);
4872 zevpn_mac_del_all(zevpn
, 1, 0, DEL_ALL_MAC
);
4874 /* Free up all remote VTEPs, if any. */
4875 zevpn_vtep_del_all(zevpn
, 1);
4877 /* Delete the hash entry. */
4882 static void zl3vni_cleanup_all(struct hash_bucket
*bucket
, void *args
)
4884 zebra_l3vni_t
*zl3vni
= NULL
;
4886 zl3vni
= (zebra_l3vni_t
*)bucket
->data
;
4888 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
4891 static void rb_find_or_add_host(struct host_rb_tree_entry
*hrbe
,
4892 const struct prefix
*host
)
4894 struct host_rb_entry lookup
;
4895 struct host_rb_entry
*hle
;
4897 memset(&lookup
, 0, sizeof(lookup
));
4898 memcpy(&lookup
.p
, host
, sizeof(*host
));
4900 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4904 hle
= XCALLOC(MTYPE_HOST_PREFIX
, sizeof(struct host_rb_entry
));
4905 memcpy(hle
, &lookup
, sizeof(lookup
));
4907 RB_INSERT(host_rb_tree_entry
, hrbe
, hle
);
4910 static void rb_delete_host(struct host_rb_tree_entry
*hrbe
, struct prefix
*host
)
4912 struct host_rb_entry lookup
;
4913 struct host_rb_entry
*hle
;
4915 memset(&lookup
, 0, sizeof(lookup
));
4916 memcpy(&lookup
.p
, host
, sizeof(*host
));
4918 hle
= RB_FIND(host_rb_tree_entry
, hrbe
, &lookup
);
4920 RB_REMOVE(host_rb_tree_entry
, hrbe
, hle
);
4921 XFREE(MTYPE_HOST_PREFIX
, hle
);
4928 * Look up MAC hash entry.
4930 static zebra_mac_t
*zl3vni_rmac_lookup(zebra_l3vni_t
*zl3vni
,
4931 const struct ethaddr
*rmac
)
4936 memset(&tmp
, 0, sizeof(tmp
));
4937 memcpy(&tmp
.macaddr
, rmac
, ETH_ALEN
);
4938 pmac
= hash_lookup(zl3vni
->rmac_table
, &tmp
);
4944 * Callback to allocate RMAC hash entry.
4946 static void *zl3vni_rmac_alloc(void *p
)
4948 const zebra_mac_t
*tmp_rmac
= p
;
4951 zrmac
= XCALLOC(MTYPE_MAC
, sizeof(zebra_mac_t
));
4954 return ((void *)zrmac
);
4958 * Add RMAC entry to l3-vni
4960 static zebra_mac_t
*zl3vni_rmac_add(zebra_l3vni_t
*zl3vni
,
4961 const struct ethaddr
*rmac
)
4963 zebra_mac_t tmp_rmac
;
4964 zebra_mac_t
*zrmac
= NULL
;
4966 memset(&tmp_rmac
, 0, sizeof(zebra_mac_t
));
4967 memcpy(&tmp_rmac
.macaddr
, rmac
, ETH_ALEN
);
4968 zrmac
= hash_get(zl3vni
->rmac_table
, &tmp_rmac
, zl3vni_rmac_alloc
);
4971 RB_INIT(host_rb_tree_entry
, &zrmac
->host_rb
);
4973 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
);
4974 SET_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
);
4982 static int zl3vni_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
4984 zebra_mac_t
*tmp_rmac
;
4985 struct host_rb_entry
*hle
;
4987 while (!RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
4988 hle
= RB_ROOT(host_rb_tree_entry
, &zrmac
->host_rb
);
4990 RB_REMOVE(host_rb_tree_entry
, &zrmac
->host_rb
, hle
);
4991 XFREE(MTYPE_HOST_PREFIX
, hle
);
4994 tmp_rmac
= hash_release(zl3vni
->rmac_table
, zrmac
);
4995 XFREE(MTYPE_MAC
, tmp_rmac
);
5001 * Install remote RMAC into the forwarding plane.
5003 static int zl3vni_rmac_install(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
5005 const struct zebra_if
*zif
= NULL
, *br_zif
= NULL
;
5006 const struct zebra_l2info_vxlan
*vxl
= NULL
;
5007 const struct interface
*br_ifp
;
5008 enum zebra_dplane_result res
;
5011 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
5012 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
5015 zif
= zl3vni
->vxlan_if
->info
;
5019 br_ifp
= zif
->brslave_info
.br_if
;
5023 vxl
= &zif
->l2info
.vxl
;
5025 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
5027 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
5028 vid
= vxl
->access_vlan
;
5032 res
= dplane_rem_mac_add(zl3vni
->vxlan_if
, br_ifp
, vid
,
5033 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
, 0, 0,
5034 false /*was_static*/);
5035 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
5042 * Uninstall remote RMAC from the forwarding plane.
5044 static int zl3vni_rmac_uninstall(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
)
5046 char buf
[ETHER_ADDR_STRLEN
];
5047 const struct zebra_if
*zif
= NULL
, *br_zif
;
5048 const struct zebra_l2info_vxlan
*vxl
= NULL
;
5049 const struct interface
*br_ifp
;
5051 enum zebra_dplane_result res
;
5053 if (!(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE
))
5054 || !(CHECK_FLAG(zrmac
->flags
, ZEBRA_MAC_REMOTE_RMAC
)))
5057 if (!zl3vni
->vxlan_if
) {
5058 if (IS_ZEBRA_DEBUG_VXLAN
)
5060 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
5061 prefix_mac2str(&zrmac
->macaddr
,
5063 zl3vni
->vni
, zl3vni
);
5067 zif
= zl3vni
->vxlan_if
->info
;
5071 br_ifp
= zif
->brslave_info
.br_if
;
5075 vxl
= &zif
->l2info
.vxl
;
5077 br_zif
= (const struct zebra_if
*)br_ifp
->info
;
5078 if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif
))
5079 vid
= vxl
->access_vlan
;
5083 res
= dplane_rem_mac_del(zl3vni
->vxlan_if
, br_ifp
, vid
,
5084 &zrmac
->macaddr
, zrmac
->fwd_info
.r_vtep_ip
);
5085 if (res
!= ZEBRA_DPLANE_REQUEST_FAILURE
)
5091 /* handle rmac add */
5092 static int zl3vni_remote_rmac_add(zebra_l3vni_t
*zl3vni
,
5093 const struct ethaddr
*rmac
,
5094 const struct ipaddr
*vtep_ip
,
5095 const struct prefix
*host_prefix
)
5097 char buf
[ETHER_ADDR_STRLEN
];
5098 char buf1
[INET6_ADDRSTRLEN
];
5099 char buf2
[PREFIX_STRLEN
];
5100 zebra_mac_t
*zrmac
= NULL
;
5102 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5105 /* Create the RMAC entry, or update its vtep, if necessary. */
5106 zrmac
= zl3vni_rmac_add(zl3vni
, rmac
);
5109 "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s",
5110 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
5112 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
5113 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
5116 memset(&zrmac
->fwd_info
, 0, sizeof(zrmac
->fwd_info
));
5117 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
5119 /* Send RMAC for FPM processing */
5120 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, false,
5123 /* install rmac in kernel */
5124 zl3vni_rmac_install(zl3vni
, zrmac
);
5125 } else if (!IPV4_ADDR_SAME(&zrmac
->fwd_info
.r_vtep_ip
,
5126 &vtep_ip
->ipaddr_v4
)) {
5127 if (IS_ZEBRA_DEBUG_VXLAN
)
5129 "L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s",
5131 inet_ntoa(zrmac
->fwd_info
.r_vtep_ip
),
5132 ipaddr2str(vtep_ip
, buf1
, sizeof(buf1
)),
5133 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
5134 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
5136 zrmac
->fwd_info
.r_vtep_ip
= vtep_ip
->ipaddr_v4
;
5138 /* install rmac in kernel */
5139 zl3vni_rmac_install(zl3vni
, zrmac
);
5142 rb_find_or_add_host(&zrmac
->host_rb
, host_prefix
);
5148 /* handle rmac delete */
5149 static void zl3vni_remote_rmac_del(zebra_l3vni_t
*zl3vni
, zebra_mac_t
*zrmac
,
5150 struct prefix
*host_prefix
)
5152 rb_delete_host(&zrmac
->host_rb
, host_prefix
);
5154 if (RB_EMPTY(host_rb_tree_entry
, &zrmac
->host_rb
)) {
5155 /* uninstall from kernel */
5156 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5158 /* Send RMAC for FPM processing */
5159 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true,
5162 /* del the rmac entry */
5163 zl3vni_rmac_del(zl3vni
, zrmac
);
5168 * Look up nh hash entry on a l3-vni.
5170 static zebra_neigh_t
*zl3vni_nh_lookup(zebra_l3vni_t
*zl3vni
,
5171 const struct ipaddr
*ip
)
5176 memset(&tmp
, 0, sizeof(tmp
));
5177 memcpy(&tmp
.ip
, ip
, sizeof(struct ipaddr
));
5178 n
= hash_lookup(zl3vni
->nh_table
, &tmp
);
5185 * Callback to allocate NH hash entry on L3-VNI.
5187 static void *zl3vni_nh_alloc(void *p
)
5189 const zebra_neigh_t
*tmp_n
= p
;
5192 n
= XCALLOC(MTYPE_NEIGH
, sizeof(zebra_neigh_t
));
5199 * Add neighbor entry.
5201 static zebra_neigh_t
*zl3vni_nh_add(zebra_l3vni_t
*zl3vni
,
5202 const struct ipaddr
*ip
,
5203 const struct ethaddr
*mac
)
5205 zebra_neigh_t tmp_n
;
5206 zebra_neigh_t
*n
= NULL
;
5208 memset(&tmp_n
, 0, sizeof(zebra_neigh_t
));
5209 memcpy(&tmp_n
.ip
, ip
, sizeof(struct ipaddr
));
5210 n
= hash_get(zl3vni
->nh_table
, &tmp_n
, zl3vni_nh_alloc
);
5213 RB_INIT(host_rb_tree_entry
, &n
->host_rb
);
5215 memcpy(&n
->emac
, mac
, ETH_ALEN
);
5216 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
5217 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE_NH
);
5223 * Delete neighbor entry.
5225 static int zl3vni_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
5227 zebra_neigh_t
*tmp_n
;
5228 struct host_rb_entry
*hle
;
5230 while (!RB_EMPTY(host_rb_tree_entry
, &n
->host_rb
)) {
5231 hle
= RB_ROOT(host_rb_tree_entry
, &n
->host_rb
);
5233 RB_REMOVE(host_rb_tree_entry
, &n
->host_rb
, hle
);
5234 XFREE(MTYPE_HOST_PREFIX
, hle
);
5237 tmp_n
= hash_release(zl3vni
->nh_table
, n
);
5238 XFREE(MTYPE_NEIGH
, tmp_n
);
5244 * Install remote nh as neigh into the kernel.
5246 static int zl3vni_nh_install(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
5251 if (!is_l3vni_oper_up(zl3vni
))
5254 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
5255 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
5258 flags
= DPLANE_NTF_EXT_LEARNED
;
5259 if (n
->flags
& ZEBRA_NEIGH_ROUTER_FLAG
)
5260 flags
|= DPLANE_NTF_ROUTER
;
5262 dplane_rem_neigh_add(zl3vni
->svi_if
, &n
->ip
, &n
->emac
, flags
,
5263 false /*was_static*/);
5269 * Uninstall remote nh from the kernel.
5271 static int zl3vni_nh_uninstall(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*n
)
5273 if (!(n
->flags
& ZEBRA_NEIGH_REMOTE
)
5274 || !(n
->flags
& ZEBRA_NEIGH_REMOTE_NH
))
5277 if (!zl3vni
->svi_if
|| !if_is_operative(zl3vni
->svi_if
))
5280 dplane_rem_neigh_delete(zl3vni
->svi_if
, &n
->ip
);
5285 /* add remote vtep as a neigh entry */
5286 static int zl3vni_remote_nh_add(zebra_l3vni_t
*zl3vni
,
5287 const struct ipaddr
*vtep_ip
,
5288 const struct ethaddr
*rmac
,
5289 const struct prefix
*host_prefix
)
5291 char buf
[ETHER_ADDR_STRLEN
];
5292 char buf1
[ETHER_ADDR_STRLEN
];
5293 char buf2
[INET6_ADDRSTRLEN
];
5294 char buf3
[PREFIX_STRLEN
];
5295 zebra_neigh_t
*nh
= NULL
;
5297 /* Create the next hop entry, or update its mac, if necessary. */
5298 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
5300 nh
= zl3vni_nh_add(zl3vni
, vtep_ip
, rmac
);
5303 "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)",
5304 ipaddr2str(vtep_ip
, buf1
, sizeof(buf2
)),
5305 prefix_mac2str(rmac
, buf
, sizeof(buf
)),
5307 prefix2str(host_prefix
, buf2
, sizeof(buf2
)));
5311 /* install the nh neigh in kernel */
5312 zl3vni_nh_install(zl3vni
, nh
);
5313 } else if (memcmp(&nh
->emac
, rmac
, ETH_ALEN
) != 0) {
5314 if (IS_ZEBRA_DEBUG_VXLAN
)
5315 zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s",
5317 prefix_mac2str(&nh
->emac
, buf
, sizeof(buf
)),
5318 prefix_mac2str(rmac
, buf1
, sizeof(buf1
)),
5319 ipaddr2str(vtep_ip
, buf2
, sizeof(buf2
)),
5320 prefix2str(host_prefix
, buf3
, sizeof(buf3
)));
5322 memcpy(&nh
->emac
, rmac
, ETH_ALEN
);
5323 /* install (update) the nh neigh in kernel */
5324 zl3vni_nh_install(zl3vni
, nh
);
5327 rb_find_or_add_host(&nh
->host_rb
, host_prefix
);
5332 /* handle nh neigh delete */
5333 static void zl3vni_remote_nh_del(zebra_l3vni_t
*zl3vni
, zebra_neigh_t
*nh
,
5334 struct prefix
*host_prefix
)
5336 rb_delete_host(&nh
->host_rb
, host_prefix
);
5338 if (RB_EMPTY(host_rb_tree_entry
, &nh
->host_rb
)) {
5339 /* uninstall from kernel */
5340 zl3vni_nh_uninstall(zl3vni
, nh
);
5342 /* delete the nh entry */
5343 zl3vni_nh_del(zl3vni
, nh
);
5347 /* handle neigh update from kernel - the only thing of interest is to
5348 * readd stale entries.
5350 static int zl3vni_local_nh_add_update(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
,
5354 zebra_neigh_t
*n
= NULL
;
5356 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5360 /* all next hop neigh are remote and installed by frr.
5361 * If the kernel has aged this entry, re-install.
5363 if (state
& NUD_STALE
)
5364 zl3vni_nh_install(zl3vni
, n
);
5369 /* handle neigh delete from kernel */
5370 static int zl3vni_local_nh_del(zebra_l3vni_t
*zl3vni
, struct ipaddr
*ip
)
5372 zebra_neigh_t
*n
= NULL
;
5374 n
= zl3vni_nh_lookup(zl3vni
, ip
);
5378 /* all next hop neigh are remote and installed by frr.
5379 * If we get an age out notification for these neigh entries, we have to
5382 zl3vni_nh_install(zl3vni
, n
);
5388 * Hash function for L3 VNI.
5390 static unsigned int l3vni_hash_keymake(const void *p
)
5392 const zebra_l3vni_t
*zl3vni
= p
;
5394 return jhash_1word(zl3vni
->vni
, 0);
5398 * Compare 2 L3 VNI hash entries.
5400 static bool l3vni_hash_cmp(const void *p1
, const void *p2
)
5402 const zebra_l3vni_t
*zl3vni1
= p1
;
5403 const zebra_l3vni_t
*zl3vni2
= p2
;
5405 return (zl3vni1
->vni
== zl3vni2
->vni
);
5409 * Callback to allocate L3 VNI hash entry.
5411 static void *zl3vni_alloc(void *p
)
5413 zebra_l3vni_t
*zl3vni
= NULL
;
5414 const zebra_l3vni_t
*tmp_l3vni
= p
;
5416 zl3vni
= XCALLOC(MTYPE_ZL3VNI
, sizeof(zebra_l3vni_t
));
5417 zl3vni
->vni
= tmp_l3vni
->vni
;
5418 return ((void *)zl3vni
);
5422 * Look up L3 VNI hash entry.
5424 zebra_l3vni_t
*zl3vni_lookup(vni_t vni
)
5426 zebra_l3vni_t tmp_l3vni
;
5427 zebra_l3vni_t
*zl3vni
= NULL
;
5429 memset(&tmp_l3vni
, 0, sizeof(zebra_l3vni_t
));
5430 tmp_l3vni
.vni
= vni
;
5431 zl3vni
= hash_lookup(zrouter
.l3vni_table
, &tmp_l3vni
);
5437 * Add L3 VNI hash entry.
5439 static zebra_l3vni_t
*zl3vni_add(vni_t vni
, vrf_id_t vrf_id
)
5441 zebra_l3vni_t tmp_zl3vni
;
5442 zebra_l3vni_t
*zl3vni
= NULL
;
5444 memset(&tmp_zl3vni
, 0, sizeof(zebra_l3vni_t
));
5445 tmp_zl3vni
.vni
= vni
;
5447 zl3vni
= hash_get(zrouter
.l3vni_table
, &tmp_zl3vni
, zl3vni_alloc
);
5450 zl3vni
->vrf_id
= vrf_id
;
5451 zl3vni
->svi_if
= NULL
;
5452 zl3vni
->vxlan_if
= NULL
;
5453 zl3vni
->l2vnis
= list_new();
5454 zl3vni
->l2vnis
->cmp
= vni_list_cmp
;
5456 /* Create hash table for remote RMAC */
5457 zl3vni
->rmac_table
= hash_create(mac_hash_keymake
, mac_cmp
,
5458 "Zebra L3-VNI RMAC-Table");
5460 /* Create hash table for neighbors */
5461 zl3vni
->nh_table
= hash_create(neigh_hash_keymake
, neigh_cmp
,
5462 "Zebra L3-VNI next-hop table");
5468 * Delete L3 VNI hash entry.
5470 static int zl3vni_del(zebra_l3vni_t
*zl3vni
)
5472 zebra_l3vni_t
*tmp_zl3vni
;
5474 /* free the list of l2vnis */
5475 list_delete(&zl3vni
->l2vnis
);
5476 zl3vni
->l2vnis
= NULL
;
5478 /* Free the rmac table */
5479 hash_free(zl3vni
->rmac_table
);
5480 zl3vni
->rmac_table
= NULL
;
5482 /* Free the nh table */
5483 hash_free(zl3vni
->nh_table
);
5484 zl3vni
->nh_table
= NULL
;
5486 /* Free the VNI hash entry and allocated memory. */
5487 tmp_zl3vni
= hash_release(zrouter
.l3vni_table
, zl3vni
);
5488 XFREE(MTYPE_ZL3VNI
, tmp_zl3vni
);
5493 struct interface
*zl3vni_map_to_vxlan_if(zebra_l3vni_t
*zl3vni
)
5495 struct zebra_ns
*zns
= NULL
;
5496 struct route_node
*rn
= NULL
;
5497 struct interface
*ifp
= NULL
;
5499 /* loop through all vxlan-interface */
5500 zns
= zebra_ns_lookup(NS_DEFAULT
);
5501 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5503 struct zebra_if
*zif
= NULL
;
5504 struct zebra_l2info_vxlan
*vxl
= NULL
;
5506 ifp
= (struct interface
*)rn
->info
;
5511 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5514 vxl
= &zif
->l2info
.vxl
;
5515 if (vxl
->vni
== zl3vni
->vni
) {
5516 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
5524 struct interface
*zl3vni_map_to_svi_if(zebra_l3vni_t
*zl3vni
)
5526 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5527 struct zebra_l2info_vxlan
*vxl
= NULL
; /* l2 info for vxlan_if */
5532 if (!zl3vni
->vxlan_if
)
5535 zif
= zl3vni
->vxlan_if
->info
;
5539 vxl
= &zif
->l2info
.vxl
;
5541 return zevpn_map_to_svi(vxl
->access_vlan
, zif
->brslave_info
.br_if
);
5544 struct interface
*zl3vni_map_to_mac_vlan_if(zebra_l3vni_t
*zl3vni
)
5546 struct zebra_if
*zif
= NULL
; /* zebra_if for vxlan_if */
5551 if (!zl3vni
->vxlan_if
)
5554 zif
= zl3vni
->vxlan_if
->info
;
5558 return zevpn_map_to_macvlan(zif
->brslave_info
.br_if
, zl3vni
->svi_if
);
5562 zebra_l3vni_t
*zl3vni_from_vrf(vrf_id_t vrf_id
)
5564 struct zebra_vrf
*zvrf
= NULL
;
5566 zvrf
= zebra_vrf_lookup_by_id(vrf_id
);
5570 return zl3vni_lookup(zvrf
->l3vni
);
5574 * Map SVI and associated bridge to a VNI. This is invoked upon getting
5575 * neighbor notifications, to see if they are of interest.
5577 static zebra_l3vni_t
*zl3vni_from_svi(struct interface
*ifp
,
5578 struct interface
*br_if
)
5582 uint8_t bridge_vlan_aware
= 0;
5583 zebra_l3vni_t
*zl3vni
= NULL
;
5584 struct zebra_ns
*zns
= NULL
;
5585 struct route_node
*rn
= NULL
;
5586 struct zebra_if
*zif
= NULL
;
5587 struct interface
*tmp_if
= NULL
;
5588 struct zebra_l2info_bridge
*br
= NULL
;
5589 struct zebra_l2info_vxlan
*vxl
= NULL
;
5594 /* Make sure the linked interface is a bridge. */
5595 if (!IS_ZEBRA_IF_BRIDGE(br_if
))
5598 /* Determine if bridge is VLAN-aware or not */
5601 br
= &zif
->l2info
.br
;
5602 bridge_vlan_aware
= br
->vlan_aware
;
5603 if (bridge_vlan_aware
) {
5604 struct zebra_l2info_vlan
*vl
;
5606 if (!IS_ZEBRA_IF_VLAN(ifp
))
5611 vl
= &zif
->l2info
.vl
;
5615 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
5616 /* TODO: Optimize with a hash. */
5617 zns
= zebra_ns_lookup(NS_DEFAULT
);
5618 for (rn
= route_top(zns
->if_table
); rn
; rn
= route_next(rn
)) {
5619 tmp_if
= (struct interface
*)rn
->info
;
5623 if (!zif
|| zif
->zif_type
!= ZEBRA_IF_VXLAN
)
5625 if (!if_is_operative(tmp_if
))
5627 vxl
= &zif
->l2info
.vxl
;
5629 if (zif
->brslave_info
.br_if
!= br_if
)
5632 if (!bridge_vlan_aware
|| vxl
->access_vlan
== vid
) {
5641 zl3vni
= zl3vni_lookup(vxl
->vni
);
5645 static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t
*zl3vni
,
5646 struct ethaddr
*rmac
)
5651 if (!is_l3vni_oper_up(zl3vni
))
5654 if (zl3vni
->mac_vlan_if
&& if_is_operative(zl3vni
->mac_vlan_if
))
5655 memcpy(rmac
->octet
, zl3vni
->mac_vlan_if
->hw_addr
, ETH_ALEN
);
5659 * Inform BGP about l3-vni.
5661 static int zl3vni_send_add_to_client(zebra_l3vni_t
*zl3vni
)
5663 struct stream
*s
= NULL
;
5664 struct zserv
*client
= NULL
;
5665 struct ethaddr svi_rmac
, vrr_rmac
= {.octet
= {0} };
5666 struct zebra_vrf
*zvrf
;
5667 char buf
[ETHER_ADDR_STRLEN
];
5668 char buf1
[ETHER_ADDR_STRLEN
];
5669 bool is_anycast_mac
= true;
5671 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5672 /* BGP may not be running. */
5676 zvrf
= zebra_vrf_lookup_by_id(zl3vni
->vrf_id
);
5679 /* get the svi and vrr rmac values */
5680 memset(&svi_rmac
, 0, sizeof(struct ethaddr
));
5681 zl3vni_get_svi_rmac(zl3vni
, &svi_rmac
);
5682 zl3vni_get_vrr_rmac(zl3vni
, &vrr_rmac
);
5684 /* In absence of vrr mac use svi mac as anycast MAC value */
5685 if (is_zero_mac(&vrr_rmac
)) {
5686 memcpy(&vrr_rmac
, &svi_rmac
, ETH_ALEN
);
5687 is_anycast_mac
= false;
5690 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5692 /* The message is used for both vni add and/or update like
5693 * vrr mac is added for l3vni SVI.
5695 zclient_create_header(s
, ZEBRA_L3VNI_ADD
, zl3vni_vrf_id(zl3vni
));
5696 stream_putl(s
, zl3vni
->vni
);
5697 stream_put(s
, &svi_rmac
, sizeof(struct ethaddr
));
5698 stream_put_in_addr(s
, &zl3vni
->local_vtep_ip
);
5699 stream_put(s
, &zl3vni
->filter
, sizeof(int));
5700 stream_putl(s
, zl3vni
->svi_if
->ifindex
);
5701 stream_put(s
, &vrr_rmac
, sizeof(struct ethaddr
));
5702 stream_putl(s
, is_anycast_mac
);
5704 /* Write packet size. */
5705 stream_putw_at(s
, 0, stream_get_endp(s
));
5707 if (IS_ZEBRA_DEBUG_VXLAN
)
5709 "Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %s filter %s to %s",
5710 zl3vni
->vni
, vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5711 prefix_mac2str(&svi_rmac
, buf
, sizeof(buf
)),
5712 prefix_mac2str(&vrr_rmac
, buf1
, sizeof(buf1
)),
5713 inet_ntoa(zl3vni
->local_vtep_ip
),
5714 CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)
5715 ? "prefix-routes-only"
5717 zebra_route_string(client
->proto
));
5719 client
->l3vniadd_cnt
++;
5720 return zserv_send_message(client
, s
);
5724 * Inform BGP about local l3-VNI deletion.
5726 static int zl3vni_send_del_to_client(zebra_l3vni_t
*zl3vni
)
5728 struct stream
*s
= NULL
;
5729 struct zserv
*client
= NULL
;
5731 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5732 /* BGP may not be running. */
5736 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5738 zclient_create_header(s
, ZEBRA_L3VNI_DEL
, zl3vni_vrf_id(zl3vni
));
5739 stream_putl(s
, zl3vni
->vni
);
5741 /* Write packet size. */
5742 stream_putw_at(s
, 0, stream_get_endp(s
));
5744 if (IS_ZEBRA_DEBUG_VXLAN
)
5745 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni
->vni
,
5746 vrf_id_to_name(zl3vni_vrf_id(zl3vni
)),
5747 zebra_route_string(client
->proto
));
5749 client
->l3vnidel_cnt
++;
5750 return zserv_send_message(client
, s
);
5753 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t
*zl3vni
)
5758 /* send l3vni add to BGP */
5759 zl3vni_send_add_to_client(zl3vni
);
5762 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t
*zl3vni
)
5767 /* send l3-vni del to BGP*/
5768 zl3vni_send_del_to_client(zl3vni
);
5771 static void zevpn_add_to_l3vni_list(struct hash_bucket
*bucket
, void *ctxt
)
5773 zebra_evpn_t
*zevpn
= (zebra_evpn_t
*)bucket
->data
;
5774 zebra_l3vni_t
*zl3vni
= (zebra_l3vni_t
*)ctxt
;
5776 if (zevpn
->vrf_id
== zl3vni_vrf_id(zl3vni
))
5777 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
5781 * handle transition of vni from l2 to l3 and vice versa
5783 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf
*zvrf
, vni_t vni
,
5786 zebra_evpn_t
*zevpn
= NULL
;
5788 /* There is a possibility that VNI notification was already received
5789 * from kernel and we programmed it as L2-VNI
5790 * In such a case we need to delete this L2-VNI first, so
5791 * that it can be reprogrammed as L3-VNI in the system. It is also
5792 * possible that the vrf-vni mapping is removed from FRR while the vxlan
5793 * interface is still present in kernel. In this case to keep it
5794 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
5797 /* Locate hash entry */
5798 zevpn
= zevpn_lookup(vni
);
5802 if (IS_ZEBRA_DEBUG_VXLAN
)
5803 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni
);
5805 /* Delete EVPN from BGP. */
5806 zevpn_send_del_to_client(zevpn
);
5808 /* Free up all neighbors and MAC, if any. */
5809 zevpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
5810 zevpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
5812 /* Free up all remote VTEPs, if any. */
5813 zevpn_vtep_del_all(zevpn
, 0);
5815 /* Delete the hash entry. */
5816 if (zevpn_del(zevpn
)) {
5817 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
5818 "Failed to del EVPN hash %p, VNI %u", zevpn
,
5823 /* TODO_MITESH: This needs to be thought through. We don't have
5824 * enough information at this point to reprogram the vni as
5825 * l2-vni. One way is to store the required info in l3-vni and
5826 * used it solely for this purpose
5833 /* delete and uninstall rmac hash entry */
5834 static void zl3vni_del_rmac_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5836 zebra_mac_t
*zrmac
= NULL
;
5837 zebra_l3vni_t
*zl3vni
= NULL
;
5839 zrmac
= (zebra_mac_t
*)bucket
->data
;
5840 zl3vni
= (zebra_l3vni_t
*)ctx
;
5841 zl3vni_rmac_uninstall(zl3vni
, zrmac
);
5843 /* Send RMAC for FPM processing */
5844 hook_call(zebra_rmac_update
, zrmac
, zl3vni
, true, "RMAC deleted");
5846 zl3vni_rmac_del(zl3vni
, zrmac
);
5849 /* delete and uninstall nh hash entry */
5850 static void zl3vni_del_nh_hash_entry(struct hash_bucket
*bucket
, void *ctx
)
5852 zebra_neigh_t
*n
= NULL
;
5853 zebra_l3vni_t
*zl3vni
= NULL
;
5855 n
= (zebra_neigh_t
*)bucket
->data
;
5856 zl3vni
= (zebra_l3vni_t
*)ctx
;
5857 zl3vni_nh_uninstall(zl3vni
, n
);
5858 zl3vni_nh_del(zl3vni
, n
);
5861 static int ip_prefix_send_to_client(vrf_id_t vrf_id
, struct prefix
*p
,
5864 struct zserv
*client
= NULL
;
5865 struct stream
*s
= NULL
;
5866 char buf
[PREFIX_STRLEN
];
5868 client
= zserv_find_client(ZEBRA_ROUTE_BGP
, 0);
5869 /* BGP may not be running. */
5873 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
5875 zclient_create_header(s
, cmd
, vrf_id
);
5876 stream_put(s
, p
, sizeof(struct prefix
));
5878 /* Write packet size. */
5879 stream_putw_at(s
, 0, stream_get_endp(s
));
5881 if (IS_ZEBRA_DEBUG_VXLAN
)
5882 zlog_debug("Send ip prefix %s %s on vrf %s",
5883 prefix2str(p
, buf
, sizeof(buf
)),
5884 (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
) ? "ADD" : "DEL",
5885 vrf_id_to_name(vrf_id
));
5887 if (cmd
== ZEBRA_IP_PREFIX_ROUTE_ADD
)
5888 client
->prefixadd_cnt
++;
5890 client
->prefixdel_cnt
++;
5892 return zserv_send_message(client
, s
);
5895 /* re-add remote rmac if needed */
5896 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t
*zl3vni
,
5897 struct ethaddr
*rmac
)
5899 char buf
[ETHER_ADDR_STRLEN
];
5900 zebra_mac_t
*zrmac
= NULL
;
5902 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
5906 if (IS_ZEBRA_DEBUG_VXLAN
)
5907 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5908 prefix_mac2str(rmac
, buf
, sizeof(buf
)), zl3vni
->vni
);
5910 zl3vni_rmac_install(zl3vni
, zrmac
);
5914 /**************************** SYNC MAC handling *****************************/
5915 /* if the mac has been added of a mac-route from the peer
5916 * or if it is being referenced by a neigh added by the
5917 * peer we cannot let it age out i.e. we set the static bit
5920 static inline bool zebra_vxlan_mac_is_static(zebra_mac_t
*mac
)
5922 return ((mac
->flags
& ZEBRA_MAC_ALL_PEER_FLAGS
) ||
5923 mac
->sync_neigh_cnt
);
5926 /* mac needs to be locally active or active on an ES peer */
5927 static inline bool zebra_vxlan_mac_is_ready_for_bgp(uint32_t flags
)
5929 return (flags
& ZEBRA_MAC_LOCAL
) &&
5930 (!(flags
& ZEBRA_MAC_LOCAL_INACTIVE
) ||
5931 (flags
& ZEBRA_MAC_ES_PEER_ACTIVE
));
5934 /* program sync mac flags in the dataplane */
5935 void zebra_vxlan_sync_mac_dp_install(zebra_mac_t
*mac
, bool set_inactive
,
5936 bool force_clear_static
, const char *caller
)
5938 char macbuf
[ETHER_ADDR_STRLEN
];
5939 struct interface
*ifp
;
5942 zebra_evpn_t
*zevpn
= mac
->zevpn
;
5944 struct zebra_if
*zif
;
5945 struct interface
*br_ifp
;
5947 /* get the access vlan from the vxlan_device */
5948 zebra_vxlan_mac_get_access_info(mac
,
5952 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
5953 zlog_debug("%s: dp-install sync-mac vni %u mac %s es %s 0x%x %sskipped, no access-port",
5956 prefix_mac2str(&mac
->macaddr
, macbuf
,
5959 mac
->es
->esi_str
: "-",
5961 set_inactive
? "inactive " : "");
5966 br_ifp
= zif
->brslave_info
.br_if
;
5968 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
5969 zlog_debug("%s: dp-install sync-mac vni %u mac %s es %s 0x%x %sskipped, no br",
5972 prefix_mac2str(&mac
->macaddr
, macbuf
,
5975 mac
->es
->esi_str
: "-",
5977 set_inactive
? "inactive " : "");
5981 sticky
= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
5982 if (force_clear_static
)
5985 set_static
= zebra_vxlan_mac_is_static(mac
);
5987 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
5988 zlog_debug("dp-install sync-mac vni %u mac %s es %s 0x%x %s%s",
5990 prefix_mac2str(&mac
->macaddr
, macbuf
,
5993 mac
->es
->esi_str
: "-", mac
->flags
,
5994 set_static
? "static " : "",
5995 set_inactive
? "inactive " : "");
5997 dplane_local_mac_add(ifp
, br_ifp
, vid
, &mac
->macaddr
, sticky
,
5998 set_static
, set_inactive
);
6002 static void zebra_vxlan_mac_send_add_del_to_client(zebra_mac_t
*mac
,
6003 bool old_bgp_ready
, bool new_bgp_ready
)
6006 zevpn_mac_send_add_to_client(mac
->zevpn
->vni
,
6007 &mac
->macaddr
, mac
->flags
,
6008 mac
->loc_seq
, mac
->es
);
6009 else if (old_bgp_ready
)
6010 zevpn_mac_send_del_to_client(mac
->zevpn
->vni
,
6011 &mac
->macaddr
, mac
->flags
,
6015 /* MAC hold timer is used to age out peer-active flag.
6017 * During this wait time we expect the dataplane component or an
6018 * external neighmgr daemon to probe existing hosts to independently
6019 * establish their presence on the ES.
6021 static int zebra_vxlan_mac_hold_exp_cb(struct thread
*t
)
6028 char macbuf
[ETHER_ADDR_STRLEN
];
6030 mac
= THREAD_ARG(t
);
6031 /* the purpose of the hold timer is to age out the peer-active
6034 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
6037 old_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
6038 old_static
= zebra_vxlan_mac_is_static(mac
);
6039 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
);
6040 new_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
6041 new_static
= zebra_vxlan_mac_is_static(mac
);
6043 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6044 zlog_debug("sync-mac vni %u mac %s es %s 0x%x hold expired",
6046 prefix_mac2str(&mac
->macaddr
, macbuf
,
6049 mac
->es
->esi_str
: "-",
6052 /* re-program the local mac in the dataplane if the mac is no
6055 if (old_static
!= new_static
)
6056 zebra_vxlan_sync_mac_dp_install(mac
, false /* set_inactive */,
6057 false /* force_clear_static */, __func__
);
6059 /* inform bgp if needed */
6060 if (old_bgp_ready
!= new_bgp_ready
)
6061 zebra_vxlan_mac_send_add_del_to_client(mac
,
6062 old_bgp_ready
, new_bgp_ready
);
6067 static inline void zebra_vxlan_mac_start_hold_timer(zebra_mac_t
*mac
)
6069 char macbuf
[ETHER_ADDR_STRLEN
];
6071 if (mac
->hold_timer
)
6074 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6075 zlog_debug("sync-mac vni %u mac %s es %s 0x%x hold started",
6077 prefix_mac2str(&mac
->macaddr
, macbuf
,
6080 mac
->es
->esi_str
: "-",
6082 thread_add_timer(zrouter
.master
,
6083 zebra_vxlan_mac_hold_exp_cb
,
6084 mac
, zmh_info
->mac_hold_time
,
6088 static inline void zebra_vxlan_mac_stop_hold_timer(zebra_mac_t
*mac
)
6090 char macbuf
[ETHER_ADDR_STRLEN
];
6092 if (!mac
->hold_timer
)
6095 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6096 zlog_debug("sync-mac vni %u mac %s es %s 0x%x hold stopped",
6098 prefix_mac2str(&mac
->macaddr
, macbuf
,
6101 mac
->es
->esi_str
: "-",
6103 THREAD_OFF(mac
->hold_timer
);
6106 static inline void zebra_vxlan_mac_clear_sync_info(zebra_mac_t
*mac
)
6108 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_PEER_FLAGS
);
6109 zebra_vxlan_mac_stop_hold_timer(mac
);
6112 static void zebra_vxlan_sync_mac_del(zebra_mac_t
*mac
)
6114 char macbuf
[ETHER_ADDR_STRLEN
];
6118 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6119 zlog_debug("sync-mac del vni %u mac %s es %s seq %d f 0x%x",
6121 prefix_mac2str(&mac
->macaddr
,
6122 macbuf
, sizeof(macbuf
)),
6123 mac
->es
? mac
->es
->esi_str
: "-",
6126 old_static
= zebra_vxlan_mac_is_static(mac
);
6127 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_PROXY
);
6128 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
))
6129 zebra_vxlan_mac_start_hold_timer(mac
);
6130 new_static
= zebra_vxlan_mac_is_static(mac
);
6132 if (old_static
!= new_static
)
6133 /* program the local mac in the kernel */
6134 zebra_vxlan_sync_mac_dp_install(mac
, false /* set_inactive */,
6135 false /* force_clear_static */, __func__
);
6138 static inline bool zebra_vxlan_mac_is_bgp_seq_ok(zebra_evpn_t
*zevpn
,
6139 zebra_mac_t
*mac
, uint32_t seq
, uint16_t ipa_len
,
6140 struct ipaddr
*ipaddr
)
6142 char macbuf
[ETHER_ADDR_STRLEN
];
6143 char ipbuf
[INET6_ADDRSTRLEN
];
6146 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
6147 tmp_seq
= mac
->loc_seq
;
6149 tmp_seq
= mac
->rem_seq
;
6151 if (seq
< tmp_seq
) {
6152 /* if the mac was never advertised to bgp we must accept
6153 * whatever sequence number bgp sends
6154 * XXX - check with Vivek
6156 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
) &&
6157 !zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
)) {
6158 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6159 zlog_debug("sync-macip accept vni %u mac %s%s%s lower seq %u f 0x%x",
6161 prefix_mac2str(&mac
->macaddr
,
6162 macbuf
, sizeof(macbuf
)),
6163 ipa_len
? " IP " : "",
6166 ipbuf
, sizeof(ipbuf
)) : "",
6167 tmp_seq
, mac
->flags
);
6171 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6172 zlog_debug("sync-macip ignore vni %u mac %s%s%s as existing has higher seq %u f 0x%x",
6174 prefix_mac2str(&mac
->macaddr
,
6175 macbuf
, sizeof(macbuf
)),
6176 ipa_len
? " IP " : "",
6179 ipbuf
, sizeof(ipbuf
)) : "",
6180 tmp_seq
, mac
->flags
);
6187 /* sync-path that is active on an ES peer */
6188 static zebra_mac_t
*zebra_vxlan_proc_sync_mac_update(zebra_evpn_t
*zevpn
,
6189 struct ethaddr
*macaddr
, uint16_t ipa_len
,
6190 struct ipaddr
*ipaddr
, uint8_t flags
,
6191 uint32_t seq
, esi_t
*esi
,
6192 struct sync_mac_ip_ctx
*ctx
)
6195 bool inform_bgp
= false;
6196 bool inform_dataplane
= false;
6197 bool seq_change
= false;
6198 bool es_change
= false;
6200 char macbuf
[ETHER_ADDR_STRLEN
];
6201 char ipbuf
[INET6_ADDRSTRLEN
];
6202 bool old_local
= false;
6206 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
6208 /* if it is a new local path we need to inform both
6209 * the control protocol and the data-plane
6212 inform_dataplane
= true;
6213 ctx
->mac_created
= true;
6214 ctx
->mac_inactive
= true;
6216 /* create the MAC and associate it with the dest ES */
6217 mac
= zevpn_mac_add(zevpn
, macaddr
);
6218 zebra_evpn_es_mac_ref(mac
, esi
);
6220 /* local mac activated by an ES peer */
6221 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
6222 /* if mac-only route setup peer flags */
6224 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
))
6225 SET_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_PROXY
);
6227 SET_FLAG(mac
->flags
, ZEBRA_MAC_ES_PEER_ACTIVE
);
6229 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
);
6230 old_bgp_ready
= false;
6231 new_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
6240 old_flags
= mac
->flags
;
6241 sticky
= !!CHECK_FLAG(old_flags
, ZEBRA_MAC_STICKY
);
6242 remote_gw
= !!CHECK_FLAG(old_flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
6243 if (sticky
|| remote_gw
) {
6244 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6245 zlog_debug("Ignore sync-macip vni %u mac %s%s%s%s%s",
6247 prefix_mac2str(macaddr
,
6248 macbuf
, sizeof(macbuf
)),
6249 ipa_len
? " IP " : "",
6251 ipaddr2str(ipaddr
, ipbuf
,
6252 sizeof(ipbuf
)) : "",
6253 sticky
? " sticky" : "",
6254 remote_gw
? " remote_gw" : "");
6255 ctx
->ignore_macip
= true;
6258 if (!zebra_vxlan_mac_is_bgp_seq_ok(zevpn
, mac
, seq
,
6260 ctx
->ignore_macip
= true;
6264 old_local
= !!CHECK_FLAG(old_flags
, ZEBRA_MAC_LOCAL
);
6265 old_static
= zebra_vxlan_mac_is_static(mac
);
6267 /* re-build the mac flags */
6269 SET_FLAG(new_flags
, ZEBRA_MAC_LOCAL
);
6270 /* retain old local activity flag */
6271 if (old_flags
& ZEBRA_MAC_LOCAL
) {
6272 new_flags
|= (old_flags
& ZEBRA_MAC_LOCAL_INACTIVE
);
6274 new_flags
|= ZEBRA_MAC_LOCAL_INACTIVE
;
6275 ctx
->mac_inactive
= true;
6278 /* if mac-ip route do NOT update the peer flags
6279 * i.e. retain only flags as is
6281 new_flags
|= (old_flags
& ZEBRA_MAC_ALL_PEER_FLAGS
);
6283 /* if mac-only route update peer flags */
6284 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
)) {
6285 SET_FLAG(new_flags
, ZEBRA_MAC_ES_PEER_PROXY
);
6286 /* if the mac was peer-active previously we
6287 * need to keep the flag and start the
6288 * holdtimer on it. the peer-active flag is
6289 * cleared on holdtimer expiry.
6291 if (CHECK_FLAG(old_flags
,
6292 ZEBRA_MAC_ES_PEER_ACTIVE
)) {
6294 ZEBRA_MAC_ES_PEER_ACTIVE
);
6295 zebra_vxlan_mac_start_hold_timer(mac
);
6298 SET_FLAG(new_flags
, ZEBRA_MAC_ES_PEER_ACTIVE
);
6299 /* stop hold timer if a peer has verified
6302 zebra_vxlan_mac_stop_hold_timer(mac
);
6306 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
6307 mac
->flags
= new_flags
;
6309 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
&&
6310 (old_flags
!= new_flags
))
6311 zlog_debug("sync-mac vni %u mac %s old_f 0x%x new_f 0x%x",
6313 prefix_mac2str(macaddr
,
6314 macbuf
, sizeof(macbuf
)),
6315 old_flags
, mac
->flags
);
6318 es_change
= zebra_evpn_es_mac_ref(mac
, esi
);
6319 /* if mac dest change - inform both sides */
6322 inform_dataplane
= true;
6323 ctx
->mac_inactive
= true;
6325 /* if peer-flag is being set notify dataplane that the
6326 * entry must not be expired because of local inactivity
6328 new_static
= zebra_vxlan_mac_is_static(mac
);
6329 if (old_static
!= new_static
)
6330 inform_dataplane
= true;
6332 old_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(old_flags
);
6333 new_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
6334 if (old_bgp_ready
!= new_bgp_ready
)
6339 /* update sequence number; if that results in a new local sequence
6342 tmp_seq
= MAX(mac
->loc_seq
, seq
);
6343 if (tmp_seq
!= mac
->loc_seq
) {
6344 mac
->loc_seq
= tmp_seq
;
6349 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
6350 zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f 0x%x%s%s",
6352 "created" : "updated",
6354 prefix_mac2str(macaddr
,
6355 macbuf
, sizeof(macbuf
)),
6356 mac
->es
? mac
->es
->esi_str
: "-",
6357 mac
->loc_seq
, mac
->flags
,
6358 inform_bgp
? " inform_bgp" : "",
6359 inform_dataplane
? " inform_dp" : "");
6362 zebra_vxlan_mac_send_add_del_to_client(mac
,
6363 old_bgp_ready
, new_bgp_ready
);
6365 /* neighs using the mac may need to be re-sent to
6366 * bgp with updated info
6368 if (seq_change
|| es_change
|| !old_local
)
6369 zevpn_process_neigh_on_local_mac_change(zevpn
, mac
,
6370 seq_change
, es_change
);
6372 if (inform_dataplane
) {
6374 /* if the mac is being created as a part of MAC-IP
6375 * route wait for the neigh to be updated or
6376 * created before programming the mac
6378 ctx
->mac_dp_update_deferred
= true;
6380 /* program the local mac in the kernel. when the ES
6381 * change we need to force the dataplane to reset
6382 * the activity as we are yet to establish activity
6385 zebra_vxlan_sync_mac_dp_install(mac
,
6387 false /* force_clear_static */,
6394 /**************************** SYNC neigh handling **************************/
6395 static inline bool zebra_vxlan_neigh_is_static(zebra_neigh_t
*neigh
)
6397 return !!(neigh
->flags
& ZEBRA_NEIGH_ALL_PEER_FLAGS
);
6400 static inline bool zebra_vxlan_neigh_is_ready_for_bgp(zebra_neigh_t
*n
)
6405 mac_ready
= !!(n
->mac
->flags
& ZEBRA_MAC_LOCAL
);
6406 neigh_ready
= ((n
->flags
& ZEBRA_NEIGH_LOCAL
) &&
6407 IS_ZEBRA_NEIGH_ACTIVE(n
) &&
6408 (!(n
->flags
& ZEBRA_NEIGH_LOCAL_INACTIVE
) ||
6409 (n
->flags
& ZEBRA_NEIGH_ES_PEER_ACTIVE
))) ?
6412 return mac_ready
&& neigh_ready
;
6415 static void zebra_vxlan_sync_neigh_dp_install(zebra_neigh_t
*n
,
6416 bool set_inactive
, bool force_clear_static
, const char *caller
)
6418 char macbuf
[ETHER_ADDR_STRLEN
];
6419 char ipbuf
[INET6_ADDRSTRLEN
];
6420 struct zebra_ns
*zns
;
6421 struct interface
*ifp
;
6425 zns
= zebra_ns_lookup(NS_DEFAULT
);
6426 ifp
= if_lookup_by_index_per_ns(zns
, n
->ifindex
);
6428 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6429 zlog_debug("%s: dp-install sync-neigh vni %u ip %s mac %s if %d f 0x%x skipped",
6430 caller
, n
->zevpn
->vni
,
6431 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6432 prefix_mac2str(&n
->emac
, macbuf
,
6434 n
->ifindex
, n
->flags
);
6438 if (force_clear_static
)
6441 set_static
= zebra_vxlan_neigh_is_static(n
);
6443 set_router
= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
6445 /* XXX - this will change post integration with the new kernel */
6446 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
))
6447 set_inactive
= true;
6449 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6450 zlog_debug("%s: dp-install sync-neigh vni %u ip %s mac %s if %s(%d) f 0x%x%s%s%s",
6451 caller
, n
->zevpn
->vni
,
6452 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6453 prefix_mac2str(&n
->emac
, macbuf
,
6455 ifp
->name
, n
->ifindex
, n
->flags
,
6456 set_router
? " router":"",
6457 set_static
? " static":"",
6458 set_inactive
? " inactive":"");
6459 dplane_local_neigh_add(ifp
, &n
->ip
,
6460 &n
->emac
, set_router
, set_static
, set_inactive
);
6463 static void zebra_vxlan_neigh_send_add_del_to_client(zebra_neigh_t
*n
,
6464 bool old_bgp_ready
, bool new_bgp_ready
)
6467 zevpn_neigh_send_add_to_client(n
->zevpn
->vni
, &n
->ip
,
6468 &n
->emac
, n
->mac
, n
->flags
, n
->loc_seq
);
6469 else if (old_bgp_ready
)
6470 zevpn_neigh_send_del_to_client(n
->zevpn
->vni
, &n
->ip
,
6471 &n
->emac
, n
->flags
, n
->state
, true /*force*/);
6474 /* if the static flag associated with the neigh changes we need
6475 * to update the sync-neigh references against the MAC
6476 * and inform the dataplane about the static flag changes.
6478 static void zebra_vxlan_sync_neigh_static_chg(zebra_neigh_t
*n
,
6479 bool old_n_static
, bool new_n_static
,
6480 bool defer_n_dp
, bool defer_mac_dp
,
6483 zebra_mac_t
*mac
= n
->mac
;
6484 bool old_mac_static
;
6485 bool new_mac_static
;
6486 char macbuf
[ETHER_ADDR_STRLEN
];
6487 char ipbuf
[INET6_ADDRSTRLEN
];
6489 if (old_n_static
== new_n_static
)
6492 /* update the neigh sync references in the dataplane. if
6493 * the neigh is in the middle of updates the caller can
6494 * request for a defer
6497 zebra_vxlan_sync_neigh_dp_install(n
, false /* set_inactive */,
6498 false /* force_clear_static */, __func__
);
6503 /* update the mac sync ref cnt */
6504 old_mac_static
= zebra_vxlan_mac_is_static(mac
);
6506 ++mac
->sync_neigh_cnt
;
6507 } else if (old_n_static
) {
6508 if (mac
->sync_neigh_cnt
)
6509 --mac
->sync_neigh_cnt
;
6511 new_mac_static
= zebra_vxlan_mac_is_static(mac
);
6513 /* update the mac sync references in the dataplane */
6514 if ((old_mac_static
!= new_mac_static
) && !defer_mac_dp
)
6515 zebra_vxlan_sync_mac_dp_install(mac
,
6516 false /* set_inactive */,
6517 false /* force_clear_static */,
6520 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6521 zlog_debug("sync-neigh ref-chg vni %u ip %s mac %s f 0x%x %d%s%s%s%s by %s",
6523 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6524 prefix_mac2str(&n
->emac
, macbuf
,
6526 n
->flags
, mac
->sync_neigh_cnt
,
6527 old_n_static
? " old_n_static" : "",
6528 new_n_static
? " new_n_static" : "",
6529 old_mac_static
? " old_mac_static" : "",
6530 new_mac_static
? " new_mac_static" : "",
6534 /* Neigh hold timer is used to age out peer-active flag.
6536 * During this wait time we expect the dataplane component or an
6537 * external neighmgr daemon to probe existing hosts to independently
6538 * establish their presence on the ES.
6540 static int zebra_vxlan_neigh_hold_exp_cb(struct thread
*t
)
6547 char macbuf
[ETHER_ADDR_STRLEN
];
6548 char ipbuf
[INET6_ADDRSTRLEN
];
6551 /* the purpose of the hold timer is to age out the peer-active
6554 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
))
6557 old_bgp_ready
= zebra_vxlan_neigh_is_ready_for_bgp(n
);
6558 old_n_static
= zebra_vxlan_neigh_is_static(n
);
6559 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
);
6560 new_bgp_ready
= zebra_vxlan_neigh_is_ready_for_bgp(n
);
6561 new_n_static
= zebra_vxlan_neigh_is_static(n
);
6563 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6564 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold expired",
6566 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6567 prefix_mac2str(&n
->emac
, macbuf
,
6571 /* re-program the local neigh in the dataplane if the neigh is no
6574 if (old_n_static
!= new_n_static
)
6575 zebra_vxlan_sync_neigh_static_chg(n
, old_n_static
,
6576 new_n_static
, false /*defer_n_dp*/,
6577 false /*defer_mac_dp*/, __func__
);
6579 /* inform bgp if needed */
6580 if (old_bgp_ready
!= new_bgp_ready
)
6581 zebra_vxlan_neigh_send_add_del_to_client(n
,
6582 old_bgp_ready
, new_bgp_ready
);
6587 static inline void zebra_vxlan_neigh_start_hold_timer(zebra_neigh_t
*n
)
6589 char macbuf
[ETHER_ADDR_STRLEN
];
6590 char ipbuf
[INET6_ADDRSTRLEN
];
6595 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6596 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold start",
6598 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6599 prefix_mac2str(&n
->emac
, macbuf
,
6602 thread_add_timer(zrouter
.master
,
6603 zebra_vxlan_neigh_hold_exp_cb
,
6604 n
, zmh_info
->neigh_hold_time
,
6608 static inline void zebra_vxlan_neigh_stop_hold_timer(zebra_neigh_t
*n
)
6610 char macbuf
[ETHER_ADDR_STRLEN
];
6611 char ipbuf
[INET6_ADDRSTRLEN
];
6616 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6617 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold stop",
6619 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6620 prefix_mac2str(&n
->emac
, macbuf
,
6623 THREAD_OFF(n
->hold_timer
);
6626 static inline bool zebra_vxlan_neigh_clear_sync_info(zebra_neigh_t
*n
)
6628 char macbuf
[ETHER_ADDR_STRLEN
];
6629 char ipbuf
[INET6_ADDRSTRLEN
];
6630 bool old_n_static
= false;
6631 bool new_n_static
= false;
6633 if (n
->flags
& ZEBRA_NEIGH_ALL_PEER_FLAGS
) {
6634 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6635 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x clear",
6637 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6638 prefix_mac2str(&n
->emac
, macbuf
,
6642 old_n_static
= zebra_vxlan_neigh_is_static(n
);
6643 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ALL_PEER_FLAGS
);
6644 new_n_static
= zebra_vxlan_neigh_is_static(n
);
6645 if (old_n_static
!= new_n_static
)
6646 zebra_vxlan_sync_neigh_static_chg(n
, old_n_static
,
6647 new_n_static
, true /*defer_dp)*/,
6648 false/*defer_mac_dp*/, __func__
);
6650 zebra_vxlan_neigh_stop_hold_timer(n
);
6652 /* if the neigh static flag changed inform that a dp
6653 * re-install maybe needed
6655 return old_n_static
!= new_n_static
;
6658 static void zebra_vxlan_local_neigh_deref_mac(zebra_neigh_t
*n
,
6659 bool send_mac_update
)
6661 zebra_mac_t
*mac
= n
->mac
;
6662 zebra_evpn_t
*zevpn
= n
->zevpn
;
6663 char macbuf
[ETHER_ADDR_STRLEN
];
6664 char ipbuf
[INET6_ADDRSTRLEN
];
6672 if ((n
->flags
& ZEBRA_NEIGH_ALL_PEER_FLAGS
) &&
6673 mac
->sync_neigh_cnt
){
6674 old_static
= zebra_vxlan_mac_is_static(mac
);
6675 --mac
->sync_neigh_cnt
;
6676 new_static
= zebra_vxlan_mac_is_static(mac
);
6677 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6678 zlog_debug("sync-neigh deref mac vni %u ip %s mac %s ref %d",
6680 ipaddr2str(&n
->ip
, ipbuf
,
6682 prefix_mac2str(&n
->emac
, macbuf
,
6684 mac
->sync_neigh_cnt
);
6685 if ((old_static
!= new_static
) && send_mac_update
)
6686 /* program the local mac in the kernel */
6687 zebra_vxlan_sync_mac_dp_install(mac
,
6688 false /* set_inactive */,
6689 false /* force_clear_static */,
6693 listnode_delete(mac
->neigh_list
, n
);
6694 zevpn_deref_ip2mac(zevpn
, mac
);
6697 static void zebra_vxlan_local_neigh_ref_mac(zebra_neigh_t
*n
,
6698 struct ethaddr
*macaddr
, zebra_mac_t
*mac
,
6699 bool send_mac_update
)
6701 char macbuf
[ETHER_ADDR_STRLEN
];
6702 char ipbuf
[INET6_ADDRSTRLEN
];
6706 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
6709 /* Link to new MAC */
6713 listnode_add_sort(mac
->neigh_list
, n
);
6714 if (n
->flags
& ZEBRA_NEIGH_ALL_PEER_FLAGS
) {
6715 old_static
= zebra_vxlan_mac_is_static(mac
);
6716 ++mac
->sync_neigh_cnt
;
6717 new_static
= zebra_vxlan_mac_is_static(mac
);
6718 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6719 zlog_debug("sync-neigh ref mac vni %u ip %s mac %s ref %d",
6721 ipaddr2str(&n
->ip
, ipbuf
,
6723 prefix_mac2str(&n
->emac
, macbuf
,
6725 mac
->sync_neigh_cnt
);
6726 if ((old_static
!= new_static
) && send_mac_update
)
6727 /* program the local mac in the kernel */
6728 zebra_vxlan_sync_mac_dp_install(mac
,
6729 false /*set_inactive*/,
6730 false /*force_clear_static*/,
6735 static inline bool zebra_vxlan_neigh_is_bgp_seq_ok(zebra_evpn_t
*zevpn
,
6736 zebra_neigh_t
*n
, struct ethaddr
*macaddr
, uint32_t seq
)
6738 char macbuf
[ETHER_ADDR_STRLEN
];
6739 char ipbuf
[INET6_ADDRSTRLEN
];
6742 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
))
6743 tmp_seq
= n
->loc_seq
;
6745 tmp_seq
= n
->rem_seq
;
6747 if (seq
< tmp_seq
) {
6748 /* if the neigh was never advertised to bgp we must accept
6749 * whatever sequence number bgp sends
6750 * XXX - check with Vivek
6752 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
) &&
6753 !zebra_vxlan_neigh_is_ready_for_bgp(n
)) {
6754 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6755 zlog_debug("sync-macip accept vni %u mac %s IP %s lower seq %u f 0x%x",
6757 prefix_mac2str(macaddr
,
6758 macbuf
, sizeof(macbuf
)),
6760 ipbuf
, sizeof(ipbuf
)),
6765 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6766 zlog_debug("sync-macip ignore vni %u mac %s IP %s as existing has higher seq %u f 0x%x",
6768 prefix_mac2str(macaddr
,
6769 macbuf
, sizeof(macbuf
)),
6771 ipbuf
, sizeof(ipbuf
)),
6779 static void zebra_vxlan_sync_neigh_del(zebra_neigh_t
*n
)
6783 char macbuf
[ETHER_ADDR_STRLEN
];
6784 char ipbuf
[INET6_ADDRSTRLEN
];
6786 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
6787 zlog_debug("sync-neigh del vni %u ip %s mac %s f 0x%x",
6789 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6790 prefix_mac2str(&n
->emac
, macbuf
,
6794 old_n_static
= zebra_vxlan_neigh_is_static(n
);
6795 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_PROXY
);
6796 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
))
6797 zebra_vxlan_neigh_start_hold_timer(n
);
6798 new_n_static
= zebra_vxlan_neigh_is_static(n
);
6800 if (old_n_static
!= new_n_static
)
6801 zebra_vxlan_sync_neigh_static_chg(n
, old_n_static
,
6802 new_n_static
, false /*defer-dp*/,
6803 false /*defer_mac_dp*/, __func__
);
6806 static zebra_neigh_t
*zebra_vxlan_proc_sync_neigh_update(zebra_evpn_t
*zevpn
,
6807 zebra_neigh_t
*n
, uint16_t ipa_len
,
6808 struct ipaddr
*ipaddr
, uint8_t flags
, uint32_t seq
,
6809 esi_t
*esi
, struct sync_mac_ip_ctx
*ctx
)
6811 struct interface
*ifp
= NULL
;
6813 zebra_mac_t
*mac
= ctx
->mac
;
6815 bool old_router
= false;
6816 bool old_bgp_ready
= false;
6818 bool inform_dataplane
= false;
6819 bool inform_bgp
= false;
6820 bool old_mac_static
;
6821 bool new_mac_static
;
6822 bool set_dp_inactive
= false;
6823 struct zebra_if
*zif
;
6824 char macbuf
[ETHER_ADDR_STRLEN
];
6825 char ipbuf
[INET6_ADDRSTRLEN
];
6827 ifindex_t ifindex
= 0;
6830 zif
= zevpn
->vxlan_if
->info
;
6832 struct zebra_l2info_vxlan
*vxl
;
6834 vxl
= &zif
->l2info
.vxl
;
6835 ifp
= zevpn_map_to_svi(vxl
->access_vlan
,
6836 zif
->brslave_info
.br_if
);
6838 ifindex
= ifp
->ifindex
;
6841 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
6842 old_mac_static
= zebra_vxlan_mac_is_static(mac
);
6845 uint32_t n_flags
= 0;
6847 /* New neighbor - create */
6848 SET_FLAG(n_flags
, ZEBRA_NEIGH_LOCAL
);
6849 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
))
6850 SET_FLAG(n_flags
, ZEBRA_NEIGH_ES_PEER_PROXY
);
6852 SET_FLAG(n_flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
);
6853 SET_FLAG(n_flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
);
6855 n
= zevpn_neigh_add(zevpn
, ipaddr
, &mac
->macaddr
, mac
,
6857 n
->ifindex
= ifindex
;
6858 ZEBRA_NEIGH_SET_ACTIVE(n
);
6861 inform_dataplane
= true;
6863 set_dp_inactive
= true;
6866 uint32_t old_flags
= n
->flags
;
6871 old_n_static
= zebra_vxlan_neigh_is_static(n
);
6872 old_bgp_ready
= zebra_vxlan_neigh_is_ready_for_bgp(n
);
6873 old_router
= !!CHECK_FLAG(n
->flags
,
6874 ZEBRA_NEIGH_ROUTER_FLAG
);
6876 mac_change
= !!memcmp(&n
->emac
, &mac
->macaddr
, ETH_ALEN
);
6878 /* deref and clear old info */
6880 if (old_bgp_ready
) {
6881 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
,
6882 &n
->emac
, n
->flags
, n
->state
,
6884 old_bgp_ready
= false;
6887 zebra_vxlan_local_neigh_deref_mac(n
,
6888 false /*send_mac_update*/);
6890 /* clear old fwd info */
6892 n
->r_vtep_ip
.s_addr
= 0;
6894 /* setup new flags */
6896 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
);
6897 /* retain activity flag if the neigh was
6900 if (old_flags
& ZEBRA_NEIGH_LOCAL
) {
6901 n
->flags
|= (old_flags
& ZEBRA_NEIGH_LOCAL_INACTIVE
);
6903 inform_dataplane
= true;
6904 set_dp_inactive
= true;
6905 n
->flags
|= ZEBRA_NEIGH_LOCAL_INACTIVE
;
6908 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
))
6909 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_PROXY
);
6911 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
);
6913 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_PROXY_ADVERT
)) {
6914 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_PROXY
);
6915 /* if the neigh was peer-active previously we
6916 * need to keep the flag and start the
6917 * holdtimer on it. the peer-active flag is
6918 * cleared on holdtimer expiry.
6920 if (CHECK_FLAG(old_flags
,
6921 ZEBRA_NEIGH_ES_PEER_ACTIVE
)) {
6923 ZEBRA_NEIGH_ES_PEER_ACTIVE
);
6924 zebra_vxlan_neigh_start_hold_timer(n
);
6927 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ES_PEER_ACTIVE
);
6928 /* stop hold timer if a peer has verified
6931 zebra_vxlan_neigh_stop_hold_timer(n
);
6933 ZEBRA_NEIGH_SET_ACTIVE(n
);
6935 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
&&
6936 (old_flags
!= n
->flags
))
6937 zlog_debug("sync-neigh vni %u ip %s mac %s old_f 0x%x new_f 0x%x",
6939 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
6940 prefix_mac2str(&n
->emac
, macbuf
,
6942 old_flags
, n
->flags
);
6944 new_n_static
= zebra_vxlan_neigh_is_static(n
);
6946 set_dp_inactive
= true;
6947 n
->flags
|= ZEBRA_NEIGH_LOCAL_INACTIVE
;
6948 inform_dataplane
= true;
6949 zebra_vxlan_local_neigh_ref_mac(n
, &mac
->macaddr
,
6950 mac
, false /*send_mac_update*/);
6951 } else if (old_n_static
!= new_n_static
) {
6952 inform_dataplane
= true;
6953 /* if static flags have changed without a mac change
6954 * we need to create the correct sync-refs against
6957 zebra_vxlan_sync_neigh_static_chg(n
,
6958 old_n_static
, new_n_static
,
6959 true /*defer_dp*/, true /*defer_mac_dp*/,
6963 /* Update the forwarding info. */
6964 if (n
->ifindex
!= ifindex
) {
6965 n
->ifindex
= ifindex
;
6966 inform_dataplane
= true;
6970 /* update the neigh seq. we don't bother with the mac seq as
6971 * sync_mac_update already took care of that
6973 tmp_seq
= MAX(n
->loc_seq
, seq
);
6974 if (tmp_seq
!= n
->loc_seq
) {
6975 n
->loc_seq
= tmp_seq
;
6979 /* Mark Router flag (R-bit) */
6981 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
6983 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
6985 if (old_router
!= is_router
)
6986 inform_dataplane
= true;
6988 new_bgp_ready
= zebra_vxlan_neigh_is_ready_for_bgp(n
);
6989 if (old_bgp_ready
!= new_bgp_ready
)
6992 new_mac_static
= zebra_vxlan_mac_is_static(mac
);
6993 if ((old_mac_static
!= new_mac_static
) ||
6994 ctx
->mac_dp_update_deferred
)
6995 zebra_vxlan_sync_mac_dp_install(mac
,
6997 false /* force_clear_static */,
7000 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
7001 zlog_debug("sync-neigh %s vni %u ip %s mac %s if %s(%d) seq %d f 0x%x%s%s",
7003 "created" : "updated",
7005 ipaddr2str(&n
->ip
, ipbuf
, sizeof(ipbuf
)),
7006 prefix_mac2str(&n
->emac
, macbuf
,
7008 ifp
? ifp
->name
: "", ifindex
,
7009 n
->loc_seq
, n
->flags
,
7010 inform_bgp
? " inform_bgp" : "",
7011 inform_dataplane
? " inform_dp" : "");
7013 if (inform_dataplane
)
7014 zebra_vxlan_sync_neigh_dp_install(n
, set_dp_inactive
,
7015 false /* force_clear_static */, __func__
);
7018 zebra_vxlan_neigh_send_add_del_to_client(n
,
7019 old_bgp_ready
, new_bgp_ready
);
7024 static void zebra_vxlan_process_sync_macip_add(zebra_evpn_t
*zevpn
,
7025 struct ethaddr
*macaddr
,
7027 struct ipaddr
*ipaddr
,
7032 struct sync_mac_ip_ctx ctx
;
7033 char macbuf
[ETHER_ADDR_STRLEN
];
7034 char ipbuf
[INET6_ADDRSTRLEN
];
7037 zebra_neigh_t
*n
= NULL
;
7039 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
7040 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
7041 /* if sticky or remote-gw ignore updates from the peer */
7042 if (sticky
|| remote_gw
) {
7043 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
||
7044 IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
7045 zlog_debug("Ignore sync-macip vni %u mac %s%s%s%s%s",
7047 prefix_mac2str(macaddr
, macbuf
, sizeof(macbuf
)),
7048 ipa_len
? " IP " : "",
7050 ipaddr2str(ipaddr
, ipbuf
, sizeof(ipbuf
)) : "",
7051 sticky
? " sticky" : "",
7052 remote_gw
? " remote_gw" : "");
7057 n
= zevpn_neigh_lookup(zevpn
, ipaddr
);
7059 !zebra_vxlan_neigh_is_bgp_seq_ok(zevpn
,
7064 memset(&ctx
, 0, sizeof(ctx
));
7065 ctx
.mac
= zebra_vxlan_proc_sync_mac_update(zevpn
, macaddr
, ipa_len
,
7066 ipaddr
, flags
, seq
, esi
, &ctx
);
7067 if (ctx
.ignore_macip
|| !ctx
.mac
|| !ipa_len
)
7070 zebra_vxlan_proc_sync_neigh_update(zevpn
, n
, ipa_len
,
7071 ipaddr
, flags
, seq
, esi
, &ctx
);
7074 /************************** remote mac-ip handling **************************/
7075 /* Process a remote MACIP add from BGP. */
7076 static void process_remote_macip_add(vni_t vni
,
7077 struct ethaddr
*macaddr
,
7079 struct ipaddr
*ipaddr
,
7082 struct in_addr vtep_ip
,
7085 zebra_evpn_t
*zevpn
;
7086 zebra_vtep_t
*zvtep
;
7087 zebra_mac_t
*mac
= NULL
, *old_mac
= NULL
;
7088 zebra_neigh_t
*n
= NULL
;
7089 int update_mac
= 0, update_neigh
= 0;
7090 char buf
[ETHER_ADDR_STRLEN
];
7091 char buf1
[INET6_ADDRSTRLEN
];
7092 struct interface
*ifp
= NULL
;
7093 struct zebra_if
*zif
= NULL
;
7094 struct zebra_vrf
*zvrf
;
7099 bool do_dad
= false;
7100 bool is_dup_detect
= false;
7102 bool old_static
= false;
7104 /* Locate EVPN hash entry - expected to exist. */
7105 zevpn
= zevpn_lookup(vni
);
7107 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni
);
7111 ifp
= zevpn
->vxlan_if
;
7115 !if_is_operative(ifp
) ||
7117 !zif
->brslave_info
.br_if
) {
7118 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
7123 /* Type-2 routes from another PE can be interpreted as remote or
7124 * SYNC based on the destination ES -
7125 * SYNC - if ES is local
7126 * REMOTE - if ES is not local
7128 if (flags
& ZEBRA_MACIP_TYPE_SYNC_PATH
) {
7129 zebra_vxlan_process_sync_macip_add(zevpn
, macaddr
, ipa_len
,
7130 ipaddr
, flags
, seq
, esi
);
7134 /* The remote VTEP specified should normally exist, but it is
7135 * possible that when peering comes up, peer may advertise MACIP
7136 * routes before advertising type-3 routes.
7138 if (vtep_ip
.s_addr
) {
7139 zvtep
= zevpn_vtep_find(zevpn
, &vtep_ip
);
7141 zvtep
= zevpn_vtep_add(zevpn
, &vtep_ip
,
7142 VXLAN_FLOOD_DISABLED
);
7145 EC_ZEBRA_VTEP_ADD_FAILED
,
7146 "Failed to add remote VTEP, VNI %u zevpn %p upon remote MACIP ADD",
7151 zevpn_vtep_install(zevpn
, zvtep
);
7155 sticky
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_STICKY
);
7156 remote_gw
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
);
7157 is_router
= !!CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
);
7159 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
7161 /* Ignore if the mac is already present as a gateway mac */
7163 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
) &&
7164 CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_GW
)) {
7165 if (IS_ZEBRA_DEBUG_VXLAN
)
7166 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
7168 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7169 ipa_len
? " IP " : "",
7171 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
7175 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
7179 old_esi
= (mac
&& mac
->es
) ? &mac
->es
->esi
: zero_esi
;
7181 /* check if the remote MAC is unknown or has a change.
7182 * If so, that needs to be updated first. Note that client could
7183 * install MAC and MACIP separately or just install the latter.
7186 || !CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)
7187 || sticky
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)
7188 || remote_gw
!= !!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
)
7189 || !IPV4_ADDR_SAME(&mac
->fwd_info
.r_vtep_ip
, &vtep_ip
)
7190 || memcmp(old_esi
, esi
, sizeof(esi_t
))
7191 || seq
!= mac
->rem_seq
)
7196 mac
= zevpn_mac_add(zevpn
, macaddr
);
7199 "Failed to add MAC %s VNI %u Remote VTEP %s",
7200 prefix_mac2str(macaddr
, buf
,
7202 vni
, inet_ntoa(vtep_ip
));
7206 zebra_evpn_es_mac_ref(mac
, esi
);
7208 /* Is this MAC created for a MACIP? */
7210 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7212 zebra_evpn_es_mac_ref(mac
, esi
);
7214 /* When host moves but changes its (MAC,IP)
7215 * binding, BGP may install a MACIP entry that
7216 * corresponds to "older" location of the host
7217 * in transient situations (because {IP1,M1}
7218 * is a different route from {IP1,M2}). Check
7219 * the sequence number and ignore this update
7222 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
7223 tmp_seq
= mac
->loc_seq
;
7225 tmp_seq
= mac
->rem_seq
;
7227 if (seq
< tmp_seq
) {
7228 if (IS_ZEBRA_DEBUG_VXLAN
)
7229 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
7231 prefix_mac2str(macaddr
,
7233 ipa_len
? " IP " : "",
7236 buf1
, sizeof(buf1
)) : "",
7237 tmp_seq
, mac
->flags
);
7242 /* Check MAC's curent state is local (this is the case
7243 * where MAC has moved from L->R) and check previous
7244 * detection started via local learning.
7245 * RFC-7432: A PE/VTEP that detects a MAC mobility
7246 * event via local learning starts an M-second timer.
7248 * VTEP-IP or seq. change alone is not considered
7249 * for dup. detection.
7251 * MAC is already marked duplicate set dad, then
7252 * is_dup_detect will be set to not install the entry.
7254 if ((!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) &&
7256 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
7259 /* Remove local MAC from BGP. */
7260 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7261 /* force drop the sync flags */
7262 old_static
= zebra_vxlan_mac_is_static(mac
);
7263 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
7264 zlog_debug("sync-mac->remote vni %u mac %s es %s seq %d f 0x%x",
7266 prefix_mac2str(macaddr
,
7269 mac
->es
->esi_str
: "-",
7272 zebra_vxlan_mac_clear_sync_info(mac
);
7273 zevpn_mac_send_del_to_client(zevpn
->vni
, macaddr
,
7274 mac
->flags
, false /* force */);
7277 /* Set "auto" and "remote" forwarding info. */
7278 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
7279 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
7280 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7281 mac
->fwd_info
.r_vtep_ip
= vtep_ip
;
7284 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7286 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
7289 SET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
7291 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE_DEF_GW
);
7293 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
,
7294 mac
->fwd_info
.r_vtep_ip
,
7295 do_dad
, &is_dup_detect
,
7298 if (!is_dup_detect
) {
7299 zevpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
7300 /* Install the entry. */
7301 zevpn_rem_mac_install(zevpn
, mac
, old_static
);
7305 /* Update seq number. */
7308 /* If there is no IP, return after clearing AUTO flag of MAC. */
7310 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7318 /* Check if the remote neighbor itself is unknown or has a
7319 * change. If so, create or update and then install the entry.
7321 n
= zevpn_neigh_lookup(zevpn
, ipaddr
);
7323 || !CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)
7324 || is_router
!= !!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
)
7325 || (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0)
7326 || !IPV4_ADDR_SAME(&n
->r_vtep_ip
, &vtep_ip
)
7327 || seq
!= n
->rem_seq
)
7332 n
= zevpn_neigh_add(zevpn
, ipaddr
, macaddr
, mac
, 0);
7335 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
7336 ipaddr2str(ipaddr
, buf1
,
7338 prefix_mac2str(macaddr
, buf
,
7340 vni
, inet_ntoa(vtep_ip
));
7347 /* When host moves but changes its (MAC,IP)
7348 * binding, BGP may install a MACIP entry that
7349 * corresponds to "older" location of the host
7350 * in transient situations (because {IP1,M1}
7351 * is a different route from {IP1,M2}). Check
7352 * the sequence number and ignore this update
7355 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7356 tmp_seq
= n
->loc_seq
;
7359 tmp_seq
= n
->rem_seq
;
7362 if (seq
< tmp_seq
) {
7363 if (IS_ZEBRA_DEBUG_VXLAN
)
7364 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
7366 prefix_mac2str(macaddr
,
7369 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
7374 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7375 old_static
= zebra_vxlan_neigh_is_static(n
);
7376 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
7377 zlog_debug("sync->remote neigh vni %u ip %s mac %s seq %d f0x%x",
7379 ipaddr2str(&n
->ip
, buf1
,
7381 prefix_mac2str(&n
->emac
, buf
,
7384 zebra_vxlan_neigh_clear_sync_info(n
);
7385 if (IS_ZEBRA_NEIGH_ACTIVE(n
))
7386 zevpn_mac_send_del_to_client(zevpn
->vni
,
7387 macaddr
, mac
->flags
,
7390 if (memcmp(&n
->emac
, macaddr
, sizeof(*macaddr
)) != 0) {
7391 /* update neigh list for macs */
7392 old_mac
= zevpn_mac_lookup(zevpn
, &n
->emac
);
7394 listnode_delete(old_mac
->neigh_list
, n
);
7396 zevpn_deref_ip2mac(zevpn
, old_mac
);
7399 listnode_add_sort(mac
->neigh_list
, n
);
7400 memcpy(&n
->emac
, macaddr
, ETH_ALEN
);
7402 /* Check Neigh's curent state is local
7403 * (this is the case where neigh/host has moved
7404 * from L->R) and check previous detction
7405 * started via local learning.
7407 * RFC-7432: A PE/VTEP that detects a MAC
7408 * mobilit event via local learning starts
7409 * an M-second timer.
7410 * VTEP-IP or seq. change along is not
7411 * considered for dup. detection.
7413 * Mobilty event scenario-B IP-MAC binding
7416 if ((!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
))
7423 /* Set "remote" forwarding info. */
7424 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ALL_LOCAL_FLAGS
);
7425 n
->r_vtep_ip
= vtep_ip
;
7426 SET_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
);
7428 /* Set router flag (R-bit) to this Neighbor entry */
7429 if (CHECK_FLAG(flags
, ZEBRA_MACIP_TYPE_ROUTER_FLAG
))
7430 SET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
7432 UNSET_FLAG(n
->flags
, ZEBRA_NEIGH_ROUTER_FLAG
);
7434 /* Check old or new MAC detected as duplicate,
7435 * inherit duplicate flag to this neigh.
7437 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf
, old_mac
,
7439 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED
,
7440 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
7442 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
7443 ipaddr2str(&n
->ip
, buf1
, sizeof(buf1
)));
7446 /* Check duplicate address detection for IP */
7447 zebra_vxlan_dup_addr_detect_for_neigh(zvrf
, n
,
7452 /* Install the entry. */
7454 zevpn_rem_neigh_install(zevpn
, n
, old_static
);
7457 zevpn_probe_neigh_on_mac_add(zevpn
, mac
);
7459 /* Update seq number. */
7463 static void zebra_vxlan_rem_mac_del(zebra_evpn_t
*zevpn
,
7466 zevpn_process_neigh_on_remote_mac_del(zevpn
, mac
);
7467 /* the remote sequence number in the auto mac entry
7468 * needs to be reset to 0 as the mac entry may have
7469 * been removed on all VTEPs (including
7470 * the originating one)
7474 /* If all remote neighbors referencing a remote MAC
7475 * go away, we need to uninstall the MAC.
7477 if (remote_neigh_count(mac
) == 0) {
7478 zevpn_rem_mac_uninstall(zevpn
, mac
);
7479 zebra_evpn_es_mac_deref_entry(mac
);
7480 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
7483 if (list_isempty(mac
->neigh_list
))
7484 zevpn_mac_del(zevpn
, mac
);
7486 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
7489 /* Process a remote MACIP delete from BGP. */
7490 static void process_remote_macip_del(vni_t vni
,
7491 struct ethaddr
*macaddr
,
7493 struct ipaddr
*ipaddr
,
7494 struct in_addr vtep_ip
)
7496 zebra_evpn_t
*zevpn
;
7497 zebra_mac_t
*mac
= NULL
;
7498 zebra_neigh_t
*n
= NULL
;
7499 struct interface
*ifp
= NULL
;
7500 struct zebra_if
*zif
= NULL
;
7501 struct zebra_ns
*zns
;
7502 struct zebra_l2info_vxlan
*vxl
;
7503 struct zebra_vrf
*zvrf
;
7504 char buf
[ETHER_ADDR_STRLEN
];
7505 char buf1
[INET6_ADDRSTRLEN
];
7507 /* Locate EVPN hash entry - expected to exist. */
7508 zevpn
= zevpn_lookup(vni
);
7510 if (IS_ZEBRA_DEBUG_VXLAN
)
7511 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni
);
7515 ifp
= zevpn
->vxlan_if
;
7519 !if_is_operative(ifp
) ||
7521 !zif
->brslave_info
.br_if
) {
7522 if (IS_ZEBRA_DEBUG_VXLAN
)
7523 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
7527 zns
= zebra_ns_lookup(NS_DEFAULT
);
7528 vxl
= &zif
->l2info
.vxl
;
7530 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
7532 n
= zevpn_neigh_lookup(zevpn
, ipaddr
);
7535 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
7536 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7537 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)), vni
);
7541 /* If the remote mac or neighbor doesn't exist there is nothing
7542 * more to do. Otherwise, uninstall the entry and then remove it.
7547 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
7549 /* Ignore the delete if this mac is a gateway mac-ip */
7550 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)
7551 && CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DEF_GW
)) {
7553 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
7555 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
7556 ipa_len
? " IP " : "",
7558 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)) : "");
7562 /* Uninstall remote neighbor or MAC. */
7564 if (zvrf
->dad_freeze
&&
7565 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
) &&
7566 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
) &&
7567 (memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
) == 0)) {
7568 struct interface
*vlan_if
;
7570 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
,
7571 zif
->brslave_info
.br_if
);
7572 if (IS_ZEBRA_DEBUG_VXLAN
)
7574 "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
7576 ipaddr2str(ipaddr
, buf1
, sizeof(buf1
)),
7578 vlan_if
? vlan_if
->name
: "Unknown");
7580 neigh_read_specific_ip(ipaddr
, vlan_if
);
7583 /* When the MAC changes for an IP, it is possible the
7584 * client may update the new MAC before trying to delete the
7585 * "old" neighbor (as these are two different MACIP routes).
7586 * Do the delete only if the MAC matches.
7588 if (!memcmp(n
->emac
.octet
, macaddr
->octet
, ETH_ALEN
)) {
7589 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL
)) {
7590 zebra_vxlan_sync_neigh_del(n
);
7591 } else if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7592 zevpn_neigh_uninstall(zevpn
, n
);
7593 zevpn_neigh_del(zevpn
, n
);
7594 zevpn_deref_ip2mac(zevpn
, mac
);
7598 /* DAD: when MAC is freeze state as remote learn event,
7599 * remote mac-ip delete event is received will result in freeze
7600 * entry removal, first fetch kernel for the same entry present
7601 * as LOCAL and reachable, avoid deleting this entry instead
7602 * use kerenel local entry to update during unfreeze time.
7604 if (zvrf
->dad_freeze
&&
7605 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
) &&
7606 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
7607 if (IS_ZEBRA_DEBUG_VXLAN
)
7609 "%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
7611 prefix_mac2str(macaddr
, buf
,
7614 macfdb_read_specific_mac(zns
, zif
->brslave_info
.br_if
,
7615 macaddr
, vxl
->access_vlan
);
7618 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
7620 zebra_vxlan_sync_mac_del(mac
);
7621 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_NEIGH_REMOTE
)) {
7622 zebra_vxlan_rem_mac_del(zevpn
, mac
);
7628 /* Public functions */
7630 int is_l3vni_for_prefix_routes_only(vni_t vni
)
7632 zebra_l3vni_t
*zl3vni
= NULL
;
7634 zl3vni
= zl3vni_lookup(vni
);
7638 return CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
) ? 1 : 0;
7641 /* handle evpn route in vrf table */
7642 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id
, const struct ethaddr
*rmac
,
7643 const struct ipaddr
*vtep_ip
,
7644 const struct prefix
*host_prefix
)
7646 zebra_l3vni_t
*zl3vni
= NULL
;
7647 struct ipaddr ipv4_vtep
;
7649 zl3vni
= zl3vni_from_vrf(vrf_id
);
7650 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
7654 * add the next hop neighbor -
7655 * neigh to be installed is the ipv6 nexthop neigh
7657 zl3vni_remote_nh_add(zl3vni
, vtep_ip
, rmac
, host_prefix
);
7660 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
7661 * address. Rmac is programmed against the ipv4 vtep because we only
7662 * support ipv4 tunnels in the h/w right now
7664 memset(&ipv4_vtep
, 0, sizeof(struct ipaddr
));
7665 ipv4_vtep
.ipa_type
= IPADDR_V4
;
7666 if (vtep_ip
->ipa_type
== IPADDR_V6
)
7667 ipv4_mapped_ipv6_to_ipv4(&vtep_ip
->ipaddr_v6
,
7668 &(ipv4_vtep
.ipaddr_v4
));
7670 memcpy(&(ipv4_vtep
.ipaddr_v4
), &vtep_ip
->ipaddr_v4
,
7671 sizeof(struct in_addr
));
7674 * add the rmac - remote rmac to be installed is against the ipv4
7677 zl3vni_remote_rmac_add(zl3vni
, rmac
, &ipv4_vtep
, host_prefix
);
7680 /* handle evpn vrf route delete */
7681 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id
,
7682 struct ipaddr
*vtep_ip
,
7683 struct prefix
*host_prefix
)
7685 zebra_l3vni_t
*zl3vni
= NULL
;
7686 zebra_neigh_t
*nh
= NULL
;
7687 zebra_mac_t
*zrmac
= NULL
;
7689 zl3vni
= zl3vni_from_vrf(vrf_id
);
7693 /* find the next hop entry and rmac entry */
7694 nh
= zl3vni_nh_lookup(zl3vni
, vtep_ip
);
7697 zrmac
= zl3vni_rmac_lookup(zl3vni
, &nh
->emac
);
7699 /* delete the next hop entry */
7700 zl3vni_remote_nh_del(zl3vni
, nh
, host_prefix
);
7702 /* delete the rmac entry */
7704 zl3vni_remote_rmac_del(zl3vni
, zrmac
, host_prefix
);
7708 void zebra_vxlan_print_specific_rmac_l3vni(struct vty
*vty
, vni_t l3vni
,
7709 struct ethaddr
*rmac
, bool use_json
)
7711 zebra_l3vni_t
*zl3vni
= NULL
;
7712 zebra_mac_t
*zrmac
= NULL
;
7713 json_object
*json
= NULL
;
7715 if (!is_evpn_enabled()) {
7717 vty_out(vty
, "{}\n");
7722 json
= json_object_new_object();
7724 zl3vni
= zl3vni_lookup(l3vni
);
7727 vty_out(vty
, "{}\n");
7729 vty_out(vty
, "%% L3-VNI %u doesn't exist\n", l3vni
);
7733 zrmac
= zl3vni_rmac_lookup(zl3vni
, rmac
);
7736 vty_out(vty
, "{}\n");
7739 "%% Requested RMAC doesn't exist in L3-VNI %u",
7744 zl3vni_print_rmac(zrmac
, vty
, json
);
7747 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7748 json
, JSON_C_TO_STRING_PRETTY
));
7749 json_object_free(json
);
7753 void zebra_vxlan_print_rmacs_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
7755 zebra_l3vni_t
*zl3vni
;
7757 struct rmac_walk_ctx wctx
;
7758 json_object
*json
= NULL
;
7760 if (!is_evpn_enabled())
7763 zl3vni
= zl3vni_lookup(l3vni
);
7766 vty_out(vty
, "{}\n");
7768 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
7771 num_rmacs
= hashcount(zl3vni
->rmac_table
);
7776 json
= json_object_new_object();
7778 memset(&wctx
, 0, sizeof(struct rmac_walk_ctx
));
7782 vty_out(vty
, "Number of Remote RMACs known for this VNI: %u\n",
7784 vty_out(vty
, "%-17s %-21s\n", "MAC", "Remote VTEP");
7786 json_object_int_add(json
, "numRmacs", num_rmacs
);
7788 hash_iterate(zl3vni
->rmac_table
, zl3vni_print_rmac_hash
, &wctx
);
7791 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7792 json
, JSON_C_TO_STRING_PRETTY
));
7793 json_object_free(json
);
7797 void zebra_vxlan_print_rmacs_all_l3vni(struct vty
*vty
, bool use_json
)
7799 json_object
*json
= NULL
;
7802 if (!is_evpn_enabled()) {
7804 vty_out(vty
, "{}\n");
7809 json
= json_object_new_object();
7813 hash_iterate(zrouter
.l3vni_table
,
7814 (void (*)(struct hash_bucket
*,
7815 void *))zl3vni_print_rmac_hash_all_vni
,
7819 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7820 json
, JSON_C_TO_STRING_PRETTY
));
7821 json_object_free(json
);
7825 void zebra_vxlan_print_specific_nh_l3vni(struct vty
*vty
, vni_t l3vni
,
7826 struct ipaddr
*ip
, bool use_json
)
7828 zebra_l3vni_t
*zl3vni
= NULL
;
7829 zebra_neigh_t
*n
= NULL
;
7830 json_object
*json
= NULL
;
7832 if (!is_evpn_enabled()) {
7834 vty_out(vty
, "{}\n");
7839 json
= json_object_new_object();
7841 zl3vni
= zl3vni_lookup(l3vni
);
7844 vty_out(vty
, "{}\n");
7846 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
7850 n
= zl3vni_nh_lookup(zl3vni
, ip
);
7853 vty_out(vty
, "{}\n");
7856 "%% Requested next-hop not present for L3-VNI %u",
7861 zl3vni_print_nh(n
, vty
, json
);
7864 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7865 json
, JSON_C_TO_STRING_PRETTY
));
7866 json_object_free(json
);
7870 void zebra_vxlan_print_nh_l3vni(struct vty
*vty
, vni_t l3vni
, bool use_json
)
7873 struct nh_walk_ctx wctx
;
7874 json_object
*json
= NULL
;
7875 zebra_l3vni_t
*zl3vni
= NULL
;
7877 if (!is_evpn_enabled())
7880 zl3vni
= zl3vni_lookup(l3vni
);
7883 vty_out(vty
, "{}\n");
7885 vty_out(vty
, "%% L3-VNI %u does not exist\n", l3vni
);
7889 num_nh
= hashcount(zl3vni
->nh_table
);
7894 json
= json_object_new_object();
7899 vty_out(vty
, "Number of NH Neighbors known for this VNI: %u\n",
7901 vty_out(vty
, "%-15s %-17s\n", "IP", "RMAC");
7903 json_object_int_add(json
, "numNextHops", num_nh
);
7905 hash_iterate(zl3vni
->nh_table
, zl3vni_print_nh_hash
, &wctx
);
7908 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7909 json
, JSON_C_TO_STRING_PRETTY
));
7910 json_object_free(json
);
7914 void zebra_vxlan_print_nh_all_l3vni(struct vty
*vty
, bool use_json
)
7916 json_object
*json
= NULL
;
7919 if (!is_evpn_enabled()) {
7921 vty_out(vty
, "{}\n");
7926 json
= json_object_new_object();
7930 hash_iterate(zrouter
.l3vni_table
,
7931 (void (*)(struct hash_bucket
*,
7932 void *))zl3vni_print_nh_hash_all_vni
,
7936 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7937 json
, JSON_C_TO_STRING_PRETTY
));
7938 json_object_free(json
);
7943 * Display L3 VNI information (VTY command handler).
7945 void zebra_vxlan_print_l3vni(struct vty
*vty
, vni_t vni
, bool use_json
)
7948 json_object
*json
= NULL
;
7949 zebra_l3vni_t
*zl3vni
= NULL
;
7951 if (!is_evpn_enabled()) {
7953 vty_out(vty
, "{}\n");
7957 zl3vni
= zl3vni_lookup(vni
);
7960 vty_out(vty
, "{}\n");
7962 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
7967 json
= json_object_new_object();
7971 zl3vni_print(zl3vni
, (void *)args
);
7974 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
7975 json
, JSON_C_TO_STRING_PRETTY
));
7976 json_object_free(json
);
7980 void zebra_vxlan_print_vrf_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
7981 json_object
*json_vrfs
)
7983 char buf
[ETHER_ADDR_STRLEN
];
7984 zebra_l3vni_t
*zl3vni
= NULL
;
7986 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
7991 vty_out(vty
, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
7992 zvrf_name(zvrf
), zl3vni
->vni
,
7993 zl3vni_vxlan_if_name(zl3vni
),
7994 zl3vni_svi_if_name(zl3vni
), zl3vni_state2str(zl3vni
),
7995 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
7997 json_object
*json_vrf
= NULL
;
7999 json_vrf
= json_object_new_object();
8000 json_object_string_add(json_vrf
, "vrf", zvrf_name(zvrf
));
8001 json_object_int_add(json_vrf
, "vni", zl3vni
->vni
);
8002 json_object_string_add(json_vrf
, "vxlanIntf",
8003 zl3vni_vxlan_if_name(zl3vni
));
8004 json_object_string_add(json_vrf
, "sviIntf",
8005 zl3vni_svi_if_name(zl3vni
));
8006 json_object_string_add(json_vrf
, "state",
8007 zl3vni_state2str(zl3vni
));
8008 json_object_string_add(
8009 json_vrf
, "routerMac",
8010 zl3vni_rmac2str(zl3vni
, buf
, sizeof(buf
)));
8011 json_object_array_add(json_vrfs
, json_vrf
);
8016 * Display Neighbors for a VNI (VTY command handler).
8018 void zebra_vxlan_print_neigh_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8019 vni_t vni
, bool use_json
)
8021 zebra_evpn_t
*zevpn
;
8023 struct neigh_walk_ctx wctx
;
8024 json_object
*json
= NULL
;
8026 if (!is_evpn_enabled())
8028 zevpn
= zevpn_lookup(vni
);
8031 vty_out(vty
, "{}\n");
8033 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8036 num_neigh
= hashcount(zevpn
->neigh_table
);
8041 json
= json_object_new_object();
8043 /* Since we have IPv6 addresses to deal with which can vary widely in
8044 * size, we try to be a bit more elegant in display by first computing
8045 * the maximum width.
8047 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
8050 wctx
.addr_width
= 15;
8052 hash_iterate(zevpn
->neigh_table
, zevpn_find_neigh_addr_width
, &wctx
);
8056 "Number of ARPs (local and remote) known for this VNI: %u\n",
8058 zevpn_print_neigh_hdr(vty
, &wctx
);
8060 json_object_int_add(json
, "numArpNd", num_neigh
);
8062 hash_iterate(zevpn
->neigh_table
, zevpn_print_neigh_hash
, &wctx
);
8064 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8065 json
, JSON_C_TO_STRING_PRETTY
));
8066 json_object_free(json
);
8071 * Display neighbors across all VNIs (VTY command handler).
8073 void zebra_vxlan_print_neigh_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8074 bool print_dup
, bool use_json
)
8076 json_object
*json
= NULL
;
8079 if (!is_evpn_enabled())
8083 json
= json_object_new_object();
8087 args
[2] = (void *)(ptrdiff_t)print_dup
;
8089 hash_iterate(zvrf
->evpn_table
,
8090 (void (*)(struct hash_bucket
*,
8091 void *))zevpn_print_neigh_hash_all_evpn
,
8094 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8095 json
, JSON_C_TO_STRING_PRETTY
));
8096 json_object_free(json
);
8101 * Display neighbors across all VNIs in detail(VTY command handler).
8103 void zebra_vxlan_print_neigh_all_vni_detail(struct vty
*vty
,
8104 struct zebra_vrf
*zvrf
,
8105 bool print_dup
, bool use_json
)
8107 json_object
*json
= NULL
;
8110 if (!is_evpn_enabled())
8114 json
= json_object_new_object();
8118 args
[2] = (void *)(ptrdiff_t)print_dup
;
8120 hash_iterate(zvrf
->evpn_table
,
8121 (void (*)(struct hash_bucket
*,
8122 void *))zevpn_print_neigh_hash_all_evpn_detail
,
8125 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8126 json
, JSON_C_TO_STRING_PRETTY
));
8127 json_object_free(json
);
8132 * Display specific neighbor for a VNI, if present (VTY command handler).
8134 void zebra_vxlan_print_specific_neigh_vni(struct vty
*vty
,
8135 struct zebra_vrf
*zvrf
, vni_t vni
,
8136 struct ipaddr
*ip
, bool use_json
)
8138 zebra_evpn_t
*zevpn
;
8140 json_object
*json
= NULL
;
8142 if (!is_evpn_enabled())
8144 zevpn
= zevpn_lookup(vni
);
8147 vty_out(vty
, "{}\n");
8149 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8152 n
= zevpn_neigh_lookup(zevpn
, ip
);
8156 "%% Requested neighbor does not exist in VNI %u\n",
8161 json
= json_object_new_object();
8163 zevpn_print_neigh(n
, vty
, json
);
8166 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8167 json
, JSON_C_TO_STRING_PRETTY
));
8168 json_object_free(json
);
8173 * Display neighbors for a VNI from specific VTEP (VTY command handler).
8174 * By definition, these are remote neighbors.
8176 void zebra_vxlan_print_neigh_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8177 vni_t vni
, struct in_addr vtep_ip
,
8180 zebra_evpn_t
*zevpn
;
8182 struct neigh_walk_ctx wctx
;
8183 json_object
*json
= NULL
;
8185 if (!is_evpn_enabled())
8187 zevpn
= zevpn_lookup(vni
);
8190 vty_out(vty
, "{}\n");
8192 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8195 num_neigh
= hashcount(zevpn
->neigh_table
);
8200 json
= json_object_new_object();
8202 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
8205 wctx
.addr_width
= 15;
8206 wctx
.flags
= SHOW_REMOTE_NEIGH_FROM_VTEP
;
8207 wctx
.r_vtep_ip
= vtep_ip
;
8209 hash_iterate(zevpn
->neigh_table
, zevpn_find_neigh_addr_width
, &wctx
);
8210 hash_iterate(zevpn
->neigh_table
, zevpn_print_neigh_hash
, &wctx
);
8213 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8214 json
, JSON_C_TO_STRING_PRETTY
));
8215 json_object_free(json
);
8220 * Display Duplicate detected Neighbors for a VNI
8221 * (VTY command handler).
8223 void zebra_vxlan_print_neigh_vni_dad(struct vty
*vty
,
8224 struct zebra_vrf
*zvrf
,
8228 zebra_evpn_t
*zevpn
;
8230 struct neigh_walk_ctx wctx
;
8231 json_object
*json
= NULL
;
8233 if (!is_evpn_enabled())
8236 zevpn
= zevpn_lookup(vni
);
8238 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8242 num_neigh
= hashcount(zevpn
->neigh_table
);
8246 num_neigh
= num_dup_detected_neighs(zevpn
);
8251 json
= json_object_new_object();
8253 /* Since we have IPv6 addresses to deal with which can vary widely in
8254 * size, we try to be a bit more elegant in display by first computing
8255 * the maximum width.
8257 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
8260 wctx
.addr_width
= 15;
8262 hash_iterate(zevpn
->neigh_table
, zevpn_find_neigh_addr_width
, &wctx
);
8266 "Number of ARPs (local and remote) known for this VNI: %u\n",
8268 vty_out(vty
, "%*s %-6s %-8s %-17s %-30s\n",
8269 -wctx
.addr_width
, "IP", "Type",
8270 "State", "MAC", "Remote ES/VTEP");
8272 json_object_int_add(json
, "numArpNd", num_neigh
);
8274 hash_iterate(zevpn
->neigh_table
, zevpn_print_dad_neigh_hash
, &wctx
);
8277 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8278 json
, JSON_C_TO_STRING_PRETTY
));
8279 json_object_free(json
);
8284 * Display MACs for a VNI (VTY command handler).
8286 void zebra_vxlan_print_macs_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8287 vni_t vni
, bool use_json
)
8289 zebra_evpn_t
*zevpn
;
8291 struct mac_walk_ctx wctx
;
8292 json_object
*json
= NULL
;
8293 json_object
*json_mac
= NULL
;
8295 if (!is_evpn_enabled())
8297 zevpn
= zevpn_lookup(vni
);
8300 vty_out(vty
, "{}\n");
8302 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8305 num_macs
= num_valid_macs(zevpn
);
8310 json
= json_object_new_object();
8311 json_mac
= json_object_new_object();
8314 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8317 wctx
.json
= json_mac
;
8321 "Number of MACs (local and remote) known for this VNI: %u\n",
8324 "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
8325 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
8326 "Type", "Flags", "Intf/Remote ES/VTEP",
8329 json_object_int_add(json
, "numMacs", num_macs
);
8331 hash_iterate(zevpn
->mac_table
, zevpn_print_mac_hash
, &wctx
);
8334 json_object_object_add(json
, "macs", json_mac
);
8335 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8336 json
, JSON_C_TO_STRING_PRETTY
));
8337 json_object_free(json
);
8342 * Display MACs for all VNIs (VTY command handler).
8344 void zebra_vxlan_print_macs_all_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8345 bool print_dup
, bool use_json
)
8347 struct mac_walk_ctx wctx
;
8348 json_object
*json
= NULL
;
8350 if (!is_evpn_enabled()) {
8352 vty_out(vty
, "{}\n");
8356 json
= json_object_new_object();
8358 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8361 wctx
.print_dup
= print_dup
;
8362 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
8365 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8366 json
, JSON_C_TO_STRING_PRETTY
));
8367 json_object_free(json
);
8372 * Display MACs in detail for all VNIs (VTY command handler).
8374 void zebra_vxlan_print_macs_all_vni_detail(struct vty
*vty
,
8375 struct zebra_vrf
*zvrf
,
8376 bool print_dup
, bool use_json
)
8378 struct mac_walk_ctx wctx
;
8379 json_object
*json
= NULL
;
8381 if (!is_evpn_enabled()) {
8383 vty_out(vty
, "{}\n");
8387 json
= json_object_new_object();
8389 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8392 wctx
.print_dup
= print_dup
;
8393 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn_detail
,
8397 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8398 json
, JSON_C_TO_STRING_PRETTY
));
8399 json_object_free(json
);
8404 * Display MACs for all VNIs (VTY command handler).
8406 void zebra_vxlan_print_macs_all_vni_vtep(struct vty
*vty
,
8407 struct zebra_vrf
*zvrf
,
8408 struct in_addr vtep_ip
, bool use_json
)
8410 struct mac_walk_ctx wctx
;
8411 json_object
*json
= NULL
;
8413 if (!is_evpn_enabled())
8417 json
= json_object_new_object();
8419 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8421 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
8422 wctx
.r_vtep_ip
= vtep_ip
;
8424 hash_iterate(zvrf
->evpn_table
, zevpn_print_mac_hash_all_evpn
, &wctx
);
8427 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8428 json
, JSON_C_TO_STRING_PRETTY
));
8429 json_object_free(json
);
8434 * Display specific MAC for a VNI, if present (VTY command handler).
8436 void zebra_vxlan_print_specific_mac_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8437 vni_t vni
, struct ethaddr
*macaddr
,
8440 zebra_evpn_t
*zevpn
;
8442 json_object
*json
= NULL
;
8444 if (!is_evpn_enabled())
8447 zevpn
= zevpn_lookup(vni
);
8450 vty_out(vty
, "{}\n");
8452 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8455 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
8458 vty_out(vty
, "{}\n");
8461 "%% Requested MAC does not exist in VNI %u\n",
8467 json
= json_object_new_object();
8469 zevpn_print_mac(mac
, vty
, json
);
8471 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8472 json
, JSON_C_TO_STRING_PRETTY
));
8473 json_object_free(json
);
8477 /* Print Duplicate MACs per VNI */
8478 void zebra_vxlan_print_macs_vni_dad(struct vty
*vty
,
8479 struct zebra_vrf
*zvrf
,
8480 vni_t vni
, bool use_json
)
8482 zebra_evpn_t
*zevpn
;
8483 struct mac_walk_ctx wctx
;
8485 json_object
*json
= NULL
;
8486 json_object
*json_mac
= NULL
;
8488 if (!is_evpn_enabled())
8491 zevpn
= zevpn_lookup(vni
);
8493 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8497 num_macs
= num_valid_macs(zevpn
);
8501 num_macs
= num_dup_detected_macs(zevpn
);
8506 json
= json_object_new_object();
8507 json_mac
= json_object_new_object();
8510 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8513 wctx
.json
= json_mac
;
8517 "Number of MACs (local and remote) known for this VNI: %u\n",
8519 vty_out(vty
, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type",
8520 "Flags", "Intf/Remote ES/VTEP", "VLAN");
8522 json_object_int_add(json
, "numMacs", num_macs
);
8524 hash_iterate(zevpn
->mac_table
, zevpn_print_dad_mac_hash
, &wctx
);
8527 json_object_object_add(json
, "macs", json_mac
);
8528 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8529 json
, JSON_C_TO_STRING_PRETTY
));
8530 json_object_free(json
);
8535 int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf
*zvrf
, vni_t vni
,
8536 struct ethaddr
*macaddr
)
8538 zebra_evpn_t
*zevpn
;
8540 struct listnode
*node
= NULL
;
8541 zebra_neigh_t
*nbr
= NULL
;
8543 if (!is_evpn_enabled())
8546 zevpn
= zevpn_lookup(vni
);
8548 zlog_warn("VNI %u does not exist\n", vni
);
8552 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
8554 zlog_warn("Requested MAC does not exist in VNI %u\n", vni
);
8558 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
8559 zlog_warn("Requested MAC is not duplicate detected\n");
8563 /* Remove all IPs as duplicate associcated with this MAC */
8564 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
8565 /* For local neigh mark inactive so MACIP update is generated
8566 * to BGP. This is a scenario where MAC update received
8567 * and detected as duplicate which marked neigh as duplicate.
8568 * Later local neigh update did not get a chance to relay
8569 * to BGP. Similarly remote macip update, neigh needs to be
8570 * installed locally.
8572 if (zvrf
->dad_freeze
&&
8573 CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
8574 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
8575 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
8576 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
8577 zevpn_rem_neigh_install(zevpn
, nbr
,
8578 false /*was_static*/);
8581 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8583 nbr
->detect_start_time
.tv_sec
= 0;
8584 nbr
->dad_dup_detect_time
= 0;
8587 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
8589 mac
->detect_start_time
.tv_sec
= 0;
8590 mac
->detect_start_time
.tv_usec
= 0;
8591 mac
->dad_dup_detect_time
= 0;
8592 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
8594 /* warn-only action return */
8595 if (!zvrf
->dad_freeze
)
8598 /* Local: Notify Peer VTEPs, Remote: Install the entry */
8599 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8601 if (zevpn_mac_send_add_to_client(zevpn
->vni
,
8604 mac
->loc_seq
, mac
->es
))
8607 /* Process all neighbors associated with this MAC. */
8608 zevpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
8611 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8612 zevpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
8614 /* Install the entry. */
8615 zevpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
8621 int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf
*zvrf
, vni_t vni
,
8624 zebra_evpn_t
*zevpn
;
8627 char buf
[INET6_ADDRSTRLEN
];
8628 char buf2
[ETHER_ADDR_STRLEN
];
8630 if (!is_evpn_enabled())
8633 zevpn
= zevpn_lookup(vni
);
8635 zlog_debug("VNI %u does not exist\n", vni
);
8639 nbr
= zevpn_neigh_lookup(zevpn
, ip
);
8641 zlog_warn("Requested host IP does not exist in VNI %u\n", vni
);
8645 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
8647 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
8648 zlog_warn("Requested host IP %s is not duplicate detected\n",
8653 mac
= zevpn_mac_lookup(zevpn
, &nbr
->emac
);
8655 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
)) {
8657 "Requested IP's associated MAC %s is still in duplicate state\n",
8658 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)));
8662 if (IS_ZEBRA_DEBUG_VXLAN
)
8663 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
8664 __func__
, buf
, nbr
->flags
, nbr
->loc_seq
);
8666 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8668 nbr
->detect_start_time
.tv_sec
= 0;
8669 nbr
->detect_start_time
.tv_usec
= 0;
8670 nbr
->dad_dup_detect_time
= 0;
8671 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
8673 if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8674 zevpn_neigh_send_add_to_client(zevpn
->vni
, ip
,
8675 &nbr
->emac
, nbr
->mac
,
8676 nbr
->flags
, nbr
->loc_seq
);
8677 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8678 zevpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
8684 static void zevpn_clear_dup_mac_hash(struct hash_bucket
*bucket
, void *ctxt
)
8686 struct mac_walk_ctx
*wctx
= ctxt
;
8688 zebra_evpn_t
*zevpn
;
8689 struct listnode
*node
= NULL
;
8690 zebra_neigh_t
*nbr
= NULL
;
8692 mac
= (zebra_mac_t
*)bucket
->data
;
8696 zevpn
= wctx
->zevpn
;
8698 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
))
8701 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
8703 mac
->detect_start_time
.tv_sec
= 0;
8704 mac
->detect_start_time
.tv_usec
= 0;
8705 mac
->dad_dup_detect_time
= 0;
8706 THREAD_OFF(mac
->dad_mac_auto_recovery_timer
);
8708 /* Remove all IPs as duplicate associcated with this MAC */
8709 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
8710 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)
8712 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
8714 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8716 nbr
->detect_start_time
.tv_sec
= 0;
8717 nbr
->dad_dup_detect_time
= 0;
8720 /* Local: Notify Peer VTEPs, Remote: Install the entry */
8721 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
8723 if (zevpn_mac_send_add_to_client(zevpn
->vni
,
8725 mac
->flags
, mac
->loc_seq
, mac
->es
))
8728 /* Process all neighbors associated with this MAC. */
8729 zevpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
8732 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
8733 zevpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
8735 /* Install the entry. */
8736 zevpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
8740 static void zevpn_clear_dup_neigh_hash(struct hash_bucket
*bucket
, void *ctxt
)
8742 struct neigh_walk_ctx
*wctx
= ctxt
;
8744 zebra_evpn_t
*zevpn
;
8745 char buf
[INET6_ADDRSTRLEN
];
8747 nbr
= (zebra_neigh_t
*)bucket
->data
;
8751 zevpn
= wctx
->zevpn
;
8753 if (!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
))
8756 if (IS_ZEBRA_DEBUG_VXLAN
) {
8757 ipaddr2str(&nbr
->ip
, buf
, sizeof(buf
));
8758 zlog_debug("%s: clear neigh %s dup state, flags 0x%x seq %u",
8759 __func__
, buf
, nbr
->flags
, nbr
->loc_seq
);
8762 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
8764 nbr
->detect_start_time
.tv_sec
= 0;
8765 nbr
->detect_start_time
.tv_usec
= 0;
8766 nbr
->dad_dup_detect_time
= 0;
8767 THREAD_OFF(nbr
->dad_ip_auto_recovery_timer
);
8769 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
8770 zevpn_neigh_send_add_to_client(zevpn
->vni
, &nbr
->ip
,
8771 &nbr
->emac
, nbr
->mac
,
8772 nbr
->flags
, nbr
->loc_seq
);
8773 } else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
8774 zevpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
8778 static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket
*bucket
,
8781 zebra_evpn_t
*zevpn
;
8782 struct zebra_vrf
*zvrf
;
8783 struct mac_walk_ctx m_wctx
;
8784 struct neigh_walk_ctx n_wctx
;
8786 zevpn
= (zebra_evpn_t
*)bucket
->data
;
8790 zvrf
= (struct zebra_vrf
*)args
[0];
8792 if (hashcount(zevpn
->neigh_table
)) {
8793 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8794 n_wctx
.zevpn
= zevpn
;
8796 hash_iterate(zevpn
->neigh_table
, zevpn_clear_dup_neigh_hash
,
8800 if (num_valid_macs(zevpn
)) {
8801 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8802 m_wctx
.zevpn
= zevpn
;
8804 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
8809 int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf
*zvrf
)
8813 if (!is_evpn_enabled())
8818 hash_iterate(zvrf
->evpn_table
,
8819 (void (*)(struct hash_bucket
*, void *))
8820 zevpn_clear_dup_detect_hash_vni_all
, args
);
8825 int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf
*zvrf
, vni_t vni
)
8827 zebra_evpn_t
*zevpn
;
8828 struct mac_walk_ctx m_wctx
;
8829 struct neigh_walk_ctx n_wctx
;
8831 if (!is_evpn_enabled())
8834 zevpn
= zevpn_lookup(vni
);
8836 zlog_warn("VNI %u does not exist\n", vni
);
8840 if (hashcount(zevpn
->neigh_table
)) {
8841 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
8842 n_wctx
.zevpn
= zevpn
;
8844 hash_iterate(zevpn
->neigh_table
, zevpn_clear_dup_neigh_hash
,
8848 if (num_valid_macs(zevpn
)) {
8849 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
8850 m_wctx
.zevpn
= zevpn
;
8852 hash_iterate(zevpn
->mac_table
, zevpn_clear_dup_mac_hash
, &m_wctx
);
8859 * Display MACs for a VNI from specific VTEP (VTY command handler).
8861 void zebra_vxlan_print_macs_vni_vtep(struct vty
*vty
, struct zebra_vrf
*zvrf
,
8862 vni_t vni
, struct in_addr vtep_ip
,
8865 zebra_evpn_t
*zevpn
;
8867 struct mac_walk_ctx wctx
;
8868 json_object
*json
= NULL
;
8869 json_object
*json_mac
= NULL
;
8871 if (!is_evpn_enabled())
8873 zevpn
= zevpn_lookup(vni
);
8876 vty_out(vty
, "{}\n");
8878 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8881 num_macs
= num_valid_macs(zevpn
);
8886 json
= json_object_new_object();
8887 json_mac
= json_object_new_object();
8890 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
8893 wctx
.flags
= SHOW_REMOTE_MAC_FROM_VTEP
;
8894 wctx
.r_vtep_ip
= vtep_ip
;
8895 wctx
.json
= json_mac
;
8896 hash_iterate(zevpn
->mac_table
, zevpn_print_mac_hash
, &wctx
);
8899 json_object_int_add(json
, "numMacs", wctx
.count
);
8901 json_object_object_add(json
, "macs", json_mac
);
8902 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8903 json
, JSON_C_TO_STRING_PRETTY
));
8904 json_object_free(json
);
8910 * Display VNI information (VTY command handler).
8912 * use_json flag indicates that output should be in JSON format.
8913 * json_array is non NULL when JSON output needs to be aggregated (by the
8914 * caller) and then printed, otherwise, JSON evpn vni info is printed
8917 void zebra_vxlan_print_vni(struct vty
*vty
, struct zebra_vrf
*zvrf
, vni_t vni
,
8918 bool use_json
, json_object
*json_array
)
8920 json_object
*json
= NULL
;
8922 zebra_l3vni_t
*zl3vni
= NULL
;
8923 zebra_evpn_t
*zevpn
= NULL
;
8925 if (!is_evpn_enabled())
8929 json
= json_object_new_object();
8934 zl3vni
= zl3vni_lookup(vni
);
8936 zl3vni_print(zl3vni
, (void *)args
);
8938 zevpn
= zevpn_lookup(vni
);
8940 zevpn_print(zevpn
, (void *)args
);
8942 vty_out(vty
, "%% VNI %u does not exist\n", vni
);
8947 * Each "json" object contains info about 1 VNI.
8948 * When "json_array" is non-null, we aggreggate the json output
8949 * into json_array and print it as a JSON array.
8952 json_object_array_add(json_array
, json
);
8954 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
8955 json
, JSON_C_TO_STRING_PRETTY
));
8956 json_object_free(json
);
8961 /* Display all global details for EVPN */
8962 void zebra_vxlan_print_evpn(struct vty
*vty
, bool uj
)
8967 json_object
*json
= NULL
;
8968 struct zebra_vrf
*zvrf
= NULL
;
8970 if (!is_evpn_enabled())
8973 zvrf
= zebra_vrf_get_evpn();
8977 num_l3vnis
= hashcount(zrouter
.l3vni_table
);
8978 num_l2vnis
= hashcount(zvrf
->evpn_table
);
8979 num_vnis
= num_l2vnis
+ num_l3vnis
;
8982 json
= json_object_new_object();
8983 json_object_string_add(json
, "advertiseGatewayMacip",
8984 zvrf
->advertise_gw_macip
? "Yes" : "No");
8985 json_object_int_add(json
, "numVnis", num_vnis
);
8986 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
8987 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
8988 if (zvrf
->dup_addr_detect
)
8989 json_object_boolean_true_add(json
,
8990 "isDuplicateAddrDetection");
8992 json_object_boolean_false_add(json
,
8993 "isDuplicateAddrDetection");
8994 json_object_int_add(json
, "maxMoves", zvrf
->dad_max_moves
);
8995 json_object_int_add(json
, "detectionTime", zvrf
->dad_time
);
8996 json_object_int_add(json
, "detectionFreezeTime",
8997 zvrf
->dad_freeze_time
);
9000 vty_out(vty
, "L2 VNIs: %u\n", num_l2vnis
);
9001 vty_out(vty
, "L3 VNIs: %u\n", num_l3vnis
);
9002 vty_out(vty
, "Advertise gateway mac-ip: %s\n",
9003 zvrf
->advertise_gw_macip
? "Yes" : "No");
9004 vty_out(vty
, "Advertise svi mac-ip: %s\n",
9005 zvrf
->advertise_svi_macip
? "Yes" : "No");
9006 vty_out(vty
, "Duplicate address detection: %s\n",
9007 zvrf
->dup_addr_detect
? "Enable" : "Disable");
9008 vty_out(vty
, " Detection max-moves %u, time %d\n",
9009 zvrf
->dad_max_moves
, zvrf
->dad_time
);
9010 if (zvrf
->dad_freeze
) {
9011 if (zvrf
->dad_freeze_time
)
9012 vty_out(vty
, " Detection freeze %u\n",
9013 zvrf
->dad_freeze_time
);
9015 vty_out(vty
, " Detection freeze %s\n",
9021 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9022 json
, JSON_C_TO_STRING_PRETTY
));
9023 json_object_free(json
);
9028 * Display VNI hash table (VTY command handler).
9030 void zebra_vxlan_print_vnis(struct vty
*vty
, struct zebra_vrf
*zvrf
,
9033 json_object
*json
= NULL
;
9036 if (!is_evpn_enabled())
9040 json
= json_object_new_object();
9042 vty_out(vty
, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
9043 "Type", "VxLAN IF", "# MACs", "# ARPs",
9044 "# Remote VTEPs", "Tenant VRF");
9049 /* Display all L2-VNIs */
9050 hash_iterate(zvrf
->evpn_table
,
9051 (void (*)(struct hash_bucket
*, void *))zevpn_print_hash
,
9054 /* Display all L3-VNIs */
9055 hash_iterate(zrouter
.l3vni_table
,
9056 (void (*)(struct hash_bucket
*, void *))zl3vni_print_hash
,
9060 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
9061 json
, JSON_C_TO_STRING_PRETTY
));
9062 json_object_free(json
);
9066 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS
)
9070 uint32_t max_moves
= 0;
9071 uint32_t freeze_time
= 0;
9072 bool dup_addr_detect
= false;
9073 bool freeze
= false;
9076 STREAM_GETL(s
, dup_addr_detect
);
9077 STREAM_GETL(s
, time
);
9078 STREAM_GETL(s
, max_moves
);
9079 STREAM_GETL(s
, freeze
);
9080 STREAM_GETL(s
, freeze_time
);
9082 /* DAD previous state was enabled, and new state is disable,
9083 * clear all duplicate detected addresses.
9085 if (zvrf
->dup_addr_detect
&& !dup_addr_detect
)
9086 zebra_vxlan_clear_dup_detect_vni_all(zvrf
);
9088 zvrf
->dup_addr_detect
= dup_addr_detect
;
9089 zvrf
->dad_time
= time
;
9090 zvrf
->dad_max_moves
= max_moves
;
9091 zvrf
->dad_freeze
= freeze
;
9092 zvrf
->dad_freeze_time
= freeze_time
;
9094 if (IS_ZEBRA_DEBUG_VXLAN
)
9096 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
9097 vrf_id_to_name(zvrf
->vrf
->vrf_id
),
9098 zvrf
->dup_addr_detect
? "enable" : "disable",
9099 zvrf
->dad_max_moves
,
9101 zvrf
->dad_freeze
? "enable" : "disable",
9102 zvrf
->dad_freeze_time
);
9109 * Display VNI hash table in detail(VTY command handler).
9111 void zebra_vxlan_print_vnis_detail(struct vty
*vty
, struct zebra_vrf
*zvrf
,
9114 json_object
*json_array
= NULL
;
9115 struct zebra_ns
*zns
= NULL
;
9116 struct zevpn_show zes
;
9118 if (!is_evpn_enabled())
9121 zns
= zebra_ns_lookup(NS_DEFAULT
);
9126 json_array
= json_object_new_array();
9129 zes
.json
= json_array
;
9131 zes
.use_json
= use_json
;
9133 /* Display all L2-VNIs */
9136 (void (*)(struct hash_bucket
*, void *))zevpn_print_hash_detail
,
9139 /* Display all L3-VNIs */
9140 hash_iterate(zrouter
.l3vni_table
,
9141 (void (*)(struct hash_bucket
*,
9142 void *))zl3vni_print_hash_detail
,
9146 vty_out(vty
, "%s\n",
9147 json_object_to_json_string_ext(
9148 json_array
, JSON_C_TO_STRING_PRETTY
));
9149 json_object_free(json_array
);
9154 * Handle neighbor delete notification from the kernel (on a VLAN device
9155 * / L3 interface). This may result in either the neighbor getting deleted
9156 * from our database or being re-added to the kernel (if it is a valid
9159 int zebra_vxlan_handle_kernel_neigh_del(struct interface
*ifp
,
9160 struct interface
*link_if
,
9163 char buf
[INET6_ADDRSTRLEN
];
9164 char buf2
[ETHER_ADDR_STRLEN
];
9165 zebra_neigh_t
*n
= NULL
;
9166 zebra_evpn_t
*zevpn
= NULL
;
9167 zebra_mac_t
*zmac
= NULL
;
9168 zebra_l3vni_t
*zl3vni
= NULL
;
9169 struct zebra_vrf
*zvrf
;
9173 /* check if this is a remote neigh entry corresponding to remote
9176 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
9178 return zl3vni_local_nh_del(zl3vni
, ip
);
9180 /* We are only interested in neighbors on an SVI that resides on top
9181 * of a VxLAN bridge.
9183 zevpn
= zevpn_from_svi(ifp
, link_if
);
9185 if (IS_ZEBRA_DEBUG_VXLAN
)
9187 "%s: Del neighbor %s EVPN is not present for interface %s",
9188 __func__
, ipaddr2str(ip
, buf
, sizeof(buf
)),
9193 if (!zevpn
->vxlan_if
) {
9195 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
9200 if (IS_ZEBRA_DEBUG_VXLAN
)
9201 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
9202 ipaddr2str(ip
, buf
, sizeof(buf
)), ifp
->name
,
9203 ifp
->ifindex
, zevpn
->vni
);
9205 /* If entry doesn't exist, nothing to do. */
9206 n
= zevpn_neigh_lookup(zevpn
, ip
);
9210 zmac
= zevpn_mac_lookup(zevpn
, &n
->emac
);
9212 if (IS_ZEBRA_DEBUG_VXLAN
)
9214 "Trying to del a neigh %s without a mac %s on VNI %u",
9215 ipaddr2str(ip
, buf
, sizeof(buf
)),
9216 prefix_mac2str(&n
->emac
, buf2
, sizeof(buf2
)),
9222 /* If it is a remote entry, the kernel has aged this out or someone has
9223 * deleted it, it needs to be re-installed as Quagga is the owner.
9225 if (CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_REMOTE
)) {
9226 zevpn_rem_neigh_install(zevpn
, n
, false /*was_static*/);
9230 /* if this is a sync entry it cannot be dropped re-install it in
9234 zebra_vxlan_neigh_is_ready_for_bgp(n
);
9235 if (zebra_vxlan_neigh_is_static(n
)) {
9236 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
9237 zlog_debug("re-add sync neigh vni %u ip %s mac %s 0x%x",
9239 ipaddr2str(&n
->ip
, buf
, sizeof(buf
)),
9240 prefix_mac2str(&n
->emac
, buf2
,
9244 if (!CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
))
9245 SET_FLAG(n
->flags
, ZEBRA_NEIGH_LOCAL_INACTIVE
);
9246 /* inform-bgp about change in local-activity if any */
9248 zebra_vxlan_neigh_is_ready_for_bgp(n
);
9249 zebra_vxlan_neigh_send_add_del_to_client(n
,
9250 old_bgp_ready
, new_bgp_ready
);
9252 /* re-install the entry in the kernel */
9253 zebra_vxlan_sync_neigh_dp_install(n
, false /* set_inactive */,
9254 false /* force_clear_static */, __func__
);
9259 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
9261 zlog_debug("%s: VNI %u vrf lookup failed.", __func__
,
9266 /* In case of feeze action, if local neigh is in duplicate state,
9267 * Mark the Neigh as inactive before sending delete request to BGPd,
9268 * If BGPd has remote entry, it will re-install
9270 if (zvrf
->dad_freeze
&&
9271 CHECK_FLAG(n
->flags
, ZEBRA_NEIGH_DUPLICATE
))
9272 ZEBRA_NEIGH_SET_INACTIVE(n
);
9274 /* Remove neighbor from BGP. */
9275 zevpn_neigh_send_del_to_client(zevpn
->vni
, &n
->ip
,
9276 &n
->emac
, n
->flags
, n
->state
,
9279 /* Delete this neighbor entry. */
9280 zevpn_neigh_del(zevpn
, n
);
9282 /* see if the AUTO mac needs to be deleted */
9283 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_AUTO
)
9284 && !listcount(zmac
->neigh_list
))
9285 zevpn_mac_del(zevpn
, zmac
);
9291 * Handle neighbor add or update notification from the kernel (on a VLAN
9292 * device / L3 interface). This is typically for a local neighbor but can
9293 * also be for a remote neighbor (e.g., ageout notification). It could
9294 * also be a "move" scenario.
9296 int zebra_vxlan_handle_kernel_neigh_update(struct interface
*ifp
,
9297 struct interface
*link_if
,
9299 struct ethaddr
*macaddr
,
9303 bool local_inactive
, bool dp_static
)
9305 char buf
[ETHER_ADDR_STRLEN
];
9306 char buf2
[INET6_ADDRSTRLEN
];
9307 zebra_evpn_t
*zevpn
= NULL
;
9308 zebra_l3vni_t
*zl3vni
= NULL
;
9310 /* check if this is a remote neigh entry corresponding to remote
9313 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
9315 return zl3vni_local_nh_add_update(zl3vni
, ip
, state
);
9317 /* We are only interested in neighbors on an SVI that resides on top
9318 * of a VxLAN bridge.
9320 zevpn
= zevpn_from_svi(ifp
, link_if
);
9324 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
)
9326 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s%s%s-> L2-VNI %u",
9327 ipaddr2str(ip
, buf2
, sizeof(buf2
)),
9328 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
9329 ifp
->ifindex
, state
, is_ext
? "ext-learned " : "",
9330 is_router
? "router " : "",
9331 local_inactive
? "local_inactive " : "",
9334 /* Is this about a local neighbor or a remote one? */
9336 return zevpn_local_neigh_update(zevpn
, ifp
, ip
, macaddr
,
9337 is_router
, local_inactive
, dp_static
);
9339 return zevpn_remote_neigh_update(zevpn
, ifp
, ip
, macaddr
, state
);
9343 zebra_vxlan_remote_macip_helper(bool add
, struct stream
*s
, vni_t
*vni
,
9344 struct ethaddr
*macaddr
, uint16_t *ipa_len
,
9345 struct ipaddr
*ip
, struct in_addr
*vtep_ip
,
9346 uint8_t *flags
, uint32_t *seq
, esi_t
*esi
)
9351 * Obtain each remote MACIP and process.
9352 * Message contains VNI, followed by MAC followed by IP (if any)
9353 * followed by remote VTEP IP.
9355 memset(ip
, 0, sizeof(*ip
));
9356 STREAM_GETL(s
, *vni
);
9357 STREAM_GET(macaddr
->octet
, s
, ETH_ALEN
);
9358 STREAM_GETL(s
, *ipa_len
);
9361 if (*ipa_len
== IPV4_MAX_BYTELEN
)
9362 ip
->ipa_type
= IPADDR_V4
;
9363 else if (*ipa_len
== IPV6_MAX_BYTELEN
)
9364 ip
->ipa_type
= IPADDR_V6
;
9366 if (IS_ZEBRA_DEBUG_VXLAN
)
9368 "ipa_len *must* be %d or %d bytes in length not %d",
9369 IPV4_MAX_BYTELEN
, IPV6_MAX_BYTELEN
,
9371 goto stream_failure
;
9374 STREAM_GET(&ip
->ip
.addr
, s
, *ipa_len
);
9376 l
+= 4 + ETH_ALEN
+ 4 + *ipa_len
;
9377 STREAM_GET(&vtep_ip
->s_addr
, s
, IPV4_MAX_BYTELEN
);
9378 l
+= IPV4_MAX_BYTELEN
;
9381 STREAM_GETC(s
, *flags
);
9382 STREAM_GETL(s
, *seq
);
9384 STREAM_GET(esi
, s
, sizeof(esi_t
));
9395 * Handle message from client to delete a remote MACIP for a VNI.
9397 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS
)
9401 struct ethaddr macaddr
;
9403 struct in_addr vtep_ip
;
9404 uint16_t l
= 0, ipa_len
;
9405 char buf
[ETHER_ADDR_STRLEN
];
9406 char buf1
[INET6_ADDRSTRLEN
];
9408 memset(&macaddr
, 0, sizeof(struct ethaddr
));
9409 memset(&ip
, 0, sizeof(struct ipaddr
));
9410 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
9414 while (l
< hdr
->length
) {
9415 int res_length
= zebra_vxlan_remote_macip_helper(
9416 false, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
, NULL
,
9419 if (res_length
== -1)
9420 goto stream_failure
;
9423 if (IS_ZEBRA_DEBUG_VXLAN
)
9425 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
9427 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
9428 ipa_len
? " IP " : "",
9430 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
9432 zebra_route_string(client
->proto
));
9434 process_remote_macip_del(vni
, &macaddr
, ipa_len
, &ip
, vtep_ip
);
9442 * Handle message from client to add a remote MACIP for a VNI. This
9443 * could be just the add of a MAC address or the add of a neighbor
9446 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS
)
9450 struct ethaddr macaddr
;
9452 struct in_addr vtep_ip
;
9453 uint16_t l
= 0, ipa_len
;
9456 char buf
[ETHER_ADDR_STRLEN
];
9457 char buf1
[INET6_ADDRSTRLEN
];
9459 char esi_buf
[ESI_STR_LEN
];
9461 memset(&macaddr
, 0, sizeof(struct ethaddr
));
9462 memset(&ip
, 0, sizeof(struct ipaddr
));
9463 memset(&vtep_ip
, 0, sizeof(struct in_addr
));
9465 if (!EVPN_ENABLED(zvrf
)) {
9466 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
9472 while (l
< hdr
->length
) {
9473 int res_length
= zebra_vxlan_remote_macip_helper(
9474 true, s
, &vni
, &macaddr
, &ipa_len
, &ip
, &vtep_ip
,
9475 &flags
, &seq
, &esi
);
9477 if (res_length
== -1)
9478 goto stream_failure
;
9481 if (IS_ZEBRA_DEBUG_VXLAN
) {
9482 if (memcmp(&esi
, zero_esi
, sizeof(esi_t
)))
9483 esi_to_str(&esi
, esi_buf
, sizeof(esi_buf
));
9485 strlcpy(esi_buf
, "-", ESI_STR_LEN
);
9487 "Recv %sMACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s ESI %s from %s",
9488 (flags
& ZEBRA_MACIP_TYPE_SYNC_PATH
) ?
9491 prefix_mac2str(&macaddr
, buf
, sizeof(buf
)),
9492 ipa_len
? " IP " : "",
9494 ipaddr2str(&ip
, buf1
, sizeof(buf1
)) : "",
9495 flags
, seq
, inet_ntoa(vtep_ip
), esi_buf
,
9496 zebra_route_string(client
->proto
));
9499 process_remote_macip_add(vni
, &macaddr
, ipa_len
, &ip
,
9500 flags
, seq
, vtep_ip
, &esi
);
9508 * Handle remote vtep delete by kernel; re-add the vtep if we have it
9510 int zebra_vxlan_check_readd_vtep(struct interface
*ifp
,
9511 struct in_addr vtep_ip
)
9513 struct zebra_if
*zif
;
9514 struct zebra_vrf
*zvrf
= NULL
;
9515 struct zebra_l2info_vxlan
*vxl
;
9517 zebra_evpn_t
*zevpn
= NULL
;
9518 zebra_vtep_t
*zvtep
= NULL
;
9522 vxl
= &zif
->l2info
.vxl
;
9525 /* If EVPN is not enabled, nothing to do. */
9526 if (!is_evpn_enabled())
9529 /* Locate VRF corresponding to interface. */
9530 zvrf
= vrf_info_lookup(ifp
->vrf_id
);
9534 /* Locate hash entry; it is expected to exist. */
9535 zevpn
= zevpn_lookup(vni
);
9539 /* If the remote vtep entry doesn't exists nothing to do */
9540 zvtep
= zevpn_vtep_find(zevpn
, &vtep_ip
);
9544 if (IS_ZEBRA_DEBUG_VXLAN
)
9546 "Del MAC for remote VTEP %s intf %s(%u) VNI %u - readd",
9547 inet_ntoa(vtep_ip
), ifp
->name
, ifp
->ifindex
, vni
);
9549 zevpn_vtep_install(zevpn
, zvtep
);
9554 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
9555 * us, this must involve a multihoming scenario. Treat this as implicit delete
9556 * of any prior local MAC.
9558 int zebra_vxlan_check_del_local_mac(struct interface
*ifp
,
9559 struct interface
*br_if
,
9560 struct ethaddr
*macaddr
, vlanid_t vid
)
9562 struct zebra_if
*zif
;
9563 struct zebra_l2info_vxlan
*vxl
;
9565 zebra_evpn_t
*zevpn
;
9567 char buf
[ETHER_ADDR_STRLEN
];
9571 vxl
= &zif
->l2info
.vxl
;
9574 /* Check if EVPN is enabled. */
9575 if (!is_evpn_enabled())
9578 /* Locate hash entry; it is expected to exist. */
9579 zevpn
= zevpn_lookup(vni
);
9583 /* If entry doesn't exist, nothing to do. */
9584 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
9588 /* Is it a local entry? */
9589 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
9592 if (IS_ZEBRA_DEBUG_VXLAN
)
9594 "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
9595 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
9596 ifp
->ifindex
, vni
, mac
->flags
);
9598 /* Remove MAC from BGP. */
9599 zevpn_mac_send_del_to_client(zevpn
->vni
, macaddr
,
9600 mac
->flags
, false /* force */);
9603 * If there are no neigh associated with the mac delete the mac
9604 * else mark it as AUTO for forward reference
9606 if (!listcount(mac
->neigh_list
)) {
9607 zevpn_mac_del(zevpn
, mac
);
9609 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
9610 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
9611 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
9618 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
9619 * This can happen because the remote MAC entries are also added as "dynamic",
9620 * so the kernel can ageout the entry.
9622 int zebra_vxlan_check_readd_remote_mac(struct interface
*ifp
,
9623 struct interface
*br_if
,
9624 struct ethaddr
*macaddr
, vlanid_t vid
)
9626 struct zebra_if
*zif
= NULL
;
9627 struct zebra_l2info_vxlan
*vxl
= NULL
;
9629 zebra_evpn_t
*zevpn
= NULL
;
9630 zebra_l3vni_t
*zl3vni
= NULL
;
9631 zebra_mac_t
*mac
= NULL
;
9632 char buf
[ETHER_ADDR_STRLEN
];
9636 vxl
= &zif
->l2info
.vxl
;
9639 /* Check if EVPN is enabled. */
9640 if (!is_evpn_enabled())
9643 /* check if this is a remote RMAC and readd simillar to remote macs */
9644 zl3vni
= zl3vni_lookup(vni
);
9646 return zebra_vxlan_readd_remote_rmac(zl3vni
, macaddr
);
9648 /* Locate hash entry; it is expected to exist. */
9649 zevpn
= zevpn_lookup(vni
);
9653 /* If entry doesn't exist, nothing to do. */
9654 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
9658 /* Is it a remote entry? */
9659 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
))
9662 if (IS_ZEBRA_DEBUG_VXLAN
)
9663 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
9664 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
9667 zevpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
9672 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
9674 int zebra_vxlan_local_mac_del(struct interface
*ifp
, struct interface
*br_if
,
9675 struct ethaddr
*macaddr
, vlanid_t vid
)
9677 zebra_evpn_t
*zevpn
;
9679 char buf
[ETHER_ADDR_STRLEN
];
9683 /* We are interested in MACs only on ports or (port, VLAN) that
9686 zevpn
= zevpn_map_vlan(ifp
, br_if
, vid
);
9689 if (!zevpn
->vxlan_if
) {
9691 "VNI %u hash %p doesn't have intf upon local MAC DEL",
9696 /* If entry doesn't exist, nothing to do. */
9697 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
9701 /* Is it a local entry? */
9702 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
))
9705 if (IS_ZEBRA_DEBUG_VXLAN
)
9706 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u",
9707 prefix_mac2str(macaddr
, buf
, sizeof(buf
)), ifp
->name
,
9708 ifp
->ifindex
, vid
, zevpn
->vni
, mac
->loc_seq
,
9709 mac
->flags
, listcount(mac
->neigh_list
));
9711 old_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
9712 if (zebra_vxlan_mac_is_static(mac
)) {
9713 /* this is a synced entry and can only be removed when the
9714 * es-peers stop advertising it.
9716 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
9718 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
9719 zlog_debug("re-add sync-mac vni %u mac %s es %s seq %d f 0x%x",
9721 prefix_mac2str(macaddr
,
9723 mac
->es
? mac
->es
->esi_str
: "-",
9727 /* inform-bgp about change in local-activity if any */
9728 if (!CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
)) {
9729 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
);
9730 new_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
9731 zebra_vxlan_mac_send_add_del_to_client(mac
,
9732 old_bgp_ready
, new_bgp_ready
);
9735 /* re-install the entry in the kernel */
9736 zebra_vxlan_sync_mac_dp_install(mac
, false /* set_inactive */,
9737 false /* force_clear_static */,
9743 /* Update all the neigh entries associated with this mac */
9744 zevpn_process_neigh_on_local_mac_del(zevpn
, mac
);
9746 /* Remove MAC from BGP. */
9747 zevpn_mac_send_del_to_client(zevpn
->vni
, macaddr
,
9748 mac
->flags
, false /* force */);
9750 zebra_evpn_es_mac_deref_entry(mac
);
9753 * If there are no neigh associated with the mac delete the mac
9754 * else mark it as AUTO for forward reference
9756 if (!listcount(mac
->neigh_list
)) {
9757 zevpn_mac_del(zevpn
, mac
);
9759 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_ALL_LOCAL_FLAGS
);
9760 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
9761 SET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
9767 /* update local fowarding info. return true if a dest-ES change
9770 static bool zebra_vxlan_local_mac_update_fwd_info(zebra_mac_t
*mac
,
9771 struct interface
*ifp
, vlanid_t vid
)
9773 struct zebra_if
*zif
= ifp
->info
;
9776 memset(&mac
->fwd_info
, 0, sizeof(mac
->fwd_info
));
9778 es_change
= zebra_evpn_es_mac_ref_entry(mac
, zif
->es_info
.es
);
9781 /* if es is set fwd_info is not-relevant/taped-out */
9782 mac
->fwd_info
.local
.ifindex
= ifp
->ifindex
;
9783 mac
->fwd_info
.local
.vid
= vid
;
9790 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
9792 int zebra_vxlan_local_mac_add_update(struct interface
*ifp
,
9793 struct interface
*br_if
,
9794 struct ethaddr
*macaddr
, vlanid_t vid
,
9795 bool sticky
, bool local_inactive
,
9798 zebra_evpn_t
*zevpn
;
9800 struct zebra_vrf
*zvrf
;
9801 char buf
[ETHER_ADDR_STRLEN
];
9802 bool mac_sticky
= false;
9803 bool inform_client
= false;
9804 bool upd_neigh
= false;
9805 bool is_dup_detect
= false;
9806 struct in_addr vtep_ip
= {.s_addr
= 0};
9807 bool es_change
= false;
9809 /* assume inactive if not present or if not local */
9810 bool old_local_inactive
= true;
9811 bool old_bgp_ready
= false;
9812 bool inform_dataplane
= false;
9813 bool new_static
= false;
9818 /* We are interested in MACs only on ports or (port, VLAN) that
9821 zevpn
= zevpn_map_vlan(ifp
, br_if
, vid
);
9823 if (IS_ZEBRA_DEBUG_VXLAN
)
9825 " Add/Update %sMAC %s intf %s(%u) VID %u, could not find EVPN",
9826 sticky
? "sticky " : "",
9827 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
9828 ifp
->name
, ifp
->ifindex
, vid
);
9832 if (!zevpn
->vxlan_if
) {
9833 if (IS_ZEBRA_DEBUG_VXLAN
)
9835 " VNI %u hash %p doesn't have intf upon local MAC ADD",
9840 zvrf
= vrf_info_lookup(zevpn
->vxlan_if
->vrf_id
);
9842 if (IS_ZEBRA_DEBUG_VXLAN
)
9843 zlog_debug(" No Vrf found for vrf_id: %d",
9844 zevpn
->vxlan_if
->vrf_id
);
9848 /* Check if we need to create or update or it is a NO-OP. */
9849 mac
= zevpn_mac_lookup(zevpn
, macaddr
);
9851 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
9853 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u%s",
9854 sticky
? "sticky " : "",
9855 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
9856 ifp
->name
, ifp
->ifindex
, vid
, zevpn
->vni
,
9857 local_inactive
? " local-inactive" : "");
9859 mac
= zevpn_mac_add(zevpn
, macaddr
);
9862 EC_ZEBRA_MAC_ADD_FAILED
,
9863 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
9864 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
9865 ifp
->name
, ifp
->ifindex
, vid
, zevpn
->vni
);
9868 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
9869 es_change
= zebra_vxlan_local_mac_update_fwd_info(mac
,
9872 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
9873 inform_client
= true;
9875 if (IS_ZEBRA_DEBUG_VXLAN
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
9877 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags 0x%x",
9878 sticky
? "sticky " : "",
9879 prefix_mac2str(macaddr
, buf
, sizeof(buf
)),
9880 ifp
->name
, ifp
->ifindex
, vid
, zevpn
->vni
,
9881 local_inactive
? "local-inactive " : "",
9884 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
9885 struct interface
*old_ifp
;
9889 zebra_vxlan_mac_get_access_info(mac
,
9890 &old_ifp
, &old_vid
);
9891 old_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(
9893 old_local_inactive
= !!(mac
->flags
&
9894 ZEBRA_MAC_LOCAL_INACTIVE
);
9895 old_static
= zebra_vxlan_mac_is_static(mac
);
9896 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
))
9900 * Update any changes and if changes are relevant to
9903 if (mac_sticky
== sticky
9906 && old_local_inactive
== local_inactive
9907 && dp_static
== old_static
) {
9908 if (IS_ZEBRA_DEBUG_VXLAN
)
9910 " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u%s, entry exists and has not changed ",
9911 sticky
? "sticky " : "",
9912 prefix_mac2str(macaddr
, buf
,
9914 ifp
->name
, ifp
->ifindex
, vid
,
9917 " local_inactive" : "");
9920 if (mac_sticky
!= sticky
) {
9922 SET_FLAG(mac
->flags
,
9925 UNSET_FLAG(mac
->flags
,
9927 inform_client
= true;
9930 es_change
= zebra_vxlan_local_mac_update_fwd_info(mac
,
9932 /* If an es_change is detected we need to advertise
9933 * the route with a sequence that is one
9934 * greater. This is need to indicate a mac-move
9938 mac
->loc_seq
= mac
->loc_seq
+ 1;
9939 /* force drop the peer/sync info as it is
9940 * simply no longer relevant
9942 if (CHECK_FLAG(mac
->flags
,
9943 ZEBRA_MAC_ALL_PEER_FLAGS
)) {
9944 zebra_vxlan_mac_clear_sync_info(mac
);
9946 zebra_vxlan_mac_is_static(mac
);
9947 /* if we clear peer-flags we
9948 * also need to notify the dataplane
9949 * to drop the static flag
9951 if (old_static
!= new_static
)
9952 inform_dataplane
= true;
9955 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
) ||
9956 CHECK_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
)) {
9957 bool do_dad
= false;
9960 * MAC has either moved or was "internally" created due
9961 * to a neighbor learn and is now actually learnt. If
9962 * it was learnt as a remote sticky MAC, this is an
9965 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
)) {
9967 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT
,
9968 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
9969 prefix_mac2str(macaddr
, buf
,
9971 inet_ntoa(mac
->fwd_info
.r_vtep_ip
),
9976 /* If an actual move, compute MAC's seq number */
9977 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
9978 mac
->loc_seq
= MAX(mac
->rem_seq
+ 1,
9980 vtep_ip
= mac
->fwd_info
.r_vtep_ip
;
9981 /* Trigger DAD for remote MAC */
9985 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
);
9986 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_AUTO
);
9987 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
);
9988 es_change
= zebra_vxlan_local_mac_update_fwd_info(mac
,
9991 SET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
9993 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_STICKY
);
9995 * We have to inform BGP of this MAC as well as process
9998 inform_client
= true;
10001 zebra_vxlan_dup_addr_detect_for_mac(zvrf
, mac
, vtep_ip
,
10005 if (is_dup_detect
) {
10006 inform_client
= false;
10012 /* if the dataplane thinks the entry is sync but it is
10013 * not sync in zebra we need to re-install to fixup
10016 new_static
= zebra_vxlan_mac_is_static(mac
);
10018 inform_dataplane
= true;
10021 if (local_inactive
)
10022 SET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
);
10024 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL_INACTIVE
);
10026 new_bgp_ready
= zebra_vxlan_mac_is_ready_for_bgp(mac
->flags
);
10027 /* if local-activity has changed we need update bgp
10028 * even if bgp already knows about the mac
10030 if ((old_local_inactive
!= local_inactive
) ||
10031 (new_bgp_ready
!= old_bgp_ready
)) {
10032 if (IS_ZEBRA_DEBUG_EVPN_MH_MAC
)
10033 zlog_debug("local mac vni %u mac %s es %s seq %d f 0x%x%s",
10035 prefix_mac2str(macaddr
,
10037 mac
->es
? mac
->es
->esi_str
: "",
10041 " local-inactive" : "");
10042 inform_client
= true;
10046 inform_client
= true;
10050 /* Inform dataplane if required. */
10051 if (inform_dataplane
)
10052 zebra_vxlan_sync_mac_dp_install(mac
, false /* set_inactive */,
10053 false /* force_clear_static */, __func__
);
10055 /* Inform BGP if required. */
10057 zebra_vxlan_mac_send_add_del_to_client(mac
,
10058 old_bgp_ready
, new_bgp_ready
);
10060 /* Process all neighbors associated with this MAC, if required. */
10062 zevpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0, es_change
);
10068 * Handle message from client to delete a remote VTEP for an EVPN.
10070 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS
)
10073 unsigned short l
= 0;
10075 struct in_addr vtep_ip
;
10076 zebra_evpn_t
*zevpn
;
10077 zebra_vtep_t
*zvtep
;
10078 struct interface
*ifp
;
10079 struct zebra_if
*zif
;
10081 if (!is_evpn_enabled()) {
10083 "%s: EVPN is not enabled yet we have received a vtep del command",
10088 if (!EVPN_ENABLED(zvrf
)) {
10089 zlog_debug("Recv MACIP DEL for non-EVPN VRF %u",
10096 while (l
< hdr
->length
) {
10097 int flood_control
__attribute__((unused
));
10099 /* Obtain each remote VTEP and process. */
10100 STREAM_GETL(s
, vni
);
10102 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
10103 l
+= IPV4_MAX_BYTELEN
;
10105 /* Flood control is intentionally ignored right now */
10106 STREAM_GETL(s
, flood_control
);
10109 if (IS_ZEBRA_DEBUG_VXLAN
)
10110 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
10111 inet_ntoa(vtep_ip
), vni
,
10112 zebra_route_string(client
->proto
));
10114 /* Locate VNI hash entry - expected to exist. */
10115 zevpn
= zevpn_lookup(vni
);
10117 if (IS_ZEBRA_DEBUG_VXLAN
)
10119 "Failed to locate VNI hash upon remote VTEP DEL, VNI %u",
10124 ifp
= zevpn
->vxlan_if
;
10127 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
10128 zevpn
->vni
, zevpn
);
10133 /* If down or not mapped to a bridge, we're done. */
10134 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
10137 /* If the remote VTEP does not exist, there's nothing more to
10139 * Otherwise, uninstall any remote MACs pointing to this VTEP
10141 * then, the VTEP entry itself and remove it.
10143 zvtep
= zevpn_vtep_find(zevpn
, &vtep_ip
);
10147 zevpn_vtep_uninstall(zevpn
, &vtep_ip
);
10148 zevpn_vtep_del(zevpn
, zvtep
);
10156 * Handle message from client to add a remote VTEP for an EVPN.
10158 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS
)
10161 unsigned short l
= 0;
10163 struct in_addr vtep_ip
;
10164 zebra_evpn_t
*zevpn
;
10165 struct interface
*ifp
;
10166 struct zebra_if
*zif
;
10168 zebra_vtep_t
*zvtep
;
10170 if (!is_evpn_enabled()) {
10172 "%s: EVPN not enabled yet we received a vtep_add zapi call",
10177 if (!EVPN_ENABLED(zvrf
)) {
10178 zlog_debug("Recv MACIP ADD for non-EVPN VRF %u",
10185 while (l
< hdr
->length
) {
10186 /* Obtain each remote VTEP and process. */
10187 STREAM_GETL(s
, vni
);
10189 STREAM_GET(&vtep_ip
.s_addr
, s
, IPV4_MAX_BYTELEN
);
10190 STREAM_GETL(s
, flood_control
);
10191 l
+= IPV4_MAX_BYTELEN
+ 4;
10193 if (IS_ZEBRA_DEBUG_VXLAN
)
10194 zlog_debug("Recv VTEP_ADD %s VNI %u flood %d from %s",
10195 inet_ntoa(vtep_ip
), vni
, flood_control
,
10196 zebra_route_string(client
->proto
));
10198 /* Locate VNI hash entry - expected to exist. */
10199 zevpn
= zevpn_lookup(vni
);
10202 EC_ZEBRA_VTEP_ADD_FAILED
,
10203 "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u",
10208 ifp
= zevpn
->vxlan_if
;
10211 EC_ZEBRA_VTEP_ADD_FAILED
,
10212 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
10213 zevpn
->vni
, zevpn
);
10219 /* If down or not mapped to a bridge, we're done. */
10220 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
10223 zvtep
= zevpn_vtep_find(zevpn
, &vtep_ip
);
10225 /* If the remote VTEP already exists check if
10226 * the flood mode has changed
10228 if (zvtep
->flood_control
!= flood_control
) {
10229 if (zvtep
->flood_control
10230 == VXLAN_FLOOD_DISABLED
)
10231 /* old mode was head-end-replication but
10232 * is no longer; get rid of the HER fdb
10233 * entry installed before
10235 zevpn_vtep_uninstall(zevpn
, &vtep_ip
);
10236 zvtep
->flood_control
= flood_control
;
10237 zevpn_vtep_install(zevpn
, zvtep
);
10240 zvtep
= zevpn_vtep_add(zevpn
, &vtep_ip
, flood_control
);
10242 zevpn_vtep_install(zevpn
, zvtep
);
10244 flog_err(EC_ZEBRA_VTEP_ADD_FAILED
,
10245 "Failed to add remote VTEP, VNI %u zevpn %p",
10255 * Add/Del gateway macip to evpn
10257 * 1. SVI interface on a vlan aware bridge
10258 * 2. SVI interface on a vlan unaware bridge
10259 * 3. vrr interface (MACVLAN) associated to a SVI
10260 * We advertise macip routes for an interface if it is associated to VxLan vlan
10262 int zebra_vxlan_add_del_gw_macip(struct interface
*ifp
, struct prefix
*p
,
10266 struct ethaddr macaddr
;
10267 zebra_evpn_t
*zevpn
= NULL
;
10269 memset(&ip
, 0, sizeof(struct ipaddr
));
10270 memset(&macaddr
, 0, sizeof(struct ethaddr
));
10272 /* Check if EVPN is enabled. */
10273 if (!is_evpn_enabled())
10276 if (IS_ZEBRA_IF_MACVLAN(ifp
)) {
10277 struct interface
*svi_if
=
10278 NULL
; /* SVI corresponding to the MACVLAN */
10279 struct zebra_if
*ifp_zif
=
10280 NULL
; /* Zebra daemon specific info for MACVLAN */
10281 struct zebra_if
*svi_if_zif
=
10282 NULL
; /* Zebra daemon specific info for SVI*/
10284 ifp_zif
= ifp
->info
;
10289 * for a MACVLAN interface the link represents the svi_if
10291 svi_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
10292 ifp_zif
->link_ifindex
);
10294 zlog_debug("MACVLAN %s(%u) without link information",
10295 ifp
->name
, ifp
->ifindex
);
10299 if (IS_ZEBRA_IF_VLAN(svi_if
)) {
10301 * If it is a vlan aware bridge then the link gives the
10302 * bridge information
10304 struct interface
*svi_if_link
= NULL
;
10306 svi_if_zif
= svi_if
->info
;
10308 svi_if_link
= if_lookup_by_index_per_ns(
10309 zebra_ns_lookup(NS_DEFAULT
),
10310 svi_if_zif
->link_ifindex
);
10311 zevpn
= zevpn_from_svi(svi_if
, svi_if_link
);
10313 } else if (IS_ZEBRA_IF_BRIDGE(svi_if
)) {
10315 * If it is a vlan unaware bridge then svi is the bridge
10318 zevpn
= zevpn_from_svi(svi_if
, svi_if
);
10320 } else if (IS_ZEBRA_IF_VLAN(ifp
)) {
10321 struct zebra_if
*svi_if_zif
=
10322 NULL
; /* Zebra daemon specific info for SVI */
10323 struct interface
*svi_if_link
=
10324 NULL
; /* link info for the SVI = bridge info */
10326 svi_if_zif
= ifp
->info
;
10328 svi_if_link
= if_lookup_by_index_per_ns(
10329 zebra_ns_lookup(NS_DEFAULT
),
10330 svi_if_zif
->link_ifindex
);
10332 zevpn
= zevpn_from_svi(ifp
, svi_if_link
);
10334 } else if (IS_ZEBRA_IF_BRIDGE(ifp
)) {
10335 zevpn
= zevpn_from_svi(ifp
, ifp
);
10341 if (!zevpn
->vxlan_if
) {
10342 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
10343 zevpn
->vni
, zevpn
);
10348 memcpy(&macaddr
.octet
, ifp
->hw_addr
, ETH_ALEN
);
10350 if (p
->family
== AF_INET
) {
10351 ip
.ipa_type
= IPADDR_V4
;
10352 memcpy(&(ip
.ipaddr_v4
), &(p
->u
.prefix4
),
10353 sizeof(struct in_addr
));
10354 } else if (p
->family
== AF_INET6
) {
10355 ip
.ipa_type
= IPADDR_V6
;
10356 memcpy(&(ip
.ipaddr_v6
), &(p
->u
.prefix6
),
10357 sizeof(struct in6_addr
));
10362 zevpn_gw_macip_add(ifp
, zevpn
, &macaddr
, &ip
);
10364 zevpn_gw_macip_del(ifp
, zevpn
, &ip
);
10370 * Handle SVI interface going down.
10371 * SVI can be associated to either L3-VNI or L2-VNI.
10372 * For L2-VNI: At this point, this is a NOP since
10373 * the kernel deletes the neighbor entries on this SVI (if any).
10374 * We only need to update the vrf corresponding to zevpn.
10375 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
10378 int zebra_vxlan_svi_down(struct interface
*ifp
, struct interface
*link_if
)
10380 zebra_l3vni_t
*zl3vni
= NULL
;
10382 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
10385 /* process l3-vni down */
10386 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10388 /* remove association with svi-if */
10389 zl3vni
->svi_if
= NULL
;
10391 zebra_evpn_t
*zevpn
= NULL
;
10393 /* since we dont have svi corresponding to zevpn, we associate it
10394 * to default vrf. Note: the corresponding neigh entries on the
10395 * SVI would have already been deleted */
10396 zevpn
= zevpn_from_svi(ifp
, link_if
);
10398 zevpn
->vrf_id
= VRF_DEFAULT
;
10400 /* update the tenant vrf in BGP */
10401 zevpn_send_add_to_client(zevpn
);
10408 * Handle SVI interface coming up.
10409 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
10411 * For L2-VNI: we need to install any remote neighbors entried (used for
10413 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
10415 int zebra_vxlan_svi_up(struct interface
*ifp
, struct interface
*link_if
)
10417 zebra_evpn_t
*zevpn
= NULL
;
10418 zebra_l3vni_t
*zl3vni
= NULL
;
10420 zl3vni
= zl3vni_from_svi(ifp
, link_if
);
10423 /* associate with svi */
10424 zl3vni
->svi_if
= ifp
;
10426 /* process oper-up */
10427 if (is_l3vni_oper_up(zl3vni
))
10428 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10431 /* process SVI up for l2-vni */
10432 struct neigh_walk_ctx n_wctx
;
10434 zevpn
= zevpn_from_svi(ifp
, link_if
);
10438 if (!zevpn
->vxlan_if
) {
10440 "VNI %u hash %p doesn't have intf upon SVI up",
10441 zevpn
->vni
, zevpn
);
10445 if (IS_ZEBRA_DEBUG_VXLAN
)
10447 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
10448 ifp
->name
, ifp
->ifindex
, zevpn
->vni
,
10449 vrf_id_to_name(ifp
->vrf_id
));
10451 /* update the vrf information for l2-vni and inform bgp */
10452 zevpn
->vrf_id
= ifp
->vrf_id
;
10453 zevpn_send_add_to_client(zevpn
);
10455 /* Install any remote neighbors for this VNI. */
10456 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
10457 n_wctx
.zevpn
= zevpn
;
10458 hash_iterate(zevpn
->neigh_table
, zevpn_install_neigh_hash
,
10466 * Handle MAC-VLAN interface going down.
10467 * L3VNI: When MAC-VLAN interface goes down,
10468 * find its associated SVI and update type2/type-5 routes
10471 void zebra_vxlan_macvlan_down(struct interface
*ifp
)
10473 zebra_l3vni_t
*zl3vni
= NULL
;
10474 struct zebra_if
*zif
, *link_zif
;
10475 struct interface
*link_ifp
, *link_if
;
10479 link_ifp
= zif
->link
;
10481 if (IS_ZEBRA_DEBUG_VXLAN
) {
10482 struct interface
*ifp
;
10484 ifp
= if_lookup_by_index_all_vrf(zif
->link_ifindex
);
10485 zlog_debug("macvlan parent link is not found. Parent index %d ifp %s",
10486 zif
->link_ifindex
, ifp
? ifp
->name
: " ");
10490 link_zif
= link_ifp
->info
;
10493 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
10494 link_zif
->link_ifindex
);
10496 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
10498 zl3vni
->mac_vlan_if
= NULL
;
10499 if (is_l3vni_oper_up(zl3vni
))
10500 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10505 * Handle MAC-VLAN interface going up.
10506 * L3VNI: When MAC-VLAN interface comes up,
10507 * find its associated SVI and update type-2 routes
10508 * with MAC-VLAN's MAC as RMAC and for type-5 routes
10509 * use SVI's MAC as RMAC.
10511 void zebra_vxlan_macvlan_up(struct interface
*ifp
)
10513 zebra_l3vni_t
*zl3vni
= NULL
;
10514 struct zebra_if
*zif
, *link_zif
;
10515 struct interface
*link_ifp
, *link_if
;
10519 link_ifp
= zif
->link
;
10520 link_zif
= link_ifp
->info
;
10523 link_if
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
10524 link_zif
->link_ifindex
);
10525 zl3vni
= zl3vni_from_svi(link_ifp
, link_if
);
10527 /* associate with macvlan (VRR) interface */
10528 zl3vni
->mac_vlan_if
= ifp
;
10530 /* process oper-up */
10531 if (is_l3vni_oper_up(zl3vni
))
10532 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10537 * Handle VxLAN interface down
10539 int zebra_vxlan_if_down(struct interface
*ifp
)
10542 struct zebra_if
*zif
= NULL
;
10543 struct zebra_l2info_vxlan
*vxl
= NULL
;
10544 zebra_l3vni_t
*zl3vni
= NULL
;
10545 zebra_evpn_t
*zevpn
;
10547 /* Check if EVPN is enabled. */
10548 if (!is_evpn_enabled())
10553 vxl
= &zif
->l2info
.vxl
;
10556 zl3vni
= zl3vni_lookup(vni
);
10558 /* process-if-down for l3-vni */
10559 if (IS_ZEBRA_DEBUG_VXLAN
)
10560 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp
->name
,
10561 ifp
->ifindex
, vni
);
10563 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10565 /* process if-down for l2-vni */
10566 if (IS_ZEBRA_DEBUG_VXLAN
)
10567 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp
->name
,
10568 ifp
->ifindex
, vni
);
10570 /* Locate hash entry; it is expected to exist. */
10571 zevpn
= zevpn_lookup(vni
);
10574 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
10575 ifp
->name
, ifp
->ifindex
, vni
);
10579 assert(zevpn
->vxlan_if
== ifp
);
10581 /* Delete this VNI from BGP. */
10582 zevpn_send_del_to_client(zevpn
);
10584 /* Free up all neighbors and MACs, if any. */
10585 zevpn_neigh_del_all(zevpn
, 1, 0, DEL_ALL_NEIGH
);
10586 zevpn_mac_del_all(zevpn
, 1, 0, DEL_ALL_MAC
);
10588 /* Free up all remote VTEPs, if any. */
10589 zevpn_vtep_del_all(zevpn
, 1);
10595 * Handle VxLAN interface up - update BGP if required.
10597 int zebra_vxlan_if_up(struct interface
*ifp
)
10600 struct zebra_if
*zif
= NULL
;
10601 struct zebra_l2info_vxlan
*vxl
= NULL
;
10602 zebra_evpn_t
*zevpn
= NULL
;
10603 zebra_l3vni_t
*zl3vni
= NULL
;
10605 /* Check if EVPN is enabled. */
10606 if (!is_evpn_enabled())
10611 vxl
= &zif
->l2info
.vxl
;
10614 zl3vni
= zl3vni_lookup(vni
);
10616 /* we need to associate with SVI, if any, we can associate with
10617 * svi-if only after association with vxlan-intf is complete
10619 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
10620 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
10622 if (IS_ZEBRA_DEBUG_VXLAN
)
10623 zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
10624 , ifp
->name
, ifp
->ifindex
, vni
,
10625 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
10626 zl3vni
->mac_vlan_if
?
10627 zl3vni
->mac_vlan_if
->name
: "NIL");
10629 if (is_l3vni_oper_up(zl3vni
))
10630 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10632 /* Handle L2-VNI add */
10633 struct interface
*vlan_if
= NULL
;
10635 if (IS_ZEBRA_DEBUG_VXLAN
)
10636 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp
->name
,
10637 ifp
->ifindex
, vni
);
10639 /* Locate hash entry; it is expected to exist. */
10640 zevpn
= zevpn_lookup(vni
);
10643 "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u",
10644 ifp
->name
, ifp
->ifindex
, vni
);
10648 assert(zevpn
->vxlan_if
== ifp
);
10649 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
,
10650 zif
->brslave_info
.br_if
);
10652 zevpn
->vrf_id
= vlan_if
->vrf_id
;
10653 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
10655 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
10658 /* If part of a bridge, inform BGP about this VNI. */
10659 /* Also, read and populate local MACs and neighbors. */
10660 if (zif
->brslave_info
.br_if
) {
10661 zevpn_send_add_to_client(zevpn
);
10662 zevpn_read_mac_neigh(zevpn
, ifp
);
10670 * Handle VxLAN interface delete. Locate and remove entry in hash table
10671 * and update BGP, if required.
10673 int zebra_vxlan_if_del(struct interface
*ifp
)
10676 struct zebra_if
*zif
= NULL
;
10677 struct zebra_l2info_vxlan
*vxl
= NULL
;
10678 zebra_evpn_t
*zevpn
= NULL
;
10679 zebra_l3vni_t
*zl3vni
= NULL
;
10681 /* Check if EVPN is enabled. */
10682 if (!is_evpn_enabled())
10687 vxl
= &zif
->l2info
.vxl
;
10690 zl3vni
= zl3vni_lookup(vni
);
10693 if (IS_ZEBRA_DEBUG_VXLAN
)
10694 zlog_debug("Del L3-VNI %u intf %s(%u)", vni
, ifp
->name
,
10697 /* process oper-down for l3-vni */
10698 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10700 /* remove the association with vxlan_if */
10701 memset(&zl3vni
->local_vtep_ip
, 0, sizeof(struct in_addr
));
10702 zl3vni
->vxlan_if
= NULL
;
10705 /* process if-del for l2-vni*/
10706 if (IS_ZEBRA_DEBUG_VXLAN
)
10707 zlog_debug("Del L2-VNI %u intf %s(%u)", vni
, ifp
->name
,
10710 /* Locate hash entry; it is expected to exist. */
10711 zevpn
= zevpn_lookup(vni
);
10714 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
10715 ifp
->name
, ifp
->ifindex
, vni
);
10719 /* remove from l3-vni list */
10720 zl3vni
= zl3vni_from_vrf(zevpn
->vrf_id
);
10722 listnode_delete(zl3vni
->l2vnis
, zevpn
);
10723 /* Delete VNI from BGP. */
10724 zevpn_send_del_to_client(zevpn
);
10726 /* Free up all neighbors and MAC, if any. */
10727 zevpn_neigh_del_all(zevpn
, 0, 0, DEL_ALL_NEIGH
);
10728 zevpn_mac_del_all(zevpn
, 0, 0, DEL_ALL_MAC
);
10730 /* Free up all remote VTEPs, if any. */
10731 zevpn_vtep_del_all(zevpn
, 0);
10733 /* Delete the hash entry. */
10734 if (zevpn_del(zevpn
)) {
10735 flog_err(EC_ZEBRA_VNI_DEL_FAILED
,
10736 "Failed to del EVPN hash %p, IF %s(%u) VNI %u",
10737 zevpn
, ifp
->name
, ifp
->ifindex
, zevpn
->vni
);
10745 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
10747 int zebra_vxlan_if_update(struct interface
*ifp
, uint16_t chgflags
)
10750 struct zebra_if
*zif
= NULL
;
10751 struct zebra_l2info_vxlan
*vxl
= NULL
;
10752 zebra_evpn_t
*zevpn
= NULL
;
10753 zebra_l3vni_t
*zl3vni
= NULL
;
10755 /* Check if EVPN is enabled. */
10756 if (!is_evpn_enabled())
10761 vxl
= &zif
->l2info
.vxl
;
10764 zl3vni
= zl3vni_lookup(vni
);
10767 if (IS_ZEBRA_DEBUG_VXLAN
)
10769 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
10770 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
10771 inet_ntoa(vxl
->vtep_ip
),
10772 zif
->brslave_info
.bridge_ifindex
, chgflags
);
10774 /* Removed from bridge? Cleanup and return */
10775 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
10776 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
10777 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10781 /* access-vlan change - process oper down, associate with new
10782 * svi_if and then process oper up again
10784 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
10785 if (if_is_operative(ifp
)) {
10786 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10787 zl3vni
->svi_if
= NULL
;
10788 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
10789 zl3vni
->mac_vlan_if
=
10790 zl3vni_map_to_mac_vlan_if(zl3vni
);
10791 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
10792 if (is_l3vni_oper_up(zl3vni
))
10793 zebra_vxlan_process_l3vni_oper_up(
10799 * local-ip change - process oper down, associate with new
10800 * local-ip and then process oper up again
10802 if (chgflags
& ZEBRA_VXLIF_LOCAL_IP_CHANGE
) {
10803 if (if_is_operative(ifp
)) {
10804 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
10805 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
10806 if (is_l3vni_oper_up(zl3vni
))
10807 zebra_vxlan_process_l3vni_oper_up(
10812 /* Update local tunnel IP. */
10813 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
10815 /* if we have a valid new master, process l3-vni oper up */
10816 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
) {
10817 if (if_is_operative(ifp
) && is_l3vni_oper_up(zl3vni
))
10818 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10822 /* Update VNI hash. */
10823 zevpn
= zevpn_lookup(vni
);
10826 "Failed to find EVPN hash on update, IF %s(%u) VNI %u",
10827 ifp
->name
, ifp
->ifindex
, vni
);
10831 if (IS_ZEBRA_DEBUG_VXLAN
)
10833 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
10834 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
10835 inet_ntoa(vxl
->vtep_ip
),
10836 zif
->brslave_info
.bridge_ifindex
, chgflags
);
10838 /* Removed from bridge? Cleanup and return */
10839 if ((chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
10840 && (zif
->brslave_info
.bridge_ifindex
== IFINDEX_INTERNAL
)) {
10841 /* Delete from client, remove all remote VTEPs */
10842 /* Also, free up all MACs and neighbors. */
10843 zevpn_send_del_to_client(zevpn
);
10844 zevpn_neigh_del_all(zevpn
, 1, 0, DEL_ALL_NEIGH
);
10845 zevpn_mac_del_all(zevpn
, 1, 0, DEL_ALL_MAC
);
10846 zevpn_vtep_del_all(zevpn
, 1);
10850 /* Handle other changes. */
10851 if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
10852 /* Remove all existing local neigh and MACs for this VNI
10853 * (including from BGP)
10855 zevpn_neigh_del_all(zevpn
, 0, 1, DEL_LOCAL_MAC
);
10856 zevpn_mac_del_all(zevpn
, 0, 1, DEL_LOCAL_MAC
);
10859 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
10860 zevpn
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
10861 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
10863 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
10864 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
10865 zevpn
->mcast_grp
= vxl
->mcast_grp
;
10866 /* on local vtep-ip check if ES orig-ip
10867 * needs to be updated
10869 zebra_evpn_es_set_base_evpn(zevpn
);
10871 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
10872 /* Take further actions needed.
10873 * Note that if we are here, there is a change of interest.
10875 /* If down or not mapped to a bridge, we're done. */
10876 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
10879 /* Inform BGP, if there is a change of interest. */
10881 & (ZEBRA_VXLIF_MASTER_CHANGE
|
10882 ZEBRA_VXLIF_LOCAL_IP_CHANGE
|
10883 ZEBRA_VXLIF_MCAST_GRP_CHANGE
))
10884 zevpn_send_add_to_client(zevpn
);
10886 /* If there is a valid new master or a VLAN mapping change,
10887 * read and populate local MACs and neighbors.
10888 * Also, reinstall any remote MACs and neighbors
10889 * for this VNI (based on new VLAN).
10891 if (chgflags
& ZEBRA_VXLIF_MASTER_CHANGE
)
10892 zevpn_read_mac_neigh(zevpn
, ifp
);
10893 else if (chgflags
& ZEBRA_VXLIF_VLAN_CHANGE
) {
10894 struct mac_walk_ctx m_wctx
;
10895 struct neigh_walk_ctx n_wctx
;
10897 zevpn_read_mac_neigh(zevpn
, ifp
);
10899 memset(&m_wctx
, 0, sizeof(struct mac_walk_ctx
));
10900 m_wctx
.zevpn
= zevpn
;
10901 hash_iterate(zevpn
->mac_table
, zevpn_install_mac_hash
,
10904 memset(&n_wctx
, 0, sizeof(struct neigh_walk_ctx
));
10905 n_wctx
.zevpn
= zevpn
;
10906 hash_iterate(zevpn
->neigh_table
, zevpn_install_neigh_hash
,
10915 * Handle VxLAN interface add.
10917 int zebra_vxlan_if_add(struct interface
*ifp
)
10920 struct zebra_if
*zif
= NULL
;
10921 struct zebra_l2info_vxlan
*vxl
= NULL
;
10922 zebra_evpn_t
*zevpn
= NULL
;
10923 zebra_l3vni_t
*zl3vni
= NULL
;
10925 /* Check if EVPN is enabled. */
10926 if (!is_evpn_enabled())
10931 vxl
= &zif
->l2info
.vxl
;
10934 zl3vni
= zl3vni_lookup(vni
);
10937 /* process if-add for l3-vni*/
10938 if (IS_ZEBRA_DEBUG_VXLAN
)
10940 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
10941 vni
, ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
10942 inet_ntoa(vxl
->vtep_ip
),
10943 zif
->brslave_info
.bridge_ifindex
);
10945 /* associate with vxlan_if */
10946 zl3vni
->local_vtep_ip
= vxl
->vtep_ip
;
10947 zl3vni
->vxlan_if
= ifp
;
10949 /* Associate with SVI, if any. We can associate with svi-if only
10950 * after association with vxlan_if is complete */
10951 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
10953 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
10955 if (is_l3vni_oper_up(zl3vni
))
10956 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
10959 /* process if-add for l2-vni */
10960 struct interface
*vlan_if
= NULL
;
10962 /* Create or update EVPN hash. */
10963 zevpn
= zevpn_lookup(vni
);
10965 zevpn
= zevpn_add(vni
);
10968 EC_ZEBRA_VNI_ADD_FAILED
,
10969 "Failed to add EVPN hash, IF %s(%u) VNI %u",
10970 ifp
->name
, ifp
->ifindex
, vni
);
10975 if (zevpn
->local_vtep_ip
.s_addr
!= vxl
->vtep_ip
.s_addr
||
10976 zevpn
->mcast_grp
.s_addr
!= vxl
->mcast_grp
.s_addr
) {
10977 zebra_vxlan_sg_deref(zevpn
->local_vtep_ip
,
10979 zebra_vxlan_sg_ref(vxl
->vtep_ip
, vxl
->mcast_grp
);
10980 zevpn
->local_vtep_ip
= vxl
->vtep_ip
;
10981 zevpn
->mcast_grp
= vxl
->mcast_grp
;
10982 /* on local vtep-ip check if ES orig-ip
10983 * needs to be updated
10985 zebra_evpn_es_set_base_evpn(zevpn
);
10987 zevpn_vxlan_if_set(zevpn
, ifp
, true /* set */);
10988 vlan_if
= zevpn_map_to_svi(vxl
->access_vlan
,
10989 zif
->brslave_info
.br_if
);
10991 zevpn
->vrf_id
= vlan_if
->vrf_id
;
10992 zl3vni
= zl3vni_from_vrf(vlan_if
->vrf_id
);
10994 listnode_add_sort(zl3vni
->l2vnis
, zevpn
);
10997 if (IS_ZEBRA_DEBUG_VXLAN
) {
10998 char addr_buf1
[INET_ADDRSTRLEN
];
10999 char addr_buf2
[INET_ADDRSTRLEN
];
11001 inet_ntop(AF_INET
, &vxl
->vtep_ip
,
11002 addr_buf1
, INET_ADDRSTRLEN
);
11003 inet_ntop(AF_INET
, &vxl
->mcast_grp
,
11004 addr_buf2
, INET_ADDRSTRLEN
);
11007 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s mcast_grp %s master %u",
11009 vlan_if
? vrf_id_to_name(vlan_if
->vrf_id
)
11010 : VRF_DEFAULT_NAME
,
11011 ifp
->name
, ifp
->ifindex
, vxl
->access_vlan
,
11012 addr_buf1
, addr_buf2
,
11013 zif
->brslave_info
.bridge_ifindex
);
11016 /* If down or not mapped to a bridge, we're done. */
11017 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
11021 zevpn_send_add_to_client(zevpn
);
11023 /* Read and populate local MACs and neighbors */
11024 zevpn_read_mac_neigh(zevpn
, ifp
);
11030 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf
*zvrf
, vni_t vni
,
11031 char *err
, int err_str_sz
, int filter
,
11034 zebra_l3vni_t
*zl3vni
= NULL
;
11035 struct zebra_vrf
*zvrf_evpn
= NULL
;
11037 zvrf_evpn
= zebra_vrf_get_evpn();
11041 if (IS_ZEBRA_DEBUG_VXLAN
)
11042 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf
), vni
,
11043 add
? "ADD" : "DEL");
11047 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
11049 /* check if the vni is already present under zvrf */
11051 snprintf(err
, err_str_sz
,
11052 "VNI is already configured under the vrf");
11056 /* check if this VNI is already present in the system */
11057 zl3vni
= zl3vni_lookup(vni
);
11059 snprintf(err
, err_str_sz
,
11060 "VNI is already configured as L3-VNI");
11064 /* add the L3-VNI to the global table */
11065 zl3vni
= zl3vni_add(vni
, zvrf_id(zvrf
));
11067 snprintf(err
, err_str_sz
, "Could not add L3-VNI");
11071 /* associate the vrf with vni */
11074 /* set the filter in l3vni to denote if we are using l3vni only
11075 * for prefix routes
11078 SET_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
);
11080 /* associate with vxlan-intf;
11081 * we need to associate with the vxlan-intf first
11083 zl3vni
->vxlan_if
= zl3vni_map_to_vxlan_if(zl3vni
);
11085 /* associate with corresponding SVI interface, we can associate
11086 * with svi-if only after vxlan interface association is
11089 zl3vni
->svi_if
= zl3vni_map_to_svi_if(zl3vni
);
11091 zl3vni
->mac_vlan_if
= zl3vni_map_to_mac_vlan_if(zl3vni
);
11093 if (IS_ZEBRA_DEBUG_VXLAN
)
11095 "%s: l3vni %u svi_if %s mac_vlan_if %s",
11097 zl3vni
->svi_if
? zl3vni
->svi_if
->name
: "NIL",
11098 zl3vni
->mac_vlan_if
? zl3vni
->mac_vlan_if
->name
11101 /* formulate l2vni list */
11102 hash_iterate(zvrf_evpn
->evpn_table
, zevpn_add_to_l3vni_list
,
11105 if (is_l3vni_oper_up(zl3vni
))
11106 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
11109 zl3vni
= zl3vni_lookup(vni
);
11111 snprintf(err
, err_str_sz
, "VNI doesn't exist");
11115 if (zvrf
->l3vni
!= vni
) {
11116 snprintf(err
, err_str_sz
,
11117 "VNI %d doesn't exist in VRF: %s",
11118 vni
, zvrf
->vrf
->name
);
11122 if (filter
&& !CHECK_FLAG(zl3vni
->filter
, PREFIX_ROUTES_ONLY
)) {
11123 snprintf(err
, ERR_STR_SZ
,
11124 "prefix-routes-only is not set for the vni");
11128 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
11130 /* delete and uninstall all rmacs */
11131 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
11134 /* delete and uninstall all next-hops */
11135 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
11139 zl3vni_del(zl3vni
);
11141 zebra_vxlan_handle_vni_transition(zvrf
, vni
, add
);
11146 int zebra_vxlan_vrf_enable(struct zebra_vrf
*zvrf
)
11148 zebra_l3vni_t
*zl3vni
= NULL
;
11151 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
11155 zl3vni
->vrf_id
= zvrf_id(zvrf
);
11156 if (is_l3vni_oper_up(zl3vni
))
11157 zebra_vxlan_process_l3vni_oper_up(zl3vni
);
11161 int zebra_vxlan_vrf_disable(struct zebra_vrf
*zvrf
)
11163 zebra_l3vni_t
*zl3vni
= NULL
;
11166 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
11170 zebra_vxlan_process_l3vni_oper_down(zl3vni
);
11172 /* delete and uninstall all rmacs */
11173 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
, zl3vni
);
11174 /* delete and uninstall all next-hops */
11175 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
, zl3vni
);
11177 zl3vni
->vrf_id
= VRF_UNKNOWN
;
11182 int zebra_vxlan_vrf_delete(struct zebra_vrf
*zvrf
)
11184 zebra_l3vni_t
*zl3vni
= NULL
;
11188 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
11193 zl3vni_del(zl3vni
);
11194 zebra_vxlan_handle_vni_transition(zvrf
, vni
, 0);
11200 * Handle message from client to specify the flooding mechanism for
11201 * BUM packets. The default is to do head-end (ingress) replication
11202 * and the other supported option is to disable it. This applies to
11203 * all BUM traffic and disabling it applies to both the transmit and
11204 * receive direction.
11206 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS
)
11209 enum vxlan_flood_control flood_ctrl
;
11211 if (!EVPN_ENABLED(zvrf
)) {
11212 zlog_err("EVPN flood control for non-EVPN VRF %u",
11218 STREAM_GETC(s
, flood_ctrl
);
11220 if (IS_ZEBRA_DEBUG_VXLAN
)
11221 zlog_debug("EVPN flood control %u, currently %u",
11222 flood_ctrl
, zvrf
->vxlan_flood_ctrl
);
11224 if (zvrf
->vxlan_flood_ctrl
== flood_ctrl
)
11227 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
11229 /* Install or uninstall flood entries corresponding to
11232 hash_iterate(zvrf
->evpn_table
, zevpn_handle_flooding_remote_vteps
,
11240 * Handle message from client to enable/disable advertisement of svi macip
11243 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS
)
11248 zebra_evpn_t
*zevpn
= NULL
;
11249 struct interface
*ifp
= NULL
;
11251 if (!EVPN_ENABLED(zvrf
)) {
11252 zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
11258 STREAM_GETC(s
, advertise
);
11259 STREAM_GETL(s
, vni
);
11262 if (IS_ZEBRA_DEBUG_VXLAN
)
11263 zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
11264 advertise
? "enabled" : "disabled",
11265 advertise_svi_macip_enabled(NULL
)
11269 if (zvrf
->advertise_svi_macip
== advertise
)
11274 zvrf
->advertise_svi_macip
= advertise
;
11275 hash_iterate(zvrf
->evpn_table
,
11276 zevpn_gw_macip_add_for_evpn_hash
, NULL
);
11278 hash_iterate(zvrf
->evpn_table
,
11279 zevpn_svi_macip_del_for_evpn_hash
, NULL
);
11280 zvrf
->advertise_svi_macip
= advertise
;
11284 struct zebra_if
*zif
= NULL
;
11285 struct zebra_l2info_vxlan zl2_info
;
11286 struct interface
*vlan_if
= NULL
;
11288 zevpn
= zevpn_lookup(vni
);
11292 if (IS_ZEBRA_DEBUG_VXLAN
)
11294 "EVPN SVI macip Adv %s on VNI %d , currently %s",
11295 advertise
? "enabled" : "disabled", vni
,
11296 advertise_svi_macip_enabled(zevpn
)
11300 if (zevpn
->advertise_svi_macip
== advertise
)
11303 /* Store flag even though SVI is not present.
11304 * Once SVI comes up triggers self MAC-IP route add.
11306 zevpn
->advertise_svi_macip
= advertise
;
11308 ifp
= zevpn
->vxlan_if
;
11314 /* If down or not mapped to a bridge, we're done. */
11315 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
11318 zl2_info
= zif
->l2info
.vxl
;
11319 vlan_if
= zevpn_map_to_svi(zl2_info
.access_vlan
,
11320 zif
->brslave_info
.br_if
);
11325 /* Add primary SVI MAC-IP */
11326 zevpn_add_macip_for_intf(vlan_if
, zevpn
);
11328 /* Del primary SVI MAC-IP */
11329 zevpn_del_macip_for_intf(vlan_if
, zevpn
);
11338 * Handle message from client to enable/disable advertisement of g/w macip
11341 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS
)
11346 zebra_evpn_t
*zevpn
= NULL
;
11347 struct interface
*ifp
= NULL
;
11348 struct zebra_if
*zif
= NULL
;
11349 struct zebra_l2info_vxlan zl2_info
;
11350 struct interface
*vlan_if
= NULL
;
11352 if (!EVPN_ENABLED(zvrf
)) {
11353 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
11359 STREAM_GETC(s
, advertise
);
11360 STREAM_GET(&vni
, s
, 3);
11362 zevpn
= zevpn_lookup(vni
);
11366 if (zevpn
->advertise_subnet
== advertise
)
11369 if (IS_ZEBRA_DEBUG_VXLAN
)
11370 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
11371 advertise
? "enabled" : "disabled", vni
,
11372 zevpn
->advertise_subnet
? "enabled" : "disabled");
11375 zevpn
->advertise_subnet
= advertise
;
11377 ifp
= zevpn
->vxlan_if
;
11383 /* If down or not mapped to a bridge, we're done. */
11384 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
11387 zl2_info
= zif
->l2info
.vxl
;
11390 zevpn_map_to_svi(zl2_info
.access_vlan
, zif
->brslave_info
.br_if
);
11394 if (zevpn
->advertise_subnet
)
11395 zevpn_advertise_subnet(zevpn
, vlan_if
, 1);
11397 zevpn_advertise_subnet(zevpn
, vlan_if
, 0);
11404 * Handle message from client to enable/disable advertisement of g/w macip
11407 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS
)
11412 zebra_evpn_t
*zevpn
= NULL
;
11413 struct interface
*ifp
= NULL
;
11415 if (!EVPN_ENABLED(zvrf
)) {
11416 zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
11422 STREAM_GETC(s
, advertise
);
11423 STREAM_GETL(s
, vni
);
11426 if (IS_ZEBRA_DEBUG_VXLAN
)
11427 zlog_debug("EVPN gateway macip Adv %s, currently %s",
11428 advertise
? "enabled" : "disabled",
11429 advertise_gw_macip_enabled(NULL
)
11433 if (zvrf
->advertise_gw_macip
== advertise
)
11436 zvrf
->advertise_gw_macip
= advertise
;
11438 if (advertise_gw_macip_enabled(zevpn
))
11439 hash_iterate(zvrf
->evpn_table
,
11440 zevpn_gw_macip_add_for_evpn_hash
, NULL
);
11442 hash_iterate(zvrf
->evpn_table
,
11443 zevpn_gw_macip_del_for_evpn_hash
, NULL
);
11446 struct zebra_if
*zif
= NULL
;
11447 struct zebra_l2info_vxlan zl2_info
;
11448 struct interface
*vlan_if
= NULL
;
11449 struct interface
*vrr_if
= NULL
;
11451 zevpn
= zevpn_lookup(vni
);
11455 if (IS_ZEBRA_DEBUG_VXLAN
)
11457 "EVPN gateway macip Adv %s on VNI %d , currently %s",
11458 advertise
? "enabled" : "disabled", vni
,
11459 advertise_gw_macip_enabled(zevpn
) ? "enabled"
11462 if (zevpn
->advertise_gw_macip
== advertise
)
11465 zevpn
->advertise_gw_macip
= advertise
;
11467 ifp
= zevpn
->vxlan_if
;
11473 /* If down or not mapped to a bridge, we're done. */
11474 if (!if_is_operative(ifp
) || !zif
->brslave_info
.br_if
)
11477 zl2_info
= zif
->l2info
.vxl
;
11479 vlan_if
= zevpn_map_to_svi(zl2_info
.access_vlan
,
11480 zif
->brslave_info
.br_if
);
11484 if (advertise_gw_macip_enabled(zevpn
)) {
11485 /* Add primary SVI MAC-IP */
11486 zevpn_add_macip_for_intf(vlan_if
, zevpn
);
11488 /* Add VRR MAC-IP - if any*/
11489 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
11491 zevpn_add_macip_for_intf(vrr_if
, zevpn
);
11493 /* Del primary MAC-IP */
11494 zevpn_del_macip_for_intf(vlan_if
, zevpn
);
11496 /* Del VRR MAC-IP - if any*/
11497 vrr_if
= zebra_get_vrr_intf_for_svi(vlan_if
);
11499 zevpn_del_macip_for_intf(vrr_if
, zevpn
);
11509 * Handle message from client to learn (or stop learning) about VNIs and MACs.
11510 * When enabled, the VNI hash table will be built and MAC FDB table read;
11511 * when disabled, the entries should be deleted and remote VTEPs and MACs
11512 * uninstalled from the kernel.
11513 * This also informs the setting for BUM handling at the time this change
11514 * occurs; it is relevant only when specifying "learn".
11516 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS
)
11518 struct stream
*s
= NULL
;
11520 enum vxlan_flood_control flood_ctrl
;
11522 /* Mismatch between EVPN VRF and current VRF (should be prevented by
11524 if (is_evpn_enabled() && !EVPN_ENABLED(zvrf
))
11528 STREAM_GETC(s
, advertise
);
11529 STREAM_GETC(s
, flood_ctrl
);
11531 if (IS_ZEBRA_DEBUG_VXLAN
)
11532 zlog_debug("EVPN VRF %s(%u) VNI Adv %s, currently %s, flood control %u",
11533 zvrf_name(zvrf
), zvrf_id(zvrf
),
11534 advertise
? "enabled" : "disabled",
11535 is_evpn_enabled() ? "enabled" : "disabled",
11538 if (zvrf
->advertise_all_vni
== advertise
)
11541 zvrf
->advertise_all_vni
= advertise
;
11542 if (EVPN_ENABLED(zvrf
)) {
11543 zrouter
.evpn_vrf
= zvrf
;
11545 /* Note BUM handling */
11546 zvrf
->vxlan_flood_ctrl
= flood_ctrl
;
11548 /* Replay all ESs */
11549 zebra_evpn_es_send_all_to_client(true /* add */);
11551 /* Build EVPN hash table and inform BGP. */
11552 zevpn_build_hash_table();
11554 /* Add all SVI (L3 GW) MACs to BGP*/
11555 hash_iterate(zvrf
->evpn_table
, zevpn_gw_macip_add_for_evpn_hash
,
11558 /* Read the MAC FDB */
11559 macfdb_read(zvrf
->zns
);
11561 /* Read neighbors */
11562 neigh_read(zvrf
->zns
);
11564 /* Cleanup VTEPs for all EVPNs - uninstall from
11565 * kernel and free entries.
11567 hash_iterate(zvrf
->evpn_table
, zevpn_cleanup_all
, zvrf
);
11569 /* Delete all ESs in BGP */
11570 zebra_evpn_es_send_all_to_client(false /* add */);
11572 /* cleanup all l3vnis */
11573 hash_iterate(zrouter
.l3vni_table
, zl3vni_cleanup_all
, NULL
);
11575 /* Mark as "no EVPN VRF" */
11576 zrouter
.evpn_vrf
= NULL
;
11584 * Allocate EVPN hash table for this VRF and do other initialization.
11585 * NOTE: Currently supported only for default VRF.
11587 void zebra_vxlan_init_tables(struct zebra_vrf
*zvrf
)
11591 zvrf
->evpn_table
= hash_create(evpn_hash_keymake
, vni_hash_cmp
,
11592 "Zebra VRF EVPN Table");
11593 zvrf
->vxlan_sg_table
= hash_create(zebra_vxlan_sg_hash_key_make
,
11594 zebra_vxlan_sg_hash_eq
, "Zebra VxLAN SG Table");
11597 /* Cleanup EVPN info, but don't free the table. */
11598 void zebra_vxlan_cleanup_tables(struct zebra_vrf
*zvrf
)
11600 struct zebra_vrf
*evpn_zvrf
= zebra_vrf_get_evpn();
11604 hash_iterate(zvrf
->evpn_table
, zevpn_cleanup_all
, zvrf
);
11605 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_cleanup
, NULL
);
11607 if (zvrf
== evpn_zvrf
)
11608 zebra_evpn_es_cleanup();
11611 /* Close all EVPN handling */
11612 void zebra_vxlan_close_tables(struct zebra_vrf
*zvrf
)
11616 hash_iterate(zvrf
->evpn_table
, zevpn_cleanup_all
, zvrf
);
11617 hash_free(zvrf
->evpn_table
);
11620 /* init the l3vni table */
11621 void zebra_vxlan_init(void)
11623 zrouter
.l3vni_table
= hash_create(l3vni_hash_keymake
, l3vni_hash_cmp
,
11624 "Zebra VRF L3 VNI table");
11625 zrouter
.evpn_vrf
= NULL
;
11626 zebra_evpn_mh_init();
11629 /* free l3vni table */
11630 void zebra_vxlan_disable(void)
11632 hash_free(zrouter
.l3vni_table
);
11633 zebra_evpn_mh_terminate();
11636 /* get the l3vni svi ifindex */
11637 ifindex_t
get_l3vni_svi_ifindex(vrf_id_t vrf_id
)
11639 zebra_l3vni_t
*zl3vni
= NULL
;
11641 zl3vni
= zl3vni_from_vrf(vrf_id
);
11642 if (!zl3vni
|| !is_l3vni_oper_up(zl3vni
))
11645 return zl3vni
->svi_if
->ifindex
;
11648 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread
*t
)
11650 struct zebra_vrf
*zvrf
= NULL
;
11651 zebra_neigh_t
*nbr
= NULL
;
11652 zebra_evpn_t
*zevpn
= NULL
;
11653 char buf1
[INET6_ADDRSTRLEN
];
11654 char buf2
[ETHER_ADDR_STRLEN
];
11656 nbr
= THREAD_ARG(t
);
11658 /* since this is asynchronous we need sanity checks*/
11659 zvrf
= vrf_info_lookup(nbr
->zevpn
->vrf_id
);
11663 zevpn
= zevpn_lookup(nbr
->zevpn
->vni
);
11667 nbr
= zevpn_neigh_lookup(zevpn
, &nbr
->ip
);
11671 if (IS_ZEBRA_DEBUG_VXLAN
)
11673 "%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
11675 prefix_mac2str(&nbr
->emac
, buf2
, sizeof(buf2
)),
11676 ipaddr2str(&nbr
->ip
, buf1
, sizeof(buf1
)), nbr
->flags
,
11677 nbr
->dad_count
, zevpn
->vni
);
11679 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
11680 nbr
->dad_count
= 0;
11681 nbr
->detect_start_time
.tv_sec
= 0;
11682 nbr
->detect_start_time
.tv_usec
= 0;
11683 nbr
->dad_dup_detect_time
= 0;
11684 nbr
->dad_ip_auto_recovery_timer
= NULL
;
11685 ZEBRA_NEIGH_SET_ACTIVE(nbr
);
11688 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
)) {
11689 zevpn_neigh_send_add_to_client(zevpn
->vni
, &nbr
->ip
, &nbr
->emac
,
11690 nbr
->mac
, nbr
->flags
, nbr
->loc_seq
);
11691 } else if (!!CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
)) {
11692 zevpn_rem_neigh_install(zevpn
, nbr
, false /*was_static*/);
11698 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread
*t
)
11700 struct zebra_vrf
*zvrf
= NULL
;
11701 zebra_mac_t
*mac
= NULL
;
11702 zebra_evpn_t
*zevpn
= NULL
;
11703 struct listnode
*node
= NULL
;
11704 zebra_neigh_t
*nbr
= NULL
;
11705 char buf
[ETHER_ADDR_STRLEN
];
11707 mac
= THREAD_ARG(t
);
11709 /* since this is asynchronous we need sanity checks*/
11710 zvrf
= vrf_info_lookup(mac
->zevpn
->vrf_id
);
11714 zevpn
= zevpn_lookup(mac
->zevpn
->vni
);
11718 mac
= zevpn_mac_lookup(zevpn
, &mac
->macaddr
);
11722 if (IS_ZEBRA_DEBUG_VXLAN
)
11724 "%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
11726 prefix_mac2str(&mac
->macaddr
, buf
, sizeof(buf
)),
11727 mac
->flags
, mac
->dad_count
, listcount(mac
->neigh_list
));
11729 /* Remove all IPs as duplicate associcated with this MAC */
11730 for (ALL_LIST_ELEMENTS_RO(mac
->neigh_list
, node
, nbr
)) {
11731 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
)) {
11732 if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_LOCAL
))
11733 ZEBRA_NEIGH_SET_INACTIVE(nbr
);
11734 else if (CHECK_FLAG(nbr
->flags
, ZEBRA_NEIGH_REMOTE
))
11735 zevpn_rem_neigh_install(zevpn
, nbr
,
11736 false /*was_static*/);
11739 UNSET_FLAG(nbr
->flags
, ZEBRA_NEIGH_DUPLICATE
);
11740 nbr
->dad_count
= 0;
11741 nbr
->detect_start_time
.tv_sec
= 0;
11742 nbr
->dad_dup_detect_time
= 0;
11745 UNSET_FLAG(mac
->flags
, ZEBRA_MAC_DUPLICATE
);
11746 mac
->dad_count
= 0;
11747 mac
->detect_start_time
.tv_sec
= 0;
11748 mac
->detect_start_time
.tv_usec
= 0;
11749 mac
->dad_dup_detect_time
= 0;
11750 mac
->dad_mac_auto_recovery_timer
= NULL
;
11752 if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_LOCAL
)) {
11753 /* Inform to BGP */
11754 if (zevpn_mac_send_add_to_client(zevpn
->vni
, &mac
->macaddr
,
11755 mac
->flags
, mac
->loc_seq
, mac
->es
))
11758 /* Process all neighbors associated with this MAC. */
11759 zevpn_process_neigh_on_local_mac_change(zevpn
, mac
, 0,
11762 } else if (CHECK_FLAG(mac
->flags
, ZEBRA_MAC_REMOTE
)) {
11763 zevpn_process_neigh_on_remote_mac_add(zevpn
, mac
);
11765 /* Install the entry. */
11766 zevpn_rem_mac_install(zevpn
, mac
, false /* was_static */);
11772 /************************** vxlan SG cache management ************************/
11773 /* Inform PIM about the mcast group */
11774 static int zebra_vxlan_sg_send(struct zebra_vrf
*zvrf
,
11775 struct prefix_sg
*sg
,
11776 char *sg_str
, uint16_t cmd
)
11778 struct zserv
*client
= NULL
;
11779 struct stream
*s
= NULL
;
11781 client
= zserv_find_client(ZEBRA_ROUTE_PIM
, 0);
11785 if (!CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
))
11788 s
= stream_new(ZEBRA_MAX_PACKET_SIZ
);
11790 zclient_create_header(s
, cmd
, VRF_DEFAULT
);
11791 stream_putl(s
, IPV4_MAX_BYTELEN
);
11792 stream_put(s
, &sg
->src
.s_addr
, IPV4_MAX_BYTELEN
);
11793 stream_put(s
, &sg
->grp
.s_addr
, IPV4_MAX_BYTELEN
);
11795 /* Write packet size. */
11796 stream_putw_at(s
, 0, stream_get_endp(s
));
11798 if (IS_ZEBRA_DEBUG_VXLAN
)
11800 "Send %s %s to %s",
11801 (cmd
== ZEBRA_VXLAN_SG_ADD
) ? "add" : "del", sg_str
,
11802 zebra_route_string(client
->proto
));
11804 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
11805 client
->vxlan_sg_add_cnt
++;
11807 client
->vxlan_sg_del_cnt
++;
11809 return zserv_send_message(client
, s
);
11812 static unsigned int zebra_vxlan_sg_hash_key_make(const void *p
)
11814 const zebra_vxlan_sg_t
*vxlan_sg
= p
;
11816 return (jhash_2words(vxlan_sg
->sg
.src
.s_addr
,
11817 vxlan_sg
->sg
.grp
.s_addr
, 0));
11820 static bool zebra_vxlan_sg_hash_eq(const void *p1
, const void *p2
)
11822 const zebra_vxlan_sg_t
*sg1
= p1
;
11823 const zebra_vxlan_sg_t
*sg2
= p2
;
11825 return ((sg1
->sg
.src
.s_addr
== sg2
->sg
.src
.s_addr
)
11826 && (sg1
->sg
.grp
.s_addr
== sg2
->sg
.grp
.s_addr
));
11829 static zebra_vxlan_sg_t
*zebra_vxlan_sg_new(struct zebra_vrf
*zvrf
,
11830 struct prefix_sg
*sg
)
11832 zebra_vxlan_sg_t
*vxlan_sg
;
11834 vxlan_sg
= XCALLOC(MTYPE_ZVXLAN_SG
, sizeof(*vxlan_sg
));
11836 vxlan_sg
->zvrf
= zvrf
;
11837 vxlan_sg
->sg
= *sg
;
11838 prefix_sg2str(sg
, vxlan_sg
->sg_str
);
11840 vxlan_sg
= hash_get(zvrf
->vxlan_sg_table
, vxlan_sg
, hash_alloc_intern
);
11842 if (IS_ZEBRA_DEBUG_VXLAN
)
11843 zlog_debug("vxlan SG %s created", vxlan_sg
->sg_str
);
11848 static zebra_vxlan_sg_t
*zebra_vxlan_sg_find(struct zebra_vrf
*zvrf
,
11849 struct prefix_sg
*sg
)
11851 zebra_vxlan_sg_t lookup
;
11854 return hash_lookup(zvrf
->vxlan_sg_table
, &lookup
);
11857 static zebra_vxlan_sg_t
*zebra_vxlan_sg_add(struct zebra_vrf
*zvrf
,
11858 struct prefix_sg
*sg
)
11860 zebra_vxlan_sg_t
*vxlan_sg
;
11861 zebra_vxlan_sg_t
*parent
= NULL
;
11862 struct in_addr sip
;
11864 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, sg
);
11868 /* create a *G entry for every BUM group implicitly -
11869 * 1. The SG entry is used by pimd to setup the vxlan-origination-mroute
11870 * 2. the XG entry is used by pimd to setup the
11871 * vxlan-termination-mroute
11873 if (sg
->src
.s_addr
!= INADDR_ANY
) {
11874 memset(&sip
, 0, sizeof(sip
));
11875 parent
= zebra_vxlan_sg_do_ref(zvrf
, sip
, sg
->grp
);
11880 vxlan_sg
= zebra_vxlan_sg_new(zvrf
, sg
);
11883 zebra_vxlan_sg_do_deref(zvrf
, sip
, sg
->grp
);
11887 zebra_vxlan_sg_send(zvrf
, sg
, vxlan_sg
->sg_str
,
11888 ZEBRA_VXLAN_SG_ADD
);
11893 static void zebra_vxlan_sg_del(zebra_vxlan_sg_t
*vxlan_sg
)
11895 struct in_addr sip
;
11896 struct zebra_vrf
*zvrf
;
11898 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
11902 /* On SG entry deletion remove the reference to its parent XG
11905 if (vxlan_sg
->sg
.src
.s_addr
!= INADDR_ANY
) {
11906 memset(&sip
, 0, sizeof(sip
));
11907 zebra_vxlan_sg_do_deref(zvrf
, sip
, vxlan_sg
->sg
.grp
);
11910 zebra_vxlan_sg_send(zvrf
, &vxlan_sg
->sg
,
11911 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_DEL
);
11913 hash_release(vxlan_sg
->zvrf
->vxlan_sg_table
, vxlan_sg
);
11915 if (IS_ZEBRA_DEBUG_VXLAN
)
11916 zlog_debug("VXLAN SG %s deleted", vxlan_sg
->sg_str
);
11918 XFREE(MTYPE_ZVXLAN_SG
, vxlan_sg
);
11921 static void zebra_vxlan_sg_do_deref(struct zebra_vrf
*zvrf
,
11922 struct in_addr sip
, struct in_addr mcast_grp
)
11924 zebra_vxlan_sg_t
*vxlan_sg
;
11925 struct prefix_sg sg
;
11927 sg
.family
= AF_INET
;
11928 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
11930 sg
.grp
= mcast_grp
;
11931 vxlan_sg
= zebra_vxlan_sg_find(zvrf
, &sg
);
11935 if (vxlan_sg
->ref_cnt
)
11936 --vxlan_sg
->ref_cnt
;
11938 if (!vxlan_sg
->ref_cnt
)
11939 zebra_vxlan_sg_del(vxlan_sg
);
11942 static zebra_vxlan_sg_t
*zebra_vxlan_sg_do_ref(struct zebra_vrf
*zvrf
,
11943 struct in_addr sip
, struct in_addr mcast_grp
)
11945 zebra_vxlan_sg_t
*vxlan_sg
;
11946 struct prefix_sg sg
;
11948 sg
.family
= AF_INET
;
11949 sg
.prefixlen
= IPV4_MAX_BYTELEN
;
11951 sg
.grp
= mcast_grp
;
11952 vxlan_sg
= zebra_vxlan_sg_add(zvrf
, &sg
);
11954 ++vxlan_sg
->ref_cnt
;
11959 static void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip
,
11960 struct in_addr mcast_grp
)
11962 struct zebra_vrf
*zvrf
;
11964 if (local_vtep_ip
.s_addr
== INADDR_ANY
11965 || mcast_grp
.s_addr
== INADDR_ANY
)
11968 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
11972 zebra_vxlan_sg_do_deref(zvrf
, local_vtep_ip
, mcast_grp
);
11975 static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip
,
11976 struct in_addr mcast_grp
)
11978 struct zebra_vrf
*zvrf
;
11980 if (local_vtep_ip
.s_addr
== INADDR_ANY
11981 || mcast_grp
.s_addr
== INADDR_ANY
)
11984 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
11987 zebra_vxlan_sg_do_ref(zvrf
, local_vtep_ip
, mcast_grp
);
11990 static void zebra_vxlan_sg_cleanup(struct hash_bucket
*backet
, void *arg
)
11992 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
11994 zebra_vxlan_sg_del(vxlan_sg
);
11997 static void zebra_vxlan_sg_replay_send(struct hash_bucket
*backet
, void *arg
)
11999 zebra_vxlan_sg_t
*vxlan_sg
= (zebra_vxlan_sg_t
*)backet
->data
;
12001 zebra_vxlan_sg_send(vxlan_sg
->zvrf
, &vxlan_sg
->sg
,
12002 vxlan_sg
->sg_str
, ZEBRA_VXLAN_SG_ADD
);
12005 /* Handle message from client to replay vxlan SG entries */
12006 void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS
)
12008 if (IS_ZEBRA_DEBUG_VXLAN
)
12009 zlog_debug("VxLAN SG updates to PIM, start");
12011 SET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
12013 if (!EVPN_ENABLED(zvrf
)) {
12014 if (IS_ZEBRA_DEBUG_VXLAN
)
12015 zlog_debug("VxLAN SG replay request on unexpected vrf %d",
12016 zvrf
->vrf
->vrf_id
);
12020 hash_iterate(zvrf
->vxlan_sg_table
, zebra_vxlan_sg_replay_send
, NULL
);
12023 /************************** EVPN BGP config management ************************/
12024 /* Notify Local MACs to the clienti, skips GW MAC */
12025 static void zevpn_send_mac_hash_entry_to_client(struct hash_bucket
*bucket
,
12028 struct mac_walk_ctx
*wctx
= arg
;
12029 zebra_mac_t
*zmac
= bucket
->data
;
12031 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_DEF_GW
))
12034 if (CHECK_FLAG(zmac
->flags
, ZEBRA_MAC_LOCAL
))
12035 zevpn_mac_send_add_to_client(wctx
->zevpn
->vni
, &zmac
->macaddr
,
12036 zmac
->flags
, zmac
->loc_seq
, zmac
->es
);
12039 /* Iterator to Notify Local MACs of a EVPN */
12040 static void zevpn_send_mac_to_client(zebra_evpn_t
*zevpn
)
12042 struct mac_walk_ctx wctx
;
12044 if (!zevpn
->mac_table
)
12047 memset(&wctx
, 0, sizeof(struct mac_walk_ctx
));
12048 wctx
.zevpn
= zevpn
;
12050 hash_iterate(zevpn
->mac_table
, zevpn_send_mac_hash_entry_to_client
,
12054 /* Notify Neighbor entries to the Client, skips the GW entry */
12055 static void zevpn_send_neigh_hash_entry_to_client(struct hash_bucket
*bucket
,
12058 struct mac_walk_ctx
*wctx
= arg
;
12059 zebra_neigh_t
*zn
= bucket
->data
;
12060 zebra_mac_t
*zmac
= NULL
;
12062 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_DEF_GW
))
12065 if (CHECK_FLAG(zn
->flags
, ZEBRA_NEIGH_LOCAL
) &&
12066 IS_ZEBRA_NEIGH_ACTIVE(zn
)) {
12067 zmac
= zevpn_mac_lookup(wctx
->zevpn
, &zn
->emac
);
12071 zevpn_neigh_send_add_to_client(wctx
->zevpn
->vni
, &zn
->ip
,
12072 &zn
->emac
, zn
->mac
, zn
->flags
,
12077 /* Iterator of a specific EVPN */
12078 static void zevpn_send_neigh_to_client(zebra_evpn_t
*zevpn
)
12080 struct neigh_walk_ctx wctx
;
12082 memset(&wctx
, 0, sizeof(struct neigh_walk_ctx
));
12083 wctx
.zevpn
= zevpn
;
12085 hash_iterate(zevpn
->neigh_table
, zevpn_send_neigh_hash_entry_to_client
,
12089 static void zevpn_cfg_cleanup(struct hash_bucket
*bucket
, void *ctxt
)
12091 zebra_evpn_t
*zevpn
= NULL
;
12093 zevpn
= (zebra_evpn_t
*)bucket
->data
;
12094 zevpn
->advertise_gw_macip
= 0;
12095 zevpn
->advertise_svi_macip
= 0;
12096 zevpn
->advertise_subnet
= 0;
12098 zevpn_neigh_del_all(zevpn
, 1, 0,
12099 DEL_REMOTE_NEIGH
| DEL_REMOTE_NEIGH_FROM_VTEP
);
12100 zevpn_mac_del_all(zevpn
, 1, 0,
12101 DEL_REMOTE_MAC
| DEL_REMOTE_MAC_FROM_VTEP
);
12102 zevpn_vtep_del_all(zevpn
, 1);
12105 /* Cleanup EVPN configuration of a specific VRF */
12106 static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf
*zvrf
)
12108 zebra_l3vni_t
*zl3vni
= NULL
;
12110 zvrf
->advertise_all_vni
= 0;
12111 zvrf
->advertise_gw_macip
= 0;
12112 zvrf
->advertise_svi_macip
= 0;
12113 zvrf
->vxlan_flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
12115 hash_iterate(zvrf
->evpn_table
, zevpn_cfg_cleanup
, NULL
);
12118 zl3vni
= zl3vni_lookup(zvrf
->l3vni
);
12120 /* delete and uninstall all rmacs */
12121 hash_iterate(zl3vni
->rmac_table
, zl3vni_del_rmac_hash_entry
,
12123 /* delete and uninstall all next-hops */
12124 hash_iterate(zl3vni
->nh_table
, zl3vni_del_nh_hash_entry
,
12129 /* Cleanup BGP EVPN configuration upon client disconnect */
12130 static int zebra_evpn_bgp_cfg_clean_up(struct zserv
*client
)
12133 struct zebra_vrf
*zvrf
;
12135 RB_FOREACH (vrf
, vrf_id_head
, &vrfs_by_id
) {
12138 zebra_evpn_vrf_cfg_cleanup(zvrf
);
12144 static int zebra_evpn_pim_cfg_clean_up(struct zserv
*client
)
12146 struct zebra_vrf
*zvrf
= zebra_vrf_get_evpn();
12148 if (zvrf
&& CHECK_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
)) {
12149 if (IS_ZEBRA_DEBUG_VXLAN
)
12150 zlog_debug("VxLAN SG updates to PIM, stop");
12151 UNSET_FLAG(zvrf
->flags
, ZEBRA_PIM_SEND_VXLAN_SG
);
12157 static int zebra_evpn_cfg_clean_up(struct zserv
*client
)
12159 if (client
->proto
== ZEBRA_ROUTE_BGP
)
12160 return zebra_evpn_bgp_cfg_clean_up(client
);
12162 if (client
->proto
== ZEBRA_ROUTE_PIM
)
12163 return zebra_evpn_pim_cfg_clean_up(client
);
12169 * Handle results for vxlan dataplane operations.
12171 extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx
*ctx
)
12173 /* TODO -- anything other than freeing the context? */
12174 dplane_ctx_fini(&ctx
);
12177 /* Cleanup BGP EVPN configuration upon client disconnect */
12178 extern void zebra_evpn_init(void)
12180 hook_register(zserv_client_close
, zebra_evpn_cfg_clean_up
);