]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vxlan.c
*: Rename backet to bucket
[mirror_frr.git] / zebra / zebra_vxlan.c
1 /*
2 * Zebra EVPN for VxLAN code
3 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
4 *
5 * This file is part of FRR.
6 *
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
10 * later version.
11 *
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.
16 *
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
20 * 02111-1307, USA.
21 */
22
23 #include <zebra.h>
24
25 #include "hash.h"
26 #include "if.h"
27 #include "jhash.h"
28 #include "linklist.h"
29 #include "log.h"
30 #include "memory.h"
31 #include "prefix.h"
32 #include "stream.h"
33 #include "table.h"
34 #include "vlan.h"
35 #include "vxlan.h"
36 #ifdef GNU_LINUX
37 #include <linux/neighbour.h>
38 #endif
39
40 #include "zebra/zebra_router.h"
41 #include "zebra/debug.h"
42 #include "zebra/interface.h"
43 #include "zebra/rib.h"
44 #include "zebra/rt.h"
45 #include "zebra/rt_netlink.h"
46 #include "zebra/zebra_errors.h"
47 #include "zebra/zebra_l2.h"
48 #include "zebra/zebra_memory.h"
49 #include "zebra/zebra_ns.h"
50 #include "zebra/zebra_vrf.h"
51 #include "zebra/zebra_vxlan.h"
52 #include "zebra/zebra_vxlan_private.h"
53 #include "zebra/zebra_router.h"
54
55 DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
56 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
57 DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
58 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
59 DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
60 DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
61
62 /* definitions */
63
64 /* static function declarations */
65 static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
66 uint16_t cmd);
67 static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
68 static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt);
69 static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt);
70 static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket,
71 void **args);
72 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
73 json_object *json);
74 static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
75 json_object *json);
76 static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json);
77 static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt);
78 static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt);
79 static void zvni_print(zebra_vni_t *zvni, void **ctxt);
80 static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]);
81
82 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
83 struct ipaddr *ip, uint8_t flags,
84 uint32_t seq, int state, uint16_t cmd);
85 static unsigned int neigh_hash_keymake(void *p);
86 static void *zvni_neigh_alloc(void *p);
87 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
88 struct ethaddr *mac);
89 static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n);
90 static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
91 struct in_addr *r_vtep_ip);
92 static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
93 uint32_t flags);
94 static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip);
95 static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
96 struct ethaddr *macaddr,
97 uint8_t flags, uint32_t seq);
98 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
99 struct ethaddr *macaddr,
100 uint8_t flags, int state);
101 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
102 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
103 static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n);
104 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
105 struct interface *br_if);
106 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if);
107
108 /* l3-vni next-hop neigh related APIs */
109 static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
110 struct ipaddr *ip);
111 static void *zl3vni_nh_alloc(void *p);
112 static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni,
113 struct ipaddr *vtep_ip,
114 struct ethaddr *rmac);
115 static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
116 static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
117 static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n);
118
119 /* l3-vni rmac related APIs */
120 static void zl3vni_print_rmac_hash(struct hash_bucket *, void *);
121 static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
122 struct ethaddr *rmac);
123 static void *zl3vni_rmac_alloc(void *p);
124 static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni,
125 struct ethaddr *rmac);
126 static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
127 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
128 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac);
129
130 /* l3-vni related APIs*/
131 static zebra_l3vni_t *zl3vni_lookup(vni_t vni);
132 static void *zl3vni_alloc(void *p);
133 static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
134 static int zl3vni_del(zebra_l3vni_t *zl3vni);
135 static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t);
136 static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
137 static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
138 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);
139 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni);
140
141 static unsigned int mac_hash_keymake(void *p);
142 static bool mac_cmp(const void *p1, const void *p2);
143 static void *zvni_mac_alloc(void *p);
144 static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr);
145 static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac);
146 static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
147 struct in_addr *r_vtep_ip);
148 static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
149 uint32_t flags);
150 static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr);
151 static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
152 uint8_t flags, uint32_t seq);
153 static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr);
154 static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
155 struct interface *br_if, vlanid_t vid);
156 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
157 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac);
158 static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt);
159
160 static unsigned int vni_hash_keymake(void *p);
161 static void *zvni_alloc(void *p);
162 static zebra_vni_t *zvni_lookup(vni_t vni);
163 static zebra_vni_t *zvni_add(vni_t vni);
164 static int zvni_del(zebra_vni_t *zvni);
165 static int zvni_send_add_to_client(zebra_vni_t *zvni);
166 static int zvni_send_del_to_client(vni_t vni);
167 static void zvni_build_hash_table(void);
168 static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
169 static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
170 static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
171 static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep);
172 static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall);
173 static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip);
174 static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip);
175 static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
176 static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni);
177 static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
178 struct ethaddr *macaddr, struct ipaddr *ip);
179 static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
180 struct ipaddr *ip);
181 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
182 static int advertise_gw_macip_enabled(zebra_vni_t *zvni);
183 static int advertise_svi_macip_enabled(zebra_vni_t *zvni);
184 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
185 zebra_mac_t *old_zmac,
186 zebra_mac_t *new_zmac,
187 zebra_neigh_t *nbr);
188 static int remote_neigh_count(zebra_mac_t *zmac);
189 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac);
190 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t);
191 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t);
192 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
193 zebra_neigh_t *nbr,
194 struct in_addr vtep_ip,
195 bool do_dad,
196 bool *is_dup_detect,
197 bool is_local);
198 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
199 zebra_mac_t *mac,
200 struct in_addr vtep_ip,
201 bool do_dad,
202 bool *is_dup_detect,
203 bool is_local);
204
205 /* Private functions */
206 static int host_rb_entry_compare(const struct host_rb_entry *hle1,
207 const struct host_rb_entry *hle2)
208 {
209 if (hle1->p.family < hle2->p.family)
210 return -1;
211
212 if (hle1->p.family > hle2->p.family)
213 return 1;
214
215 if (hle1->p.prefixlen < hle2->p.prefixlen)
216 return -1;
217
218 if (hle1->p.prefixlen > hle2->p.prefixlen)
219 return 1;
220
221 if (hle1->p.family == AF_INET) {
222 if (hle1->p.u.prefix4.s_addr < hle2->p.u.prefix4.s_addr)
223 return -1;
224
225 if (hle1->p.u.prefix4.s_addr > hle2->p.u.prefix4.s_addr)
226 return 1;
227
228 return 0;
229 } else if (hle1->p.family == AF_INET6) {
230 return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
231 IPV6_MAX_BYTELEN);
232 } else {
233 zlog_debug("%s: Unexpected family type: %d",
234 __PRETTY_FUNCTION__, hle1->p.family);
235 return 0;
236 }
237 }
238 RB_GENERATE(host_rb_tree_entry, host_rb_entry, hl_entry, host_rb_entry_compare);
239
240 static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
241 {
242 struct host_rb_entry *hle;
243 uint32_t count = 0;
244
245 RB_FOREACH (hle, host_rb_tree_entry, hrbe)
246 count++;
247
248 return count;
249 }
250
251 /*
252 * Return number of valid MACs in a VNI's MAC hash table - all
253 * remote MACs and non-internal (auto) local MACs count.
254 */
255 static uint32_t num_valid_macs(zebra_vni_t *zvni)
256 {
257 unsigned int i;
258 uint32_t num_macs = 0;
259 struct hash *hash;
260 struct hash_bucket *hb;
261 zebra_mac_t *mac;
262
263 hash = zvni->mac_table;
264 if (!hash)
265 return num_macs;
266 for (i = 0; i < hash->size; i++) {
267 for (hb = hash->index[i]; hb; hb = hb->next) {
268 mac = (zebra_mac_t *)hb->data;
269 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
270 || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
271 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
272 num_macs++;
273 }
274 }
275
276 return num_macs;
277 }
278
279 static uint32_t num_dup_detected_macs(zebra_vni_t *zvni)
280 {
281 unsigned int i;
282 uint32_t num_macs = 0;
283 struct hash *hash;
284 struct hash_bucket *hb;
285 zebra_mac_t *mac;
286
287 hash = zvni->mac_table;
288 if (!hash)
289 return num_macs;
290 for (i = 0; i < hash->size; i++) {
291 for (hb = hash->index[i]; hb; hb = hb->next) {
292 mac = (zebra_mac_t *)hb->data;
293 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
294 num_macs++;
295 }
296 }
297
298 return num_macs;
299 }
300
301 static uint32_t num_dup_detected_neighs(zebra_vni_t *zvni)
302 {
303 unsigned int i;
304 uint32_t num_neighs = 0;
305 struct hash *hash;
306 struct hash_bucket *hb;
307 zebra_neigh_t *nbr;
308
309 hash = zvni->neigh_table;
310 if (!hash)
311 return num_neighs;
312 for (i = 0; i < hash->size; i++) {
313 for (hb = hash->index[i]; hb; hb = hb->next) {
314 nbr = (zebra_neigh_t *)hb->data;
315 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
316 num_neighs++;
317 }
318 }
319
320 return num_neighs;
321 }
322
323 static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
324 {
325 struct zebra_vrf *zvrf;
326
327 zvrf = vrf_info_lookup(VRF_DEFAULT);
328 if (zvrf && zvrf->advertise_gw_macip)
329 return 1;
330
331 if (zvni && zvni->advertise_gw_macip)
332 return 1;
333
334 return 0;
335 }
336
337 static int advertise_svi_macip_enabled(zebra_vni_t *zvni)
338 {
339 struct zebra_vrf *zvrf;
340
341 zvrf = vrf_info_lookup(VRF_DEFAULT);
342 if (zvrf && zvrf->advertise_svi_macip)
343 return 1;
344
345 if (zvni && zvni->advertise_svi_macip)
346 return 1;
347
348 return 0;
349 }
350
351 /* As part Duplicate Address Detection (DAD) for IP mobility
352 * MAC binding changes, ensure to inherit duplicate flag
353 * from MAC.
354 */
355 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
356 zebra_mac_t *old_zmac,
357 zebra_mac_t *new_zmac,
358 zebra_neigh_t *nbr)
359 {
360 bool is_old_mac_dup = false;
361 bool is_new_mac_dup = false;
362
363 if (!zvrf->dup_addr_detect)
364 return 0;
365 /* Check old or new MAC is detected as duplicate
366 * mark this neigh as duplicate
367 */
368 if (old_zmac)
369 is_old_mac_dup = CHECK_FLAG(old_zmac->flags,
370 ZEBRA_MAC_DUPLICATE);
371 if (new_zmac)
372 is_new_mac_dup = CHECK_FLAG(new_zmac->flags,
373 ZEBRA_MAC_DUPLICATE);
374 /* Old and/or new MAC can be in duplicate state,
375 * based on that IP/Neigh Inherits the flag.
376 * If New MAC is marked duplicate, inherit to the IP.
377 * If old MAC is duplicate but new MAC is not, clear
378 * duplicate flag for IP and reset detection params
379 * and let IP DAD retrigger.
380 */
381 if (is_new_mac_dup && !CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
382 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
383 /* Capture Duplicate detection time */
384 nbr->dad_dup_detect_time = monotime(NULL);
385 return 1;
386 } else if (is_old_mac_dup && !is_new_mac_dup) {
387 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
388 nbr->dad_count = 0;
389 nbr->detect_start_time.tv_sec = 0;
390 nbr->detect_start_time.tv_usec = 0;
391 }
392 return 0;
393 }
394
395 static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
396 zebra_mac_t *mac,
397 struct in_addr vtep_ip,
398 bool do_dad,
399 bool *is_dup_detect,
400 bool is_local)
401 {
402 zebra_neigh_t *nbr;
403 struct listnode *node = NULL;
404 struct timeval elapsed = {0, 0};
405 char buf[ETHER_ADDR_STRLEN];
406 char buf1[INET6_ADDRSTRLEN];
407 bool reset_params = false;
408
409 if (!(zvrf->dup_addr_detect && do_dad))
410 return;
411
412 /* MAC is detected as duplicate,
413 * Local MAC event -> hold on advertising to BGP.
414 * Remote MAC event -> hold on installing it.
415 */
416 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
417 if (IS_ZEBRA_DEBUG_VXLAN)
418 zlog_debug(
419 "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
420 __PRETTY_FUNCTION__,
421 prefix_mac2str(&mac->macaddr, buf,
422 sizeof(buf)),
423 mac->flags, mac->dad_count,
424 zvrf->dad_freeze_time);
425
426 /* For duplicate MAC do not update
427 * client but update neigh due to
428 * this MAC update.
429 */
430 if (zvrf->dad_freeze)
431 *is_dup_detect = true;
432
433 return;
434 }
435
436 /* Check if detection time (M-secs) expired.
437 * Reset learn count and detection start time.
438 */
439 monotime_since(&mac->detect_start_time, &elapsed);
440 reset_params = (elapsed.tv_sec > zvrf->dad_time);
441 if (is_local && !reset_params) {
442 /* RFC-7432: A PE/VTEP that detects a MAC mobility
443 * event via LOCAL learning starts an M-second timer.
444 *
445 * NOTE: This is the START of the probe with count is
446 * 0 during LOCAL learn event.
447 * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
448 */
449 reset_params = !mac->dad_count;
450 }
451
452 if (reset_params) {
453 if (IS_ZEBRA_DEBUG_VXLAN)
454 zlog_debug(
455 "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
456 , __PRETTY_FUNCTION__,
457 prefix_mac2str(&mac->macaddr, buf,
458 sizeof(buf)),
459 mac->flags, mac->dad_count);
460
461 mac->dad_count = 0;
462 /* Start dup. addr detection (DAD) start time,
463 * ONLY during LOCAL learn.
464 */
465 if (is_local)
466 monotime(&mac->detect_start_time);
467
468 } else if (!is_local) {
469 /* For REMOTE MAC, increment detection count
470 * ONLY while in probe window, once window passed,
471 * next local learn event should trigger DAD.
472 */
473 mac->dad_count++;
474 }
475
476 /* For LOCAL MAC learn event, once count is reset above via either
477 * initial/start detection time or passed the probe time, the count
478 * needs to be incremented.
479 */
480 if (is_local)
481 mac->dad_count++;
482
483 if (mac->dad_count >= zvrf->dad_max_moves) {
484 flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
485 "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
486 mac->zvni->vni,
487 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
488 is_local ? "local update, last" :
489 "remote update, from", inet_ntoa(vtep_ip));
490
491 SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
492
493 /* Capture Duplicate detection time */
494 mac->dad_dup_detect_time = monotime(NULL);
495
496 /* Mark all IPs/Neighs as duplicate
497 * associcated with this MAC
498 */
499 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
500
501 /* Ony Mark IPs which are Local */
502 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
503 continue;
504
505 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
506
507 nbr->dad_dup_detect_time = monotime(NULL);
508
509 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
510 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
511 mac->zvni->vni,
512 prefix_mac2str(&mac->macaddr,
513 buf, sizeof(buf)),
514 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
515 is_local ? "local" : "remote");
516 }
517
518 /* Start auto recovery timer for this MAC */
519 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
520 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
521 if (IS_ZEBRA_DEBUG_VXLAN)
522 zlog_debug(
523 "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
524 , __PRETTY_FUNCTION__,
525 prefix_mac2str(&mac->macaddr, buf,
526 sizeof(buf)),
527 mac->flags, zvrf->dad_freeze_time);
528
529 thread_add_timer(zrouter.master,
530 zebra_vxlan_dad_mac_auto_recovery_exp,
531 mac, zvrf->dad_freeze_time,
532 &mac->dad_mac_auto_recovery_timer);
533 }
534
535 /* In case of local update, do not inform to client (BGPd),
536 * upd_neigh for neigh sequence change.
537 */
538 if (zvrf->dad_freeze)
539 *is_dup_detect = true;
540 }
541 }
542
543 static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
544 zebra_neigh_t *nbr,
545 struct in_addr vtep_ip,
546 bool do_dad,
547 bool *is_dup_detect,
548 bool is_local)
549 {
550
551 struct timeval elapsed = {0, 0};
552 char buf[ETHER_ADDR_STRLEN];
553 char buf1[INET6_ADDRSTRLEN];
554 bool reset_params = false;
555
556 if (!zvrf->dup_addr_detect)
557 return;
558
559 /* IP is detected as duplicate or inherit dup
560 * state, hold on to install as remote entry
561 * only if freeze is enabled.
562 */
563 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
564 if (IS_ZEBRA_DEBUG_VXLAN)
565 zlog_debug(
566 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
567 __PRETTY_FUNCTION__,
568 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
569 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
570 nbr->flags, nbr->dad_count,
571 zvrf->dad_freeze_time);
572
573 if (zvrf->dad_freeze)
574 *is_dup_detect = true;
575
576 /* warn-only action, neigh will be installed.
577 * freeze action, it wil not be installed.
578 */
579 return;
580 }
581
582 if (!do_dad)
583 return;
584
585 /* Check if detection time (M-secs) expired.
586 * Reset learn count and detection start time.
587 * During remote mac add, count should already be 1
588 * via local learning.
589 */
590 monotime_since(&nbr->detect_start_time, &elapsed);
591 reset_params = (elapsed.tv_sec > zvrf->dad_time);
592
593 if (is_local && !reset_params) {
594 /* RFC-7432: A PE/VTEP that detects a MAC mobility
595 * event via LOCAL learning starts an M-second timer.
596 *
597 * NOTE: This is the START of the probe with count is
598 * 0 during LOCAL learn event.
599 */
600 reset_params = !nbr->dad_count;
601 }
602
603 if (reset_params) {
604 if (IS_ZEBRA_DEBUG_VXLAN)
605 zlog_debug(
606 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
607 __PRETTY_FUNCTION__,
608 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
609 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
610 nbr->flags, nbr->dad_count);
611 /* Reset learn count but do not start detection
612 * during REMOTE learn event.
613 */
614 nbr->dad_count = 0;
615 /* Start dup. addr detection (DAD) start time,
616 * ONLY during LOCAL learn.
617 */
618 if (is_local)
619 monotime(&nbr->detect_start_time);
620
621 } else if (!is_local) {
622 /* For REMOTE IP/Neigh, increment detection count
623 * ONLY while in probe window, once window passed,
624 * next local learn event should trigger DAD.
625 */
626 nbr->dad_count++;
627 }
628
629 /* For LOCAL IP/Neigh learn event, once count is reset above via either
630 * initial/start detection time or passed the probe time, the count
631 * needs to be incremented.
632 */
633 if (is_local)
634 nbr->dad_count++;
635
636 if (nbr->dad_count >= zvrf->dad_max_moves) {
637 flog_warn(EC_ZEBRA_DUP_IP_DETECTED,
638 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
639 nbr->zvni->vni,
640 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
641 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
642 is_local ? "local update, last" :
643 "remote update, from",
644 inet_ntoa(vtep_ip));
645
646 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
647
648 /* Capture Duplicate detection time */
649 nbr->dad_dup_detect_time = monotime(NULL);
650
651 /* Start auto recovery timer for this IP */
652 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
653 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
654 if (IS_ZEBRA_DEBUG_VXLAN)
655 zlog_debug(
656 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
657 __PRETTY_FUNCTION__,
658 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
659 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
660 nbr->flags, zvrf->dad_freeze_time);
661
662 thread_add_timer(zrouter.master,
663 zebra_vxlan_dad_ip_auto_recovery_exp,
664 nbr, zvrf->dad_freeze_time,
665 &nbr->dad_ip_auto_recovery_timer);
666 }
667 if (zvrf->dad_freeze)
668 *is_dup_detect = true;
669 }
670 }
671
672 /*
673 * Helper function to determine maximum width of neighbor IP address for
674 * display - just because we're dealing with IPv6 addresses that can
675 * widely vary.
676 */
677 static void zvni_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt)
678 {
679 zebra_neigh_t *n;
680 char buf[INET6_ADDRSTRLEN];
681 struct neigh_walk_ctx *wctx = ctxt;
682 int width;
683
684 n = (zebra_neigh_t *)bucket->data;
685
686 ipaddr2str(&n->ip, buf, sizeof(buf));
687 width = strlen(buf);
688 if (width > wctx->addr_width)
689 wctx->addr_width = width;
690
691 }
692
693 /*
694 * Print a specific neighbor entry.
695 */
696 static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
697 {
698 struct vty *vty;
699 char buf1[ETHER_ADDR_STRLEN];
700 char buf2[INET6_ADDRSTRLEN];
701 const char *type_str;
702 const char *state_str;
703 bool flags_present = false;
704 struct zebra_vrf *zvrf = NULL;
705 struct timeval detect_start_time = {0, 0};
706
707 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
708 if (!zvrf)
709 return;
710
711 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
712 ipaddr2str(&n->ip, buf2, sizeof(buf2));
713 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
714 type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ?
715 "local" : "remote";
716 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
717 vty = (struct vty *)ctxt;
718 if (json == NULL) {
719 vty_out(vty, "IP: %s\n",
720 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
721 vty_out(vty, " Type: %s\n", type_str);
722 vty_out(vty, " State: %s\n", state_str);
723 vty_out(vty, " MAC: %s\n",
724 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
725 } else {
726 json_object_string_add(json, "ip", buf2);
727 json_object_string_add(json, "type", type_str);
728 json_object_string_add(json, "state", state_str);
729 json_object_string_add(json, "mac", buf1);
730 }
731 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
732 if (json == NULL) {
733 vty_out(vty, " Remote VTEP: %s\n",
734 inet_ntoa(n->r_vtep_ip));
735 } else
736 json_object_string_add(json, "remoteVtep",
737 inet_ntoa(n->r_vtep_ip));
738 }
739 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
740 if (!json) {
741 vty_out(vty, " Flags: Default-gateway");
742 flags_present = true;
743 } else
744 json_object_boolean_true_add(json, "defaultGateway");
745 }
746 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
747 if (!json) {
748 vty_out(vty,
749 flags_present ? " ,Router" : " Flags: Router");
750 flags_present = true;
751 }
752 }
753 if (json == NULL) {
754 if (flags_present)
755 vty_out(vty, "\n");
756 vty_out(vty, " Local Seq: %u Remote Seq: %u\n",
757 n->loc_seq, n->rem_seq);
758
759 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
760 vty_out(vty, " Duplicate, detected at %s",
761 time_to_string(n->dad_dup_detect_time));
762 } else if (n->dad_count) {
763 monotime_since(&n->detect_start_time,
764 &detect_start_time);
765 if (detect_start_time.tv_sec <= zvrf->dad_time) {
766 char *buf = time_to_string(
767 n->detect_start_time.tv_sec);
768 char tmp_buf[30];
769
770 memset(tmp_buf, 0, 30);
771 strncpy(tmp_buf, buf, strlen(buf) - 1);
772 vty_out(vty,
773 " Duplicate detection started at %s, detection count %u\n",
774 tmp_buf, n->dad_count);
775 }
776 }
777 } else {
778 json_object_int_add(json, "localSequence", n->loc_seq);
779 json_object_int_add(json, "remoteSequence", n->rem_seq);
780 json_object_int_add(json, "detectionCount",
781 n->dad_count);
782 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
783 json_object_boolean_true_add(json, "isDuplicate");
784 else
785 json_object_boolean_false_add(json, "isDuplicate");
786
787
788 }
789 }
790
791 /*
792 * Print neighbor hash entry - called for display of all neighbors.
793 */
794 static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
795 {
796 struct vty *vty;
797 json_object *json_vni = NULL, *json_row = NULL;
798 zebra_neigh_t *n;
799 char buf1[ETHER_ADDR_STRLEN];
800 char buf2[INET6_ADDRSTRLEN];
801 struct neigh_walk_ctx *wctx = ctxt;
802 const char *state_str;
803
804 vty = wctx->vty;
805 json_vni = wctx->json;
806 n = (zebra_neigh_t *)bucket->data;
807
808 if (json_vni)
809 json_row = json_object_new_object();
810
811 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
812 ipaddr2str(&n->ip, buf2, sizeof(buf2));
813 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
814 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
815 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
816 return;
817
818 if (json_vni == NULL) {
819 vty_out(vty, "%*s %-6s %-8s %-17s\n",
820 -wctx->addr_width, buf2, "local",
821 state_str, buf1);
822 } else {
823 json_object_string_add(json_row, "type", "local");
824 json_object_string_add(json_row, "state", state_str);
825 json_object_string_add(json_row, "mac", buf1);
826 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
827 json_object_boolean_true_add(
828 json_row, "defaultGateway");
829 json_object_int_add(json_row, "localSequence",
830 n->loc_seq);
831 json_object_int_add(json_row, "remoteSequence",
832 n->rem_seq);
833 json_object_int_add(json_row, "detectionCount",
834 n->dad_count);
835 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
836 json_object_boolean_true_add(json_row,
837 "isDuplicate");
838 else
839 json_object_boolean_false_add(json_row,
840 "isDuplicate");
841 }
842 wctx->count++;
843 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
844 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) &&
845 !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))
846 return;
847
848 if (json_vni == NULL) {
849 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) &&
850 (wctx->count == 0))
851 vty_out(vty,
852 "%*s %-6s %-8s %-17s %-21s\n",
853 -wctx->addr_width, "Neighbor", "Type",
854 "State", "MAC", "Remote VTEP");
855 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
856 -wctx->addr_width, buf2, "remote", state_str,
857 buf1, inet_ntoa(n->r_vtep_ip));
858 } else {
859 json_object_string_add(json_row, "type", "remote");
860 json_object_string_add(json_row, "state", state_str);
861 json_object_string_add(json_row, "mac", buf1);
862 json_object_string_add(json_row, "remoteVtep",
863 inet_ntoa(n->r_vtep_ip));
864 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
865 json_object_boolean_true_add(json_row,
866 "defaultGateway");
867 json_object_int_add(json_row, "localSequence",
868 n->loc_seq);
869 json_object_int_add(json_row, "remoteSequence",
870 n->rem_seq);
871 json_object_int_add(json_row, "detectionCount",
872 n->dad_count);
873 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
874 json_object_boolean_true_add(json_row,
875 "isDuplicate");
876 else
877 json_object_boolean_false_add(json_row,
878 "isDuplicate");
879 }
880 wctx->count++;
881 }
882
883 if (json_vni)
884 json_object_object_add(json_vni, buf2, json_row);
885 }
886
887 /*
888 * Print neighbor hash entry in detail - called for display of all neighbors.
889 */
890 static void zvni_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt)
891 {
892 struct vty *vty;
893 json_object *json_vni = NULL, *json_row = NULL;
894 zebra_neigh_t *n;
895 char buf[INET6_ADDRSTRLEN];
896 struct neigh_walk_ctx *wctx = ctxt;
897
898 vty = wctx->vty;
899 json_vni = wctx->json;
900 n = (zebra_neigh_t *)bucket->data;
901 if (!n)
902 return;
903
904 ipaddr2str(&n->ip, buf, sizeof(buf));
905 if (json_vni)
906 json_row = json_object_new_object();
907
908 zvni_print_neigh(n, vty, json_row);
909
910 if (json_vni)
911 json_object_object_add(json_vni, buf, json_row);
912 }
913
914 /*
915 * Print neighbors for all VNI.
916 */
917 static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket,
918 void **args)
919 {
920 struct vty *vty;
921 json_object *json = NULL, *json_vni = NULL;
922 zebra_vni_t *zvni;
923 uint32_t num_neigh;
924 struct neigh_walk_ctx wctx;
925 char vni_str[VNI_STR_LEN];
926 uint32_t print_dup;
927
928 vty = (struct vty *)args[0];
929 json = (json_object *)args[1];
930 print_dup = (uint32_t)(uintptr_t)args[2];
931
932 zvni = (zebra_vni_t *)bucket->data;
933
934 num_neigh = hashcount(zvni->neigh_table);
935
936 if (print_dup)
937 num_neigh = num_dup_detected_neighs(zvni);
938
939 if (json == NULL) {
940 vty_out(vty,
941 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
942 zvni->vni, num_neigh);
943 } else {
944 json_vni = json_object_new_object();
945 json_object_int_add(json_vni, "numArpNd", num_neigh);
946 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
947 }
948
949 if (!num_neigh) {
950 if (json)
951 json_object_object_add(json, vni_str, json_vni);
952 return;
953 }
954
955 /* Since we have IPv6 addresses to deal with which can vary widely in
956 * size, we try to be a bit more elegant in display by first computing
957 * the maximum width.
958 */
959 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
960 wctx.zvni = zvni;
961 wctx.vty = vty;
962 wctx.addr_width = 15;
963 wctx.json = json_vni;
964 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
965
966 if (json == NULL) {
967 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
968 -wctx.addr_width, "IP", "Type",
969 "State", "MAC", "Remote VTEP");
970 }
971 if (print_dup)
972 hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash,
973 &wctx);
974 else
975 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
976
977 if (json)
978 json_object_object_add(json, vni_str, json_vni);
979 }
980
981 static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt)
982 {
983 zebra_neigh_t *nbr;
984
985 nbr = (zebra_neigh_t *)bucket->data;
986 if (!nbr)
987 return;
988
989 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
990 zvni_print_neigh_hash(bucket, ctxt);
991 }
992
993 static void zvni_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
994 void *ctxt)
995 {
996 zebra_neigh_t *nbr;
997
998 nbr = (zebra_neigh_t *)bucket->data;
999 if (!nbr)
1000 return;
1001
1002 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
1003 zvni_print_neigh_hash_detail(bucket, ctxt);
1004 }
1005
1006 /*
1007 * Print neighbors for all VNIs in detail.
1008 */
1009 static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket *bucket,
1010 void **args)
1011 {
1012 struct vty *vty;
1013 json_object *json = NULL, *json_vni = NULL;
1014 zebra_vni_t *zvni;
1015 uint32_t num_neigh;
1016 struct neigh_walk_ctx wctx;
1017 char vni_str[VNI_STR_LEN];
1018 uint32_t print_dup;
1019
1020 vty = (struct vty *)args[0];
1021 json = (json_object *)args[1];
1022 print_dup = (uint32_t)(uintptr_t)args[2];
1023
1024 zvni = (zebra_vni_t *)bucket->data;
1025 if (!zvni) {
1026 if (json)
1027 vty_out(vty, "{}\n");
1028 return;
1029 }
1030 num_neigh = hashcount(zvni->neigh_table);
1031
1032 if (print_dup && num_dup_detected_neighs(zvni) == 0)
1033 return;
1034
1035 if (json == NULL) {
1036 vty_out(vty,
1037 "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
1038 zvni->vni, num_neigh);
1039 } else {
1040 json_vni = json_object_new_object();
1041 json_object_int_add(json_vni, "numArpNd", num_neigh);
1042 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1043 }
1044 if (!num_neigh) {
1045 if (json)
1046 json_object_object_add(json, vni_str, json_vni);
1047 return;
1048 }
1049
1050 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
1051 wctx.zvni = zvni;
1052 wctx.vty = vty;
1053 wctx.addr_width = 15;
1054 wctx.json = json_vni;
1055
1056 if (print_dup)
1057 hash_iterate(zvni->neigh_table,
1058 zvni_print_dad_neigh_hash_detail, &wctx);
1059 else
1060 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash_detail,
1061 &wctx);
1062
1063 if (json)
1064 json_object_object_add(json, vni_str, json_vni);
1065 }
1066
1067 /* print a specific next hop for an l3vni */
1068 static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
1069 json_object *json)
1070 {
1071 char buf1[ETHER_ADDR_STRLEN];
1072 char buf2[INET6_ADDRSTRLEN];
1073 json_object *json_hosts = NULL;
1074 struct host_rb_entry *hle;
1075
1076 if (!json) {
1077 vty_out(vty, "Ip: %s\n",
1078 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1079 vty_out(vty, " RMAC: %s\n",
1080 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
1081 vty_out(vty, " Refcount: %d\n",
1082 rb_host_count(&n->host_rb));
1083 vty_out(vty, " Prefixes:\n");
1084 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
1085 vty_out(vty, " %s\n",
1086 prefix2str(&hle->p, buf2, sizeof(buf2)));
1087 } else {
1088 json_hosts = json_object_new_array();
1089 json_object_string_add(
1090 json, "ip", ipaddr2str(&(n->ip), buf2, sizeof(buf2)));
1091 json_object_string_add(
1092 json, "routerMac",
1093 prefix_mac2str(&n->emac, buf2, sizeof(buf2)));
1094 json_object_int_add(json, "refCount",
1095 rb_host_count(&n->host_rb));
1096 RB_FOREACH (hle, host_rb_tree_entry, &n->host_rb)
1097 json_object_array_add(json_hosts,
1098 json_object_new_string(prefix2str(
1099 &hle->p, buf2, sizeof(buf2))));
1100 json_object_object_add(json, "prefixList", json_hosts);
1101 }
1102 }
1103
1104 /* Print a specific RMAC entry */
1105 static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
1106 json_object *json)
1107 {
1108 char buf1[ETHER_ADDR_STRLEN];
1109 char buf2[PREFIX_STRLEN];
1110 json_object *json_hosts = NULL;
1111 struct host_rb_entry *hle;
1112
1113 if (!json) {
1114 vty_out(vty, "MAC: %s\n",
1115 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
1116 vty_out(vty, " Remote VTEP: %s\n",
1117 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
1118 vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb));
1119 vty_out(vty, " Prefixes:\n");
1120 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
1121 vty_out(vty, " %s\n",
1122 prefix2str(&hle->p, buf2, sizeof(buf2)));
1123 } else {
1124 json_hosts = json_object_new_array();
1125 json_object_string_add(
1126 json, "routerMac",
1127 prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
1128 json_object_string_add(json, "vtepIp",
1129 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
1130 json_object_int_add(json, "refCount",
1131 rb_host_count(&zrmac->host_rb));
1132 json_object_int_add(json, "localSequence", zrmac->loc_seq);
1133 json_object_int_add(json, "remoteSequence", zrmac->rem_seq);
1134 RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
1135 json_object_array_add(
1136 json_hosts,
1137 json_object_new_string(prefix2str(
1138 &hle->p, buf2, sizeof(buf2))));
1139 json_object_object_add(json, "prefixList", json_hosts);
1140 }
1141 }
1142
1143 /*
1144 * Print a specific MAC entry.
1145 */
1146 static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
1147 {
1148 struct vty *vty;
1149 zebra_neigh_t *n = NULL;
1150 struct listnode *node = NULL;
1151 char buf1[20];
1152 char buf2[INET6_ADDRSTRLEN];
1153 struct zebra_vrf *zvrf;
1154 struct timeval detect_start_time = {0, 0};
1155
1156 zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
1157
1158 vty = (struct vty *)ctxt;
1159 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
1160
1161 if (json) {
1162 json_object *json_mac = json_object_new_object();
1163
1164 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1165 struct zebra_ns *zns;
1166 struct interface *ifp;
1167 ifindex_t ifindex;
1168
1169 ifindex = mac->fwd_info.local.ifindex;
1170 zns = zebra_ns_lookup(NS_DEFAULT);
1171 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1172 if (!ifp)
1173 return;
1174 json_object_string_add(json_mac, "type", "local");
1175 json_object_string_add(json_mac, "intf", ifp->name);
1176 json_object_int_add(json_mac, "ifindex", ifindex);
1177 if (mac->fwd_info.local.vid)
1178 json_object_int_add(json_mac, "vlan",
1179 mac->fwd_info.local.vid);
1180 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1181 json_object_string_add(json_mac, "type", "remote");
1182 json_object_string_add(
1183 json_mac, "remoteVtep",
1184 inet_ntoa(mac->fwd_info.r_vtep_ip));
1185 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
1186 json_object_string_add(json_mac, "type", "auto");
1187
1188 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
1189 json_object_boolean_true_add(json_mac, "stickyMac");
1190
1191 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
1192 json_object_boolean_true_add(json_mac,
1193 "defaultGateway");
1194
1195 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
1196 json_object_boolean_true_add(json_mac,
1197 "remoteGatewayMac");
1198
1199 json_object_int_add(json_mac, "localSequence", mac->loc_seq);
1200 json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
1201
1202 json_object_int_add(json_mac, "detectionCount", mac->dad_count);
1203 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1204 json_object_boolean_true_add(json_mac, "isDuplicate");
1205 else
1206 json_object_boolean_false_add(json_mac, "isDuplicate");
1207
1208 /* print all the associated neigh */
1209 if (!listcount(mac->neigh_list))
1210 json_object_string_add(json_mac, "neighbors", "none");
1211 else {
1212 json_object *json_active_nbrs = json_object_new_array();
1213 json_object *json_inactive_nbrs =
1214 json_object_new_array();
1215 json_object *json_nbrs = json_object_new_object();
1216
1217 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
1218 if (IS_ZEBRA_NEIGH_ACTIVE(n))
1219 json_object_array_add(
1220 json_active_nbrs,
1221 json_object_new_string(
1222 ipaddr2str(
1223 &n->ip, buf2,
1224 sizeof(buf2))));
1225 else
1226 json_object_array_add(
1227 json_inactive_nbrs,
1228 json_object_new_string(
1229 ipaddr2str(
1230 &n->ip, buf2,
1231 sizeof(buf2))));
1232 }
1233
1234 json_object_object_add(json_nbrs, "active",
1235 json_active_nbrs);
1236 json_object_object_add(json_nbrs, "inactive",
1237 json_inactive_nbrs);
1238 json_object_object_add(json_mac, "neighbors",
1239 json_nbrs);
1240 }
1241
1242 json_object_object_add(json, buf1, json_mac);
1243 } else {
1244 vty_out(vty, "MAC: %s\n", buf1);
1245
1246 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1247 struct zebra_ns *zns;
1248 struct interface *ifp;
1249 ifindex_t ifindex;
1250
1251 ifindex = mac->fwd_info.local.ifindex;
1252 zns = zebra_ns_lookup(NS_DEFAULT);
1253 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1254 if (!ifp)
1255 return;
1256 vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
1257 if (mac->fwd_info.local.vid)
1258 vty_out(vty, " VLAN: %u",
1259 mac->fwd_info.local.vid);
1260 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1261 vty_out(vty, " Remote VTEP: %s",
1262 inet_ntoa(mac->fwd_info.r_vtep_ip));
1263 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
1264 vty_out(vty, " Auto Mac ");
1265 }
1266
1267 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
1268 vty_out(vty, " Sticky Mac ");
1269
1270 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
1271 vty_out(vty, " Default-gateway Mac ");
1272
1273 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
1274 vty_out(vty, " Remote-gateway Mac ");
1275
1276 vty_out(vty, "\n");
1277 vty_out(vty, " Local Seq: %u Remote Seq: %u", mac->loc_seq,
1278 mac->rem_seq);
1279 vty_out(vty, "\n");
1280
1281 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
1282 vty_out(vty, " Duplicate, detected at %s",
1283 time_to_string(mac->dad_dup_detect_time));
1284 } else if (mac->dad_count) {
1285 monotime_since(&mac->detect_start_time,
1286 &detect_start_time);
1287 if (detect_start_time.tv_sec <= zvrf->dad_time) {
1288 char *buf = time_to_string(
1289 mac->detect_start_time.tv_sec);
1290 char tmp_buf[30];
1291
1292 memset(tmp_buf, 0, 30);
1293 strncpy(tmp_buf, buf, strlen(buf) - 1);
1294 vty_out(vty,
1295 " Duplicate detection started at %s, detection count %u\n",
1296 tmp_buf, mac->dad_count);
1297 }
1298 }
1299
1300 /* print all the associated neigh */
1301 vty_out(vty, " Neighbors:\n");
1302 if (!listcount(mac->neigh_list))
1303 vty_out(vty, " No Neighbors\n");
1304 else {
1305 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
1306 vty_out(vty, " %s %s\n",
1307 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
1308 (IS_ZEBRA_NEIGH_ACTIVE(n)
1309 ? "Active"
1310 : "Inactive"));
1311 }
1312 }
1313
1314 vty_out(vty, "\n");
1315 }
1316 }
1317
1318 /*
1319 * Print MAC hash entry - called for display of all MACs.
1320 */
1321 static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
1322 {
1323 struct vty *vty;
1324 json_object *json_mac_hdr = NULL, *json_mac = NULL;
1325 zebra_mac_t *mac;
1326 char buf1[20];
1327 struct mac_walk_ctx *wctx = ctxt;
1328
1329 vty = wctx->vty;
1330 json_mac_hdr = wctx->json;
1331 mac = (zebra_mac_t *)bucket->data;
1332
1333 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
1334
1335 if (json_mac_hdr)
1336 json_mac = json_object_new_object();
1337
1338 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
1339 struct zebra_ns *zns;
1340 ifindex_t ifindex;
1341 struct interface *ifp;
1342 vlanid_t vid;
1343
1344 if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
1345 return;
1346
1347 zns = zebra_ns_lookup(NS_DEFAULT);
1348 ifindex = mac->fwd_info.local.ifindex;
1349 ifp = if_lookup_by_index_per_ns(zns, ifindex);
1350 if (!ifp) // unexpected
1351 return;
1352 vid = mac->fwd_info.local.vid;
1353 if (json_mac_hdr == NULL)
1354 vty_out(vty, "%-17s %-6s %-21s", buf1, "local",
1355 ifp->name);
1356 else {
1357 json_object_string_add(json_mac, "type", "local");
1358 json_object_string_add(json_mac, "intf", ifp->name);
1359 }
1360 if (vid) {
1361 if (json_mac_hdr == NULL)
1362 vty_out(vty, " %-5u", vid);
1363 else
1364 json_object_int_add(json_mac, "vlan", vid);
1365 }
1366 if (json_mac_hdr == NULL) {
1367 vty_out(vty, "\n");
1368 } else {
1369 json_object_int_add(json_mac, "localSequence",
1370 mac->loc_seq);
1371 json_object_int_add(json_mac, "remoteSequence",
1372 mac->rem_seq);
1373 json_object_int_add(json_mac, "detectionCount",
1374 mac->dad_count);
1375 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1376 json_object_boolean_true_add(json_mac,
1377 "isDuplicate");
1378 else
1379 json_object_boolean_false_add(json_mac,
1380 "isDuplicate");
1381 json_object_object_add(json_mac_hdr, buf1, json_mac);
1382 }
1383
1384 wctx->count++;
1385
1386 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
1387
1388 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) &&
1389 !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
1390 &wctx->r_vtep_ip))
1391 return;
1392
1393 if (json_mac_hdr == NULL) {
1394 if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) &&
1395 (wctx->count == 0)) {
1396 vty_out(vty, "\nVNI %u\n\n", wctx->zvni->vni);
1397 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC",
1398 "Type", "Intf/Remote VTEP", "VLAN");
1399 }
1400 vty_out(vty, "%-17s %-6s %-21s\n", buf1, "remote",
1401 inet_ntoa(mac->fwd_info.r_vtep_ip));
1402 } else {
1403 json_object_string_add(json_mac, "type", "remote");
1404 json_object_string_add(json_mac, "remoteVtep",
1405 inet_ntoa(mac->fwd_info.r_vtep_ip));
1406 json_object_object_add(json_mac_hdr, buf1, json_mac);
1407 json_object_int_add(json_mac, "localSequence",
1408 mac->loc_seq);
1409 json_object_int_add(json_mac, "remoteSequence",
1410 mac->rem_seq);
1411 json_object_int_add(json_mac, "detectionCount",
1412 mac->dad_count);
1413 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1414 json_object_boolean_true_add(json_mac,
1415 "isDuplicate");
1416 else
1417 json_object_boolean_false_add(json_mac,
1418 "isDuplicate");
1419
1420 }
1421
1422 wctx->count++;
1423 }
1424 }
1425
1426 /* Print Duplicate MAC */
1427 static void zvni_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
1428 {
1429 zebra_mac_t *mac;
1430
1431 mac = (zebra_mac_t *)bucket->data;
1432 if (!mac)
1433 return;
1434
1435 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1436 zvni_print_mac_hash(bucket, ctxt);
1437 }
1438
1439 /*
1440 * Print MAC hash entry in detail - called for display of all MACs.
1441 */
1442 static void zvni_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
1443 {
1444 struct vty *vty;
1445 json_object *json_mac_hdr = NULL;
1446 zebra_mac_t *mac;
1447 struct mac_walk_ctx *wctx = ctxt;
1448 char buf1[20];
1449
1450 vty = wctx->vty;
1451 json_mac_hdr = wctx->json;
1452 mac = (zebra_mac_t *)bucket->data;
1453 if (!mac)
1454 return;
1455
1456 wctx->count++;
1457 prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
1458
1459 zvni_print_mac(mac, vty, json_mac_hdr);
1460 }
1461
1462 /* Print Duplicate MAC in detail */
1463 static void zvni_print_dad_mac_hash_detail(struct hash_bucket *bucket,
1464 void *ctxt)
1465 {
1466 zebra_mac_t *mac;
1467
1468 mac = (zebra_mac_t *)bucket->data;
1469 if (!mac)
1470 return;
1471
1472 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
1473 zvni_print_mac_hash_detail(bucket, ctxt);
1474 }
1475
1476 /*
1477 * Print MACs for all VNI.
1478 */
1479 static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt)
1480 {
1481 struct vty *vty;
1482 json_object *json = NULL, *json_vni = NULL;
1483 json_object *json_mac = NULL;
1484 zebra_vni_t *zvni;
1485 uint32_t num_macs;
1486 struct mac_walk_ctx *wctx = ctxt;
1487 char vni_str[VNI_STR_LEN];
1488
1489 vty = (struct vty *)wctx->vty;
1490 json = (struct json_object *)wctx->json;
1491
1492 zvni = (zebra_vni_t *)bucket->data;
1493 wctx->zvni = zvni;
1494
1495 /*We are iterating over a new VNI, set the count to 0*/
1496 wctx->count = 0;
1497
1498 num_macs = num_valid_macs(zvni);
1499 if (!num_macs)
1500 return;
1501
1502 if (wctx->print_dup)
1503 num_macs = num_dup_detected_macs(zvni);
1504
1505 if (json) {
1506 json_vni = json_object_new_object();
1507 json_mac = json_object_new_object();
1508 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1509 }
1510
1511 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
1512 if (json == NULL) {
1513 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
1514 zvni->vni, num_macs);
1515 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
1516 "Intf/Remote VTEP", "VLAN");
1517 } else
1518 json_object_int_add(json_vni, "numMacs", num_macs);
1519 }
1520
1521 if (!num_macs) {
1522 if (json) {
1523 json_object_int_add(json_vni, "numMacs", num_macs);
1524 json_object_object_add(json, vni_str, json_vni);
1525 }
1526 return;
1527 }
1528
1529 /* assign per-vni to wctx->json object to fill macs
1530 * under the vni. Re-assign primary json object to fill
1531 * next vni information.
1532 */
1533 wctx->json = json_mac;
1534 if (wctx->print_dup)
1535 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, wctx);
1536 else
1537 hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
1538 wctx->json = json;
1539 if (json) {
1540 if (wctx->count)
1541 json_object_object_add(json_vni, "macs", json_mac);
1542 json_object_object_add(json, vni_str, json_vni);
1543 }
1544 }
1545
1546 /*
1547 * Print MACs in detail for all VNI.
1548 */
1549 static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket *bucket,
1550 void *ctxt)
1551 {
1552 struct vty *vty;
1553 json_object *json = NULL, *json_vni = NULL;
1554 json_object *json_mac = NULL;
1555 zebra_vni_t *zvni;
1556 uint32_t num_macs;
1557 struct mac_walk_ctx *wctx = ctxt;
1558 char vni_str[VNI_STR_LEN];
1559
1560 vty = (struct vty *)wctx->vty;
1561 json = (struct json_object *)wctx->json;
1562
1563 zvni = (zebra_vni_t *)bucket->data;
1564 if (!zvni) {
1565 if (json)
1566 vty_out(vty, "{}\n");
1567 return;
1568 }
1569 wctx->zvni = zvni;
1570
1571 /*We are iterating over a new VNI, set the count to 0*/
1572 wctx->count = 0;
1573
1574 num_macs = num_valid_macs(zvni);
1575 if (!num_macs)
1576 return;
1577
1578 if (wctx->print_dup && (num_dup_detected_macs(zvni) == 0))
1579 return;
1580
1581 if (json) {
1582 json_vni = json_object_new_object();
1583 json_mac = json_object_new_object();
1584 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
1585 }
1586
1587 if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
1588 if (json == NULL) {
1589 vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
1590 zvni->vni, num_macs);
1591 } else
1592 json_object_int_add(json_vni, "numMacs", num_macs);
1593 }
1594 /* assign per-vni to wctx->json object to fill macs
1595 * under the vni. Re-assign primary json object to fill
1596 * next vni information.
1597 */
1598 wctx->json = json_mac;
1599 if (wctx->print_dup)
1600 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash_detail,
1601 wctx);
1602 else
1603 hash_iterate(zvni->mac_table, zvni_print_mac_hash_detail, wctx);
1604 wctx->json = json;
1605 if (json) {
1606 if (wctx->count)
1607 json_object_object_add(json_vni, "macs", json_mac);
1608 json_object_object_add(json, vni_str, json_vni);
1609 }
1610 }
1611
1612 static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx)
1613 {
1614 struct nh_walk_ctx *wctx = NULL;
1615 struct vty *vty = NULL;
1616 struct json_object *json_vni = NULL;
1617 struct json_object *json_nh = NULL;
1618 zebra_neigh_t *n = NULL;
1619 char buf1[ETHER_ADDR_STRLEN];
1620 char buf2[INET6_ADDRSTRLEN];
1621
1622 wctx = (struct nh_walk_ctx *)ctx;
1623 vty = wctx->vty;
1624 json_vni = wctx->json;
1625 if (json_vni)
1626 json_nh = json_object_new_object();
1627 n = (zebra_neigh_t *)bucket->data;
1628
1629 if (!json_vni) {
1630 vty_out(vty, "%-15s %-17s\n",
1631 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
1632 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
1633 } else {
1634 json_object_string_add(json_nh, "nexthopIp",
1635 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1636 json_object_string_add(
1637 json_nh, "routerMac",
1638 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
1639 json_object_object_add(json_vni,
1640 ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
1641 json_nh);
1642 }
1643 }
1644
1645 static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket,
1646 void **args)
1647 {
1648 struct vty *vty = NULL;
1649 json_object *json = NULL;
1650 json_object *json_vni = NULL;
1651 zebra_l3vni_t *zl3vni = NULL;
1652 uint32_t num_nh = 0;
1653 struct nh_walk_ctx wctx;
1654 char vni_str[VNI_STR_LEN];
1655
1656 vty = (struct vty *)args[0];
1657 json = (struct json_object *)args[1];
1658
1659 zl3vni = (zebra_l3vni_t *)bucket->data;
1660
1661 num_nh = hashcount(zl3vni->nh_table);
1662 if (!num_nh)
1663 return;
1664
1665 if (json) {
1666 json_vni = json_object_new_object();
1667 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1668 }
1669
1670 if (json == NULL) {
1671 vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh);
1672 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
1673 } else
1674 json_object_int_add(json_vni, "numNextHops", num_nh);
1675
1676 memset(&wctx, 0, sizeof(struct nh_walk_ctx));
1677 wctx.vty = vty;
1678 wctx.json = json_vni;
1679 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
1680 if (json)
1681 json_object_object_add(json, vni_str, json_vni);
1682 }
1683
1684 static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket,
1685 void **args)
1686 {
1687 struct vty *vty = NULL;
1688 json_object *json = NULL;
1689 json_object *json_vni = NULL;
1690 zebra_l3vni_t *zl3vni = NULL;
1691 uint32_t num_rmacs;
1692 struct rmac_walk_ctx wctx;
1693 char vni_str[VNI_STR_LEN];
1694
1695 vty = (struct vty *)args[0];
1696 json = (struct json_object *)args[1];
1697
1698 zl3vni = (zebra_l3vni_t *)bucket->data;
1699
1700 num_rmacs = hashcount(zl3vni->rmac_table);
1701 if (!num_rmacs)
1702 return;
1703
1704 if (json) {
1705 json_vni = json_object_new_object();
1706 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1707 }
1708
1709 if (json == NULL) {
1710 vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs);
1711 vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
1712 } else
1713 json_object_int_add(json_vni, "numRmacs", num_rmacs);
1714
1715 /* assign per-vni to wctx->json object to fill macs
1716 * under the vni. Re-assign primary json object to fill
1717 * next vni information.
1718 */
1719 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
1720 wctx.vty = vty;
1721 wctx.json = json_vni;
1722 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
1723 if (json)
1724 json_object_object_add(json, vni_str, json_vni);
1725 }
1726
1727 static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx)
1728 {
1729 zebra_mac_t *zrmac = NULL;
1730 struct rmac_walk_ctx *wctx = NULL;
1731 struct vty *vty = NULL;
1732 struct json_object *json = NULL;
1733 struct json_object *json_rmac = NULL;
1734 char buf[ETHER_ADDR_STRLEN];
1735
1736 wctx = (struct rmac_walk_ctx *)ctx;
1737 vty = wctx->vty;
1738 json = wctx->json;
1739 if (json)
1740 json_rmac = json_object_new_object();
1741 zrmac = (zebra_mac_t *)bucket->data;
1742
1743 if (!json) {
1744 vty_out(vty, "%-17s %-21s\n",
1745 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
1746 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
1747 } else {
1748 json_object_string_add(
1749 json_rmac, "routerMac",
1750 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)));
1751 json_object_string_add(json_rmac, "vtepIp",
1752 inet_ntoa(zrmac->fwd_info.r_vtep_ip));
1753 json_object_object_add(
1754 json, prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
1755 json_rmac);
1756 }
1757 }
1758
1759 /* print a specific L3 VNI entry */
1760 static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)
1761 {
1762 char buf[ETHER_ADDR_STRLEN];
1763 struct vty *vty = NULL;
1764 json_object *json = NULL;
1765 zebra_vni_t *zvni = NULL;
1766 json_object *json_vni_list = NULL;
1767 struct listnode *node = NULL, *nnode = NULL;
1768
1769 vty = ctx[0];
1770 json = ctx[1];
1771
1772 if (!json) {
1773 vty_out(vty, "VNI: %u\n", zl3vni->vni);
1774 vty_out(vty, " Type: %s\n", "L3");
1775 vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
1776 vty_out(vty, " Local Vtep Ip: %s\n",
1777 inet_ntoa(zl3vni->local_vtep_ip));
1778 vty_out(vty, " Vxlan-Intf: %s\n",
1779 zl3vni_vxlan_if_name(zl3vni));
1780 vty_out(vty, " SVI-If: %s\n", zl3vni_svi_if_name(zl3vni));
1781 vty_out(vty, " State: %s\n", zl3vni_state2str(zl3vni));
1782 vty_out(vty, " VNI Filter: %s\n",
1783 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
1784 ? "prefix-routes-only"
1785 : "none");
1786 vty_out(vty, " Router MAC: %s\n",
1787 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
1788 vty_out(vty, " L2 VNIs: ");
1789 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni))
1790 vty_out(vty, "%u ", zvni->vni);
1791 vty_out(vty, "\n");
1792 } else {
1793 json_vni_list = json_object_new_array();
1794 json_object_int_add(json, "vni", zl3vni->vni);
1795 json_object_string_add(json, "type", "L3");
1796 json_object_string_add(json, "localVtepIp",
1797 inet_ntoa(zl3vni->local_vtep_ip));
1798 json_object_string_add(json, "vxlanIntf",
1799 zl3vni_vxlan_if_name(zl3vni));
1800 json_object_string_add(json, "sviIntf",
1801 zl3vni_svi_if_name(zl3vni));
1802 json_object_string_add(json, "state", zl3vni_state2str(zl3vni));
1803 json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
1804 json_object_string_add(
1805 json, "routerMac",
1806 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
1807 json_object_string_add(
1808 json, "vniFilter",
1809 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
1810 ? "prefix-routes-only"
1811 : "none");
1812 for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) {
1813 json_object_array_add(json_vni_list,
1814 json_object_new_int(zvni->vni));
1815 }
1816 json_object_object_add(json, "l2Vnis", json_vni_list);
1817 }
1818 }
1819
1820 /*
1821 * Print a specific VNI entry.
1822 */
1823 static void zvni_print(zebra_vni_t *zvni, void **ctxt)
1824 {
1825 struct vty *vty;
1826 zebra_vtep_t *zvtep;
1827 uint32_t num_macs;
1828 uint32_t num_neigh;
1829 json_object *json = NULL;
1830 json_object *json_vtep_list = NULL;
1831 json_object *json_ip_str = NULL;
1832
1833 vty = ctxt[0];
1834 json = ctxt[1];
1835
1836 if (json == NULL) {
1837 vty_out(vty, "VNI: %u\n", zvni->vni);
1838 vty_out(vty, " Type: %s\n", "L2");
1839 vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zvni->vrf_id));
1840 } else {
1841 json_object_int_add(json, "vni", zvni->vni);
1842 json_object_string_add(json, "type", "L2");
1843 json_object_string_add(json, "vrf",
1844 vrf_id_to_name(zvni->vrf_id));
1845 }
1846
1847 if (!zvni->vxlan_if) { // unexpected
1848 if (json == NULL)
1849 vty_out(vty, " VxLAN interface: unknown\n");
1850 return;
1851 }
1852 num_macs = num_valid_macs(zvni);
1853 num_neigh = hashcount(zvni->neigh_table);
1854 if (json == NULL) {
1855 vty_out(vty, " VxLAN interface: %s\n", zvni->vxlan_if->name);
1856 vty_out(vty, " VxLAN ifIndex: %u\n", zvni->vxlan_if->ifindex);
1857 vty_out(vty, " Local VTEP IP: %s\n",
1858 inet_ntoa(zvni->local_vtep_ip));
1859 } else {
1860 json_object_string_add(json, "vxlanInterface",
1861 zvni->vxlan_if->name);
1862 json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex);
1863 json_object_string_add(json, "vtepIp",
1864 inet_ntoa(zvni->local_vtep_ip));
1865 json_object_string_add(json, "advertiseGatewayMacip",
1866 zvni->advertise_gw_macip ? "Yes" : "No");
1867 json_object_int_add(json, "numMacs", num_macs);
1868 json_object_int_add(json, "numArpNd", num_neigh);
1869 }
1870 if (!zvni->vteps) {
1871 if (json == NULL)
1872 vty_out(vty, " No remote VTEPs known for this VNI\n");
1873 } else {
1874 if (json == NULL)
1875 vty_out(vty, " Remote VTEPs for this VNI:\n");
1876 else
1877 json_vtep_list = json_object_new_array();
1878 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
1879 if (json == NULL)
1880 vty_out(vty, " %s\n",
1881 inet_ntoa(zvtep->vtep_ip));
1882 else {
1883 json_ip_str = json_object_new_string(
1884 inet_ntoa(zvtep->vtep_ip));
1885 json_object_array_add(json_vtep_list,
1886 json_ip_str);
1887 }
1888 }
1889 if (json)
1890 json_object_object_add(json, "numRemoteVteps",
1891 json_vtep_list);
1892 }
1893 if (json == NULL) {
1894 vty_out(vty,
1895 " Number of MACs (local and remote) known for this VNI: %u\n",
1896 num_macs);
1897 vty_out(vty,
1898 " Number of ARPs (IPv4 and IPv6, local and remote) "
1899 "known for this VNI: %u\n",
1900 num_neigh);
1901 vty_out(vty, " Advertise-gw-macip: %s\n",
1902 zvni->advertise_gw_macip ? "Yes" : "No");
1903 }
1904 }
1905
1906 /* print a L3 VNI hash entry */
1907 static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[])
1908 {
1909 struct vty *vty = NULL;
1910 json_object *json = NULL;
1911 json_object *json_vni = NULL;
1912 zebra_l3vni_t *zl3vni = NULL;
1913
1914 vty = (struct vty *)ctx[0];
1915 json = (json_object *)ctx[1];
1916
1917 zl3vni = (zebra_l3vni_t *)bucket->data;
1918
1919 if (!json) {
1920 vty_out(vty, "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
1921 zl3vni->vni, "L3", zl3vni_vxlan_if_name(zl3vni),
1922 hashcount(zl3vni->rmac_table),
1923 hashcount(zl3vni->nh_table), "n/a",
1924 zl3vni_vrf_name(zl3vni));
1925 } else {
1926 char vni_str[VNI_STR_LEN];
1927
1928 snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
1929 json_vni = json_object_new_object();
1930 json_object_int_add(json_vni, "vni", zl3vni->vni);
1931 json_object_string_add(json_vni, "vxlanIf",
1932 zl3vni_vxlan_if_name(zl3vni));
1933 json_object_int_add(json_vni, "numMacs",
1934 hashcount(zl3vni->rmac_table));
1935 json_object_int_add(json_vni, "numArpNd",
1936 hashcount(zl3vni->nh_table));
1937 json_object_string_add(json_vni, "numRemoteVteps", "n/a");
1938 json_object_string_add(json_vni, "type", "L3");
1939 json_object_string_add(json_vni, "tenantVrf",
1940 zl3vni_vrf_name(zl3vni));
1941 json_object_object_add(json, vni_str, json_vni);
1942 }
1943 }
1944
1945 /* Private Structure to pass callback data for hash iterator */
1946 struct zvni_evpn_show {
1947 struct vty *vty;
1948 json_object *json;
1949 struct zebra_vrf *zvrf;
1950 };
1951
1952 /* print a L3 VNI hash entry in detail*/
1953 static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
1954 {
1955 struct vty *vty = NULL;
1956 zebra_l3vni_t *zl3vni = NULL;
1957 json_object *json = NULL;
1958 bool use_json = false;
1959 struct zvni_evpn_show *zes = data;
1960
1961 vty = zes->vty;
1962 json = zes->json;
1963
1964 if (json)
1965 use_json = true;
1966
1967 zl3vni = (zebra_l3vni_t *)bucket->data;
1968
1969 zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni, use_json);
1970 vty_out(vty, "\n");
1971 }
1972
1973
1974 /*
1975 * Print a VNI hash entry - called for display of all VNIs.
1976 */
1977 static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[])
1978 {
1979 struct vty *vty;
1980 zebra_vni_t *zvni;
1981 zebra_vtep_t *zvtep;
1982 uint32_t num_vteps = 0;
1983 uint32_t num_macs = 0;
1984 uint32_t num_neigh = 0;
1985 json_object *json = NULL;
1986 json_object *json_vni = NULL;
1987 json_object *json_ip_str = NULL;
1988 json_object *json_vtep_list = NULL;
1989
1990 vty = ctxt[0];
1991 json = ctxt[1];
1992
1993 zvni = (zebra_vni_t *)bucket->data;
1994
1995 zvtep = zvni->vteps;
1996 while (zvtep) {
1997 num_vteps++;
1998 zvtep = zvtep->next;
1999 }
2000
2001 num_macs = num_valid_macs(zvni);
2002 num_neigh = hashcount(zvni->neigh_table);
2003 if (json == NULL)
2004 vty_out(vty, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
2005 zvni->vni, "L2",
2006 zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
2007 num_macs, num_neigh, num_vteps,
2008 vrf_id_to_name(zvni->vrf_id));
2009 else {
2010 char vni_str[VNI_STR_LEN];
2011 snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
2012 json_vni = json_object_new_object();
2013 json_object_int_add(json_vni, "vni", zvni->vni);
2014 json_object_string_add(json_vni, "type", "L2");
2015 json_object_string_add(json_vni, "vxlanIf",
2016 zvni->vxlan_if ? zvni->vxlan_if->name
2017 : "unknown");
2018 json_object_int_add(json_vni, "numMacs", num_macs);
2019 json_object_int_add(json_vni, "numArpNd", num_neigh);
2020 json_object_int_add(json_vni, "numRemoteVteps", num_vteps);
2021 json_object_string_add(json_vni, "tenantVrf",
2022 vrf_id_to_name(zvni->vrf_id));
2023 if (num_vteps) {
2024 json_vtep_list = json_object_new_array();
2025 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
2026 json_ip_str = json_object_new_string(
2027 inet_ntoa(zvtep->vtep_ip));
2028 json_object_array_add(json_vtep_list,
2029 json_ip_str);
2030 }
2031 json_object_object_add(json_vni, "remoteVteps",
2032 json_vtep_list);
2033 }
2034 json_object_object_add(json, vni_str, json_vni);
2035 }
2036 }
2037
2038 /*
2039 * Print a VNI hash entry in detail - called for display of all VNIs.
2040 */
2041 static void zvni_print_hash_detail(struct hash_bucket *bucket, void *data)
2042 {
2043 struct vty *vty;
2044 zebra_vni_t *zvni;
2045 json_object *json = NULL;
2046 bool use_json = false;
2047 struct zvni_evpn_show *zes = data;
2048
2049 vty = zes->vty;
2050 json = zes->json;
2051
2052 if (json)
2053 use_json = true;
2054
2055 zvni = (zebra_vni_t *)bucket->data;
2056
2057 zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json);
2058 vty_out(vty, "\n");
2059 }
2060
2061 /*
2062 * Inform BGP about local MACIP.
2063 */
2064 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
2065 struct ipaddr *ip, uint8_t flags,
2066 uint32_t seq, int state, uint16_t cmd)
2067 {
2068 char buf[ETHER_ADDR_STRLEN];
2069 char buf2[INET6_ADDRSTRLEN];
2070 int ipa_len;
2071 struct zserv *client = NULL;
2072 struct stream *s = NULL;
2073
2074 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
2075 /* BGP may not be running. */
2076 if (!client)
2077 return 0;
2078
2079 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
2080
2081 zclient_create_header(s, cmd, VRF_DEFAULT);
2082 stream_putl(s, vni);
2083 stream_put(s, macaddr->octet, ETH_ALEN);
2084 if (ip) {
2085 ipa_len = 0;
2086 if (IS_IPADDR_V4(ip))
2087 ipa_len = IPV4_MAX_BYTELEN;
2088 else if (IS_IPADDR_V6(ip))
2089 ipa_len = IPV6_MAX_BYTELEN;
2090
2091 stream_putl(s, ipa_len); /* IP address length */
2092 if (ipa_len)
2093 stream_put(s, &ip->ip.addr, ipa_len); /* IP address */
2094 } else
2095 stream_putl(s, 0); /* Just MAC. */
2096
2097 if (cmd == ZEBRA_MACIP_ADD) {
2098 stream_putc(s, flags); /* sticky mac/gateway mac */
2099 stream_putl(s, seq); /* sequence number */
2100 } else {
2101 stream_putl(s, state); /* state - active/inactive */
2102 }
2103
2104
2105 /* Write packet size. */
2106 stream_putw_at(s, 0, stream_get_endp(s));
2107
2108 if (IS_ZEBRA_DEBUG_VXLAN)
2109 zlog_debug(
2110 "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s",
2111 (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags,
2112 prefix_mac2str(macaddr, buf, sizeof(buf)),
2113 ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni,
2114 zebra_route_string(client->proto));
2115
2116 if (cmd == ZEBRA_MACIP_ADD)
2117 client->macipadd_cnt++;
2118 else
2119 client->macipdel_cnt++;
2120
2121 return zserv_send_message(client, s);
2122 }
2123
2124 /*
2125 * Make hash key for neighbors.
2126 */
2127 static unsigned int neigh_hash_keymake(void *p)
2128 {
2129 zebra_neigh_t *n = p;
2130 struct ipaddr *ip = &n->ip;
2131
2132 if (IS_IPADDR_V4(ip))
2133 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
2134
2135 return jhash2(ip->ipaddr_v6.s6_addr32,
2136 ZEBRA_NUM_OF(ip->ipaddr_v6.s6_addr32), 0);
2137 }
2138
2139 /*
2140 * Compare two neighbor hash structures.
2141 */
2142 static bool neigh_cmp(const void *p1, const void *p2)
2143 {
2144 const zebra_neigh_t *n1 = p1;
2145 const zebra_neigh_t *n2 = p2;
2146
2147 if (n1 == NULL && n2 == NULL)
2148 return true;
2149
2150 if (n1 == NULL || n2 == NULL)
2151 return false;
2152
2153 return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0);
2154 }
2155
2156 static int neigh_list_cmp(void *p1, void *p2)
2157 {
2158 const zebra_neigh_t *n1 = p1;
2159 const zebra_neigh_t *n2 = p2;
2160
2161 return memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr));
2162 }
2163
2164 /*
2165 * Callback to allocate neighbor hash entry.
2166 */
2167 static void *zvni_neigh_alloc(void *p)
2168 {
2169 const zebra_neigh_t *tmp_n = p;
2170 zebra_neigh_t *n;
2171
2172 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
2173 *n = *tmp_n;
2174
2175 return ((void *)n);
2176 }
2177
2178 /*
2179 * Add neighbor entry.
2180 */
2181 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
2182 struct ethaddr *mac)
2183 {
2184 zebra_neigh_t tmp_n;
2185 zebra_neigh_t *n = NULL;
2186 zebra_mac_t *zmac = NULL;
2187
2188 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
2189 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
2190 n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
2191 assert(n);
2192
2193 memcpy(&n->emac, mac, ETH_ALEN);
2194 n->state = ZEBRA_NEIGH_INACTIVE;
2195
2196 /* Associate the neigh to mac */
2197 zmac = zvni_mac_lookup(zvni, mac);
2198 if (zmac)
2199 listnode_add_sort(zmac->neigh_list, n);
2200
2201 return n;
2202 }
2203
2204 /*
2205 * Delete neighbor entry.
2206 */
2207 static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
2208 {
2209 zebra_neigh_t *tmp_n;
2210 zebra_mac_t *zmac = NULL;
2211
2212 zmac = zvni_mac_lookup(zvni, &n->emac);
2213 if (zmac)
2214 listnode_delete(zmac->neigh_list, n);
2215
2216 /* Free the VNI hash entry and allocated memory. */
2217 tmp_n = hash_release(zvni->neigh_table, n);
2218 if (tmp_n)
2219 XFREE(MTYPE_NEIGH, tmp_n);
2220
2221 return 0;
2222 }
2223
2224 /*
2225 * Free neighbor hash entry (callback)
2226 */
2227 static void zvni_neigh_del_hash_entry(struct hash_bucket *bucket, void *arg)
2228 {
2229 struct neigh_walk_ctx *wctx = arg;
2230 zebra_neigh_t *n = bucket->data;
2231
2232 if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
2233 || ((wctx->flags & DEL_REMOTE_NEIGH)
2234 && (n->flags & ZEBRA_NEIGH_REMOTE))
2235 || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
2236 && (n->flags & ZEBRA_NEIGH_REMOTE)
2237 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
2238 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
2239 zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
2240 &n->emac, 0, n->state);
2241
2242 if (wctx->uninstall)
2243 zvni_neigh_uninstall(wctx->zvni, n);
2244
2245 zvni_neigh_del(wctx->zvni, n);
2246 }
2247
2248 return;
2249 }
2250
2251 /*
2252 * Delete all neighbor entries from specific VTEP for a particular VNI.
2253 */
2254 static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
2255 struct in_addr *r_vtep_ip)
2256 {
2257 struct neigh_walk_ctx wctx;
2258
2259 if (!zvni->neigh_table)
2260 return;
2261
2262 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2263 wctx.zvni = zvni;
2264 wctx.uninstall = uninstall;
2265 wctx.flags = DEL_REMOTE_NEIGH_FROM_VTEP;
2266 wctx.r_vtep_ip = *r_vtep_ip;
2267
2268 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
2269 }
2270
2271 /*
2272 * Delete all neighbor entries for this VNI.
2273 */
2274 static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
2275 uint32_t flags)
2276 {
2277 struct neigh_walk_ctx wctx;
2278
2279 if (!zvni->neigh_table)
2280 return;
2281
2282 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
2283 wctx.zvni = zvni;
2284 wctx.uninstall = uninstall;
2285 wctx.upd_client = upd_client;
2286 wctx.flags = flags;
2287
2288 hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx);
2289 }
2290
2291 /*
2292 * Look up neighbor hash entry.
2293 */
2294 static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
2295 {
2296 zebra_neigh_t tmp;
2297 zebra_neigh_t *n;
2298
2299 memset(&tmp, 0, sizeof(tmp));
2300 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
2301 n = hash_lookup(zvni->neigh_table, &tmp);
2302
2303 return n;
2304 }
2305
2306 /*
2307 * Process all neighbors associated with a MAC upon the MAC being learnt
2308 * locally or undergoing any other change (such as sequence number).
2309 */
2310 static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni,
2311 zebra_mac_t *zmac,
2312 bool seq_change)
2313 {
2314 zebra_neigh_t *n = NULL;
2315 struct listnode *node = NULL;
2316 struct zebra_vrf *zvrf = NULL;
2317 char buf[ETHER_ADDR_STRLEN];
2318
2319 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2320
2321 if (IS_ZEBRA_DEBUG_VXLAN)
2322 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
2323 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2324 seq_change ? "CHANGE" : "ADD", zvni->vni);
2325
2326 /* Walk all neighbors and mark any inactive local neighbors as
2327 * active and/or update sequence number upon a move, and inform BGP.
2328 * The action for remote neighbors is TBD.
2329 * NOTE: We can't simply uninstall remote neighbors as the kernel may
2330 * accidentally end up deleting a just-learnt local neighbor.
2331 */
2332 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2333 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2334 if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change) {
2335 ZEBRA_NEIGH_SET_ACTIVE(n);
2336 n->loc_seq = zmac->loc_seq;
2337 if (!(zvrf->dup_addr_detect &&
2338 zvrf->dad_freeze && !!CHECK_FLAG(n->flags,
2339 ZEBRA_NEIGH_DUPLICATE)))
2340 zvni_neigh_send_add_to_client(
2341 zvni->vni, &n->ip, &n->emac,
2342 n->flags, n->loc_seq);
2343 }
2344 }
2345 }
2346 }
2347
2348 /*
2349 * Process all neighbors associated with a local MAC upon the MAC being
2350 * deleted.
2351 */
2352 static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
2353 zebra_mac_t *zmac)
2354 {
2355 zebra_neigh_t *n = NULL;
2356 struct listnode *node = NULL;
2357 char buf[ETHER_ADDR_STRLEN];
2358
2359 if (IS_ZEBRA_DEBUG_VXLAN)
2360 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
2361 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2362 zvni->vni);
2363
2364 /* Walk all local neighbors and mark as inactive and inform
2365 * BGP, if needed.
2366 * TBD: There is currently no handling for remote neighbors. We
2367 * don't expect them to exist, if they do, do we install the MAC
2368 * as a remote MAC and the neighbor as remote?
2369 */
2370 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2371 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2372 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
2373 ZEBRA_NEIGH_SET_INACTIVE(n);
2374 n->loc_seq = 0;
2375 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2376 &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
2377 }
2378 }
2379 }
2380 }
2381
2382 /*
2383 * Process all neighbors associated with a MAC upon the MAC being remotely
2384 * learnt.
2385 */
2386 static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
2387 zebra_mac_t *zmac)
2388 {
2389 zebra_neigh_t *n = NULL;
2390 struct listnode *node = NULL;
2391 char buf[ETHER_ADDR_STRLEN];
2392
2393 if (IS_ZEBRA_DEBUG_VXLAN)
2394 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
2395 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
2396 zvni->vni);
2397
2398 /* Walk all local neighbors and mark as inactive and inform
2399 * BGP, if needed.
2400 */
2401 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
2402 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2403 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
2404 ZEBRA_NEIGH_SET_INACTIVE(n);
2405 n->loc_seq = 0;
2406 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
2407 &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
2408 }
2409 }
2410 }
2411 }
2412
2413 /*
2414 * Process all neighbors associated with a remote MAC upon the MAC being
2415 * deleted.
2416 */
2417 static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
2418 zebra_mac_t *zmac)
2419 {
2420 /* NOTE: Currently a NO-OP. */
2421 }
2422
2423 static void zvni_probe_neigh_on_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac)
2424 {
2425 zebra_neigh_t *nbr = NULL;
2426 struct listnode *node = NULL;
2427
2428 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, nbr)) {
2429 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) &&
2430 IS_ZEBRA_NEIGH_INACTIVE(nbr))
2431 zvni_neigh_probe(zvni, nbr);
2432 }
2433 }
2434
2435 /*
2436 * Inform BGP about local neighbor addition.
2437 */
2438 static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
2439 struct ethaddr *macaddr,
2440 uint8_t neigh_flags,
2441 uint32_t seq)
2442 {
2443 uint8_t flags = 0;
2444
2445 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
2446 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
2447 /* Set router flag (R-bit) based on local neigh entry add */
2448 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
2449 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
2450
2451 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
2452 seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
2453 }
2454
2455 /*
2456 * Inform BGP about local neighbor deletion.
2457 */
2458 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
2459 struct ethaddr *macaddr, uint8_t flags,
2460 int state)
2461 {
2462 return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
2463 0, state, ZEBRA_MACIP_DEL);
2464 }
2465
2466 /*
2467 * Install remote neighbor into the kernel.
2468 */
2469 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n)
2470 {
2471 struct zebra_if *zif;
2472 struct zebra_l2info_vxlan *vxl;
2473 struct interface *vlan_if;
2474 #ifdef GNU_LINUX
2475 uint8_t flags;
2476 #endif
2477 int ret = 0;
2478
2479 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
2480 return 0;
2481
2482 zif = zvni->vxlan_if->info;
2483 if (!zif)
2484 return -1;
2485 vxl = &zif->l2info.vxl;
2486
2487 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
2488 if (!vlan_if)
2489 return -1;
2490 #ifdef GNU_LINUX
2491 flags = NTF_EXT_LEARNED;
2492 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
2493 flags |= NTF_ROUTER;
2494 ZEBRA_NEIGH_SET_ACTIVE(n);
2495 ret = kernel_add_neigh(vlan_if, &n->ip, &n->emac, flags);
2496 #endif
2497 return ret;
2498 }
2499
2500 /*
2501 * Uninstall remote neighbor from the kernel.
2502 */
2503 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
2504 {
2505 struct zebra_if *zif;
2506 struct zebra_l2info_vxlan *vxl;
2507 struct interface *vlan_if;
2508
2509 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
2510 return 0;
2511
2512 if (!zvni->vxlan_if) {
2513 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
2514 zvni->vni, zvni);
2515 return -1;
2516 }
2517
2518 zif = zvni->vxlan_if->info;
2519 if (!zif)
2520 return -1;
2521 vxl = &zif->l2info.vxl;
2522 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
2523 if (!vlan_if)
2524 return -1;
2525
2526 ZEBRA_NEIGH_SET_INACTIVE(n);
2527 n->loc_seq = 0;
2528 return kernel_del_neigh(vlan_if, &n->ip);
2529 }
2530
2531 /*
2532 * Probe neighbor from the kernel.
2533 */
2534 static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n)
2535 {
2536 struct zebra_if *zif;
2537 struct zebra_l2info_vxlan *vxl;
2538 struct interface *vlan_if;
2539
2540 zif = zvni->vxlan_if->info;
2541 if (!zif)
2542 return -1;
2543 vxl = &zif->l2info.vxl;
2544
2545 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
2546 if (!vlan_if)
2547 return -1;
2548
2549 #ifdef GNU_LINUX
2550 return kernel_upd_neigh(vlan_if, &n->ip, &n->emac,
2551 0, NUD_PROBE);
2552 #else
2553 return 0;
2554 #endif
2555 }
2556
2557 /*
2558 * Install neighbor hash entry - called upon access VLAN change.
2559 */
2560 static void zvni_install_neigh_hash(struct hash_bucket *bucket, void *ctxt)
2561 {
2562 zebra_neigh_t *n;
2563 struct neigh_walk_ctx *wctx = ctxt;
2564
2565 n = (zebra_neigh_t *)bucket->data;
2566
2567 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
2568 zvni_neigh_install(wctx->zvni, n);
2569 }
2570
2571 /* Get the VRR interface for SVI if any */
2572 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp)
2573 {
2574 struct zebra_vrf *zvrf = NULL;
2575 struct interface *tmp_if = NULL;
2576 struct zebra_if *zif = NULL;
2577
2578 zvrf = vrf_info_lookup(ifp->vrf_id);
2579 assert(zvrf);
2580
2581 FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) {
2582 zif = tmp_if->info;
2583 if (!zif)
2584 continue;
2585
2586 if (!IS_ZEBRA_IF_MACVLAN(tmp_if))
2587 continue;
2588
2589 if (zif->link == ifp)
2590 return tmp_if;
2591 }
2592
2593 return NULL;
2594 }
2595
2596 static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
2597 {
2598 struct listnode *cnode = NULL, *cnnode = NULL;
2599 struct connected *c = NULL;
2600 struct ethaddr macaddr;
2601
2602 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2603
2604 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2605 struct ipaddr ip;
2606
2607 memset(&ip, 0, sizeof(struct ipaddr));
2608 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
2609 continue;
2610
2611 if (c->address->family == AF_INET) {
2612 ip.ipa_type = IPADDR_V4;
2613 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
2614 sizeof(struct in_addr));
2615 } else if (c->address->family == AF_INET6) {
2616 ip.ipa_type = IPADDR_V6;
2617 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
2618 sizeof(struct in6_addr));
2619 } else {
2620 continue;
2621 }
2622
2623 zvni_gw_macip_del(ifp, zvni, &ip);
2624 }
2625
2626 return 0;
2627 }
2628
2629 static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
2630 {
2631 struct listnode *cnode = NULL, *cnnode = NULL;
2632 struct connected *c = NULL;
2633 struct ethaddr macaddr;
2634
2635 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2636
2637 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2638 struct ipaddr ip;
2639
2640 memset(&ip, 0, sizeof(struct ipaddr));
2641 if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
2642 continue;
2643
2644 if (c->address->family == AF_INET) {
2645 ip.ipa_type = IPADDR_V4;
2646 memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4),
2647 sizeof(struct in_addr));
2648 } else if (c->address->family == AF_INET6) {
2649 ip.ipa_type = IPADDR_V6;
2650 memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6),
2651 sizeof(struct in6_addr));
2652 } else {
2653 continue;
2654 }
2655
2656 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
2657 }
2658 return 0;
2659 }
2660
2661
2662 static int zvni_advertise_subnet(zebra_vni_t *zvni, struct interface *ifp,
2663 int advertise)
2664 {
2665 struct listnode *cnode = NULL, *cnnode = NULL;
2666 struct connected *c = NULL;
2667 struct ethaddr macaddr;
2668
2669 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
2670
2671 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
2672 struct prefix p;
2673
2674 memcpy(&p, c->address, sizeof(struct prefix));
2675
2676 /* skip link local address */
2677 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
2678 continue;
2679
2680 apply_mask(&p);
2681 if (advertise)
2682 ip_prefix_send_to_client(ifp->vrf_id, &p,
2683 ZEBRA_IP_PREFIX_ROUTE_ADD);
2684 else
2685 ip_prefix_send_to_client(ifp->vrf_id, &p,
2686 ZEBRA_IP_PREFIX_ROUTE_DEL);
2687 }
2688 return 0;
2689 }
2690
2691 /*
2692 * zvni_gw_macip_add_to_client
2693 */
2694 static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
2695 struct ethaddr *macaddr, struct ipaddr *ip)
2696 {
2697 char buf[ETHER_ADDR_STRLEN];
2698 char buf2[INET6_ADDRSTRLEN];
2699 zebra_neigh_t *n = NULL;
2700 zebra_mac_t *mac = NULL;
2701 struct zebra_if *zif = NULL;
2702 struct zebra_l2info_vxlan *vxl = NULL;
2703
2704 zif = zvni->vxlan_if->info;
2705 if (!zif)
2706 return -1;
2707
2708 vxl = &zif->l2info.vxl;
2709
2710 mac = zvni_mac_lookup(zvni, macaddr);
2711 if (!mac) {
2712 mac = zvni_mac_add(zvni, macaddr);
2713 if (!mac) {
2714 flog_err(EC_ZEBRA_MAC_ADD_FAILED,
2715 "Failed to add MAC %s intf %s(%u) VID %u",
2716 prefix_mac2str(macaddr, buf, sizeof(buf)),
2717 ifp->name, ifp->ifindex, vxl->access_vlan);
2718 return -1;
2719 }
2720 }
2721
2722 /* Set "local" forwarding info. */
2723 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
2724 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
2725 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
2726 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
2727 mac->fwd_info.local.ifindex = ifp->ifindex;
2728 mac->fwd_info.local.vid = vxl->access_vlan;
2729
2730 n = zvni_neigh_lookup(zvni, ip);
2731 if (!n) {
2732 n = zvni_neigh_add(zvni, ip, macaddr);
2733 if (!n) {
2734 flog_err(
2735 EC_ZEBRA_MAC_ADD_FAILED,
2736 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2737 ipaddr2str(ip, buf2, sizeof(buf2)),
2738 prefix_mac2str(macaddr, buf, sizeof(buf)),
2739 ifp->name, ifp->ifindex, zvni->vni);
2740 return -1;
2741 }
2742 }
2743
2744 /* Set "local" forwarding info. */
2745 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2746 SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
2747 ZEBRA_NEIGH_SET_ACTIVE(n);
2748 /* Set Router flag (R-bit) */
2749 if (ip->ipa_type == IPADDR_V6)
2750 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
2751 memcpy(&n->emac, macaddr, ETH_ALEN);
2752 n->ifindex = ifp->ifindex;
2753
2754 /* Only advertise in BGP if the knob is enabled */
2755 if (!advertise_gw_macip_enabled(zvni))
2756 return 0;
2757
2758 if (IS_ZEBRA_DEBUG_VXLAN)
2759 zlog_debug(
2760 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2761 ifp->name, ifp->ifindex, zvni->vni,
2762 prefix_mac2str(macaddr, buf, sizeof(buf)),
2763 ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
2764
2765 zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
2766 n->flags, n->loc_seq);
2767
2768 return 0;
2769 }
2770
2771 /*
2772 * zvni_gw_macip_del_from_client
2773 */
2774 static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
2775 struct ipaddr *ip)
2776 {
2777 char buf1[ETHER_ADDR_STRLEN];
2778 char buf2[INET6_ADDRSTRLEN];
2779 zebra_neigh_t *n = NULL;
2780 zebra_mac_t *mac = NULL;
2781
2782 /* If the neigh entry is not present nothing to do*/
2783 n = zvni_neigh_lookup(zvni, ip);
2784 if (!n)
2785 return 0;
2786
2787 /* mac entry should be present */
2788 mac = zvni_mac_lookup(zvni, &n->emac);
2789 if (!mac) {
2790 zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
2791 prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
2792 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2793 return -1;
2794 }
2795
2796 /* If the entry is not local nothing to do*/
2797 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
2798 return -1;
2799
2800 /* only need to delete the entry from bgp if we sent it before */
2801 if (IS_ZEBRA_DEBUG_VXLAN)
2802 zlog_debug(
2803 "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
2804 ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
2805 prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
2806 ipaddr2str(ip, buf2, sizeof(buf2)));
2807
2808 /* Remove neighbor from BGP. */
2809 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
2810 ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
2811
2812 /* Delete this neighbor entry. */
2813 zvni_neigh_del(zvni, n);
2814
2815 /* see if the mac needs to be deleted as well*/
2816 if (mac)
2817 zvni_deref_ip2mac(zvni, mac);
2818
2819 return 0;
2820 }
2821
2822 static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket *bucket,
2823 void *ctxt)
2824 {
2825 zebra_vni_t *zvni = NULL;
2826 struct zebra_if *zif = NULL;
2827 struct zebra_l2info_vxlan zl2_info;
2828 struct interface *vlan_if = NULL;
2829 struct interface *vrr_if = NULL;
2830 struct interface *ifp;
2831
2832 /* Add primary SVI MAC*/
2833 zvni = (zebra_vni_t *)bucket->data;
2834
2835 ifp = zvni->vxlan_if;
2836 if (!ifp)
2837 return;
2838 zif = ifp->info;
2839
2840 /* If down or not mapped to a bridge, we're done. */
2841 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
2842 return;
2843
2844 zl2_info = zif->l2info.vxl;
2845
2846 vlan_if =
2847 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
2848 if (!vlan_if)
2849 return;
2850
2851 /* Del primary MAC-IP */
2852 zvni_del_macip_for_intf(vlan_if, zvni);
2853
2854 /* Del VRR MAC-IP - if any*/
2855 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2856 if (vrr_if)
2857 zvni_del_macip_for_intf(vrr_if, zvni);
2858
2859 return;
2860 }
2861
2862 static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket *bucket,
2863 void *ctxt)
2864 {
2865 zebra_vni_t *zvni = NULL;
2866 struct zebra_if *zif = NULL;
2867 struct zebra_l2info_vxlan zl2_info;
2868 struct interface *vlan_if = NULL;
2869 struct interface *vrr_if = NULL;
2870 struct interface *ifp = NULL;
2871
2872 zvni = (zebra_vni_t *)bucket->data;
2873
2874 ifp = zvni->vxlan_if;
2875 if (!ifp)
2876 return;
2877 zif = ifp->info;
2878
2879 /* If down or not mapped to a bridge, we're done. */
2880 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
2881 return;
2882 zl2_info = zif->l2info.vxl;
2883
2884 vlan_if =
2885 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
2886 if (!vlan_if)
2887 return;
2888
2889 /* Add primary SVI MAC-IP */
2890 zvni_add_macip_for_intf(vlan_if, zvni);
2891
2892 if (advertise_gw_macip_enabled(zvni)) {
2893 /* Add VRR MAC-IP - if any*/
2894 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
2895 if (vrr_if)
2896 zvni_add_macip_for_intf(vrr_if, zvni);
2897 }
2898
2899 return;
2900 }
2901
2902 static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket *bucket,
2903 void *ctxt)
2904 {
2905 zebra_vni_t *zvni = NULL;
2906 struct zebra_if *zif = NULL;
2907 struct zebra_l2info_vxlan zl2_info;
2908 struct interface *vlan_if = NULL;
2909 struct interface *ifp;
2910
2911 /* Add primary SVI MAC*/
2912 zvni = (zebra_vni_t *)bucket->data;
2913 if (!zvni)
2914 return;
2915
2916 ifp = zvni->vxlan_if;
2917 if (!ifp)
2918 return;
2919 zif = ifp->info;
2920
2921 /* If down or not mapped to a bridge, we're done. */
2922 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
2923 return;
2924
2925 zl2_info = zif->l2info.vxl;
2926
2927 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
2928 zif->brslave_info.br_if);
2929 if (!vlan_if)
2930 return;
2931
2932 /* Del primary MAC-IP */
2933 zvni_del_macip_for_intf(vlan_if, zvni);
2934
2935 return;
2936 }
2937
2938 static int zvni_local_neigh_update(zebra_vni_t *zvni,
2939 struct interface *ifp,
2940 struct ipaddr *ip,
2941 struct ethaddr *macaddr,
2942 bool is_router)
2943 {
2944 char buf[ETHER_ADDR_STRLEN];
2945 char buf2[INET6_ADDRSTRLEN];
2946 struct zebra_vrf *zvrf;
2947 zebra_neigh_t *n = NULL;
2948 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
2949 uint32_t old_mac_seq = 0, mac_new_seq = 0;
2950 bool upd_mac_seq = false;
2951 bool neigh_mac_change = false;
2952 bool neigh_on_hold = false;
2953 bool neigh_was_remote = false;
2954 bool do_dad = false;
2955 struct in_addr vtep_ip = {.s_addr = 0};
2956
2957 /* Check if the MAC exists. */
2958 zmac = zvni_mac_lookup(zvni, macaddr);
2959 if (!zmac) {
2960 /* create a dummy MAC if the MAC is not already present */
2961 if (IS_ZEBRA_DEBUG_VXLAN)
2962 zlog_debug(
2963 "AUTO MAC %s created for neigh %s on VNI %u",
2964 prefix_mac2str(macaddr, buf, sizeof(buf)),
2965 ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
2966
2967 zmac = zvni_mac_add(zvni, macaddr);
2968 if (!zmac) {
2969 zlog_debug("Failed to add MAC %s VNI %u",
2970 prefix_mac2str(macaddr, buf, sizeof(buf)),
2971 zvni->vni);
2972 return -1;
2973 }
2974
2975 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
2976 memset(&zmac->flags, 0, sizeof(uint32_t));
2977 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
2978 } else {
2979 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
2980 /*
2981 * We don't change the MAC to local upon a neighbor
2982 * learn event, we wait for the explicit local MAC
2983 * learn. However, we have to compute its sequence
2984 * number in preparation for when it actually turns
2985 * local.
2986 */
2987 upd_mac_seq = true;
2988 }
2989 }
2990
2991 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
2992 if (!zvrf)
2993 return -1;
2994
2995 /* Check if the neighbor exists. */
2996 n = zvni_neigh_lookup(zvni, ip);
2997 if (!n) {
2998 /* New neighbor - create */
2999 n = zvni_neigh_add(zvni, ip, macaddr);
3000 if (!n) {
3001 flog_err(
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, zvni->vni);
3007 return -1;
3008 }
3009 /* Set "local" forwarding info. */
3010 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3011 n->ifindex = ifp->ifindex;
3012 } else {
3013 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
3014 bool mac_different;
3015 bool cur_is_router;
3016
3017 /* Note any changes and see if of interest to BGP. */
3018 mac_different = (memcmp(n->emac.octet,
3019 macaddr->octet, ETH_ALEN) != 0) ? 1 : 0;
3020 cur_is_router = !!CHECK_FLAG(n->flags,
3021 ZEBRA_NEIGH_ROUTER_FLAG);
3022 if (!mac_different && is_router == cur_is_router) {
3023 n->ifindex = ifp->ifindex;
3024 return 0;
3025 }
3026
3027 if (!mac_different) {
3028 bool is_neigh_freezed = false;
3029
3030 /* Only the router flag has changed. */
3031 if (is_router)
3032 SET_FLAG(n->flags,
3033 ZEBRA_NEIGH_ROUTER_FLAG);
3034 else
3035 UNSET_FLAG(n->flags,
3036 ZEBRA_NEIGH_ROUTER_FLAG);
3037
3038 /* Neigh is in freeze state and freeze action
3039 * is enabled, do not send update to client.
3040 */
3041 is_neigh_freezed = (zvrf->dup_addr_detect &&
3042 zvrf->dad_freeze &&
3043 CHECK_FLAG(n->flags,
3044 ZEBRA_NEIGH_DUPLICATE));
3045
3046 if (IS_ZEBRA_NEIGH_ACTIVE(n) &&
3047 !is_neigh_freezed)
3048 return zvni_neigh_send_add_to_client(
3049 zvni->vni, ip, macaddr,
3050 n->flags, n->loc_seq);
3051 return 0;
3052 }
3053
3054 /* The MAC has changed, need to issue a delete
3055 * first as this means a different MACIP route.
3056 * Also, need to do some unlinking/relinking.
3057 * We also need to update the MAC's sequence number
3058 * in different situations.
3059 */
3060 if (IS_ZEBRA_NEIGH_ACTIVE(n))
3061 zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
3062 &n->emac, 0, n->state);
3063 old_zmac = zvni_mac_lookup(zvni, &n->emac);
3064 if (old_zmac) {
3065 old_mac_seq = CHECK_FLAG(old_zmac->flags,
3066 ZEBRA_MAC_REMOTE) ?
3067 old_zmac->rem_seq : old_zmac->loc_seq;
3068 neigh_mac_change = upd_mac_seq = true;
3069 listnode_delete(old_zmac->neigh_list, n);
3070 zvni_deref_ip2mac(zvni, old_zmac);
3071 }
3072
3073 /* Update the forwarding info. */
3074 n->ifindex = ifp->ifindex;
3075 memcpy(&n->emac, macaddr, ETH_ALEN);
3076
3077 /* Link to new MAC */
3078 listnode_add_sort(zmac->neigh_list, n);
3079 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
3080 /*
3081 * Neighbor has moved from remote to local. Its
3082 * MAC could have also changed as part of the move.
3083 */
3084 if (memcmp(n->emac.octet, macaddr->octet,
3085 ETH_ALEN) != 0) {
3086 old_zmac = zvni_mac_lookup(zvni, &n->emac);
3087 if (old_zmac) {
3088 old_mac_seq = CHECK_FLAG(
3089 old_zmac->flags,
3090 ZEBRA_MAC_REMOTE) ?
3091 old_zmac->rem_seq :
3092 old_zmac->loc_seq;
3093 neigh_mac_change = upd_mac_seq = true;
3094 listnode_delete(old_zmac->neigh_list,
3095 n);
3096 zvni_deref_ip2mac(zvni, old_zmac);
3097 }
3098
3099 /* Link to new MAC */
3100 memcpy(&n->emac, macaddr, ETH_ALEN);
3101 listnode_add_sort(zmac->neigh_list, n);
3102 }
3103 /* Based on Mobility event Scenario-B from the
3104 * draft, neigh's previous state was remote treat this
3105 * event for DAD.
3106 */
3107 neigh_was_remote = true;
3108 vtep_ip = n->r_vtep_ip;
3109 /* Mark appropriately */
3110 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3111 n->r_vtep_ip.s_addr = 0;
3112 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3113 n->ifindex = ifp->ifindex;
3114 }
3115 }
3116
3117 /* If MAC was previously remote, or the neighbor had a different
3118 * MAC earlier, recompute the sequence number.
3119 */
3120 if (upd_mac_seq) {
3121 uint32_t seq1, seq2;
3122
3123 seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE) ?
3124 zmac->rem_seq + 1 : zmac->loc_seq;
3125 seq2 = neigh_mac_change ? old_mac_seq + 1 : 0;
3126 mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ?
3127 MAX(seq1, seq2) : zmac->loc_seq;
3128 }
3129
3130 /* Mark Router flag (R-bit) */
3131 if (is_router)
3132 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
3133 else
3134 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
3135
3136 /* Check old and/or new MAC detected as duplicate mark
3137 * the neigh as duplicate
3138 */
3139 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
3140 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
3141 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
3142 zvni->vni,
3143 prefix_mac2str(macaddr, buf, sizeof(buf)),
3144 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
3145 }
3146
3147 /* For IP Duplicate Address Detection (DAD) is trigger,
3148 * when the event is extended mobility based on scenario-B
3149 * from the draft, IP/Neigh's MAC binding changed and
3150 * neigh's previous state was remote.
3151 */
3152 if (neigh_mac_change && neigh_was_remote)
3153 do_dad = true;
3154
3155 zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad,
3156 &neigh_on_hold, true);
3157
3158 /* Before we program this in BGP, we need to check if MAC is locally
3159 * learnt. If not, force neighbor to be inactive and reset its seq.
3160 */
3161 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
3162 ZEBRA_NEIGH_SET_INACTIVE(n);
3163 n->loc_seq = 0;
3164 zmac->loc_seq = mac_new_seq;
3165 return 0;
3166 }
3167
3168 /* If the MAC's sequence number has changed, inform the MAC and all
3169 * neighbors associated with the MAC to BGP, else just inform this
3170 * neighbor.
3171 */
3172 if (upd_mac_seq && zmac->loc_seq != mac_new_seq) {
3173 if (IS_ZEBRA_DEBUG_VXLAN)
3174 zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u",
3175 prefix_mac2str(macaddr, buf, sizeof(buf)),
3176 zvni->vni, zmac->loc_seq, mac_new_seq);
3177 zmac->loc_seq = mac_new_seq;
3178 if (zvni_mac_send_add_to_client(zvni->vni, macaddr,
3179 zmac->flags, zmac->loc_seq))
3180 return -1;
3181 zvni_process_neigh_on_local_mac_change(zvni, zmac, 1);
3182 return 0;
3183 }
3184
3185 ZEBRA_NEIGH_SET_ACTIVE(n);
3186 n->loc_seq = zmac->loc_seq;
3187
3188 if (!neigh_on_hold)
3189 return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
3190 n->flags, n->loc_seq);
3191 return 0;
3192 }
3193
3194 static int zvni_remote_neigh_update(zebra_vni_t *zvni,
3195 struct interface *ifp,
3196 struct ipaddr *ip,
3197 struct ethaddr *macaddr,
3198 uint16_t state)
3199 {
3200 char buf[ETHER_ADDR_STRLEN];
3201 char buf2[INET6_ADDRSTRLEN];
3202 zebra_neigh_t *n = NULL;
3203 zebra_mac_t *zmac = NULL;
3204
3205 /* If the neighbor is unknown, there is no further action. */
3206 n = zvni_neigh_lookup(zvni, ip);
3207 if (!n)
3208 return 0;
3209
3210 /* If a remote entry, see if it needs to be refreshed */
3211 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
3212 #ifdef GNU_LINUX
3213 if (state & NUD_STALE)
3214 zvni_neigh_install(zvni, n);
3215 #endif
3216 } else {
3217 /* We got a "remote" neighbor notification for an entry
3218 * we think is local. This can happen in a multihoming
3219 * scenario - but only if the MAC is already "remote".
3220 * Just mark our entry as "remote".
3221 */
3222 zmac = zvni_mac_lookup(zvni, macaddr);
3223 if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
3224 zlog_debug(
3225 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
3226 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
3227 prefix_mac2str(macaddr, buf, sizeof(buf)),
3228 zvni->vni);
3229 return -1;
3230 }
3231
3232 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
3233 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
3234 ZEBRA_NEIGH_SET_ACTIVE(n);
3235 n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
3236 }
3237
3238 return 0;
3239 }
3240
3241 /*
3242 * Make hash key for MAC.
3243 */
3244 static unsigned int mac_hash_keymake(void *p)
3245 {
3246 zebra_mac_t *pmac = p;
3247 const void *pnt = (void *)pmac->macaddr.octet;
3248
3249 return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
3250 }
3251
3252 /*
3253 * Compare two MAC addresses.
3254 */
3255 static bool mac_cmp(const void *p1, const void *p2)
3256 {
3257 const zebra_mac_t *pmac1 = p1;
3258 const zebra_mac_t *pmac2 = p2;
3259
3260 if (pmac1 == NULL && pmac2 == NULL)
3261 return true;
3262
3263 if (pmac1 == NULL || pmac2 == NULL)
3264 return false;
3265
3266 return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
3267 == 0);
3268 }
3269
3270 /*
3271 * Callback to allocate MAC hash entry.
3272 */
3273 static void *zvni_mac_alloc(void *p)
3274 {
3275 const zebra_mac_t *tmp_mac = p;
3276 zebra_mac_t *mac;
3277
3278 mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
3279 *mac = *tmp_mac;
3280
3281 return ((void *)mac);
3282 }
3283
3284 /*
3285 * Add MAC entry.
3286 */
3287 static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
3288 {
3289 zebra_mac_t tmp_mac;
3290 zebra_mac_t *mac = NULL;
3291
3292 memset(&tmp_mac, 0, sizeof(zebra_mac_t));
3293 memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN);
3294 mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
3295 assert(mac);
3296
3297 mac->neigh_list = list_new();
3298 mac->neigh_list->cmp = neigh_list_cmp;
3299
3300 return mac;
3301 }
3302
3303 /*
3304 * Delete MAC entry.
3305 */
3306 static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
3307 {
3308 zebra_mac_t *tmp_mac;
3309
3310 list_delete(&mac->neigh_list);
3311
3312 /* Free the VNI hash entry and allocated memory. */
3313 tmp_mac = hash_release(zvni->mac_table, mac);
3314 if (tmp_mac)
3315 XFREE(MTYPE_MAC, tmp_mac);
3316
3317 return 0;
3318 }
3319
3320 /*
3321 * Free MAC hash entry (callback)
3322 */
3323 static void zvni_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
3324 {
3325 struct mac_walk_ctx *wctx = arg;
3326 zebra_mac_t *mac = bucket->data;
3327
3328 if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
3329 || ((wctx->flags & DEL_REMOTE_MAC)
3330 && (mac->flags & ZEBRA_MAC_REMOTE))
3331 || ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
3332 && (mac->flags & ZEBRA_MAC_REMOTE)
3333 && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
3334 &wctx->r_vtep_ip))) {
3335 if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
3336 zvni_mac_send_del_to_client(wctx->zvni->vni,
3337 &mac->macaddr);
3338 }
3339
3340 if (wctx->uninstall)
3341 zvni_mac_uninstall(wctx->zvni, mac);
3342
3343 zvni_mac_del(wctx->zvni, mac);
3344 }
3345
3346 return;
3347 }
3348
3349 /*
3350 * Delete all MAC entries from specific VTEP for a particular VNI.
3351 */
3352 static void zvni_mac_del_from_vtep(zebra_vni_t *zvni, int uninstall,
3353 struct in_addr *r_vtep_ip)
3354 {
3355 struct mac_walk_ctx wctx;
3356
3357 if (!zvni->mac_table)
3358 return;
3359
3360 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
3361 wctx.zvni = zvni;
3362 wctx.uninstall = uninstall;
3363 wctx.flags = DEL_REMOTE_MAC_FROM_VTEP;
3364 wctx.r_vtep_ip = *r_vtep_ip;
3365
3366 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
3367 }
3368
3369 /*
3370 * Delete all MAC entries for this VNI.
3371 */
3372 static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client,
3373 uint32_t flags)
3374 {
3375 struct mac_walk_ctx wctx;
3376
3377 if (!zvni->mac_table)
3378 return;
3379
3380 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
3381 wctx.zvni = zvni;
3382 wctx.uninstall = uninstall;
3383 wctx.upd_client = upd_client;
3384 wctx.flags = flags;
3385
3386 hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx);
3387 }
3388
3389 /*
3390 * Look up MAC hash entry.
3391 */
3392 static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
3393 {
3394 zebra_mac_t tmp;
3395 zebra_mac_t *pmac;
3396
3397 memset(&tmp, 0, sizeof(tmp));
3398 memcpy(&tmp.macaddr, mac, ETH_ALEN);
3399 pmac = hash_lookup(zvni->mac_table, &tmp);
3400
3401 return pmac;
3402 }
3403
3404 /*
3405 * Inform BGP about local MAC addition.
3406 */
3407 static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
3408 uint8_t mac_flags, uint32_t seq)
3409 {
3410 uint8_t flags = 0;
3411
3412 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
3413 SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
3414 if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
3415 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
3416
3417 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
3418 seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
3419 }
3420
3421 /*
3422 * Inform BGP about local MAC deletion.
3423 */
3424 static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
3425 {
3426 return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
3427 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
3428 }
3429
3430 /*
3431 * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
3432 * notifications, to see if they are of interest.
3433 */
3434 static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
3435 struct interface *br_if, vlanid_t vid)
3436 {
3437 struct zebra_ns *zns;
3438 struct route_node *rn;
3439 struct interface *tmp_if = NULL;
3440 struct zebra_if *zif;
3441 struct zebra_l2info_bridge *br;
3442 struct zebra_l2info_vxlan *vxl = NULL;
3443 uint8_t bridge_vlan_aware;
3444 zebra_vni_t *zvni;
3445 int found = 0;
3446
3447 /* Determine if bridge is VLAN-aware or not */
3448 zif = br_if->info;
3449 assert(zif);
3450 br = &zif->l2info.br;
3451 bridge_vlan_aware = br->vlan_aware;
3452
3453 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3454 /* TODO: Optimize with a hash. */
3455 zns = zebra_ns_lookup(NS_DEFAULT);
3456 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3457 tmp_if = (struct interface *)rn->info;
3458 if (!tmp_if)
3459 continue;
3460 zif = tmp_if->info;
3461 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3462 continue;
3463 if (!if_is_operative(tmp_if))
3464 continue;
3465 vxl = &zif->l2info.vxl;
3466
3467 if (zif->brslave_info.br_if != br_if)
3468 continue;
3469
3470 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3471 found = 1;
3472 break;
3473 }
3474 }
3475
3476 if (!found)
3477 return NULL;
3478
3479 zvni = zvni_lookup(vxl->vni);
3480 return zvni;
3481 }
3482
3483 /*
3484 * Map SVI and associated bridge to a VNI. This is invoked upon getting
3485 * neighbor notifications, to see if they are of interest.
3486 */
3487 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
3488 struct interface *br_if)
3489 {
3490 struct zebra_ns *zns;
3491 struct route_node *rn;
3492 struct interface *tmp_if = NULL;
3493 struct zebra_if *zif;
3494 struct zebra_l2info_bridge *br;
3495 struct zebra_l2info_vxlan *vxl = NULL;
3496 uint8_t bridge_vlan_aware;
3497 vlanid_t vid = 0;
3498 zebra_vni_t *zvni;
3499 int found = 0;
3500
3501 if (!br_if)
3502 return NULL;
3503
3504 /* Make sure the linked interface is a bridge. */
3505 if (!IS_ZEBRA_IF_BRIDGE(br_if))
3506 return NULL;
3507
3508 /* Determine if bridge is VLAN-aware or not */
3509 zif = br_if->info;
3510 assert(zif);
3511 br = &zif->l2info.br;
3512 bridge_vlan_aware = br->vlan_aware;
3513 if (bridge_vlan_aware) {
3514 struct zebra_l2info_vlan *vl;
3515
3516 if (!IS_ZEBRA_IF_VLAN(ifp))
3517 return NULL;
3518
3519 zif = ifp->info;
3520 assert(zif);
3521 vl = &zif->l2info.vl;
3522 vid = vl->vid;
3523 }
3524
3525 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
3526 /* TODO: Optimize with a hash. */
3527 zns = zebra_ns_lookup(NS_DEFAULT);
3528 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3529 tmp_if = (struct interface *)rn->info;
3530 if (!tmp_if)
3531 continue;
3532 zif = tmp_if->info;
3533 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3534 continue;
3535 if (!if_is_operative(tmp_if))
3536 continue;
3537 vxl = &zif->l2info.vxl;
3538
3539 if (zif->brslave_info.br_if != br_if)
3540 continue;
3541
3542 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
3543 found = 1;
3544 break;
3545 }
3546 }
3547
3548 if (!found)
3549 return NULL;
3550
3551 zvni = zvni_lookup(vxl->vni);
3552 return zvni;
3553 }
3554
3555 /* Map to SVI on bridge corresponding to specified VLAN. This can be one
3556 * of two cases:
3557 * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
3558 * linked to the bridge
3559 * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
3560 * itself
3561 */
3562 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
3563 {
3564 struct zebra_ns *zns;
3565 struct route_node *rn;
3566 struct interface *tmp_if = NULL;
3567 struct zebra_if *zif;
3568 struct zebra_l2info_bridge *br;
3569 struct zebra_l2info_vlan *vl;
3570 uint8_t bridge_vlan_aware;
3571 int found = 0;
3572
3573 /* Defensive check, caller expected to invoke only with valid bridge. */
3574 if (!br_if)
3575 return NULL;
3576
3577 /* Determine if bridge is VLAN-aware or not */
3578 zif = br_if->info;
3579 assert(zif);
3580 br = &zif->l2info.br;
3581 bridge_vlan_aware = br->vlan_aware;
3582
3583 /* Check oper status of the SVI. */
3584 if (!bridge_vlan_aware)
3585 return if_is_operative(br_if) ? br_if : NULL;
3586
3587 /* Identify corresponding VLAN interface. */
3588 /* TODO: Optimize with a hash. */
3589 zns = zebra_ns_lookup(NS_DEFAULT);
3590 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3591 tmp_if = (struct interface *)rn->info;
3592 /* Check oper status of the SVI. */
3593 if (!tmp_if || !if_is_operative(tmp_if))
3594 continue;
3595 zif = tmp_if->info;
3596 if (!zif || zif->zif_type != ZEBRA_IF_VLAN
3597 || zif->link != br_if)
3598 continue;
3599 vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
3600
3601 if (vl->vid == vid) {
3602 found = 1;
3603 break;
3604 }
3605 }
3606
3607 return found ? tmp_if : NULL;
3608 }
3609
3610 /*
3611 * Install remote MAC into the kernel.
3612 */
3613 static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
3614 {
3615 struct zebra_if *zif;
3616 struct zebra_l2info_vxlan *vxl;
3617 bool sticky;
3618
3619 if (!(mac->flags & ZEBRA_MAC_REMOTE))
3620 return 0;
3621
3622 zif = zvni->vxlan_if->info;
3623 if (!zif)
3624 return -1;
3625 vxl = &zif->l2info.vxl;
3626
3627 sticky = !!CHECK_FLAG(mac->flags,
3628 (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
3629
3630 return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
3631 mac->fwd_info.r_vtep_ip, sticky);
3632 }
3633
3634 /*
3635 * Uninstall remote MAC from the kernel.
3636 */
3637 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
3638 {
3639 struct zebra_if *zif;
3640 struct zebra_l2info_vxlan *vxl;
3641 struct in_addr vtep_ip;
3642 struct interface *ifp;
3643
3644 if (!(mac->flags & ZEBRA_MAC_REMOTE))
3645 return 0;
3646
3647 if (!zvni->vxlan_if) {
3648 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
3649 zvni->vni, zvni);
3650 return -1;
3651 }
3652
3653 zif = zvni->vxlan_if->info;
3654 if (!zif)
3655 return -1;
3656 vxl = &zif->l2info.vxl;
3657
3658 ifp = zvni->vxlan_if;
3659 vtep_ip = mac->fwd_info.r_vtep_ip;
3660
3661 return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
3662 }
3663
3664 /*
3665 * Install MAC hash entry - called upon access VLAN change.
3666 */
3667 static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt)
3668 {
3669 zebra_mac_t *mac;
3670 struct mac_walk_ctx *wctx = ctxt;
3671
3672 mac = (zebra_mac_t *)bucket->data;
3673
3674 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
3675 zvni_mac_install(wctx->zvni, mac);
3676 }
3677
3678 /*
3679 * Count of remote neighbors referencing this MAC.
3680 */
3681 static int remote_neigh_count(zebra_mac_t *zmac)
3682 {
3683 zebra_neigh_t *n = NULL;
3684 struct listnode *node = NULL;
3685 int count = 0;
3686
3687 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
3688 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
3689 count++;
3690 }
3691
3692 return count;
3693 }
3694
3695 /*
3696 * Decrement neighbor refcount of MAC; uninstall and free it if
3697 * appropriate.
3698 */
3699 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac)
3700 {
3701 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
3702 return;
3703
3704 /* If all remote neighbors referencing a remote MAC go away,
3705 * we need to uninstall the MAC.
3706 */
3707 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) &&
3708 remote_neigh_count(mac) == 0) {
3709 zvni_mac_uninstall(zvni, mac);
3710 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
3711 }
3712
3713 /* If no neighbors, delete the MAC. */
3714 if (list_isempty(mac->neigh_list))
3715 zvni_mac_del(zvni, mac);
3716 }
3717
3718 /*
3719 * Read and populate local MACs and neighbors corresponding to this VNI.
3720 */
3721 static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
3722 {
3723 struct zebra_ns *zns;
3724 struct zebra_if *zif;
3725 struct interface *vlan_if;
3726 struct zebra_l2info_vxlan *vxl;
3727 struct interface *vrr_if;
3728
3729 zif = ifp->info;
3730 vxl = &zif->l2info.vxl;
3731 zns = zebra_ns_lookup(NS_DEFAULT);
3732
3733 if (IS_ZEBRA_DEBUG_VXLAN)
3734 zlog_debug(
3735 "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u",
3736 ifp->name, ifp->ifindex, zvni->vni,
3737 zif->brslave_info.bridge_ifindex);
3738
3739 macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
3740 vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
3741 if (vlan_if) {
3742
3743 /* Add SVI MAC-IP */
3744 zvni_add_macip_for_intf(vlan_if, zvni);
3745
3746 /* Add VRR MAC-IP - if any*/
3747 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
3748 if (vrr_if)
3749 zvni_add_macip_for_intf(vrr_if, zvni);
3750
3751 neigh_read_for_vlan(zns, vlan_if);
3752 }
3753 }
3754
3755 /*
3756 * Hash function for VNI.
3757 */
3758 static unsigned int vni_hash_keymake(void *p)
3759 {
3760 const zebra_vni_t *zvni = p;
3761
3762 return (jhash_1word(zvni->vni, 0));
3763 }
3764
3765 /*
3766 * Compare 2 VNI hash entries.
3767 */
3768 static bool vni_hash_cmp(const void *p1, const void *p2)
3769 {
3770 const zebra_vni_t *zvni1 = p1;
3771 const zebra_vni_t *zvni2 = p2;
3772
3773 return (zvni1->vni == zvni2->vni);
3774 }
3775
3776 static int vni_list_cmp(void *p1, void *p2)
3777 {
3778 const zebra_vni_t *zvni1 = p1;
3779 const zebra_vni_t *zvni2 = p2;
3780
3781 if (zvni1->vni == zvni2->vni)
3782 return 0;
3783 return (zvni1->vni < zvni2->vni) ? -1 : 1;
3784 }
3785
3786 /*
3787 * Callback to allocate VNI hash entry.
3788 */
3789 static void *zvni_alloc(void *p)
3790 {
3791 const zebra_vni_t *tmp_vni = p;
3792 zebra_vni_t *zvni;
3793
3794 zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t));
3795 zvni->vni = tmp_vni->vni;
3796 return ((void *)zvni);
3797 }
3798
3799 /*
3800 * Look up VNI hash entry.
3801 */
3802 static zebra_vni_t *zvni_lookup(vni_t vni)
3803 {
3804 struct zebra_vrf *zvrf;
3805 zebra_vni_t tmp_vni;
3806 zebra_vni_t *zvni = NULL;
3807
3808 zvrf = vrf_info_lookup(VRF_DEFAULT);
3809 assert(zvrf);
3810 memset(&tmp_vni, 0, sizeof(zebra_vni_t));
3811 tmp_vni.vni = vni;
3812 zvni = hash_lookup(zvrf->vni_table, &tmp_vni);
3813
3814 return zvni;
3815 }
3816
3817 /*
3818 * Add VNI hash entry.
3819 */
3820 static zebra_vni_t *zvni_add(vni_t vni)
3821 {
3822 struct zebra_vrf *zvrf;
3823 zebra_vni_t tmp_zvni;
3824 zebra_vni_t *zvni = NULL;
3825
3826 zvrf = vrf_info_lookup(VRF_DEFAULT);
3827 assert(zvrf);
3828 memset(&tmp_zvni, 0, sizeof(zebra_vni_t));
3829 tmp_zvni.vni = vni;
3830 zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc);
3831 assert(zvni);
3832
3833 /* Create hash table for MAC */
3834 zvni->mac_table =
3835 hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table");
3836
3837 /* Create hash table for neighbors */
3838 zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp,
3839 "Zebra VNI Neighbor Table");
3840
3841 return zvni;
3842 }
3843
3844 /*
3845 * Delete VNI hash entry.
3846 */
3847 static int zvni_del(zebra_vni_t *zvni)
3848 {
3849 struct zebra_vrf *zvrf;
3850 zebra_vni_t *tmp_zvni;
3851
3852 zvrf = vrf_info_lookup(VRF_DEFAULT);
3853 assert(zvrf);
3854
3855 zvni->vxlan_if = NULL;
3856
3857 /* Free the neighbor hash table. */
3858 hash_free(zvni->neigh_table);
3859 zvni->neigh_table = NULL;
3860
3861 /* Free the MAC hash table. */
3862 hash_free(zvni->mac_table);
3863 zvni->mac_table = NULL;
3864
3865 /* Free the VNI hash entry and allocated memory. */
3866 tmp_zvni = hash_release(zvrf->vni_table, zvni);
3867 if (tmp_zvni)
3868 XFREE(MTYPE_ZVNI, tmp_zvni);
3869
3870 return 0;
3871 }
3872
3873 /*
3874 * Inform BGP about local VNI addition.
3875 */
3876 static int zvni_send_add_to_client(zebra_vni_t *zvni)
3877 {
3878 struct zserv *client;
3879 struct stream *s;
3880
3881 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
3882 /* BGP may not be running. */
3883 if (!client)
3884 return 0;
3885
3886 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3887
3888 zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
3889 stream_putl(s, zvni->vni);
3890 stream_put_in_addr(s, &zvni->local_vtep_ip);
3891 stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
3892
3893 /* Write packet size. */
3894 stream_putw_at(s, 0, stream_get_endp(s));
3895
3896 if (IS_ZEBRA_DEBUG_VXLAN)
3897 zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni->vni,
3898 inet_ntoa(zvni->local_vtep_ip),
3899 vrf_id_to_name(zvni->vrf_id),
3900 zebra_route_string(client->proto));
3901
3902 client->vniadd_cnt++;
3903 return zserv_send_message(client, s);
3904 }
3905
3906 /*
3907 * Inform BGP about local VNI deletion.
3908 */
3909 static int zvni_send_del_to_client(vni_t vni)
3910 {
3911 struct zserv *client;
3912 struct stream *s;
3913
3914 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
3915 /* BGP may not be running. */
3916 if (!client)
3917 return 0;
3918
3919 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
3920 stream_reset(s);
3921
3922 zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
3923 stream_putl(s, vni);
3924
3925 /* Write packet size. */
3926 stream_putw_at(s, 0, stream_get_endp(s));
3927
3928 if (IS_ZEBRA_DEBUG_VXLAN)
3929 zlog_debug("Send VNI_DEL %u to %s", vni,
3930 zebra_route_string(client->proto));
3931
3932 client->vnidel_cnt++;
3933 return zserv_send_message(client, s);
3934 }
3935
3936 /*
3937 * Build the VNI hash table by going over the VxLAN interfaces. This
3938 * is called when EVPN (advertise-all-vni) is enabled.
3939 */
3940 static void zvni_build_hash_table(void)
3941 {
3942 struct zebra_ns *zns;
3943 struct route_node *rn;
3944 struct interface *ifp;
3945
3946 /* Walk VxLAN interfaces and create VNI hash. */
3947 zns = zebra_ns_lookup(NS_DEFAULT);
3948 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
3949 vni_t vni;
3950 zebra_vni_t *zvni = NULL;
3951 zebra_l3vni_t *zl3vni = NULL;
3952 struct zebra_if *zif;
3953 struct zebra_l2info_vxlan *vxl;
3954
3955 ifp = (struct interface *)rn->info;
3956 if (!ifp)
3957 continue;
3958 zif = ifp->info;
3959 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
3960 continue;
3961
3962 vxl = &zif->l2info.vxl;
3963 vni = vxl->vni;
3964
3965 /* L3-VNI and L2-VNI are handled seperately */
3966 zl3vni = zl3vni_lookup(vni);
3967 if (zl3vni) {
3968
3969 if (IS_ZEBRA_DEBUG_VXLAN)
3970 zlog_debug(
3971 "create L3-VNI hash for Intf %s(%u) L3-VNI %u",
3972 ifp->name, ifp->ifindex, vni);
3973
3974 /* associate with vxlan_if */
3975 zl3vni->local_vtep_ip = vxl->vtep_ip;
3976 zl3vni->vxlan_if = ifp;
3977
3978 /*
3979 * we need to associate with SVI.
3980 * we can associate with svi-if only after association
3981 * with vxlan-intf is complete
3982 */
3983 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
3984
3985 if (is_l3vni_oper_up(zl3vni))
3986 zebra_vxlan_process_l3vni_oper_up(zl3vni);
3987
3988 } else {
3989 struct interface *vlan_if = NULL;
3990
3991 if (IS_ZEBRA_DEBUG_VXLAN)
3992 zlog_debug(
3993 "Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %s",
3994 ifp->name, ifp->ifindex, vni,
3995 inet_ntoa(vxl->vtep_ip));
3996
3997 /* VNI hash entry is not expected to exist. */
3998 zvni = zvni_lookup(vni);
3999 if (zvni) {
4000 zlog_debug(
4001 "VNI hash already present for IF %s(%u) L2-VNI %u",
4002 ifp->name, ifp->ifindex, vni);
4003 continue;
4004 }
4005
4006 zvni = zvni_add(vni);
4007 if (!zvni) {
4008 zlog_debug(
4009 "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
4010 ifp->name, ifp->ifindex, vni);
4011 return;
4012 }
4013
4014 zvni->local_vtep_ip = vxl->vtep_ip;
4015 zvni->vxlan_if = ifp;
4016 vlan_if = zvni_map_to_svi(vxl->access_vlan,
4017 zif->brslave_info.br_if);
4018 if (vlan_if) {
4019 zvni->vrf_id = vlan_if->vrf_id;
4020 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
4021 if (zl3vni)
4022 listnode_add_sort(zl3vni->l2vnis, zvni);
4023 }
4024
4025
4026 /* Inform BGP if intf is up and mapped to bridge. */
4027 if (if_is_operative(ifp) && zif->brslave_info.br_if)
4028 zvni_send_add_to_client(zvni);
4029 }
4030 }
4031 }
4032
4033 /*
4034 * See if remote VTEP matches with prefix.
4035 */
4036 static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep)
4037 {
4038 return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip));
4039 }
4040
4041 /*
4042 * Locate remote VTEP in VNI hash table.
4043 */
4044 static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip)
4045 {
4046 zebra_vtep_t *zvtep;
4047
4048 if (!zvni)
4049 return NULL;
4050
4051 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
4052 if (zvni_vtep_match(vtep_ip, zvtep))
4053 break;
4054 }
4055
4056 return zvtep;
4057 }
4058
4059 /*
4060 * Add remote VTEP to VNI hash table.
4061 */
4062 static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip)
4063 {
4064 zebra_vtep_t *zvtep;
4065
4066 zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t));
4067
4068 zvtep->vtep_ip = *vtep_ip;
4069
4070 if (zvni->vteps)
4071 zvni->vteps->prev = zvtep;
4072 zvtep->next = zvni->vteps;
4073 zvni->vteps = zvtep;
4074
4075 return zvtep;
4076 }
4077
4078 /*
4079 * Remove remote VTEP from VNI hash table.
4080 */
4081 static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep)
4082 {
4083 if (zvtep->next)
4084 zvtep->next->prev = zvtep->prev;
4085 if (zvtep->prev)
4086 zvtep->prev->next = zvtep->next;
4087 else
4088 zvni->vteps = zvtep->next;
4089
4090 zvtep->prev = zvtep->next = NULL;
4091 XFREE(MTYPE_ZVNI_VTEP, zvtep);
4092
4093 return 0;
4094 }
4095
4096 /*
4097 * Delete all remote VTEPs for this VNI (upon VNI delete). Also
4098 * uninstall from kernel if asked to.
4099 */
4100 static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall)
4101 {
4102 zebra_vtep_t *zvtep, *zvtep_next;
4103
4104 if (!zvni)
4105 return -1;
4106
4107 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) {
4108 zvtep_next = zvtep->next;
4109 if (uninstall)
4110 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
4111 zvni_vtep_del(zvni, zvtep);
4112 }
4113
4114 return 0;
4115 }
4116
4117 /*
4118 * Install remote VTEP into the kernel.
4119 */
4120 static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip)
4121 {
4122 if (is_vxlan_flooding_head_end())
4123 return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
4124 return 0;
4125 }
4126
4127 /*
4128 * Uninstall remote VTEP from the kernel.
4129 */
4130 static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
4131 {
4132 if (!zvni->vxlan_if) {
4133 zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf",
4134 zvni->vni, zvni);
4135 return -1;
4136 }
4137
4138 return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip);
4139 }
4140
4141 /*
4142 * Install or uninstall flood entries in the kernel corresponding to
4143 * remote VTEPs. This is invoked upon change to BUM handling.
4144 */
4145 static void zvni_handle_flooding_remote_vteps(struct hash_bucket *bucket,
4146 void *zvrf)
4147 {
4148 zebra_vni_t *zvni;
4149 zebra_vtep_t *zvtep;
4150
4151 zvni = (zebra_vni_t *)bucket->data;
4152 if (!zvni)
4153 return;
4154
4155 for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
4156 if (is_vxlan_flooding_head_end())
4157 zvni_vtep_install(zvni, &zvtep->vtep_ip);
4158 else
4159 zvni_vtep_uninstall(zvni, &zvtep->vtep_ip);
4160 }
4161 }
4162
4163 /*
4164 * Cleanup VNI/VTEP and update kernel
4165 */
4166 static void zvni_cleanup_all(struct hash_bucket *bucket, void *arg)
4167 {
4168 zebra_vni_t *zvni = NULL;
4169 zebra_l3vni_t *zl3vni = NULL;
4170 struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
4171
4172 zvni = (zebra_vni_t *)bucket->data;
4173
4174 /* remove from l3-vni list */
4175 if (zvrf->l3vni)
4176 zl3vni = zl3vni_lookup(zvrf->l3vni);
4177 if (zl3vni)
4178 listnode_delete(zl3vni->l2vnis, zvni);
4179
4180 /* Free up all neighbors and MACs, if any. */
4181 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
4182 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
4183
4184 /* Free up all remote VTEPs, if any. */
4185 zvni_vtep_del_all(zvni, 1);
4186
4187 /* Delete the hash entry. */
4188 zvni_del(zvni);
4189 }
4190
4191 /* cleanup L3VNI */
4192 static void zl3vni_cleanup_all(struct hash_bucket *bucket, void *args)
4193 {
4194 zebra_l3vni_t *zl3vni = NULL;
4195
4196 zl3vni = (zebra_l3vni_t *)bucket->data;
4197
4198 zebra_vxlan_process_l3vni_oper_down(zl3vni);
4199 }
4200
4201 static void rb_find_or_add_host(struct host_rb_tree_entry *hrbe,
4202 struct prefix *host)
4203 {
4204 struct host_rb_entry lookup;
4205 struct host_rb_entry *hle;
4206
4207 memset(&lookup, 0, sizeof(lookup));
4208 memcpy(&lookup.p, host, sizeof(*host));
4209
4210 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
4211 if (hle)
4212 return;
4213
4214 hle = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct host_rb_entry));
4215 memcpy(hle, &lookup, sizeof(lookup));
4216
4217 RB_INSERT(host_rb_tree_entry, hrbe, hle);
4218 }
4219
4220 static void rb_delete_host(struct host_rb_tree_entry *hrbe, struct prefix *host)
4221 {
4222 struct host_rb_entry lookup;
4223 struct host_rb_entry *hle;
4224
4225 memset(&lookup, 0, sizeof(lookup));
4226 memcpy(&lookup.p, host, sizeof(*host));
4227
4228 hle = RB_FIND(host_rb_tree_entry, hrbe, &lookup);
4229 if (hle) {
4230 RB_REMOVE(host_rb_tree_entry, hrbe, hle);
4231 XFREE(MTYPE_HOST_PREFIX, hle);
4232 }
4233
4234 return;
4235 }
4236
4237 /*
4238 * Look up MAC hash entry.
4239 */
4240 static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
4241 struct ethaddr *rmac)
4242 {
4243 zebra_mac_t tmp;
4244 zebra_mac_t *pmac;
4245
4246 memset(&tmp, 0, sizeof(tmp));
4247 memcpy(&tmp.macaddr, rmac, ETH_ALEN);
4248 pmac = hash_lookup(zl3vni->rmac_table, &tmp);
4249
4250 return pmac;
4251 }
4252
4253 /*
4254 * Callback to allocate RMAC hash entry.
4255 */
4256 static void *zl3vni_rmac_alloc(void *p)
4257 {
4258 const zebra_mac_t *tmp_rmac = p;
4259 zebra_mac_t *zrmac;
4260
4261 zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t));
4262 *zrmac = *tmp_rmac;
4263
4264 return ((void *)zrmac);
4265 }
4266
4267 /*
4268 * Add RMAC entry to l3-vni
4269 */
4270 static zebra_mac_t *zl3vni_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac)
4271 {
4272 zebra_mac_t tmp_rmac;
4273 zebra_mac_t *zrmac = NULL;
4274
4275 memset(&tmp_rmac, 0, sizeof(zebra_mac_t));
4276 memcpy(&tmp_rmac.macaddr, rmac, ETH_ALEN);
4277 zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
4278 assert(zrmac);
4279
4280 RB_INIT(host_rb_tree_entry, &zrmac->host_rb);
4281
4282 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
4283 SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
4284
4285 return zrmac;
4286 }
4287
4288 /*
4289 * Delete MAC entry.
4290 */
4291 static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
4292 {
4293 zebra_mac_t *tmp_rmac;
4294 struct host_rb_entry *hle;
4295
4296 while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
4297 hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb);
4298
4299 RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle);
4300 XFREE(MTYPE_HOST_PREFIX, hle);
4301 }
4302
4303 tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
4304 if (tmp_rmac)
4305 XFREE(MTYPE_MAC, tmp_rmac);
4306
4307 return 0;
4308 }
4309
4310 /*
4311 * Install remote RMAC into the kernel.
4312 */
4313 static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
4314 {
4315 struct zebra_if *zif = NULL;
4316 struct zebra_l2info_vxlan *vxl = NULL;
4317
4318 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
4319 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
4320 return 0;
4321
4322 zif = zl3vni->vxlan_if->info;
4323 if (!zif)
4324 return -1;
4325
4326 vxl = &zif->l2info.vxl;
4327
4328 return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
4329 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
4330 }
4331
4332 /*
4333 * Uninstall remote RMAC from the kernel.
4334 */
4335 static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
4336 {
4337 char buf[ETHER_ADDR_STRLEN];
4338 struct zebra_if *zif = NULL;
4339 struct zebra_l2info_vxlan *vxl = NULL;
4340
4341 if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
4342 || !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
4343 return 0;
4344
4345 if (!zl3vni->vxlan_if) {
4346 zlog_debug(
4347 "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
4348 prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
4349 zl3vni->vni, zl3vni);
4350 return -1;
4351 }
4352
4353 zif = zl3vni->vxlan_if->info;
4354 if (!zif)
4355 return -1;
4356
4357 vxl = &zif->l2info.vxl;
4358
4359 return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
4360 &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
4361 }
4362
4363 /* handle rmac add */
4364 static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
4365 struct ipaddr *vtep_ip,
4366 struct prefix *host_prefix)
4367 {
4368 char buf[ETHER_ADDR_STRLEN];
4369 char buf1[INET6_ADDRSTRLEN];
4370 zebra_mac_t *zrmac = NULL;
4371
4372 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
4373 if (!zrmac) {
4374
4375 zrmac = zl3vni_rmac_add(zl3vni, rmac);
4376 if (!zrmac) {
4377 zlog_debug(
4378 "Failed to add RMAC %s L3VNI %u Remote VTEP %s",
4379 prefix_mac2str(rmac, buf, sizeof(buf)),
4380 zl3vni->vni,
4381 ipaddr2str(vtep_ip, buf1, sizeof(buf1)));
4382 return -1;
4383 }
4384 memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
4385 zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
4386
4387 /* install rmac in kernel */
4388 zl3vni_rmac_install(zl3vni, zrmac);
4389 }
4390
4391 rb_find_or_add_host(&zrmac->host_rb, host_prefix);
4392
4393 return 0;
4394 }
4395
4396
4397 /* handle rmac delete */
4398 static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
4399 struct prefix *host_prefix)
4400 {
4401 rb_delete_host(&zrmac->host_rb, host_prefix);
4402
4403 if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
4404 /* uninstall from kernel */
4405 zl3vni_rmac_uninstall(zl3vni, zrmac);
4406
4407 /* del the rmac entry */
4408 zl3vni_rmac_del(zl3vni, zrmac);
4409 }
4410 }
4411
4412 /*
4413 * Look up nh hash entry on a l3-vni.
4414 */
4415 static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
4416 {
4417 zebra_neigh_t tmp;
4418 zebra_neigh_t *n;
4419
4420 memset(&tmp, 0, sizeof(tmp));
4421 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
4422 n = hash_lookup(zl3vni->nh_table, &tmp);
4423
4424 return n;
4425 }
4426
4427
4428 /*
4429 * Callback to allocate NH hash entry on L3-VNI.
4430 */
4431 static void *zl3vni_nh_alloc(void *p)
4432 {
4433 const zebra_neigh_t *tmp_n = p;
4434 zebra_neigh_t *n;
4435
4436 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
4437 *n = *tmp_n;
4438
4439 return ((void *)n);
4440 }
4441
4442 /*
4443 * Add neighbor entry.
4444 */
4445 static zebra_neigh_t *zl3vni_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
4446 struct ethaddr *mac)
4447 {
4448 zebra_neigh_t tmp_n;
4449 zebra_neigh_t *n = NULL;
4450
4451 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
4452 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
4453 n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
4454 assert(n);
4455
4456 RB_INIT(host_rb_tree_entry, &n->host_rb);
4457
4458 memcpy(&n->emac, mac, ETH_ALEN);
4459 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
4460 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
4461
4462 return n;
4463 }
4464
4465 /*
4466 * Delete neighbor entry.
4467 */
4468 static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
4469 {
4470 zebra_neigh_t *tmp_n;
4471 struct host_rb_entry *hle;
4472
4473 while (!RB_EMPTY(host_rb_tree_entry, &n->host_rb)) {
4474 hle = RB_ROOT(host_rb_tree_entry, &n->host_rb);
4475
4476 RB_REMOVE(host_rb_tree_entry, &n->host_rb, hle);
4477 XFREE(MTYPE_HOST_PREFIX, hle);
4478 }
4479
4480 tmp_n = hash_release(zl3vni->nh_table, n);
4481 if (tmp_n)
4482 XFREE(MTYPE_NEIGH, tmp_n);
4483
4484 return 0;
4485 }
4486
4487 /*
4488 * Install remote nh as neigh into the kernel.
4489 */
4490 static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
4491 {
4492 #ifdef GNU_LINUX
4493 uint8_t flags;
4494 #endif
4495 int ret = 0;
4496
4497 if (!is_l3vni_oper_up(zl3vni))
4498 return -1;
4499
4500 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
4501 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
4502 return 0;
4503 #ifdef GNU_LINUX
4504 flags = NTF_EXT_LEARNED;
4505 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
4506 flags |= NTF_ROUTER;
4507 ret = kernel_add_neigh(zl3vni->svi_if, &n->ip, &n->emac, flags);
4508 #endif
4509 return ret;
4510 }
4511
4512 /*
4513 * Uninstall remote nh from the kernel.
4514 */
4515 static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
4516 {
4517 if (!(n->flags & ZEBRA_NEIGH_REMOTE)
4518 || !(n->flags & ZEBRA_NEIGH_REMOTE_NH))
4519 return 0;
4520
4521 if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
4522 return 0;
4523
4524 return kernel_del_neigh(zl3vni->svi_if, &n->ip);
4525 }
4526
4527 /* add remote vtep as a neigh entry */
4528 static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
4529 struct ethaddr *rmac,
4530 struct prefix *host_prefix)
4531 {
4532 char buf[ETHER_ADDR_STRLEN];
4533 char buf1[INET6_ADDRSTRLEN];
4534 zebra_neigh_t *nh = NULL;
4535
4536 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
4537 if (!nh) {
4538 nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
4539 if (!nh) {
4540
4541 zlog_debug(
4542 "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)",
4543 ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
4544 prefix_mac2str(rmac, buf, sizeof(buf)),
4545 zl3vni->vni);
4546 return -1;
4547 }
4548
4549 /* install the nh neigh in kernel */
4550 zl3vni_nh_install(zl3vni, nh);
4551 }
4552
4553 rb_find_or_add_host(&nh->host_rb, host_prefix);
4554
4555 return 0;
4556 }
4557
4558 /* handle nh neigh delete */
4559 static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh,
4560 struct prefix *host_prefix)
4561 {
4562 rb_delete_host(&nh->host_rb, host_prefix);
4563
4564 if (RB_EMPTY(host_rb_tree_entry, &nh->host_rb)) {
4565 /* uninstall from kernel */
4566 zl3vni_nh_uninstall(zl3vni, nh);
4567
4568 /* delete the nh entry */
4569 zl3vni_nh_del(zl3vni, nh);
4570 }
4571 }
4572
4573 /* handle neigh update from kernel - the only thing of interest is to
4574 * readd stale entries.
4575 */
4576 static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni, struct ipaddr *ip,
4577 uint16_t state)
4578 {
4579 #ifdef GNU_LINUX
4580 zebra_neigh_t *n = NULL;
4581
4582 n = zl3vni_nh_lookup(zl3vni, ip);
4583 if (!n)
4584 return 0;
4585
4586 /* all next hop neigh are remote and installed by frr.
4587 * If the kernel has aged this entry, re-install.
4588 */
4589 if (state & NUD_STALE)
4590 zl3vni_nh_install(zl3vni, n);
4591 #endif
4592 return 0;
4593 }
4594
4595 /* handle neigh delete from kernel */
4596 static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
4597 {
4598 zebra_neigh_t *n = NULL;
4599
4600 n = zl3vni_nh_lookup(zl3vni, ip);
4601 if (!n)
4602 return 0;
4603
4604 /* all next hop neigh are remote and installed by frr.
4605 * If we get an age out notification for these neigh entries, we have to
4606 * install it back
4607 */
4608 zl3vni_nh_install(zl3vni, n);
4609
4610 return 0;
4611 }
4612
4613 /*
4614 * Hash function for L3 VNI.
4615 */
4616 static unsigned int l3vni_hash_keymake(void *p)
4617 {
4618 const zebra_l3vni_t *zl3vni = p;
4619
4620 return jhash_1word(zl3vni->vni, 0);
4621 }
4622
4623 /*
4624 * Compare 2 L3 VNI hash entries.
4625 */
4626 static bool l3vni_hash_cmp(const void *p1, const void *p2)
4627 {
4628 const zebra_l3vni_t *zl3vni1 = p1;
4629 const zebra_l3vni_t *zl3vni2 = p2;
4630
4631 return (zl3vni1->vni == zl3vni2->vni);
4632 }
4633
4634 /*
4635 * Callback to allocate L3 VNI hash entry.
4636 */
4637 static void *zl3vni_alloc(void *p)
4638 {
4639 zebra_l3vni_t *zl3vni = NULL;
4640 const zebra_l3vni_t *tmp_l3vni = p;
4641
4642 zl3vni = XCALLOC(MTYPE_ZL3VNI, sizeof(zebra_l3vni_t));
4643 zl3vni->vni = tmp_l3vni->vni;
4644 return ((void *)zl3vni);
4645 }
4646
4647 /*
4648 * Look up L3 VNI hash entry.
4649 */
4650 static zebra_l3vni_t *zl3vni_lookup(vni_t vni)
4651 {
4652 zebra_l3vni_t tmp_l3vni;
4653 zebra_l3vni_t *zl3vni = NULL;
4654
4655 memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t));
4656 tmp_l3vni.vni = vni;
4657 zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni);
4658
4659 return zl3vni;
4660 }
4661
4662 /*
4663 * Add L3 VNI hash entry.
4664 */
4665 static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id)
4666 {
4667 zebra_l3vni_t tmp_zl3vni;
4668 zebra_l3vni_t *zl3vni = NULL;
4669
4670 memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t));
4671 tmp_zl3vni.vni = vni;
4672
4673 zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc);
4674 assert(zl3vni);
4675
4676 zl3vni->vrf_id = vrf_id;
4677 zl3vni->svi_if = NULL;
4678 zl3vni->vxlan_if = NULL;
4679 zl3vni->l2vnis = list_new();
4680 zl3vni->l2vnis->cmp = vni_list_cmp;
4681
4682 /* Create hash table for remote RMAC */
4683 zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp,
4684 "Zebra L3-VNI RMAC-Table");
4685
4686 /* Create hash table for neighbors */
4687 zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp,
4688 "Zebra L3-VNI next-hop table");
4689
4690 return zl3vni;
4691 }
4692
4693 /*
4694 * Delete L3 VNI hash entry.
4695 */
4696 static int zl3vni_del(zebra_l3vni_t *zl3vni)
4697 {
4698 zebra_l3vni_t *tmp_zl3vni;
4699
4700 /* free the list of l2vnis */
4701 list_delete(&zl3vni->l2vnis);
4702 zl3vni->l2vnis = NULL;
4703
4704 /* Free the rmac table */
4705 hash_free(zl3vni->rmac_table);
4706 zl3vni->rmac_table = NULL;
4707
4708 /* Free the nh table */
4709 hash_free(zl3vni->nh_table);
4710 zl3vni->nh_table = NULL;
4711
4712 /* Free the VNI hash entry and allocated memory. */
4713 tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
4714 if (tmp_zl3vni)
4715 XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
4716
4717 return 0;
4718 }
4719
4720 static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
4721 {
4722 struct zebra_ns *zns = NULL;
4723 struct route_node *rn = NULL;
4724 struct interface *ifp = NULL;
4725
4726 /* loop through all vxlan-interface */
4727 zns = zebra_ns_lookup(NS_DEFAULT);
4728 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
4729
4730 struct zebra_if *zif = NULL;
4731 struct zebra_l2info_vxlan *vxl = NULL;
4732
4733 ifp = (struct interface *)rn->info;
4734 if (!ifp)
4735 continue;
4736
4737 zif = ifp->info;
4738 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
4739 continue;
4740
4741 vxl = &zif->l2info.vxl;
4742 if (vxl->vni == zl3vni->vni) {
4743 zl3vni->local_vtep_ip = vxl->vtep_ip;
4744 return ifp;
4745 }
4746 }
4747
4748 return NULL;
4749 }
4750
4751 static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
4752 {
4753 struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
4754 struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
4755
4756 if (!zl3vni)
4757 return NULL;
4758
4759 if (!zl3vni->vxlan_if)
4760 return NULL;
4761
4762 zif = zl3vni->vxlan_if->info;
4763 if (!zif)
4764 return NULL;
4765
4766 vxl = &zif->l2info.vxl;
4767
4768 return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
4769 }
4770
4771 static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
4772 {
4773 struct zebra_vrf *zvrf = NULL;
4774
4775 zvrf = zebra_vrf_lookup_by_id(vrf_id);
4776 if (!zvrf)
4777 return NULL;
4778
4779 return zl3vni_lookup(zvrf->l3vni);
4780 }
4781
4782 /*
4783 * Map SVI and associated bridge to a VNI. This is invoked upon getting
4784 * neighbor notifications, to see if they are of interest.
4785 */
4786 static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
4787 struct interface *br_if)
4788 {
4789 int found = 0;
4790 vlanid_t vid = 0;
4791 uint8_t bridge_vlan_aware = 0;
4792 zebra_l3vni_t *zl3vni = NULL;
4793 struct zebra_ns *zns = NULL;
4794 struct route_node *rn = NULL;
4795 struct zebra_if *zif = NULL;
4796 struct interface *tmp_if = NULL;
4797 struct zebra_l2info_bridge *br = NULL;
4798 struct zebra_l2info_vxlan *vxl = NULL;
4799
4800 if (!br_if)
4801 return NULL;
4802
4803 /* Make sure the linked interface is a bridge. */
4804 if (!IS_ZEBRA_IF_BRIDGE(br_if))
4805 return NULL;
4806
4807 /* Determine if bridge is VLAN-aware or not */
4808 zif = br_if->info;
4809 assert(zif);
4810 br = &zif->l2info.br;
4811 bridge_vlan_aware = br->vlan_aware;
4812 if (bridge_vlan_aware) {
4813 struct zebra_l2info_vlan *vl;
4814
4815 if (!IS_ZEBRA_IF_VLAN(ifp))
4816 return NULL;
4817
4818 zif = ifp->info;
4819 assert(zif);
4820 vl = &zif->l2info.vl;
4821 vid = vl->vid;
4822 }
4823
4824 /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
4825 /* TODO: Optimize with a hash. */
4826 zns = zebra_ns_lookup(NS_DEFAULT);
4827 for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
4828 tmp_if = (struct interface *)rn->info;
4829 if (!tmp_if)
4830 continue;
4831 zif = tmp_if->info;
4832 if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
4833 continue;
4834 if (!if_is_operative(tmp_if))
4835 continue;
4836 vxl = &zif->l2info.vxl;
4837
4838 if (zif->brslave_info.br_if != br_if)
4839 continue;
4840
4841 if (!bridge_vlan_aware || vxl->access_vlan == vid) {
4842 found = 1;
4843 break;
4844 }
4845 }
4846
4847 if (!found)
4848 return NULL;
4849
4850 zl3vni = zl3vni_lookup(vxl->vni);
4851 return zl3vni;
4852 }
4853
4854 /*
4855 * Inform BGP about l3-vni.
4856 */
4857 static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
4858 {
4859 struct stream *s = NULL;
4860 struct zserv *client = NULL;
4861 struct ethaddr rmac;
4862 char buf[ETHER_ADDR_STRLEN];
4863
4864 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
4865 /* BGP may not be running. */
4866 if (!client)
4867 return 0;
4868
4869 /* get the rmac */
4870 memset(&rmac, 0, sizeof(struct ethaddr));
4871 zl3vni_get_rmac(zl3vni, &rmac);
4872
4873 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
4874
4875 zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
4876 stream_putl(s, zl3vni->vni);
4877 stream_put(s, &rmac, sizeof(struct ethaddr));
4878 stream_put_in_addr(s, &zl3vni->local_vtep_ip);
4879 stream_put(s, &zl3vni->filter, sizeof(int));
4880
4881 /* Write packet size. */
4882 stream_putw_at(s, 0, stream_get_endp(s));
4883
4884 if (IS_ZEBRA_DEBUG_VXLAN)
4885 zlog_debug(
4886 "Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
4887 zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
4888 prefix_mac2str(&rmac, buf, sizeof(buf)),
4889 inet_ntoa(zl3vni->local_vtep_ip),
4890 CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
4891 ? "prefix-routes-only"
4892 : "none",
4893 zebra_route_string(client->proto));
4894
4895 client->l3vniadd_cnt++;
4896 return zserv_send_message(client, s);
4897 }
4898
4899 /*
4900 * Inform BGP about local l3-VNI deletion.
4901 */
4902 static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
4903 {
4904 struct stream *s = NULL;
4905 struct zserv *client = NULL;
4906
4907 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
4908 /* BGP may not be running. */
4909 if (!client)
4910 return 0;
4911
4912 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
4913
4914 zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
4915 stream_putl(s, zl3vni->vni);
4916
4917 /* Write packet size. */
4918 stream_putw_at(s, 0, stream_get_endp(s));
4919
4920 if (IS_ZEBRA_DEBUG_VXLAN)
4921 zlog_debug("Send L3_VNI_DEL %u VRF %s to %s", zl3vni->vni,
4922 vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
4923 zebra_route_string(client->proto));
4924
4925 client->l3vnidel_cnt++;
4926 return zserv_send_message(client, s);
4927 }
4928
4929 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
4930 {
4931 if (!zl3vni)
4932 return;
4933
4934 /* send l3vni add to BGP */
4935 zl3vni_send_add_to_client(zl3vni);
4936 }
4937
4938 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
4939 {
4940 if (!zl3vni)
4941 return;
4942
4943 /* send l3-vni del to BGP*/
4944 zl3vni_send_del_to_client(zl3vni);
4945 }
4946
4947 static void zvni_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
4948 {
4949 zebra_vni_t *zvni = (zebra_vni_t *)bucket->data;
4950 zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt;
4951
4952 if (zvni->vrf_id == zl3vni_vrf_id(zl3vni))
4953 listnode_add_sort(zl3vni->l2vnis, zvni);
4954 }
4955
4956 /*
4957 * handle transition of vni from l2 to l3 and vice versa
4958 */
4959 static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
4960 int add)
4961 {
4962 zebra_vni_t *zvni = NULL;
4963
4964 /* There is a possibility that VNI notification was already received
4965 * from kernel and we programmed it as L2-VNI
4966 * In such a case we need to delete this L2-VNI first, so
4967 * that it can be reprogrammed as L3-VNI in the system. It is also
4968 * possible that the vrf-vni mapping is removed from FRR while the vxlan
4969 * interface is still present in kernel. In this case to keep it
4970 * symmetric, we will delete the l3-vni and reprogram it as l2-vni
4971 */
4972 if (add) {
4973 /* Locate hash entry */
4974 zvni = zvni_lookup(vni);
4975 if (!zvni)
4976 return 0;
4977
4978 if (IS_ZEBRA_DEBUG_VXLAN)
4979 zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni);
4980
4981 /* Delete VNI from BGP. */
4982 zvni_send_del_to_client(zvni->vni);
4983
4984 /* Free up all neighbors and MAC, if any. */
4985 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
4986 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
4987
4988 /* Free up all remote VTEPs, if any. */
4989 zvni_vtep_del_all(zvni, 0);
4990
4991 /* Delete the hash entry. */
4992 if (zvni_del(zvni)) {
4993 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
4994 "Failed to del VNI hash %p, VNI %u", zvni,
4995 zvni->vni);
4996 return -1;
4997 }
4998 } else {
4999 /* TODO_MITESH: This needs to be thought through. We don't have
5000 * enough information at this point to reprogram the vni as
5001 * l2-vni. One way is to store the required info in l3-vni and
5002 * used it solely for this purpose
5003 */
5004 }
5005
5006 return 0;
5007 }
5008
5009 /* delete and uninstall rmac hash entry */
5010 static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
5011 {
5012 zebra_mac_t *zrmac = NULL;
5013 zebra_l3vni_t *zl3vni = NULL;
5014
5015 zrmac = (zebra_mac_t *)bucket->data;
5016 zl3vni = (zebra_l3vni_t *)ctx;
5017 zl3vni_rmac_uninstall(zl3vni, zrmac);
5018 zl3vni_rmac_del(zl3vni, zrmac);
5019 }
5020
5021 /* delete and uninstall nh hash entry */
5022 static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
5023 {
5024 zebra_neigh_t *n = NULL;
5025 zebra_l3vni_t *zl3vni = NULL;
5026
5027 n = (zebra_neigh_t *)bucket->data;
5028 zl3vni = (zebra_l3vni_t *)ctx;
5029 zl3vni_nh_uninstall(zl3vni, n);
5030 zl3vni_nh_del(zl3vni, n);
5031 }
5032
5033 static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
5034 uint16_t cmd)
5035 {
5036 struct zserv *client = NULL;
5037 struct stream *s = NULL;
5038 char buf[PREFIX_STRLEN];
5039
5040 client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
5041 /* BGP may not be running. */
5042 if (!client)
5043 return 0;
5044
5045 s = stream_new(ZEBRA_MAX_PACKET_SIZ);
5046
5047 zclient_create_header(s, cmd, vrf_id);
5048 stream_put(s, p, sizeof(struct prefix));
5049
5050 /* Write packet size. */
5051 stream_putw_at(s, 0, stream_get_endp(s));
5052
5053 if (IS_ZEBRA_DEBUG_VXLAN)
5054 zlog_debug("Send ip prefix %s %s on vrf %s",
5055 prefix2str(p, buf, sizeof(buf)),
5056 (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
5057 vrf_id_to_name(vrf_id));
5058
5059 if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD)
5060 client->prefixadd_cnt++;
5061 else
5062 client->prefixdel_cnt++;
5063
5064 return zserv_send_message(client, s);
5065 }
5066
5067 /* re-add remote rmac if needed */
5068 static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
5069 struct ethaddr *rmac)
5070 {
5071 char buf[ETHER_ADDR_STRLEN];
5072 zebra_mac_t *zrmac = NULL;
5073
5074 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
5075 if (!zrmac)
5076 return 0;
5077
5078 if (IS_ZEBRA_DEBUG_VXLAN)
5079 zlog_debug("Del remote RMAC %s L3VNI %u - readd",
5080 prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni);
5081
5082 zl3vni_rmac_install(zl3vni, zrmac);
5083 return 0;
5084 }
5085
5086 /* Process a remote MACIP add from BGP. */
5087 static void process_remote_macip_add(vni_t vni,
5088 struct ethaddr *macaddr,
5089 uint16_t ipa_len,
5090 struct ipaddr *ipaddr,
5091 uint8_t flags,
5092 uint32_t seq,
5093 struct in_addr vtep_ip)
5094 {
5095 zebra_vni_t *zvni;
5096 zebra_vtep_t *zvtep;
5097 zebra_mac_t *mac = NULL, *old_mac = NULL;
5098 zebra_neigh_t *n = NULL;
5099 int update_mac = 0, update_neigh = 0;
5100 char buf[ETHER_ADDR_STRLEN];
5101 char buf1[INET6_ADDRSTRLEN];
5102 struct interface *ifp = NULL;
5103 struct zebra_if *zif = NULL;
5104 struct zebra_vrf *zvrf;
5105 uint32_t tmp_seq;
5106 bool sticky;
5107 bool remote_gw;
5108 bool is_router;
5109 bool do_dad = false;
5110 bool is_dup_detect = false;
5111
5112 /* Locate VNI hash entry - expected to exist. */
5113 zvni = zvni_lookup(vni);
5114 if (!zvni) {
5115 zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni);
5116 return;
5117 }
5118
5119 ifp = zvni->vxlan_if;
5120 if (ifp)
5121 zif = ifp->info;
5122 if (!ifp ||
5123 !if_is_operative(ifp) ||
5124 !zif ||
5125 !zif->brslave_info.br_if) {
5126 zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info",
5127 vni);
5128 return;
5129 }
5130
5131 /* The remote VTEP specified should normally exist, but it is
5132 * possible that when peering comes up, peer may advertise MACIP
5133 * routes before advertising type-3 routes.
5134 */
5135 zvtep = zvni_vtep_find(zvni, &vtep_ip);
5136 if (!zvtep) {
5137 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
5138 flog_err(
5139 EC_ZEBRA_VTEP_ADD_FAILED,
5140 "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD",
5141 vni, zvni);
5142 return;
5143 }
5144
5145 zvni_vtep_install(zvni, &vtep_ip);
5146 }
5147
5148 sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
5149 remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
5150 is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
5151
5152 mac = zvni_mac_lookup(zvni, macaddr);
5153
5154 /* Ignore if the mac is already present as a gateway mac */
5155 if (mac &&
5156 CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) &&
5157 CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
5158 if (IS_ZEBRA_DEBUG_VXLAN)
5159 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5160 vni,
5161 prefix_mac2str(macaddr, buf, sizeof(buf)),
5162 ipa_len ? " IP " : "",
5163 ipa_len ?
5164 ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");
5165 return;
5166 }
5167
5168 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
5169 if (!zvrf)
5170 return;
5171
5172 /* check if the remote MAC is unknown or has a change.
5173 * If so, that needs to be updated first. Note that client could
5174 * install MAC and MACIP separately or just install the latter.
5175 */
5176 if (!mac
5177 || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
5178 || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
5179 || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
5180 || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
5181 || seq != mac->rem_seq)
5182 update_mac = 1;
5183
5184 if (update_mac) {
5185 if (!mac) {
5186 mac = zvni_mac_add(zvni, macaddr);
5187 if (!mac) {
5188 zlog_warn(
5189 "Failed to add MAC %s VNI %u Remote VTEP %s",
5190 prefix_mac2str(macaddr, buf,
5191 sizeof(buf)),
5192 vni, inet_ntoa(vtep_ip));
5193 return;
5194 }
5195
5196 /* Is this MAC created for a MACIP? */
5197 if (ipa_len)
5198 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5199 } else {
5200 const char *mac_type;
5201
5202 /* When host moves but changes its (MAC,IP)
5203 * binding, BGP may install a MACIP entry that
5204 * corresponds to "older" location of the host
5205 * in transient situations (because {IP1,M1}
5206 * is a different route from {IP1,M2}). Check
5207 * the sequence number and ignore this update
5208 * if appropriate.
5209 */
5210 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
5211 tmp_seq = mac->loc_seq;
5212 mac_type = "local";
5213 } else {
5214 tmp_seq = mac->rem_seq;
5215 mac_type = "remote";
5216 }
5217 if (seq < tmp_seq) {
5218 if (IS_ZEBRA_DEBUG_VXLAN)
5219 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s MAC has higher seq %u",
5220 vni,
5221 prefix_mac2str(macaddr,
5222 buf, sizeof(buf)),
5223 ipa_len ? " IP " : "",
5224 ipa_len ?
5225 ipaddr2str(ipaddr,
5226 buf1, sizeof(buf1)) : "",
5227 mac_type,
5228 tmp_seq);
5229 return;
5230 }
5231 }
5232
5233 /* Check MAC's curent state is local (this is the case
5234 * where MAC has moved from L->R) and check previous
5235 * detection started via local learning.
5236 * RFC-7432: A PE/VTEP that detects a MAC mobility
5237 * event via local learning starts an M-second timer.
5238 *
5239 * VTEP-IP or seq. change alone is not considered
5240 * for dup. detection.
5241 *
5242 * MAC is already marked duplicate set dad, then
5243 * is_dup_detect will be set to not install the entry.
5244 */
5245 if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) &&
5246 mac->dad_count) ||
5247 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
5248 do_dad = true;
5249
5250 /* Remove local MAC from BGP. */
5251 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
5252 zvni_mac_send_del_to_client(zvni->vni, macaddr);
5253
5254 /* Set "auto" and "remote" forwarding info. */
5255 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
5256 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
5257 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5258 mac->fwd_info.r_vtep_ip = vtep_ip;
5259
5260 if (sticky)
5261 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5262 else
5263 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
5264
5265 if (remote_gw)
5266 SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5267 else
5268 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
5269
5270 zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac,
5271 mac->fwd_info.r_vtep_ip,
5272 do_dad, &is_dup_detect,
5273 false);
5274
5275 if (!is_dup_detect) {
5276 zvni_process_neigh_on_remote_mac_add(zvni, mac);
5277 /* Install the entry. */
5278 zvni_mac_install(zvni, mac);
5279 }
5280 }
5281
5282 /* Update seq number. */
5283 mac->rem_seq = seq;
5284
5285 /* If there is no IP, return after clearing AUTO flag of MAC. */
5286 if (!ipa_len) {
5287 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5288 return;
5289 }
5290
5291 /* Reset flag */
5292 do_dad = false;
5293
5294 /* Check if the remote neighbor itself is unknown or has a
5295 * change. If so, create or update and then install the entry.
5296 */
5297 n = zvni_neigh_lookup(zvni, ipaddr);
5298 if (!n
5299 || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5300 || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)
5301 || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0)
5302 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)
5303 || seq != n->rem_seq)
5304 update_neigh = 1;
5305
5306 if (update_neigh) {
5307 if (!n) {
5308 n = zvni_neigh_add(zvni, ipaddr, macaddr);
5309 if (!n) {
5310 zlog_warn(
5311 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
5312 ipaddr2str(ipaddr, buf1,
5313 sizeof(buf1)),
5314 prefix_mac2str(macaddr, buf,
5315 sizeof(buf)),
5316 vni, inet_ntoa(vtep_ip));
5317 return;
5318 }
5319
5320 } else {
5321 const char *n_type;
5322
5323 /* When host moves but changes its (MAC,IP)
5324 * binding, BGP may install a MACIP entry that
5325 * corresponds to "older" location of the host
5326 * in transient situations (because {IP1,M1}
5327 * is a different route from {IP1,M2}). Check
5328 * the sequence number and ignore this update
5329 * if appropriate.
5330 */
5331 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
5332 tmp_seq = n->loc_seq;
5333 n_type = "local";
5334 } else {
5335 tmp_seq = n->rem_seq;
5336 n_type = "remote";
5337 }
5338 if (seq < tmp_seq) {
5339 if (IS_ZEBRA_DEBUG_VXLAN)
5340 zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
5341 vni,
5342 prefix_mac2str(macaddr,
5343 buf, sizeof(buf)),
5344 " IP ",
5345 ipaddr2str(ipaddr, buf1, sizeof(buf1)),
5346 n_type,
5347 tmp_seq);
5348 return;
5349 }
5350 if (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) {
5351 /* MAC change, send a delete for old
5352 * neigh if learnt locally.
5353 */
5354 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) &&
5355 IS_ZEBRA_NEIGH_ACTIVE(n))
5356 zvni_neigh_send_del_to_client(
5357 zvni->vni, &n->ip,
5358 &n->emac, 0, n->state);
5359
5360 /* update neigh list for macs */
5361 old_mac = zvni_mac_lookup(zvni, &n->emac);
5362 if (old_mac) {
5363 listnode_delete(old_mac->neigh_list, n);
5364 zvni_deref_ip2mac(zvni, old_mac);
5365 }
5366 listnode_add_sort(mac->neigh_list, n);
5367 memcpy(&n->emac, macaddr, ETH_ALEN);
5368
5369 /* Check Neigh's curent state is local
5370 * (this is the case where neigh/host has moved
5371 * from L->R) and check previous detction
5372 * started via local learning.
5373 *
5374 * RFC-7432: A PE/VTEP that detects a MAC
5375 * mobilit event via local learning starts
5376 * an M-second timer.
5377 * VTEP-IP or seq. change along is not
5378 * considered for dup. detection.
5379 *
5380 * Mobilty event scenario-B IP-MAC binding
5381 * changed.
5382 */
5383 if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
5384 && n->dad_count)
5385 do_dad = true;
5386
5387 }
5388 }
5389
5390 /* Set "remote" forwarding info. */
5391 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
5392 n->r_vtep_ip = vtep_ip;
5393 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
5394
5395 /* Set router flag (R-bit) to this Neighbor entry */
5396 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
5397 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
5398 else
5399 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
5400
5401 /* Check old or new MAC detected as duplicate,
5402 * inherit duplicate flag to this neigh.
5403 */
5404 if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_mac,
5405 mac, n)) {
5406 flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
5407 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
5408 zvni->vni,
5409 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
5410 ipaddr2str(&n->ip, buf1, sizeof(buf1)));
5411 }
5412
5413 /* Check duplicate address detection for IP */
5414 zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n,
5415 n->r_vtep_ip,
5416 do_dad,
5417 &is_dup_detect,
5418 false);
5419 /* Install the entry. */
5420 if (!is_dup_detect)
5421 zvni_neigh_install(zvni, n);
5422 }
5423
5424 zvni_probe_neigh_on_mac_add(zvni, mac);
5425
5426 /* Update seq number. */
5427 n->rem_seq = seq;
5428 }
5429
5430 /* Process a remote MACIP delete from BGP. */
5431 static void process_remote_macip_del(vni_t vni,
5432 struct ethaddr *macaddr,
5433 uint16_t ipa_len,
5434 struct ipaddr *ipaddr,
5435 struct in_addr vtep_ip)
5436 {
5437 zebra_vni_t *zvni;
5438 zebra_mac_t *mac = NULL;
5439 zebra_neigh_t *n = NULL;
5440 struct interface *ifp = NULL;
5441 struct zebra_if *zif = NULL;
5442 struct zebra_ns *zns;
5443 struct zebra_l2info_vxlan *vxl;
5444 struct zebra_vrf *zvrf;
5445 char buf[ETHER_ADDR_STRLEN];
5446 char buf1[INET6_ADDRSTRLEN];
5447
5448 /* Locate VNI hash entry - expected to exist. */
5449 zvni = zvni_lookup(vni);
5450 if (!zvni) {
5451 if (IS_ZEBRA_DEBUG_VXLAN)
5452 zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni);
5453 return;
5454 }
5455
5456 ifp = zvni->vxlan_if;
5457 if (ifp)
5458 zif = ifp->info;
5459 if (!ifp ||
5460 !if_is_operative(ifp) ||
5461 !zif ||
5462 !zif->brslave_info.br_if) {
5463 if (IS_ZEBRA_DEBUG_VXLAN)
5464 zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info",
5465 vni);
5466 return;
5467 }
5468 zns = zebra_ns_lookup(NS_DEFAULT);
5469 vxl = &zif->l2info.vxl;
5470
5471 /* The remote VTEP specified is normally expected to exist, but
5472 * it is possible that the peer may delete the VTEP before deleting
5473 * any MACs referring to the VTEP, in which case the handler (see
5474 * remote_vtep_del) would have already deleted the MACs.
5475 */
5476 if (!zvni_vtep_find(zvni, &vtep_ip))
5477 return;
5478
5479 mac = zvni_mac_lookup(zvni, macaddr);
5480 if (ipa_len)
5481 n = zvni_neigh_lookup(zvni, ipaddr);
5482
5483 if (n && !mac) {
5484 zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
5485 prefix_mac2str(macaddr, buf, sizeof(buf)),
5486 ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni);
5487 return;
5488 }
5489
5490 /* If the remote mac or neighbor doesn't exist there is nothing
5491 * more to do. Otherwise, uninstall the entry and then remove it.
5492 */
5493 if (!mac && !n)
5494 return;
5495
5496 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
5497
5498 /* Ignore the delete if this mac is a gateway mac-ip */
5499 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
5500 && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
5501 zlog_warn(
5502 "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
5503 vni,
5504 prefix_mac2str(macaddr, buf, sizeof(buf)),
5505 ipa_len ? " IP " : "",
5506 ipa_len ?
5507 ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");
5508 return;
5509 }
5510
5511 /* Uninstall remote neighbor or MAC. */
5512 if (n) {
5513 if (zvrf->dad_freeze &&
5514 CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) &&
5515 CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) &&
5516 (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
5517 struct interface *vlan_if;
5518
5519 vlan_if = zvni_map_to_svi(vxl->access_vlan,
5520 zif->brslave_info.br_if);
5521 if (IS_ZEBRA_DEBUG_VXLAN)
5522 zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
5523 __PRETTY_FUNCTION__,
5524 ipaddr2str(ipaddr, buf1,
5525 sizeof(buf1)), n->flags,
5526 vlan_if->name);
5527 neigh_read_specific_ip(ipaddr, vlan_if);
5528 }
5529
5530 /* When the MAC changes for an IP, it is possible the
5531 * client may update the new MAC before trying to delete the
5532 * "old" neighbor (as these are two different MACIP routes).
5533 * Do the delete only if the MAC matches.
5534 */
5535 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
5536 && (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
5537 zvni_neigh_uninstall(zvni, n);
5538 zvni_neigh_del(zvni, n);
5539 zvni_deref_ip2mac(zvni, mac);
5540 }
5541 } else {
5542 /* DAD: when MAC is freeze state as remote learn event,
5543 * remote mac-ip delete event is received will result in freeze
5544 * entry removal, first fetch kernel for the same entry present
5545 * as LOCAL and reachable, avoid deleting this entry instead
5546 * use kerenel local entry to update during unfreeze time.
5547 */
5548 if (zvrf->dad_freeze &&
5549 CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) &&
5550 CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5551 if (IS_ZEBRA_DEBUG_VXLAN)
5552 zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
5553 __PRETTY_FUNCTION__,
5554 prefix_mac2str(macaddr, buf,
5555 sizeof(buf)),
5556 mac->flags);
5557 macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
5558 macaddr, vxl->access_vlan);
5559 }
5560
5561 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
5562 zvni_process_neigh_on_remote_mac_del(zvni, mac);
5563 /*
5564 * the remote sequence number in the auto mac entry
5565 * needs to be reset to 0 as the mac entry may have
5566 * been removed on all VTEPs (including
5567 * the originating one)
5568 */
5569 mac->rem_seq = 0;
5570
5571 /* If all remote neighbors referencing a remote MAC
5572 * go away, we need to uninstall the MAC.
5573 */
5574 if (remote_neigh_count(mac) == 0) {
5575 zvni_mac_uninstall(zvni, mac);
5576 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
5577 }
5578 if (list_isempty(mac->neigh_list))
5579 zvni_mac_del(zvni, mac);
5580 else
5581 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
5582 }
5583 }
5584 }
5585
5586
5587 /* Public functions */
5588
5589 int is_l3vni_for_prefix_routes_only(vni_t vni)
5590 {
5591 zebra_l3vni_t *zl3vni = NULL;
5592
5593 zl3vni = zl3vni_lookup(vni);
5594 if (!zl3vni)
5595 return 0;
5596
5597 return CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? 1 : 0;
5598 }
5599
5600 /* handle evpn route in vrf table */
5601 void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
5602 struct ipaddr *vtep_ip,
5603 struct prefix *host_prefix)
5604 {
5605 zebra_l3vni_t *zl3vni = NULL;
5606 struct ipaddr ipv4_vtep;
5607
5608 zl3vni = zl3vni_from_vrf(vrf_id);
5609 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
5610 return;
5611
5612 /*
5613 * add the next hop neighbor -
5614 * neigh to be installed is the ipv6 nexthop neigh
5615 */
5616 zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
5617
5618 /*
5619 * if the remote vtep is a ipv4 mapped ipv6 address convert it to ipv4
5620 * address. Rmac is programmed against the ipv4 vtep because we only
5621 * support ipv4 tunnels in the h/w right now
5622 */
5623 memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
5624 ipv4_vtep.ipa_type = IPADDR_V4;
5625 if (vtep_ip->ipa_type == IPADDR_V6)
5626 ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
5627 &(ipv4_vtep.ipaddr_v4));
5628 else
5629 memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
5630 sizeof(struct in_addr));
5631
5632 /*
5633 * add the rmac - remote rmac to be installed is against the ipv4
5634 * nexthop address
5635 */
5636 zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
5637 }
5638
5639 /* handle evpn vrf route delete */
5640 void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
5641 struct ipaddr *vtep_ip,
5642 struct prefix *host_prefix)
5643 {
5644 zebra_l3vni_t *zl3vni = NULL;
5645 zebra_neigh_t *nh = NULL;
5646 zebra_mac_t *zrmac = NULL;
5647
5648 zl3vni = zl3vni_from_vrf(vrf_id);
5649 if (!zl3vni)
5650 return;
5651
5652 /* find the next hop entry and rmac entry */
5653 nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
5654 if (!nh)
5655 return;
5656 zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
5657
5658 /* delete the next hop entry */
5659 zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
5660
5661 /* delete the rmac entry */
5662 if (zrmac)
5663 zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
5664
5665 }
5666
5667 void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
5668 struct ethaddr *rmac, bool use_json)
5669 {
5670 zebra_l3vni_t *zl3vni = NULL;
5671 zebra_mac_t *zrmac = NULL;
5672 json_object *json = NULL;
5673
5674 if (!is_evpn_enabled()) {
5675 if (use_json)
5676 vty_out(vty, "{}\n");
5677 return;
5678 }
5679
5680 if (use_json)
5681 json = json_object_new_object();
5682
5683 zl3vni = zl3vni_lookup(l3vni);
5684 if (!zl3vni) {
5685 if (use_json)
5686 vty_out(vty, "{}\n");
5687 else
5688 vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni);
5689 return;
5690 }
5691
5692 zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
5693 if (!zrmac) {
5694 if (use_json)
5695 vty_out(vty, "{}\n");
5696 else
5697 vty_out(vty,
5698 "%% Requested RMAC doesn't exist in L3-VNI %u",
5699 l3vni);
5700 return;
5701 }
5702
5703 zl3vni_print_rmac(zrmac, vty, json);
5704
5705 if (use_json) {
5706 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5707 json, JSON_C_TO_STRING_PRETTY));
5708 json_object_free(json);
5709 }
5710 }
5711
5712 void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
5713 {
5714 zebra_l3vni_t *zl3vni;
5715 uint32_t num_rmacs;
5716 struct rmac_walk_ctx wctx;
5717 json_object *json = NULL;
5718
5719 if (!is_evpn_enabled())
5720 return;
5721
5722 zl3vni = zl3vni_lookup(l3vni);
5723 if (!zl3vni) {
5724 if (use_json)
5725 vty_out(vty, "{}\n");
5726 else
5727 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
5728 return;
5729 }
5730 num_rmacs = hashcount(zl3vni->rmac_table);
5731 if (!num_rmacs)
5732 return;
5733
5734 if (use_json)
5735 json = json_object_new_object();
5736
5737 memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
5738 wctx.vty = vty;
5739 wctx.json = json;
5740 if (!use_json) {
5741 vty_out(vty, "Number of Remote RMACs known for this VNI: %u\n",
5742 num_rmacs);
5743 vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
5744 } else
5745 json_object_int_add(json, "numRmacs", num_rmacs);
5746
5747 hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
5748
5749 if (use_json) {
5750 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5751 json, JSON_C_TO_STRING_PRETTY));
5752 json_object_free(json);
5753 }
5754 }
5755
5756 void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json)
5757 {
5758 json_object *json = NULL;
5759 void *args[2];
5760
5761 if (!is_evpn_enabled()) {
5762 if (use_json)
5763 vty_out(vty, "{}\n");
5764 return;
5765 }
5766
5767 if (use_json)
5768 json = json_object_new_object();
5769
5770 args[0] = vty;
5771 args[1] = json;
5772 hash_iterate(zrouter.l3vni_table,
5773 (void (*)(struct hash_bucket *,
5774 void *))zl3vni_print_rmac_hash_all_vni,
5775 args);
5776
5777 if (use_json) {
5778 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5779 json, JSON_C_TO_STRING_PRETTY));
5780 json_object_free(json);
5781 }
5782 }
5783
5784 void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
5785 struct ipaddr *ip, bool use_json)
5786 {
5787 zebra_l3vni_t *zl3vni = NULL;
5788 zebra_neigh_t *n = NULL;
5789 json_object *json = NULL;
5790
5791 if (!is_evpn_enabled()) {
5792 if (use_json)
5793 vty_out(vty, "{}\n");
5794 return;
5795 }
5796
5797 if (use_json)
5798 json = json_object_new_object();
5799
5800 zl3vni = zl3vni_lookup(l3vni);
5801 if (!zl3vni) {
5802 if (use_json)
5803 vty_out(vty, "{}\n");
5804 else
5805 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
5806 return;
5807 }
5808
5809 n = zl3vni_nh_lookup(zl3vni, ip);
5810 if (!n) {
5811 if (use_json)
5812 vty_out(vty, "{}\n");
5813 else
5814 vty_out(vty,
5815 "%% Requested next-hop not present for L3-VNI %u",
5816 l3vni);
5817 return;
5818 }
5819
5820 zl3vni_print_nh(n, vty, json);
5821
5822 if (use_json) {
5823 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5824 json, JSON_C_TO_STRING_PRETTY));
5825 json_object_free(json);
5826 }
5827 }
5828
5829 void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json)
5830 {
5831 uint32_t num_nh;
5832 struct nh_walk_ctx wctx;
5833 json_object *json = NULL;
5834 zebra_l3vni_t *zl3vni = NULL;
5835
5836 if (!is_evpn_enabled())
5837 return;
5838
5839 zl3vni = zl3vni_lookup(l3vni);
5840 if (!zl3vni) {
5841 if (use_json)
5842 vty_out(vty, "{}\n");
5843 else
5844 vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
5845 return;
5846 }
5847
5848 num_nh = hashcount(zl3vni->nh_table);
5849 if (!num_nh)
5850 return;
5851
5852 if (use_json)
5853 json = json_object_new_object();
5854
5855 wctx.vty = vty;
5856 wctx.json = json;
5857 if (!use_json) {
5858 vty_out(vty, "Number of NH Neighbors known for this VNI: %u\n",
5859 num_nh);
5860 vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
5861 } else
5862 json_object_int_add(json, "numNextHops", num_nh);
5863
5864 hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
5865
5866 if (use_json) {
5867 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5868 json, JSON_C_TO_STRING_PRETTY));
5869 json_object_free(json);
5870 }
5871 }
5872
5873 void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json)
5874 {
5875 json_object *json = NULL;
5876 void *args[2];
5877
5878 if (!is_evpn_enabled()) {
5879 if (use_json)
5880 vty_out(vty, "{}\n");
5881 return;
5882 }
5883
5884 if (use_json)
5885 json = json_object_new_object();
5886
5887 args[0] = vty;
5888 args[1] = json;
5889 hash_iterate(zrouter.l3vni_table,
5890 (void (*)(struct hash_bucket *,
5891 void *))zl3vni_print_nh_hash_all_vni,
5892 args);
5893
5894 if (use_json) {
5895 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5896 json, JSON_C_TO_STRING_PRETTY));
5897 json_object_free(json);
5898 }
5899 }
5900
5901 /*
5902 * Display L3 VNI information (VTY command handler).
5903 */
5904 void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, bool use_json)
5905 {
5906 void *args[2];
5907 json_object *json = NULL;
5908 zebra_l3vni_t *zl3vni = NULL;
5909
5910 if (!is_evpn_enabled()) {
5911 if (use_json)
5912 vty_out(vty, "{}\n");
5913 return;
5914 }
5915
5916 zl3vni = zl3vni_lookup(vni);
5917 if (!zl3vni) {
5918 if (use_json)
5919 vty_out(vty, "{}\n");
5920 else
5921 vty_out(vty, "%% VNI %u does not exist\n", vni);
5922 return;
5923 }
5924
5925 if (use_json)
5926 json = json_object_new_object();
5927
5928 args[0] = vty;
5929 args[1] = json;
5930 zl3vni_print(zl3vni, (void *)args);
5931
5932 if (use_json) {
5933 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5934 json, JSON_C_TO_STRING_PRETTY));
5935 json_object_free(json);
5936 }
5937 }
5938
5939 void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
5940 json_object *json_vrfs)
5941 {
5942 char buf[ETHER_ADDR_STRLEN];
5943 zebra_l3vni_t *zl3vni = NULL;
5944
5945 zl3vni = zl3vni_lookup(zvrf->l3vni);
5946 if (!zl3vni)
5947 return;
5948
5949 if (!json_vrfs) {
5950 vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
5951 zvrf_name(zvrf), zl3vni->vni,
5952 zl3vni_vxlan_if_name(zl3vni),
5953 zl3vni_svi_if_name(zl3vni), zl3vni_state2str(zl3vni),
5954 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
5955 } else {
5956 json_object *json_vrf = NULL;
5957
5958 json_vrf = json_object_new_object();
5959 json_object_string_add(json_vrf, "vrf", zvrf_name(zvrf));
5960 json_object_int_add(json_vrf, "vni", zl3vni->vni);
5961 json_object_string_add(json_vrf, "vxlanIntf",
5962 zl3vni_vxlan_if_name(zl3vni));
5963 json_object_string_add(json_vrf, "sviIntf",
5964 zl3vni_svi_if_name(zl3vni));
5965 json_object_string_add(json_vrf, "state",
5966 zl3vni_state2str(zl3vni));
5967 json_object_string_add(
5968 json_vrf, "routerMac",
5969 zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
5970 json_object_array_add(json_vrfs, json_vrf);
5971 }
5972 }
5973
5974 /*
5975 * Display Neighbors for a VNI (VTY command handler).
5976 */
5977 void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
5978 vni_t vni, bool use_json)
5979 {
5980 zebra_vni_t *zvni;
5981 uint32_t num_neigh;
5982 struct neigh_walk_ctx wctx;
5983 json_object *json = NULL;
5984
5985 if (!is_evpn_enabled())
5986 return;
5987 zvni = zvni_lookup(vni);
5988 if (!zvni) {
5989 if (use_json)
5990 vty_out(vty, "{}\n");
5991 else
5992 vty_out(vty, "%% VNI %u does not exist\n", vni);
5993 return;
5994 }
5995 num_neigh = hashcount(zvni->neigh_table);
5996 if (!num_neigh)
5997 return;
5998
5999 if (use_json)
6000 json = json_object_new_object();
6001
6002 /* Since we have IPv6 addresses to deal with which can vary widely in
6003 * size, we try to be a bit more elegant in display by first computing
6004 * the maximum width.
6005 */
6006 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6007 wctx.zvni = zvni;
6008 wctx.vty = vty;
6009 wctx.addr_width = 15;
6010 wctx.json = json;
6011 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
6012
6013 if (!use_json) {
6014 vty_out(vty,
6015 "Number of ARPs (local and remote) known for this VNI: %u\n",
6016 num_neigh);
6017 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
6018 -wctx.addr_width, "IP", "Type",
6019 "State", "MAC", "Remote VTEP");
6020 } else
6021 json_object_int_add(json, "numArpNd", num_neigh);
6022
6023 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
6024 if (use_json) {
6025 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6026 json, JSON_C_TO_STRING_PRETTY));
6027 json_object_free(json);
6028 }
6029 }
6030
6031 /*
6032 * Display neighbors across all VNIs (VTY command handler).
6033 */
6034 void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
6035 bool print_dup, bool use_json)
6036 {
6037 json_object *json = NULL;
6038 void *args[3];
6039
6040 if (!is_evpn_enabled())
6041 return;
6042
6043 if (use_json)
6044 json = json_object_new_object();
6045
6046 args[0] = vty;
6047 args[1] = json;
6048 args[2] = (void *)(ptrdiff_t)print_dup;
6049
6050 hash_iterate(zvrf->vni_table,
6051 (void (*)(struct hash_bucket *,
6052 void *))zvni_print_neigh_hash_all_vni,
6053 args);
6054 if (use_json) {
6055 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6056 json, JSON_C_TO_STRING_PRETTY));
6057 json_object_free(json);
6058 }
6059 }
6060
6061 /*
6062 * Display neighbors across all VNIs in detail(VTY command handler).
6063 */
6064 void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
6065 struct zebra_vrf *zvrf,
6066 bool print_dup, bool use_json)
6067 {
6068 json_object *json = NULL;
6069 void *args[3];
6070
6071 if (!is_evpn_enabled())
6072 return;
6073
6074 if (use_json)
6075 json = json_object_new_object();
6076
6077 args[0] = vty;
6078 args[1] = json;
6079 args[2] = (void *)(ptrdiff_t)print_dup;
6080
6081 hash_iterate(zvrf->vni_table,
6082 (void (*)(struct hash_bucket *,
6083 void *))zvni_print_neigh_hash_all_vni_detail,
6084 args);
6085 if (use_json) {
6086 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6087 json, JSON_C_TO_STRING_PRETTY));
6088 json_object_free(json);
6089 }
6090 }
6091
6092 /*
6093 * Display specific neighbor for a VNI, if present (VTY command handler).
6094 */
6095 void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
6096 struct zebra_vrf *zvrf, vni_t vni,
6097 struct ipaddr *ip, bool use_json)
6098 {
6099 zebra_vni_t *zvni;
6100 zebra_neigh_t *n;
6101 json_object *json = NULL;
6102
6103 if (!is_evpn_enabled())
6104 return;
6105 zvni = zvni_lookup(vni);
6106 if (!zvni) {
6107 if (use_json)
6108 vty_out(vty, "{}\n");
6109 else
6110 vty_out(vty, "%% VNI %u does not exist\n", vni);
6111 return;
6112 }
6113 n = zvni_neigh_lookup(zvni, ip);
6114 if (!n) {
6115 if (!use_json)
6116 vty_out(vty,
6117 "%% Requested neighbor does not exist in VNI %u\n",
6118 vni);
6119 return;
6120 }
6121 if (use_json)
6122 json = json_object_new_object();
6123
6124 zvni_print_neigh(n, vty, json);
6125
6126 if (use_json) {
6127 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6128 json, JSON_C_TO_STRING_PRETTY));
6129 json_object_free(json);
6130 }
6131 }
6132
6133 /*
6134 * Display neighbors for a VNI from specific VTEP (VTY command handler).
6135 * By definition, these are remote neighbors.
6136 */
6137 void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
6138 vni_t vni, struct in_addr vtep_ip,
6139 bool use_json)
6140 {
6141 zebra_vni_t *zvni;
6142 uint32_t num_neigh;
6143 struct neigh_walk_ctx wctx;
6144 json_object *json = NULL;
6145
6146 if (!is_evpn_enabled())
6147 return;
6148 zvni = zvni_lookup(vni);
6149 if (!zvni) {
6150 if (use_json)
6151 vty_out(vty, "{}\n");
6152 else
6153 vty_out(vty, "%% VNI %u does not exist\n", vni);
6154 return;
6155 }
6156 num_neigh = hashcount(zvni->neigh_table);
6157 if (!num_neigh)
6158 return;
6159
6160 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6161 wctx.zvni = zvni;
6162 wctx.vty = vty;
6163 wctx.addr_width = 15;
6164 wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP;
6165 wctx.r_vtep_ip = vtep_ip;
6166 wctx.json = json;
6167 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
6168 hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
6169
6170 if (use_json) {
6171 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6172 json, JSON_C_TO_STRING_PRETTY));
6173 json_object_free(json);
6174 }
6175 }
6176
6177 /*
6178 * Display Duplicate detected Neighbors for a VNI
6179 * (VTY command handler).
6180 */
6181 void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
6182 struct zebra_vrf *zvrf,
6183 vni_t vni,
6184 bool use_json)
6185 {
6186 zebra_vni_t *zvni;
6187 uint32_t num_neigh;
6188 struct neigh_walk_ctx wctx;
6189 json_object *json = NULL;
6190
6191 if (!is_evpn_enabled())
6192 return;
6193
6194 zvni = zvni_lookup(vni);
6195 if (!zvni) {
6196 vty_out(vty, "%% VNI %u does not exist\n", vni);
6197 return;
6198 }
6199
6200 num_neigh = hashcount(zvni->neigh_table);
6201 if (!num_neigh)
6202 return;
6203
6204 num_neigh = num_dup_detected_neighs(zvni);
6205 if (!num_neigh)
6206 return;
6207
6208 if (use_json)
6209 json = json_object_new_object();
6210
6211 /* Since we have IPv6 addresses to deal with which can vary widely in
6212 * size, we try to be a bit more elegant in display by first computing
6213 * the maximum width.
6214 */
6215 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
6216 wctx.zvni = zvni;
6217 wctx.vty = vty;
6218 wctx.addr_width = 15;
6219 wctx.json = json;
6220 hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
6221
6222 if (!use_json) {
6223 vty_out(vty,
6224 "Number of ARPs (local and remote) known for this VNI: %u\n",
6225 num_neigh);
6226 vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
6227 -wctx.addr_width, "IP", "Type",
6228 "State", "MAC", "Remote VTEP");
6229 } else
6230 json_object_int_add(json, "numArpNd", num_neigh);
6231
6232 hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, &wctx);
6233
6234 if (use_json) {
6235 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6236 json, JSON_C_TO_STRING_PRETTY));
6237 json_object_free(json);
6238 }
6239 }
6240
6241 /*
6242 * Display MACs for a VNI (VTY command handler).
6243 */
6244 void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
6245 vni_t vni, bool use_json)
6246 {
6247 zebra_vni_t *zvni;
6248 uint32_t num_macs;
6249 struct mac_walk_ctx wctx;
6250 json_object *json = NULL;
6251 json_object *json_mac = NULL;
6252
6253 if (!is_evpn_enabled())
6254 return;
6255 zvni = zvni_lookup(vni);
6256 if (!zvni) {
6257 if (use_json)
6258 vty_out(vty, "{}\n");
6259 else
6260 vty_out(vty, "%% VNI %u does not exist\n", vni);
6261 return;
6262 }
6263 num_macs = num_valid_macs(zvni);
6264 if (!num_macs)
6265 return;
6266
6267 if (use_json) {
6268 json = json_object_new_object();
6269 json_mac = json_object_new_object();
6270 }
6271
6272 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6273 wctx.zvni = zvni;
6274 wctx.vty = vty;
6275 wctx.json = json_mac;
6276
6277 if (!use_json) {
6278 vty_out(vty,
6279 "Number of MACs (local and remote) known for this VNI: %u\n",
6280 num_macs);
6281 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6282 "Intf/Remote VTEP", "VLAN");
6283 } else
6284 json_object_int_add(json, "numMacs", num_macs);
6285
6286 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
6287
6288 if (use_json) {
6289 json_object_object_add(json, "macs", json_mac);
6290 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6291 json, JSON_C_TO_STRING_PRETTY));
6292 json_object_free(json);
6293 }
6294 }
6295
6296 /*
6297 * Display MACs for all VNIs (VTY command handler).
6298 */
6299 void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
6300 bool print_dup, bool use_json)
6301 {
6302 struct mac_walk_ctx wctx;
6303 json_object *json = NULL;
6304
6305 if (!is_evpn_enabled()) {
6306 if (use_json)
6307 vty_out(vty, "{}\n");
6308 return;
6309 }
6310 if (use_json)
6311 json = json_object_new_object();
6312
6313 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6314 wctx.vty = vty;
6315 wctx.json = json;
6316 wctx.print_dup = print_dup;
6317 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
6318
6319 if (use_json) {
6320 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6321 json, JSON_C_TO_STRING_PRETTY));
6322 json_object_free(json);
6323 }
6324 }
6325
6326 /*
6327 * Display MACs in detail for all VNIs (VTY command handler).
6328 */
6329 void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
6330 struct zebra_vrf *zvrf,
6331 bool print_dup, bool use_json)
6332 {
6333 struct mac_walk_ctx wctx;
6334 json_object *json = NULL;
6335
6336 if (!is_evpn_enabled()) {
6337 if (use_json)
6338 vty_out(vty, "{}\n");
6339 return;
6340 }
6341 if (use_json)
6342 json = json_object_new_object();
6343
6344 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6345 wctx.vty = vty;
6346 wctx.json = json;
6347 wctx.print_dup = print_dup;
6348 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni_detail,
6349 &wctx);
6350
6351 if (use_json) {
6352 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6353 json, JSON_C_TO_STRING_PRETTY));
6354 json_object_free(json);
6355 }
6356 }
6357
6358 /*
6359 * Display MACs for all VNIs (VTY command handler).
6360 */
6361 void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
6362 struct zebra_vrf *zvrf,
6363 struct in_addr vtep_ip, bool use_json)
6364 {
6365 struct mac_walk_ctx wctx;
6366 json_object *json = NULL;
6367
6368 if (!is_evpn_enabled())
6369 return;
6370
6371 if (use_json)
6372 json = json_object_new_object();
6373
6374 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6375 wctx.vty = vty;
6376 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
6377 wctx.r_vtep_ip = vtep_ip;
6378 wctx.json = json;
6379 hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
6380
6381 if (use_json) {
6382 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6383 json, JSON_C_TO_STRING_PRETTY));
6384 json_object_free(json);
6385 }
6386 }
6387
6388 /*
6389 * Display specific MAC for a VNI, if present (VTY command handler).
6390 */
6391 void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
6392 vni_t vni, struct ethaddr *macaddr,
6393 bool use_json)
6394 {
6395 zebra_vni_t *zvni;
6396 zebra_mac_t *mac;
6397 json_object *json = NULL;
6398
6399 if (!is_evpn_enabled())
6400 return;
6401
6402 zvni = zvni_lookup(vni);
6403 if (!zvni) {
6404 if (use_json)
6405 vty_out(vty, "{}\n");
6406 else
6407 vty_out(vty, "%% VNI %u does not exist\n", vni);
6408 return;
6409 }
6410 mac = zvni_mac_lookup(zvni, macaddr);
6411 if (!mac) {
6412 if (use_json)
6413 vty_out(vty, "{}\n");
6414 else
6415 vty_out(vty,
6416 "%% Requested MAC does not exist in VNI %u\n",
6417 vni);
6418 return;
6419 }
6420
6421 if (use_json)
6422 json = json_object_new_object();
6423
6424 zvni_print_mac(mac, vty, json);
6425 if (use_json) {
6426 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6427 json, JSON_C_TO_STRING_PRETTY));
6428 json_object_free(json);
6429 }
6430 }
6431
6432 /* Print Duplicate MACs per VNI */
6433 void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
6434 struct zebra_vrf *zvrf,
6435 vni_t vni, bool use_json)
6436 {
6437 zebra_vni_t *zvni;
6438 struct mac_walk_ctx wctx;
6439 uint32_t num_macs;
6440 json_object *json = NULL;
6441 json_object *json_mac = NULL;
6442
6443 if (!is_evpn_enabled())
6444 return;
6445
6446 zvni = zvni_lookup(vni);
6447 if (!zvni) {
6448 vty_out(vty, "%% VNI %u does not exist\n", vni);
6449 return;
6450 }
6451
6452 num_macs = num_valid_macs(zvni);
6453 if (!num_macs)
6454 return;
6455
6456 num_macs = num_dup_detected_macs(zvni);
6457 if (!num_macs)
6458 return;
6459
6460 if (use_json) {
6461 json = json_object_new_object();
6462 json_mac = json_object_new_object();
6463 }
6464
6465 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6466 wctx.zvni = zvni;
6467 wctx.vty = vty;
6468 wctx.json = json_mac;
6469
6470 if (!use_json) {
6471 vty_out(vty,
6472 "Number of MACs (local and remote) known for this VNI: %u\n",
6473 num_macs);
6474 vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
6475 "Intf/Remote VTEP", "VLAN");
6476 } else
6477 json_object_int_add(json, "numMacs", num_macs);
6478
6479 hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, &wctx);
6480
6481 if (use_json) {
6482 json_object_object_add(json, "macs", json_mac);
6483 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6484 json, JSON_C_TO_STRING_PRETTY));
6485 json_object_free(json);
6486 }
6487
6488 }
6489
6490 int zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
6491 struct zebra_vrf *zvrf,
6492 vni_t vni, struct ethaddr *macaddr)
6493 {
6494 zebra_vni_t *zvni;
6495 zebra_mac_t *mac;
6496 struct listnode *node = NULL;
6497 zebra_neigh_t *nbr = NULL;
6498
6499 if (!is_evpn_enabled())
6500 return CMD_SUCCESS;
6501
6502 zvni = zvni_lookup(vni);
6503 if (!zvni) {
6504 vty_out(vty, "%% VNI %u does not exist\n", vni);
6505 return CMD_WARNING;
6506 }
6507
6508 mac = zvni_mac_lookup(zvni, macaddr);
6509 if (!mac) {
6510 vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
6511 vni);
6512 return CMD_WARNING;
6513 }
6514
6515 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
6516 vty_out(vty, "%% Requested MAC is not duplicate detected\n");
6517 return CMD_WARNING;
6518 }
6519
6520 /* Remove all IPs as duplicate associcated with this MAC */
6521 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
6522 /* For local neigh mark inactive so MACIP update is generated
6523 * to BGP. This is a scenario where MAC update received
6524 * and detected as duplicate which marked neigh as duplicate.
6525 * Later local neigh update did not get a chance to relay
6526 * to BGP. Similarly remote macip update, neigh needs to be
6527 * installed locally.
6528 */
6529 if (zvrf->dad_freeze &&
6530 CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
6531 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
6532 ZEBRA_NEIGH_SET_INACTIVE(nbr);
6533 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
6534 zvni_neigh_install(zvni, nbr);
6535 }
6536
6537 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6538 nbr->dad_count = 0;
6539 nbr->detect_start_time.tv_sec = 0;
6540 nbr->dad_dup_detect_time = 0;
6541 }
6542
6543 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
6544 mac->dad_count = 0;
6545 mac->detect_start_time.tv_sec = 0;
6546 mac->detect_start_time.tv_usec = 0;
6547 mac->dad_dup_detect_time = 0;
6548 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
6549
6550 /* warn-only action return */
6551 if (!zvrf->dad_freeze)
6552 return CMD_SUCCESS;
6553
6554 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6555 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
6556 /* Inform to BGP */
6557 if (zvni_mac_send_add_to_client(zvni->vni,
6558 &mac->macaddr,
6559 mac->flags,
6560 mac->loc_seq))
6561 return CMD_SUCCESS;
6562
6563 /* Process all neighbors associated with this MAC. */
6564 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
6565
6566 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
6567 zvni_process_neigh_on_remote_mac_add(zvni, mac);
6568
6569 /* Install the entry. */
6570 zvni_mac_install(zvni, mac);
6571 }
6572
6573 return CMD_SUCCESS;
6574 }
6575
6576 int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
6577 struct zebra_vrf *zvrf,
6578 vni_t vni, struct ipaddr *ip)
6579 {
6580 zebra_vni_t *zvni;
6581 zebra_neigh_t *nbr;
6582 zebra_mac_t *mac;
6583 char buf[INET6_ADDRSTRLEN];
6584 char buf2[ETHER_ADDR_STRLEN];
6585
6586 if (!is_evpn_enabled())
6587 return CMD_SUCCESS;
6588
6589 zvni = zvni_lookup(vni);
6590 if (!zvni) {
6591 vty_out(vty, "%% VNI %u does not exist\n", vni);
6592 return CMD_WARNING;
6593 }
6594
6595 nbr = zvni_neigh_lookup(zvni, ip);
6596 if (!nbr) {
6597 vty_out(vty,
6598 "%% Requested host IP does not exist in VNI %u\n",
6599 vni);
6600 return CMD_WARNING;
6601 }
6602
6603 ipaddr2str(&nbr->ip, buf, sizeof(buf));
6604
6605 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
6606 vty_out(vty,
6607 "%% Requsted host IP %s is not duplicate detected\n",
6608 buf);
6609 return CMD_WARNING;
6610 }
6611
6612 mac = zvni_mac_lookup(zvni, &nbr->emac);
6613
6614 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
6615 vty_out(vty,
6616 "%% Requested IP's associated MAC %s is still in duplicate state\n",
6617 prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
6618 return CMD_WARNING_CONFIG_FAILED;
6619 }
6620
6621 if (IS_ZEBRA_DEBUG_VXLAN)
6622 zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
6623 __PRETTY_FUNCTION__, buf, nbr->flags,
6624 nbr->loc_seq);
6625
6626 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6627 nbr->dad_count = 0;
6628 nbr->detect_start_time.tv_sec = 0;
6629 nbr->detect_start_time.tv_usec = 0;
6630 nbr->dad_dup_detect_time = 0;
6631 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
6632
6633 if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
6634 zvni_neigh_send_add_to_client(zvni->vni, ip,
6635 &nbr->emac,
6636 nbr->flags, nbr->loc_seq);
6637 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
6638 zvni_neigh_install(zvni, nbr);
6639 }
6640
6641 return CMD_SUCCESS;
6642 }
6643
6644 static void zvni_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt)
6645 {
6646 struct mac_walk_ctx *wctx = ctxt;
6647 zebra_mac_t *mac;
6648 zebra_vni_t *zvni;
6649 struct listnode *node = NULL;
6650 zebra_neigh_t *nbr = NULL;
6651
6652 mac = (zebra_mac_t *)bucket->data;
6653 if (!mac)
6654 return;
6655
6656 zvni = wctx->zvni;
6657
6658 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
6659 return;
6660
6661 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
6662 mac->dad_count = 0;
6663 mac->detect_start_time.tv_sec = 0;
6664 mac->detect_start_time.tv_usec = 0;
6665 mac->dad_dup_detect_time = 0;
6666 THREAD_OFF(mac->dad_mac_auto_recovery_timer);
6667
6668 /* Remove all IPs as duplicate associcated with this MAC */
6669 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
6670 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
6671 && nbr->dad_count)
6672 ZEBRA_NEIGH_SET_INACTIVE(nbr);
6673
6674 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6675 nbr->dad_count = 0;
6676 nbr->detect_start_time.tv_sec = 0;
6677 nbr->dad_dup_detect_time = 0;
6678 }
6679
6680 /* Local: Notify Peer VTEPs, Remote: Install the entry */
6681 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
6682 /* Inform to BGP */
6683 if (zvni_mac_send_add_to_client(zvni->vni,
6684 &mac->macaddr,
6685 mac->flags, mac->loc_seq))
6686 return;
6687
6688 /* Process all neighbors associated with this MAC. */
6689 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
6690
6691 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
6692 zvni_process_neigh_on_remote_mac_add(zvni, mac);
6693
6694 /* Install the entry. */
6695 zvni_mac_install(zvni, mac);
6696 }
6697 }
6698
6699 static void zvni_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt)
6700 {
6701 struct neigh_walk_ctx *wctx = ctxt;
6702 zebra_neigh_t *nbr;
6703 zebra_vni_t *zvni;
6704 char buf[INET6_ADDRSTRLEN];
6705
6706 nbr = (zebra_neigh_t *)bucket->data;
6707 if (!nbr)
6708 return;
6709
6710 zvni = wctx->zvni;
6711
6712 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
6713 return;
6714
6715 if (IS_ZEBRA_DEBUG_VXLAN) {
6716 ipaddr2str(&nbr->ip, buf, sizeof(buf));
6717 zlog_debug(
6718 "%s: clear neigh %s dup state, flags 0x%x seq %u",
6719 __PRETTY_FUNCTION__, buf,
6720 nbr->flags, nbr->loc_seq);
6721 }
6722
6723 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
6724 nbr->dad_count = 0;
6725 nbr->detect_start_time.tv_sec = 0;
6726 nbr->detect_start_time.tv_usec = 0;
6727 nbr->dad_dup_detect_time = 0;
6728 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
6729
6730 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
6731 zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip,
6732 &nbr->emac,
6733 nbr->flags, nbr->loc_seq);
6734 } else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
6735 zvni_neigh_install(zvni, nbr);
6736 }
6737 }
6738
6739 static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket,
6740 void **args)
6741 {
6742 struct vty *vty;
6743 zebra_vni_t *zvni;
6744 struct zebra_vrf *zvrf;
6745 struct mac_walk_ctx m_wctx;
6746 struct neigh_walk_ctx n_wctx;
6747
6748 zvni = (zebra_vni_t *)bucket->data;
6749 if (!zvni)
6750 return;
6751
6752 vty = (struct vty *)args[0];
6753 zvrf = (struct zebra_vrf *)args[1];
6754
6755 if (hashcount(zvni->neigh_table)) {
6756 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6757 n_wctx.vty = vty;
6758 n_wctx.zvni = zvni;
6759 n_wctx.zvrf = zvrf;
6760 hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
6761 &n_wctx);
6762 }
6763
6764 if (num_valid_macs(zvni)) {
6765 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6766 m_wctx.zvni = zvni;
6767 m_wctx.vty = vty;
6768 m_wctx.zvrf = zvrf;
6769 hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
6770 }
6771
6772 }
6773
6774 int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
6775 struct zebra_vrf *zvrf)
6776 {
6777 void *args[2];
6778
6779 if (!is_evpn_enabled())
6780 return CMD_SUCCESS;
6781
6782 args[0] = vty;
6783 args[1] = zvrf;
6784
6785 hash_iterate(zvrf->vni_table,
6786 (void (*)(struct hash_bucket *, void *))
6787 zvni_clear_dup_detect_hash_vni_all, args);
6788
6789 return CMD_SUCCESS;
6790 }
6791
6792 int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
6793 struct zebra_vrf *zvrf,
6794 vni_t vni)
6795 {
6796 zebra_vni_t *zvni;
6797 struct mac_walk_ctx m_wctx;
6798 struct neigh_walk_ctx n_wctx;
6799
6800 if (!is_evpn_enabled())
6801 return CMD_SUCCESS;
6802
6803 zvni = zvni_lookup(vni);
6804 if (!zvni) {
6805 vty_out(vty, "%% VNI %u does not exist\n", vni);
6806 return CMD_WARNING;
6807 }
6808
6809 if (hashcount(zvni->neigh_table)) {
6810 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
6811 n_wctx.vty = vty;
6812 n_wctx.zvni = zvni;
6813 n_wctx.zvrf = zvrf;
6814 hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
6815 &n_wctx);
6816 }
6817
6818 if (num_valid_macs(zvni)) {
6819 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
6820 m_wctx.zvni = zvni;
6821 m_wctx.vty = vty;
6822 m_wctx.zvrf = zvrf;
6823 hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
6824 }
6825
6826 return CMD_SUCCESS;
6827 }
6828
6829 /*
6830 * Display MACs for a VNI from specific VTEP (VTY command handler).
6831 */
6832 void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
6833 vni_t vni, struct in_addr vtep_ip,
6834 bool use_json)
6835 {
6836 zebra_vni_t *zvni;
6837 uint32_t num_macs;
6838 struct mac_walk_ctx wctx;
6839 json_object *json = NULL;
6840 json_object *json_mac = NULL;
6841
6842 if (!is_evpn_enabled())
6843 return;
6844 zvni = zvni_lookup(vni);
6845 if (!zvni) {
6846 if (use_json)
6847 vty_out(vty, "{}\n");
6848 else
6849 vty_out(vty, "%% VNI %u does not exist\n", vni);
6850 return;
6851 }
6852 num_macs = num_valid_macs(zvni);
6853 if (!num_macs)
6854 return;
6855
6856 if (use_json) {
6857 json = json_object_new_object();
6858 json_mac = json_object_new_object();
6859 }
6860
6861 memset(&wctx, 0, sizeof(struct mac_walk_ctx));
6862 wctx.zvni = zvni;
6863 wctx.vty = vty;
6864 wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP;
6865 wctx.r_vtep_ip = vtep_ip;
6866 wctx.json = json_mac;
6867 hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx);
6868
6869 if (use_json) {
6870 json_object_int_add(json, "numMacs", wctx.count);
6871 if (wctx.count)
6872 json_object_object_add(json, "macs", json_mac);
6873 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6874 json, JSON_C_TO_STRING_PRETTY));
6875 json_object_free(json);
6876 }
6877 }
6878
6879
6880 /*
6881 * Display VNI information (VTY command handler).
6882 */
6883 void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
6884 bool use_json)
6885 {
6886 json_object *json = NULL;
6887 void *args[2];
6888 zebra_l3vni_t *zl3vni = NULL;
6889 zebra_vni_t *zvni = NULL;
6890
6891 if (!is_evpn_enabled())
6892 return;
6893
6894 if (use_json)
6895 json = json_object_new_object();
6896 args[0] = vty;
6897 args[1] = json;
6898
6899 zl3vni = zl3vni_lookup(vni);
6900 if (zl3vni) {
6901 zl3vni_print(zl3vni, (void *)args);
6902 } else {
6903 zvni = zvni_lookup(vni);
6904 if (!zvni) {
6905 if (use_json)
6906 vty_out(vty, "{}\n");
6907 else
6908 vty_out(vty, "%% VNI %u does not exist\n", vni);
6909 return;
6910 }
6911
6912 zvni_print(zvni, (void *)args);
6913 }
6914
6915 if (use_json) {
6916 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6917 json, JSON_C_TO_STRING_PRETTY));
6918 json_object_free(json);
6919 }
6920 }
6921
6922 /* Display all global details for EVPN */
6923 void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
6924 {
6925 int num_l2vnis = 0;
6926 int num_l3vnis = 0;
6927 int num_vnis = 0;
6928 json_object *json = NULL;
6929 struct zebra_vrf *zvrf = NULL;
6930
6931 if (!is_evpn_enabled())
6932 return;
6933
6934 zvrf = vrf_info_lookup(VRF_DEFAULT);
6935 if (!zvrf)
6936 return;
6937
6938 num_l3vnis = hashcount(zrouter.l3vni_table);
6939 num_l2vnis = hashcount(zvrf->vni_table);
6940 num_vnis = num_l2vnis + num_l3vnis;
6941
6942 if (uj) {
6943 json = json_object_new_object();
6944 json_object_string_add(json, "advertiseGatewayMacip",
6945 zvrf->advertise_gw_macip ? "Yes" : "No");
6946 json_object_int_add(json, "numVnis", num_vnis);
6947 json_object_int_add(json, "numL2Vnis", num_l2vnis);
6948 json_object_int_add(json, "numL3Vnis", num_l3vnis);
6949 if (zvrf->dup_addr_detect)
6950 json_object_boolean_true_add(json,
6951 "isDuplicateAddrDetection");
6952 else
6953 json_object_boolean_false_add(json,
6954 "isDuplicateAddrDetection");
6955 json_object_int_add(json, "maxMoves", zvrf->dad_max_moves);
6956 json_object_int_add(json, "detectionTime", zvrf->dad_time);
6957 json_object_int_add(json, "detectionFreezeTime",
6958 zvrf->dad_freeze_time);
6959
6960 } else {
6961 vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
6962 vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
6963 vty_out(vty, "Advertise gateway mac-ip: %s\n",
6964 zvrf->advertise_gw_macip ? "Yes" : "No");
6965 vty_out(vty, "Advertise svi mac-ip: %s\n",
6966 zvrf->advertise_svi_macip ? "Yes" : "No");
6967 vty_out(vty, "Duplicate address detection: %s\n",
6968 zvrf->dup_addr_detect ? "Enable" : "Disable");
6969 vty_out(vty, " Detection max-moves %u, time %d\n",
6970 zvrf->dad_max_moves, zvrf->dad_time);
6971 if (zvrf->dad_freeze) {
6972 if (zvrf->dad_freeze_time)
6973 vty_out(vty, " Detection freeze %u\n",
6974 zvrf->dad_freeze_time);
6975 else
6976 vty_out(vty, " Detection freeze %s\n",
6977 "permanent");
6978 }
6979 }
6980
6981 if (uj) {
6982 vty_out(vty, "%s\n", json_object_to_json_string_ext(
6983 json, JSON_C_TO_STRING_PRETTY));
6984 json_object_free(json);
6985 }
6986 }
6987
6988 /*
6989 * Display VNI hash table (VTY command handler).
6990 */
6991 void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
6992 bool use_json)
6993 {
6994 json_object *json = NULL;
6995 void *args[2];
6996
6997 if (!is_evpn_enabled())
6998 return;
6999
7000 if (use_json)
7001 json = json_object_new_object();
7002 else
7003 vty_out(vty, "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n", "VNI",
7004 "Type", "VxLAN IF", "# MACs", "# ARPs",
7005 "# Remote VTEPs", "Tenant VRF");
7006
7007 args[0] = vty;
7008 args[1] = json;
7009
7010 /* Display all L2-VNIs */
7011 hash_iterate(zvrf->vni_table,
7012 (void (*)(struct hash_bucket *, void *))zvni_print_hash,
7013 args);
7014
7015 /* Display all L3-VNIs */
7016 hash_iterate(zrouter.l3vni_table,
7017 (void (*)(struct hash_bucket *, void *))zl3vni_print_hash,
7018 args);
7019
7020 if (use_json) {
7021 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7022 json, JSON_C_TO_STRING_PRETTY));
7023 json_object_free(json);
7024 }
7025 }
7026
7027 void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
7028 {
7029 struct stream *s;
7030 int time = 0;
7031 uint32_t max_moves = 0;
7032 uint32_t freeze_time = 0;
7033 bool dup_addr_detect = false;
7034 bool freeze = false;
7035
7036 s = msg;
7037 STREAM_GETL(s, dup_addr_detect);
7038 STREAM_GETL(s, time);
7039 STREAM_GETL(s, max_moves);
7040 STREAM_GETL(s, freeze);
7041 STREAM_GETL(s, freeze_time);
7042
7043 /* DAD previous state was enabled, and new state is disable,
7044 * clear all duplicate detected addresses.
7045 */
7046 if (zvrf->dup_addr_detect && !dup_addr_detect)
7047 zebra_vxlan_clear_dup_detect_vni_all(NULL, zvrf);
7048
7049 zvrf->dup_addr_detect = dup_addr_detect;
7050 zvrf->dad_time = time;
7051 zvrf->dad_max_moves = max_moves;
7052 zvrf->dad_freeze = freeze;
7053 zvrf->dad_freeze_time = freeze_time;
7054
7055 if (IS_ZEBRA_DEBUG_VXLAN)
7056 zlog_debug(
7057 "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
7058 vrf_id_to_name(zvrf->vrf->vrf_id),
7059 zvrf->dup_addr_detect ? "enable" : "disable",
7060 zvrf->dad_max_moves,
7061 zvrf->dad_time,
7062 zvrf->dad_freeze ? "enable" : "disable",
7063 zvrf->dad_freeze_time);
7064
7065 stream_failure:
7066 return;
7067 }
7068
7069 /*
7070 * Display VNI hash table in detail(VTY command handler).
7071 */
7072 void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
7073 bool use_json)
7074 {
7075 json_object *json = NULL;
7076 struct zebra_ns *zns = NULL;
7077 struct zvni_evpn_show zes;
7078
7079 if (!is_evpn_enabled())
7080 return;
7081
7082 zns = zebra_ns_lookup(NS_DEFAULT);
7083 if (!zns)
7084 return;
7085
7086
7087 if (use_json)
7088 json = json_object_new_object();
7089
7090 zes.vty = vty;
7091 zes.json = json;
7092 zes.zvrf = zvrf;
7093
7094 /* Display all L2-VNIs */
7095 hash_iterate(zvrf->vni_table, (void (*)(struct hash_bucket *,
7096 void *))zvni_print_hash_detail,
7097 &zes);
7098
7099 /* Display all L3-VNIs */
7100 hash_iterate(zrouter.l3vni_table,
7101 (void (*)(struct hash_bucket *,
7102 void *))zl3vni_print_hash_detail,
7103 &zes);
7104
7105 if (use_json) {
7106 vty_out(vty, "%s\n", json_object_to_json_string_ext(
7107 json, JSON_C_TO_STRING_PRETTY));
7108 json_object_free(json);
7109 }
7110 }
7111
7112 /*
7113 * Handle neighbor delete notification from the kernel (on a VLAN device
7114 * / L3 interface). This may result in either the neighbor getting deleted
7115 * from our database or being re-added to the kernel (if it is a valid
7116 * remote neighbor).
7117 */
7118 int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
7119 struct interface *link_if,
7120 struct ipaddr *ip)
7121 {
7122 char buf[INET6_ADDRSTRLEN];
7123 char buf2[ETHER_ADDR_STRLEN];
7124 zebra_neigh_t *n = NULL;
7125 zebra_vni_t *zvni = NULL;
7126 zebra_mac_t *zmac = NULL;
7127 zebra_l3vni_t *zl3vni = NULL;
7128 struct zebra_vrf *zvrf;
7129
7130 /* check if this is a remote neigh entry corresponding to remote
7131 * next-hop
7132 */
7133 zl3vni = zl3vni_from_svi(ifp, link_if);
7134 if (zl3vni)
7135 return zl3vni_local_nh_del(zl3vni, ip);
7136
7137 /* We are only interested in neighbors on an SVI that resides on top
7138 * of a VxLAN bridge.
7139 */
7140 zvni = zvni_from_svi(ifp, link_if);
7141 if (!zvni)
7142 return 0;
7143
7144 if (!zvni->vxlan_if) {
7145 zlog_debug(
7146 "VNI %u hash %p doesn't have intf upon local neighbor DEL",
7147 zvni->vni, zvni);
7148 return -1;
7149 }
7150
7151 if (IS_ZEBRA_DEBUG_VXLAN)
7152 zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
7153 ipaddr2str(ip, buf, sizeof(buf)), ifp->name,
7154 ifp->ifindex, zvni->vni);
7155
7156 /* If entry doesn't exist, nothing to do. */
7157 n = zvni_neigh_lookup(zvni, ip);
7158 if (!n)
7159 return 0;
7160
7161 zmac = zvni_mac_lookup(zvni, &n->emac);
7162 if (!zmac) {
7163 if (IS_ZEBRA_DEBUG_VXLAN)
7164 zlog_debug(
7165 "Trying to del a neigh %s without a mac %s on VNI %u",
7166 ipaddr2str(ip, buf, sizeof(buf)),
7167 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
7168 zvni->vni);
7169
7170 return 0;
7171 }
7172
7173 /* If it is a remote entry, the kernel has aged this out or someone has
7174 * deleted it, it needs to be re-installed as Quagga is the owner.
7175 */
7176 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
7177 zvni_neigh_install(zvni, n);
7178 return 0;
7179 }
7180
7181 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
7182 if (!zvrf) {
7183 zlog_debug("%s: VNI %u vrf lookup failed.",
7184 __PRETTY_FUNCTION__, zvni->vni);
7185 return -1;
7186 }
7187
7188 /* In case of feeze action, if local neigh is in duplicate state,
7189 * Mark the Neigh as inactive before sending delete request to BGPd,
7190 * If BGPd has remote entry, it will re-install
7191 */
7192 if (zvrf->dad_freeze &&
7193 CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
7194 ZEBRA_NEIGH_SET_INACTIVE(n);
7195
7196 /* Remove neighbor from BGP. */
7197 zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0, n->state);
7198
7199 /* Delete this neighbor entry. */
7200 zvni_neigh_del(zvni, n);
7201
7202 /* see if the AUTO mac needs to be deleted */
7203 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
7204 && !listcount(zmac->neigh_list))
7205 zvni_mac_del(zvni, zmac);
7206
7207 return 0;
7208 }
7209
7210 /*
7211 * Handle neighbor add or update notification from the kernel (on a VLAN
7212 * device / L3 interface). This is typically for a local neighbor but can
7213 * also be for a remote neighbor (e.g., ageout notification). It could
7214 * also be a "move" scenario.
7215 */
7216 int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
7217 struct interface *link_if,
7218 struct ipaddr *ip,
7219 struct ethaddr *macaddr,
7220 uint16_t state,
7221 bool is_ext,
7222 bool is_router)
7223 {
7224 char buf[ETHER_ADDR_STRLEN];
7225 char buf2[INET6_ADDRSTRLEN];
7226 zebra_vni_t *zvni = NULL;
7227 zebra_l3vni_t *zl3vni = NULL;
7228
7229 /* check if this is a remote neigh entry corresponding to remote
7230 * next-hop
7231 */
7232 zl3vni = zl3vni_from_svi(ifp, link_if);
7233 if (zl3vni)
7234 return zl3vni_local_nh_add_update(zl3vni, ip, state);
7235
7236 /* We are only interested in neighbors on an SVI that resides on top
7237 * of a VxLAN bridge.
7238 */
7239 zvni = zvni_from_svi(ifp, link_if);
7240 if (!zvni)
7241 return 0;
7242
7243 if (IS_ZEBRA_DEBUG_VXLAN)
7244 zlog_debug(
7245 "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u",
7246 ipaddr2str(ip, buf2, sizeof(buf2)),
7247 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7248 ifp->ifindex, state, is_ext ? "ext-learned " : "",
7249 is_router ? "router " : "",
7250 zvni->vni);
7251
7252 /* Is this about a local neighbor or a remote one? */
7253 if (!is_ext)
7254 return zvni_local_neigh_update(zvni, ifp, ip, macaddr,
7255 is_router);
7256
7257 return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
7258 }
7259
7260
7261 /*
7262 * Handle message from client to delete a remote MACIP for a VNI.
7263 */
7264 void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
7265 {
7266 struct stream *s;
7267 vni_t vni;
7268 struct ethaddr macaddr;
7269 struct ipaddr ip;
7270 struct in_addr vtep_ip;
7271 uint16_t l = 0, ipa_len;
7272 char buf[ETHER_ADDR_STRLEN];
7273 char buf1[INET6_ADDRSTRLEN];
7274
7275 memset(&macaddr, 0, sizeof(struct ethaddr));
7276 memset(&ip, 0, sizeof(struct ipaddr));
7277 memset(&vtep_ip, 0, sizeof(struct in_addr));
7278
7279 s = msg;
7280
7281 while (l < hdr->length) {
7282 /* Obtain each remote MACIP and process. */
7283 /* Message contains VNI, followed by MAC followed by IP (if any)
7284 * followed by remote VTEP IP.
7285 */
7286 memset(&ip, 0, sizeof(ip));
7287 STREAM_GETL(s, vni);
7288 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
7289 STREAM_GETL(s, ipa_len);
7290 if (ipa_len) {
7291 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
7292 : IPADDR_V6;
7293 STREAM_GET(&ip.ip.addr, s, ipa_len);
7294 }
7295 l += 4 + ETH_ALEN + 4 + ipa_len;
7296 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
7297 l += IPV4_MAX_BYTELEN;
7298
7299 if (IS_ZEBRA_DEBUG_VXLAN)
7300 zlog_debug(
7301 "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %s from %s",
7302 vni,
7303 prefix_mac2str(&macaddr, buf, sizeof(buf)),
7304 ipa_len ? " IP " : "",
7305 ipa_len ?
7306 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
7307 inet_ntoa(vtep_ip),
7308 zebra_route_string(client->proto));
7309
7310 process_remote_macip_del(vni, &macaddr, ipa_len, &ip, vtep_ip);
7311 }
7312
7313 stream_failure:
7314 return;
7315 }
7316
7317 /*
7318 * Handle message from client to add a remote MACIP for a VNI. This
7319 * could be just the add of a MAC address or the add of a neighbor
7320 * (IP+MAC).
7321 */
7322 void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
7323 {
7324 struct stream *s;
7325 vni_t vni;
7326 struct ethaddr macaddr;
7327 struct ipaddr ip;
7328 struct in_addr vtep_ip;
7329 uint16_t l = 0, ipa_len;
7330 uint8_t flags = 0;
7331 uint32_t seq;
7332 char buf[ETHER_ADDR_STRLEN];
7333 char buf1[INET6_ADDRSTRLEN];
7334
7335 memset(&macaddr, 0, sizeof(struct ethaddr));
7336 memset(&ip, 0, sizeof(struct ipaddr));
7337 memset(&vtep_ip, 0, sizeof(struct in_addr));
7338
7339 if (!EVPN_ENABLED(zvrf)) {
7340 zlog_debug("EVPN not enabled, ignoring remote MACIP ADD");
7341 return;
7342 }
7343
7344 s = msg;
7345
7346 while (l < hdr->length) {
7347 /* Obtain each remote MACIP and process. */
7348 /* Message contains VNI, followed by MAC followed by IP (if any)
7349 * followed by remote VTEP IP.
7350 */
7351 memset(&ip, 0, sizeof(ip));
7352 STREAM_GETL(s, vni);
7353 STREAM_GET(&macaddr.octet, s, ETH_ALEN);
7354 STREAM_GETL(s, ipa_len);
7355 if (ipa_len) {
7356 ip.ipa_type = (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4
7357 : IPADDR_V6;
7358 STREAM_GET(&ip.ip.addr, s, ipa_len);
7359 }
7360 l += 4 + ETH_ALEN + 4 + ipa_len;
7361 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
7362 l += IPV4_MAX_BYTELEN;
7363
7364 /* Get flags - sticky mac and/or gateway mac */
7365 STREAM_GETC(s, flags);
7366 l++;
7367 STREAM_GETL(s, seq);
7368 l += 4;
7369
7370 if (IS_ZEBRA_DEBUG_VXLAN)
7371 zlog_debug(
7372 "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s",
7373 vni,
7374 prefix_mac2str(&macaddr, buf, sizeof(buf)),
7375 ipa_len ? " IP " : "",
7376 ipa_len ?
7377 ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
7378 flags, seq, inet_ntoa(vtep_ip),
7379 zebra_route_string(client->proto));
7380
7381 process_remote_macip_add(vni, &macaddr, ipa_len, &ip,
7382 flags, seq, vtep_ip);
7383 }
7384
7385 stream_failure:
7386 return;
7387 }
7388
7389 /*
7390 * Handle notification of MAC add/update over VxLAN. If the kernel is notifying
7391 * us, this must involve a multihoming scenario. Treat this as implicit delete
7392 * of any prior local MAC.
7393 */
7394 int zebra_vxlan_check_del_local_mac(struct interface *ifp,
7395 struct interface *br_if,
7396 struct ethaddr *macaddr, vlanid_t vid)
7397 {
7398 struct zebra_if *zif;
7399 struct zebra_l2info_vxlan *vxl;
7400 vni_t vni;
7401 zebra_vni_t *zvni;
7402 zebra_mac_t *mac;
7403 char buf[ETHER_ADDR_STRLEN];
7404
7405 zif = ifp->info;
7406 assert(zif);
7407 vxl = &zif->l2info.vxl;
7408 vni = vxl->vni;
7409
7410 /* Check if EVPN is enabled. */
7411 if (!is_evpn_enabled())
7412 return 0;
7413
7414 /* Locate hash entry; it is expected to exist. */
7415 zvni = zvni_lookup(vni);
7416 if (!zvni)
7417 return 0;
7418
7419 /* If entry doesn't exist, nothing to do. */
7420 mac = zvni_mac_lookup(zvni, macaddr);
7421 if (!mac)
7422 return 0;
7423
7424 /* Is it a local entry? */
7425 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
7426 return 0;
7427
7428 if (IS_ZEBRA_DEBUG_VXLAN)
7429 zlog_debug(
7430 "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
7431 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7432 ifp->ifindex, vni);
7433
7434 /* Remove MAC from BGP. */
7435 zvni_mac_send_del_to_client(zvni->vni, macaddr);
7436
7437 /*
7438 * If there are no neigh associated with the mac delete the mac
7439 * else mark it as AUTO for forward reference
7440 */
7441 if (!listcount(mac->neigh_list)) {
7442 zvni_mac_del(zvni, mac);
7443 } else {
7444 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7445 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7446 }
7447
7448 return 0;
7449 }
7450
7451 /*
7452 * Handle remote MAC delete by kernel; readd the remote MAC if we have it.
7453 * This can happen because the remote MAC entries are also added as "dynamic",
7454 * so the kernel can ageout the entry.
7455 */
7456 int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
7457 struct interface *br_if,
7458 struct ethaddr *macaddr, vlanid_t vid)
7459 {
7460 struct zebra_if *zif = NULL;
7461 struct zebra_l2info_vxlan *vxl = NULL;
7462 vni_t vni;
7463 zebra_vni_t *zvni = NULL;
7464 zebra_l3vni_t *zl3vni = NULL;
7465 zebra_mac_t *mac = NULL;
7466 char buf[ETHER_ADDR_STRLEN];
7467
7468 zif = ifp->info;
7469 assert(zif);
7470 vxl = &zif->l2info.vxl;
7471 vni = vxl->vni;
7472
7473 /* Check if EVPN is enabled. */
7474 if (!is_evpn_enabled())
7475 return 0;
7476
7477 /* check if this is a remote RMAC and readd simillar to remote macs */
7478 zl3vni = zl3vni_lookup(vni);
7479 if (zl3vni)
7480 return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
7481
7482 /* Locate hash entry; it is expected to exist. */
7483 zvni = zvni_lookup(vni);
7484 if (!zvni)
7485 return 0;
7486
7487 /* If entry doesn't exist, nothing to do. */
7488 mac = zvni_mac_lookup(zvni, macaddr);
7489 if (!mac)
7490 return 0;
7491
7492 /* Is it a remote entry? */
7493 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
7494 return 0;
7495
7496 if (IS_ZEBRA_DEBUG_VXLAN)
7497 zlog_debug("Del remote MAC %s intf %s(%u) VNI %u - readd",
7498 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7499 ifp->ifindex, vni);
7500
7501 zvni_mac_install(zvni, mac);
7502 return 0;
7503 }
7504
7505 /*
7506 * Handle local MAC delete (on a port or VLAN corresponding to this VNI).
7507 */
7508 int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
7509 struct ethaddr *macaddr, vlanid_t vid)
7510 {
7511 zebra_vni_t *zvni;
7512 zebra_mac_t *mac;
7513 char buf[ETHER_ADDR_STRLEN];
7514
7515 /* We are interested in MACs only on ports or (port, VLAN) that
7516 * map to a VNI.
7517 */
7518 zvni = zvni_map_vlan(ifp, br_if, vid);
7519 if (!zvni)
7520 return 0;
7521 if (!zvni->vxlan_if) {
7522 zlog_debug(
7523 "VNI %u hash %p doesn't have intf upon local MAC DEL",
7524 zvni->vni, zvni);
7525 return -1;
7526 }
7527
7528 if (IS_ZEBRA_DEBUG_VXLAN)
7529 zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
7530 prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
7531 ifp->ifindex, vid, zvni->vni);
7532
7533 /* If entry doesn't exist, nothing to do. */
7534 mac = zvni_mac_lookup(zvni, macaddr);
7535 if (!mac)
7536 return 0;
7537
7538 /* Is it a local entry? */
7539 if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
7540 return 0;
7541
7542 /* Update all the neigh entries associated with this mac */
7543 zvni_process_neigh_on_local_mac_del(zvni, mac);
7544
7545 /* Remove MAC from BGP. */
7546 zvni_mac_send_del_to_client(zvni->vni, macaddr);
7547
7548 /*
7549 * If there are no neigh associated with the mac delete the mac
7550 * else mark it as AUTO for forward reference
7551 */
7552 if (!listcount(mac->neigh_list)) {
7553 zvni_mac_del(zvni, mac);
7554 } else {
7555 UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7556 SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7557 }
7558
7559 return 0;
7560 }
7561
7562 /*
7563 * Handle local MAC add (on a port or VLAN corresponding to this VNI).
7564 */
7565 int zebra_vxlan_local_mac_add_update(struct interface *ifp,
7566 struct interface *br_if,
7567 struct ethaddr *macaddr, vlanid_t vid,
7568 bool sticky)
7569 {
7570 zebra_vni_t *zvni;
7571 zebra_mac_t *mac;
7572 struct zebra_vrf *zvrf;
7573 char buf[ETHER_ADDR_STRLEN];
7574 bool mac_sticky = false;
7575 bool inform_client = false;
7576 bool upd_neigh = false;
7577 bool is_dup_detect = false;
7578 struct in_addr vtep_ip = {.s_addr = 0};
7579
7580 /* We are interested in MACs only on ports or (port, VLAN) that
7581 * map to a VNI.
7582 */
7583 zvni = zvni_map_vlan(ifp, br_if, vid);
7584 if (!zvni) {
7585 if (IS_ZEBRA_DEBUG_VXLAN)
7586 zlog_debug(
7587 "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
7588 sticky ? "sticky " : "",
7589 prefix_mac2str(macaddr, buf, sizeof(buf)),
7590 ifp->name, ifp->ifindex, vid);
7591 return 0;
7592 }
7593
7594 if (!zvni->vxlan_if) {
7595 zlog_debug(
7596 "VNI %u hash %p doesn't have intf upon local MAC ADD",
7597 zvni->vni, zvni);
7598 return -1;
7599 }
7600
7601 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
7602 if (!zvrf)
7603 return -1;
7604
7605 /* Check if we need to create or update or it is a NO-OP. */
7606 mac = zvni_mac_lookup(zvni, macaddr);
7607 if (!mac) {
7608 if (IS_ZEBRA_DEBUG_VXLAN)
7609 zlog_debug(
7610 "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u",
7611 sticky ? "sticky " : "",
7612 prefix_mac2str(macaddr, buf, sizeof(buf)),
7613 ifp->name, ifp->ifindex, vid, zvni->vni);
7614
7615 mac = zvni_mac_add(zvni, macaddr);
7616 if (!mac) {
7617 flog_err(
7618 EC_ZEBRA_MAC_ADD_FAILED,
7619 "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
7620 prefix_mac2str(macaddr, buf, sizeof(buf)),
7621 ifp->name, ifp->ifindex, vid, zvni->vni);
7622 return -1;
7623 }
7624 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7625 mac->fwd_info.local.ifindex = ifp->ifindex;
7626 mac->fwd_info.local.vid = vid;
7627 if (sticky)
7628 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7629 inform_client = true;
7630
7631 } else {
7632 if (IS_ZEBRA_DEBUG_VXLAN)
7633 zlog_debug(
7634 "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x",
7635 sticky ? "sticky " : "",
7636 prefix_mac2str(macaddr, buf, sizeof(buf)),
7637 ifp->name, ifp->ifindex, vid, zvni->vni,
7638 mac->flags);
7639
7640 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
7641 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
7642 mac_sticky = true;
7643
7644 /*
7645 * Update any changes and if changes are relevant to
7646 * BGP, note it.
7647 */
7648 if (mac_sticky == sticky
7649 && mac->fwd_info.local.ifindex == ifp->ifindex
7650 && mac->fwd_info.local.vid == vid) {
7651 if (IS_ZEBRA_DEBUG_VXLAN)
7652 zlog_debug(
7653 "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
7654 "entry exists and has not changed ",
7655 sticky ? "sticky " : "",
7656 prefix_mac2str(macaddr, buf,
7657 sizeof(buf)),
7658 ifp->name, ifp->ifindex, vid,
7659 zvni->vni);
7660 return 0;
7661 }
7662 if (mac_sticky != sticky) {
7663 if (sticky)
7664 SET_FLAG(mac->flags,
7665 ZEBRA_MAC_STICKY);
7666 else
7667 UNSET_FLAG(mac->flags,
7668 ZEBRA_MAC_STICKY);
7669 inform_client = true;
7670 }
7671
7672 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
7673 mac->fwd_info.local.ifindex = ifp->ifindex;
7674 mac->fwd_info.local.vid = vid;
7675
7676 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ||
7677 CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
7678 bool do_dad = false;
7679
7680 /*
7681 * MAC has either moved or was "internally" created due
7682 * to a neighbor learn and is now actually learnt. If
7683 * it was learnt as a remote sticky MAC, this is an
7684 * operator error.
7685 */
7686 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
7687 flog_warn(
7688 EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
7689 "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u",
7690 prefix_mac2str(macaddr, buf,
7691 sizeof(buf)),
7692 inet_ntoa(mac->fwd_info.r_vtep_ip),
7693 zvni->vni);
7694 return 0;
7695 }
7696
7697 /* If an actual move, compute MAC's seq number */
7698 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
7699 mac->loc_seq = MAX(mac->rem_seq + 1,
7700 mac->loc_seq);
7701 vtep_ip = mac->fwd_info.r_vtep_ip;
7702 /* Trigger DAD for remote MAC */
7703 do_dad = true;
7704 }
7705
7706 UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
7707 UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
7708 SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
7709 memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
7710 mac->fwd_info.local.ifindex = ifp->ifindex;
7711 mac->fwd_info.local.vid = vid;
7712 if (sticky)
7713 SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7714 else
7715 UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
7716 /*
7717 * We have to inform BGP of this MAC as well as process
7718 * all neighbors.
7719 */
7720 inform_client = true;
7721 upd_neigh = true;
7722
7723 zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip,
7724 do_dad,
7725 &is_dup_detect,
7726 true);
7727 if (is_dup_detect) {
7728 inform_client = false;
7729 upd_neigh = false;
7730 }
7731 }
7732 }
7733
7734 /* Inform BGP if required. */
7735 if (inform_client) {
7736 if (zvni_mac_send_add_to_client(zvni->vni, macaddr,
7737 mac->flags, mac->loc_seq))
7738 return -1;
7739 }
7740
7741 /* Process all neighbors associated with this MAC, if required. */
7742 if (upd_neigh)
7743 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
7744
7745 return 0;
7746 }
7747
7748 /*
7749 * Handle message from client to delete a remote VTEP for a VNI.
7750 */
7751 void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
7752 {
7753 struct stream *s;
7754 unsigned short l = 0;
7755 vni_t vni;
7756 struct in_addr vtep_ip;
7757 zebra_vni_t *zvni;
7758 zebra_vtep_t *zvtep;
7759 struct interface *ifp;
7760 struct zebra_if *zif;
7761
7762 if (!is_evpn_enabled()) {
7763 zlog_debug(
7764 "%s: EVPN is not enabled yet we have received a vtep del command",
7765 __PRETTY_FUNCTION__);
7766 return;
7767 }
7768
7769 if (zvrf_id(zvrf) != VRF_DEFAULT) {
7770 zlog_debug("Recv MACIP DEL for non-default VRF %u",
7771 zvrf_id(zvrf));
7772 return;
7773 }
7774
7775 s = msg;
7776
7777 while (l < hdr->length) {
7778 /* Obtain each remote VTEP and process. */
7779 STREAM_GETL(s, vni);
7780 l += 4;
7781 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
7782 l += IPV4_MAX_BYTELEN;
7783
7784 if (IS_ZEBRA_DEBUG_VXLAN)
7785 zlog_debug("Recv VTEP_DEL %s VNI %u from %s",
7786 inet_ntoa(vtep_ip), vni,
7787 zebra_route_string(client->proto));
7788
7789 /* Locate VNI hash entry - expected to exist. */
7790 zvni = zvni_lookup(vni);
7791 if (!zvni) {
7792 if (IS_ZEBRA_DEBUG_VXLAN)
7793 zlog_debug(
7794 "Failed to locate VNI hash upon remote VTEP DEL, "
7795 "VNI %u",
7796 vni);
7797 continue;
7798 }
7799
7800 ifp = zvni->vxlan_if;
7801 if (!ifp) {
7802 zlog_debug(
7803 "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
7804 zvni->vni, zvni);
7805 continue;
7806 }
7807 zif = ifp->info;
7808
7809 /* If down or not mapped to a bridge, we're done. */
7810 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
7811 continue;
7812
7813 /* If the remote VTEP does not exist, there's nothing more to
7814 * do.
7815 * Otherwise, uninstall any remote MACs pointing to this VTEP
7816 * and
7817 * then, the VTEP entry itself and remove it.
7818 */
7819 zvtep = zvni_vtep_find(zvni, &vtep_ip);
7820 if (!zvtep)
7821 continue;
7822
7823 zvni_neigh_del_from_vtep(zvni, 1, &vtep_ip);
7824 zvni_mac_del_from_vtep(zvni, 1, &vtep_ip);
7825 zvni_vtep_uninstall(zvni, &vtep_ip);
7826 zvni_vtep_del(zvni, zvtep);
7827 }
7828
7829 stream_failure:
7830 return;
7831 }
7832
7833 /*
7834 * Handle message from client to add a remote VTEP for a VNI.
7835 */
7836 void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
7837 {
7838 struct stream *s;
7839 unsigned short l = 0;
7840 vni_t vni;
7841 struct in_addr vtep_ip;
7842 zebra_vni_t *zvni;
7843 struct interface *ifp;
7844 struct zebra_if *zif;
7845
7846 if (!is_evpn_enabled()) {
7847 zlog_debug(
7848 "%s: EVPN not enabled yet we received a vtep_add zapi call",
7849 __PRETTY_FUNCTION__);
7850 return;
7851 }
7852
7853 if (zvrf_id(zvrf) != VRF_DEFAULT) {
7854 zlog_debug("Recv MACIP ADD for non-default VRF %u",
7855 zvrf_id(zvrf));
7856 return;
7857 }
7858
7859 s = msg;
7860
7861 while (l < hdr->length) {
7862 /* Obtain each remote VTEP and process. */
7863 STREAM_GETL(s, vni);
7864 l += 4;
7865 STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
7866 l += IPV4_MAX_BYTELEN;
7867
7868 if (IS_ZEBRA_DEBUG_VXLAN)
7869 zlog_debug("Recv VTEP_ADD %s VNI %u from %s",
7870 inet_ntoa(vtep_ip), vni,
7871 zebra_route_string(client->proto));
7872
7873 /* Locate VNI hash entry - expected to exist. */
7874 zvni = zvni_lookup(vni);
7875 if (!zvni) {
7876 flog_err(
7877 EC_ZEBRA_VTEP_ADD_FAILED,
7878 "Failed to locate VNI hash upon remote VTEP ADD, VNI %u",
7879 vni);
7880 continue;
7881 }
7882
7883 ifp = zvni->vxlan_if;
7884 if (!ifp) {
7885 flog_err(
7886 EC_ZEBRA_VTEP_ADD_FAILED,
7887 "VNI %u hash %p doesn't have intf upon remote VTEP ADD",
7888 zvni->vni, zvni);
7889 continue;
7890 }
7891
7892 zif = ifp->info;
7893
7894 /* If down or not mapped to a bridge, we're done. */
7895 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
7896 continue;
7897
7898 /* If the remote VTEP already exists,
7899 there's nothing more to do. */
7900 if (zvni_vtep_find(zvni, &vtep_ip))
7901 continue;
7902
7903 if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
7904 flog_err(EC_ZEBRA_VTEP_ADD_FAILED,
7905 "Failed to add remote VTEP, VNI %u zvni %p",
7906 vni, zvni);
7907 continue;
7908 }
7909
7910 zvni_vtep_install(zvni, &vtep_ip);
7911 }
7912
7913 stream_failure:
7914 return;
7915 }
7916
7917 /*
7918 * Add/Del gateway macip to evpn
7919 * g/w can be:
7920 * 1. SVI interface on a vlan aware bridge
7921 * 2. SVI interface on a vlan unaware bridge
7922 * 3. vrr interface (MACVLAN) associated to a SVI
7923 * We advertise macip routes for an interface if it is associated to VxLan vlan
7924 */
7925 int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
7926 int add)
7927 {
7928 struct ipaddr ip;
7929 struct ethaddr macaddr;
7930 zebra_vni_t *zvni = NULL;
7931
7932 memset(&ip, 0, sizeof(struct ipaddr));
7933 memset(&macaddr, 0, sizeof(struct ethaddr));
7934
7935 /* Check if EVPN is enabled. */
7936 if (!is_evpn_enabled())
7937 return 0;
7938
7939 if (IS_ZEBRA_IF_MACVLAN(ifp)) {
7940 struct interface *svi_if =
7941 NULL; /* SVI corresponding to the MACVLAN */
7942 struct zebra_if *ifp_zif =
7943 NULL; /* Zebra daemon specific info for MACVLAN */
7944 struct zebra_if *svi_if_zif =
7945 NULL; /* Zebra daemon specific info for SVI*/
7946
7947 ifp_zif = ifp->info;
7948 if (!ifp_zif)
7949 return -1;
7950
7951 /*
7952 * for a MACVLAN interface the link represents the svi_if
7953 */
7954 svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
7955 ifp_zif->link_ifindex);
7956 if (!svi_if) {
7957 zlog_debug("MACVLAN %s(%u) without link information",
7958 ifp->name, ifp->ifindex);
7959 return -1;
7960 }
7961
7962 if (IS_ZEBRA_IF_VLAN(svi_if)) {
7963 /*
7964 * If it is a vlan aware bridge then the link gives the
7965 * bridge information
7966 */
7967 struct interface *svi_if_link = NULL;
7968
7969 svi_if_zif = svi_if->info;
7970 if (svi_if_zif) {
7971 svi_if_link = if_lookup_by_index_per_ns(
7972 zebra_ns_lookup(NS_DEFAULT),
7973 svi_if_zif->link_ifindex);
7974 zvni = zvni_from_svi(svi_if, svi_if_link);
7975 }
7976 } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
7977 /*
7978 * If it is a vlan unaware bridge then svi is the bridge
7979 * itself
7980 */
7981 zvni = zvni_from_svi(svi_if, svi_if);
7982 }
7983 } else if (IS_ZEBRA_IF_VLAN(ifp)) {
7984 struct zebra_if *svi_if_zif =
7985 NULL; /* Zebra daemon specific info for SVI */
7986 struct interface *svi_if_link =
7987 NULL; /* link info for the SVI = bridge info */
7988
7989 svi_if_zif = ifp->info;
7990 if (svi_if_zif) {
7991 svi_if_link = if_lookup_by_index_per_ns(
7992 zebra_ns_lookup(NS_DEFAULT),
7993 svi_if_zif->link_ifindex);
7994 if (svi_if_link)
7995 zvni = zvni_from_svi(ifp, svi_if_link);
7996 }
7997 } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
7998 zvni = zvni_from_svi(ifp, ifp);
7999 }
8000
8001 if (!zvni)
8002 return 0;
8003
8004 if (!zvni->vxlan_if) {
8005 zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up",
8006 zvni->vni, zvni);
8007 return -1;
8008 }
8009
8010
8011 memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
8012
8013 if (p->family == AF_INET) {
8014 ip.ipa_type = IPADDR_V4;
8015 memcpy(&(ip.ipaddr_v4), &(p->u.prefix4),
8016 sizeof(struct in_addr));
8017 } else if (p->family == AF_INET6) {
8018 ip.ipa_type = IPADDR_V6;
8019 memcpy(&(ip.ipaddr_v6), &(p->u.prefix6),
8020 sizeof(struct in6_addr));
8021 }
8022
8023
8024 if (add)
8025 zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
8026 else
8027 zvni_gw_macip_del(ifp, zvni, &ip);
8028
8029 return 0;
8030 }
8031
8032 /*
8033 * Handle SVI interface going down.
8034 * SVI can be associated to either L3-VNI or L2-VNI.
8035 * For L2-VNI: At this point, this is a NOP since
8036 * the kernel deletes the neighbor entries on this SVI (if any).
8037 * We only need to update the vrf corresponding to zvni.
8038 * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete
8039 * from bgp
8040 */
8041 int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
8042 {
8043 zebra_l3vni_t *zl3vni = NULL;
8044
8045 zl3vni = zl3vni_from_svi(ifp, link_if);
8046 if (zl3vni) {
8047
8048 /* process l3-vni down */
8049 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8050
8051 /* remove association with svi-if */
8052 zl3vni->svi_if = NULL;
8053 } else {
8054 zebra_vni_t *zvni = NULL;
8055
8056 /* since we dont have svi corresponding to zvni, we associate it
8057 * to default vrf. Note: the corresponding neigh entries on the
8058 * SVI would have already been deleted */
8059 zvni = zvni_from_svi(ifp, link_if);
8060 if (zvni) {
8061 zvni->vrf_id = VRF_DEFAULT;
8062
8063 /* update the tenant vrf in BGP */
8064 zvni_send_add_to_client(zvni);
8065 }
8066 }
8067 return 0;
8068 }
8069
8070 /*
8071 * Handle SVI interface coming up.
8072 * SVI can be associated to L3-VNI (l3vni vxlan interface) or L2-VNI (l2-vni
8073 * vxlan intf).
8074 * For L2-VNI: we need to install any remote neighbors entried (used for
8075 * apr-suppression)
8076 * For L3-VNI: SVI will be used to get the rmac to be used with L3-VNI
8077 */
8078 int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
8079 {
8080 zebra_vni_t *zvni = NULL;
8081 zebra_l3vni_t *zl3vni = NULL;
8082
8083 zl3vni = zl3vni_from_svi(ifp, link_if);
8084 if (zl3vni) {
8085
8086 /* associate with svi */
8087 zl3vni->svi_if = ifp;
8088
8089 /* process oper-up */
8090 if (is_l3vni_oper_up(zl3vni))
8091 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8092 } else {
8093
8094 /* process SVI up for l2-vni */
8095 struct neigh_walk_ctx n_wctx;
8096
8097 zvni = zvni_from_svi(ifp, link_if);
8098 if (!zvni)
8099 return 0;
8100
8101 if (!zvni->vxlan_if) {
8102 zlog_debug(
8103 "VNI %u hash %p doesn't have intf upon SVI up",
8104 zvni->vni, zvni);
8105 return -1;
8106 }
8107
8108 if (IS_ZEBRA_DEBUG_VXLAN)
8109 zlog_debug(
8110 "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors",
8111 ifp->name, ifp->ifindex, zvni->vni,
8112 vrf_id_to_name(ifp->vrf_id));
8113
8114 /* update the vrf information for l2-vni and inform bgp */
8115 zvni->vrf_id = ifp->vrf_id;
8116 zvni_send_add_to_client(zvni);
8117
8118 /* Install any remote neighbors for this VNI. */
8119 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
8120 n_wctx.zvni = zvni;
8121 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
8122 &n_wctx);
8123 }
8124
8125 return 0;
8126 }
8127
8128 /*
8129 * Handle VxLAN interface down
8130 */
8131 int zebra_vxlan_if_down(struct interface *ifp)
8132 {
8133 vni_t vni;
8134 struct zebra_if *zif = NULL;
8135 struct zebra_l2info_vxlan *vxl = NULL;
8136 zebra_l3vni_t *zl3vni = NULL;
8137 zebra_vni_t *zvni;
8138
8139 /* Check if EVPN is enabled. */
8140 if (!is_evpn_enabled())
8141 return 0;
8142
8143 zif = ifp->info;
8144 assert(zif);
8145 vxl = &zif->l2info.vxl;
8146 vni = vxl->vni;
8147
8148 zl3vni = zl3vni_lookup(vni);
8149 if (zl3vni) {
8150 /* process-if-down for l3-vni */
8151 if (IS_ZEBRA_DEBUG_VXLAN)
8152 zlog_debug("Intf %s(%u) L3-VNI %u is DOWN", ifp->name,
8153 ifp->ifindex, vni);
8154
8155 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8156 } else {
8157 /* process if-down for l2-vni */
8158 if (IS_ZEBRA_DEBUG_VXLAN)
8159 zlog_debug("Intf %s(%u) L2-VNI %u is DOWN", ifp->name,
8160 ifp->ifindex, vni);
8161
8162 /* Locate hash entry; it is expected to exist. */
8163 zvni = zvni_lookup(vni);
8164 if (!zvni) {
8165 zlog_debug(
8166 "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u",
8167 ifp->name, ifp->ifindex, vni);
8168 return -1;
8169 }
8170
8171 assert(zvni->vxlan_if == ifp);
8172
8173 /* Delete this VNI from BGP. */
8174 zvni_send_del_to_client(zvni->vni);
8175
8176 /* Free up all neighbors and MACs, if any. */
8177 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
8178 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
8179
8180 /* Free up all remote VTEPs, if any. */
8181 zvni_vtep_del_all(zvni, 1);
8182 }
8183 return 0;
8184 }
8185
8186 /*
8187 * Handle VxLAN interface up - update BGP if required.
8188 */
8189 int zebra_vxlan_if_up(struct interface *ifp)
8190 {
8191 vni_t vni;
8192 struct zebra_if *zif = NULL;
8193 struct zebra_l2info_vxlan *vxl = NULL;
8194 zebra_vni_t *zvni = NULL;
8195 zebra_l3vni_t *zl3vni = NULL;
8196
8197 /* Check if EVPN is enabled. */
8198 if (!is_evpn_enabled())
8199 return 0;
8200
8201 zif = ifp->info;
8202 assert(zif);
8203 vxl = &zif->l2info.vxl;
8204 vni = vxl->vni;
8205
8206 zl3vni = zl3vni_lookup(vni);
8207 if (zl3vni) {
8208
8209 if (IS_ZEBRA_DEBUG_VXLAN)
8210 zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp->name,
8211 ifp->ifindex, vni);
8212
8213 /* we need to associate with SVI, if any, we can associate with
8214 * svi-if only after association with vxlan-intf is complete
8215 */
8216 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8217
8218 if (is_l3vni_oper_up(zl3vni))
8219 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8220 } else {
8221 /* Handle L2-VNI add */
8222 struct interface *vlan_if = NULL;
8223
8224 if (IS_ZEBRA_DEBUG_VXLAN)
8225 zlog_debug("Intf %s(%u) L2-VNI %u is UP", ifp->name,
8226 ifp->ifindex, vni);
8227
8228 /* Locate hash entry; it is expected to exist. */
8229 zvni = zvni_lookup(vni);
8230 if (!zvni) {
8231 zlog_debug(
8232 "Failed to locate VNI hash at UP, IF %s(%u) VNI %u",
8233 ifp->name, ifp->ifindex, vni);
8234 return -1;
8235 }
8236
8237 assert(zvni->vxlan_if == ifp);
8238 vlan_if = zvni_map_to_svi(vxl->access_vlan,
8239 zif->brslave_info.br_if);
8240 if (vlan_if) {
8241 zvni->vrf_id = vlan_if->vrf_id;
8242 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
8243 if (zl3vni)
8244 listnode_add_sort(zl3vni->l2vnis, zvni);
8245 }
8246
8247 /* If part of a bridge, inform BGP about this VNI. */
8248 /* Also, read and populate local MACs and neighbors. */
8249 if (zif->brslave_info.br_if) {
8250 zvni_send_add_to_client(zvni);
8251 zvni_read_mac_neigh(zvni, ifp);
8252 }
8253 }
8254
8255 return 0;
8256 }
8257
8258 /*
8259 * Handle VxLAN interface delete. Locate and remove entry in hash table
8260 * and update BGP, if required.
8261 */
8262 int zebra_vxlan_if_del(struct interface *ifp)
8263 {
8264 vni_t vni;
8265 struct zebra_if *zif = NULL;
8266 struct zebra_l2info_vxlan *vxl = NULL;
8267 zebra_vni_t *zvni = NULL;
8268 zebra_l3vni_t *zl3vni = NULL;
8269
8270 /* Check if EVPN is enabled. */
8271 if (!is_evpn_enabled())
8272 return 0;
8273
8274 zif = ifp->info;
8275 assert(zif);
8276 vxl = &zif->l2info.vxl;
8277 vni = vxl->vni;
8278
8279 zl3vni = zl3vni_lookup(vni);
8280 if (zl3vni) {
8281
8282 if (IS_ZEBRA_DEBUG_VXLAN)
8283 zlog_debug("Del L3-VNI %u intf %s(%u)", vni, ifp->name,
8284 ifp->ifindex);
8285
8286 /* process oper-down for l3-vni */
8287 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8288
8289 /* remove the association with vxlan_if */
8290 memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
8291 zl3vni->vxlan_if = NULL;
8292 } else {
8293
8294 /* process if-del for l2-vni*/
8295 if (IS_ZEBRA_DEBUG_VXLAN)
8296 zlog_debug("Del L2-VNI %u intf %s(%u)", vni, ifp->name,
8297 ifp->ifindex);
8298
8299 /* Locate hash entry; it is expected to exist. */
8300 zvni = zvni_lookup(vni);
8301 if (!zvni) {
8302 zlog_debug(
8303 "Failed to locate VNI hash at del, IF %s(%u) VNI %u",
8304 ifp->name, ifp->ifindex, vni);
8305 return 0;
8306 }
8307
8308 /* remove from l3-vni list */
8309 zl3vni = zl3vni_from_vrf(zvni->vrf_id);
8310 if (zl3vni)
8311 listnode_delete(zl3vni->l2vnis, zvni);
8312
8313 /* Delete VNI from BGP. */
8314 zvni_send_del_to_client(zvni->vni);
8315
8316 /* Free up all neighbors and MAC, if any. */
8317 zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH);
8318 zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC);
8319
8320 /* Free up all remote VTEPs, if any. */
8321 zvni_vtep_del_all(zvni, 0);
8322
8323 /* Delete the hash entry. */
8324 if (zvni_del(zvni)) {
8325 flog_err(EC_ZEBRA_VNI_DEL_FAILED,
8326 "Failed to del VNI hash %p, IF %s(%u) VNI %u",
8327 zvni, ifp->name, ifp->ifindex, zvni->vni);
8328 return -1;
8329 }
8330 }
8331 return 0;
8332 }
8333
8334 /*
8335 * Handle VxLAN interface update - change to tunnel IP, master or VLAN.
8336 */
8337 int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
8338 {
8339 vni_t vni;
8340 struct zebra_if *zif = NULL;
8341 struct zebra_l2info_vxlan *vxl = NULL;
8342 zebra_vni_t *zvni = NULL;
8343 zebra_l3vni_t *zl3vni = NULL;
8344
8345 /* Check if EVPN is enabled. */
8346 if (!is_evpn_enabled())
8347 return 0;
8348
8349 zif = ifp->info;
8350 assert(zif);
8351 vxl = &zif->l2info.vxl;
8352 vni = vxl->vni;
8353
8354 zl3vni = zl3vni_lookup(vni);
8355 if (zl3vni) {
8356
8357 if (IS_ZEBRA_DEBUG_VXLAN)
8358 zlog_debug(
8359 "Update L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8360 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8361 inet_ntoa(vxl->vtep_ip),
8362 zif->brslave_info.bridge_ifindex, chgflags);
8363
8364 /* Removed from bridge? Cleanup and return */
8365 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8366 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
8367 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8368 return 0;
8369 }
8370
8371 /* access-vlan change - process oper down, associate with new
8372 * svi_if and then process oper up again
8373 */
8374 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8375 if (if_is_operative(ifp)) {
8376 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8377 zl3vni->svi_if = NULL;
8378 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8379 zl3vni->local_vtep_ip = vxl->vtep_ip;
8380 if (is_l3vni_oper_up(zl3vni))
8381 zebra_vxlan_process_l3vni_oper_up(
8382 zl3vni);
8383 }
8384 }
8385
8386 /*
8387 * local-ip change - process oper down, associate with new
8388 * local-ip and then process oper up again
8389 */
8390 if (chgflags & ZEBRA_VXLIF_LOCAL_IP_CHANGE) {
8391 if (if_is_operative(ifp)) {
8392 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8393 zl3vni->local_vtep_ip = vxl->vtep_ip;
8394 if (is_l3vni_oper_up(zl3vni))
8395 zebra_vxlan_process_l3vni_oper_up(
8396 zl3vni);
8397 }
8398 }
8399
8400 /* Update local tunnel IP. */
8401 zl3vni->local_vtep_ip = vxl->vtep_ip;
8402
8403 /* if we have a valid new master, process l3-vni oper up */
8404 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
8405 if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
8406 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8407 }
8408 } else {
8409
8410 /* Update VNI hash. */
8411 zvni = zvni_lookup(vni);
8412 if (!zvni) {
8413 zlog_debug(
8414 "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u",
8415 ifp->name, ifp->ifindex, vni);
8416 return -1;
8417 }
8418
8419 if (IS_ZEBRA_DEBUG_VXLAN)
8420 zlog_debug(
8421 "Update L2-VNI %u intf %s(%u) VLAN %u local IP %s master %u chg 0x%x",
8422 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8423 inet_ntoa(vxl->vtep_ip),
8424 zif->brslave_info.bridge_ifindex, chgflags);
8425
8426 /* Removed from bridge? Cleanup and return */
8427 if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8428 && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
8429 /* Delete from client, remove all remote VTEPs */
8430 /* Also, free up all MACs and neighbors. */
8431 zvni_send_del_to_client(zvni->vni);
8432 zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH);
8433 zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC);
8434 zvni_vtep_del_all(zvni, 1);
8435 return 0;
8436 }
8437
8438 /* Handle other changes. */
8439 if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8440 /* Remove all existing local neigh and MACs for this VNI
8441 * (including from BGP)
8442 */
8443 zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
8444 zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC);
8445 }
8446
8447 zvni->local_vtep_ip = vxl->vtep_ip;
8448 zvni->vxlan_if = ifp;
8449
8450 /* Take further actions needed.
8451 * Note that if we are here, there is a change of interest.
8452 */
8453 /* If down or not mapped to a bridge, we're done. */
8454 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8455 return 0;
8456
8457 /* Inform BGP, if there is a change of interest. */
8458 if (chgflags
8459 & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE))
8460 zvni_send_add_to_client(zvni);
8461
8462 /* If there is a valid new master or a VLAN mapping change,
8463 * read and populate local MACs and neighbors.
8464 * Also, reinstall any remote MACs and neighbors
8465 * for this VNI (based on new VLAN).
8466 */
8467 if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
8468 zvni_read_mac_neigh(zvni, ifp);
8469 else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
8470 struct mac_walk_ctx m_wctx;
8471 struct neigh_walk_ctx n_wctx;
8472
8473 zvni_read_mac_neigh(zvni, ifp);
8474
8475 memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
8476 m_wctx.zvni = zvni;
8477 hash_iterate(zvni->mac_table, zvni_install_mac_hash,
8478 &m_wctx);
8479
8480 memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
8481 n_wctx.zvni = zvni;
8482 hash_iterate(zvni->neigh_table, zvni_install_neigh_hash,
8483 &n_wctx);
8484 }
8485 }
8486
8487 return 0;
8488 }
8489
8490 /*
8491 * Handle VxLAN interface add.
8492 */
8493 int zebra_vxlan_if_add(struct interface *ifp)
8494 {
8495 vni_t vni;
8496 struct zebra_if *zif = NULL;
8497 struct zebra_l2info_vxlan *vxl = NULL;
8498 zebra_vni_t *zvni = NULL;
8499 zebra_l3vni_t *zl3vni = NULL;
8500
8501 /* Check if EVPN is enabled. */
8502 if (!is_evpn_enabled())
8503 return 0;
8504
8505 zif = ifp->info;
8506 assert(zif);
8507 vxl = &zif->l2info.vxl;
8508 vni = vxl->vni;
8509
8510 zl3vni = zl3vni_lookup(vni);
8511 if (zl3vni) {
8512
8513 /* process if-add for l3-vni*/
8514 if (IS_ZEBRA_DEBUG_VXLAN)
8515 zlog_debug(
8516 "Add L3-VNI %u intf %s(%u) VLAN %u local IP %s master %u",
8517 vni, ifp->name, ifp->ifindex, vxl->access_vlan,
8518 inet_ntoa(vxl->vtep_ip),
8519 zif->brslave_info.bridge_ifindex);
8520
8521 /* associate with vxlan_if */
8522 zl3vni->local_vtep_ip = vxl->vtep_ip;
8523 zl3vni->vxlan_if = ifp;
8524
8525 /* Associate with SVI, if any. We can associate with svi-if only
8526 * after association with vxlan_if is complete */
8527 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8528
8529 if (is_l3vni_oper_up(zl3vni))
8530 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8531 } else {
8532
8533 /* process if-add for l2-vni */
8534 struct interface *vlan_if = NULL;
8535
8536 /* Create or update VNI hash. */
8537 zvni = zvni_lookup(vni);
8538 if (!zvni) {
8539 zvni = zvni_add(vni);
8540 if (!zvni) {
8541 flog_err(
8542 EC_ZEBRA_VNI_ADD_FAILED,
8543 "Failed to add VNI hash, IF %s(%u) VNI %u",
8544 ifp->name, ifp->ifindex, vni);
8545 return -1;
8546 }
8547 }
8548
8549 zvni->local_vtep_ip = vxl->vtep_ip;
8550 zvni->vxlan_if = ifp;
8551 vlan_if = zvni_map_to_svi(vxl->access_vlan,
8552 zif->brslave_info.br_if);
8553 if (vlan_if) {
8554 zvni->vrf_id = vlan_if->vrf_id;
8555 zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
8556 if (zl3vni)
8557 listnode_add_sort(zl3vni->l2vnis, zvni);
8558 }
8559
8560 if (IS_ZEBRA_DEBUG_VXLAN)
8561 zlog_debug(
8562 "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
8563 vni,
8564 vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
8565 : VRF_DEFAULT_NAME,
8566 ifp->name, ifp->ifindex, vxl->access_vlan,
8567 inet_ntoa(vxl->vtep_ip),
8568 zif->brslave_info.bridge_ifindex);
8569
8570 /* If down or not mapped to a bridge, we're done. */
8571 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8572 return 0;
8573
8574 /* Inform BGP */
8575 zvni_send_add_to_client(zvni);
8576
8577 /* Read and populate local MACs and neighbors */
8578 zvni_read_mac_neigh(zvni, ifp);
8579 }
8580
8581 return 0;
8582 }
8583
8584 int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
8585 char *err, int err_str_sz, int filter,
8586 int add)
8587 {
8588 zebra_l3vni_t *zl3vni = NULL;
8589 struct zebra_vrf *zvrf_default = NULL;
8590
8591 zvrf_default = zebra_vrf_lookup_by_id(VRF_DEFAULT);
8592 if (!zvrf_default)
8593 return -1;
8594
8595 if (IS_ZEBRA_DEBUG_VXLAN)
8596 zlog_debug("vrf %s vni %u %s", zvrf_name(zvrf), vni,
8597 add ? "ADD" : "DEL");
8598
8599 if (add) {
8600
8601 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
8602
8603 /* check if the vni is already present under zvrf */
8604 if (zvrf->l3vni) {
8605 snprintf(err, err_str_sz,
8606 "VNI is already configured under the vrf");
8607 return -1;
8608 }
8609
8610 /* check if this VNI is already present in the system */
8611 zl3vni = zl3vni_lookup(vni);
8612 if (zl3vni) {
8613 snprintf(err, err_str_sz,
8614 "VNI is already configured as L3-VNI");
8615 return -1;
8616 }
8617
8618 /* add the L3-VNI to the global table */
8619 zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
8620 if (!zl3vni) {
8621 snprintf(err, err_str_sz, "Could not add L3-VNI");
8622 return -1;
8623 }
8624
8625 /* associate the vrf with vni */
8626 zvrf->l3vni = vni;
8627
8628 /* set the filter in l3vni to denote if we are using l3vni only
8629 * for prefix routes
8630 */
8631 if (filter)
8632 SET_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY);
8633
8634 /* associate with vxlan-intf;
8635 * we need to associate with the vxlan-intf first
8636 */
8637 zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
8638
8639 /* associate with corresponding SVI interface, we can associate
8640 * with svi-if only after vxlan interface association is
8641 * complete
8642 */
8643 zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
8644
8645 /* formulate l2vni list */
8646 hash_iterate(zvrf_default->vni_table, zvni_add_to_l3vni_list,
8647 zl3vni);
8648
8649 if (is_l3vni_oper_up(zl3vni))
8650 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8651
8652 } else {
8653 zl3vni = zl3vni_lookup(vni);
8654 if (!zl3vni) {
8655 snprintf(err, err_str_sz, "VNI doesn't exist");
8656 return -1;
8657 }
8658
8659 if (filter && !CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)) {
8660 snprintf(err, ERR_STR_SZ,
8661 "prefix-routes-only is not set for the vni");
8662 return -1;
8663 }
8664
8665 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8666
8667 /* delete and uninstall all rmacs */
8668 hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry,
8669 zl3vni);
8670
8671 /* delete and uninstall all next-hops */
8672 hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry,
8673 zl3vni);
8674
8675 zvrf->l3vni = 0;
8676 zl3vni_del(zl3vni);
8677
8678 zebra_vxlan_handle_vni_transition(zvrf, vni, add);
8679 }
8680 return 0;
8681 }
8682
8683 int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
8684 {
8685 zebra_l3vni_t *zl3vni = NULL;
8686
8687 if (zvrf->l3vni)
8688 zl3vni = zl3vni_lookup(zvrf->l3vni);
8689 if (!zl3vni)
8690 return 0;
8691
8692 zl3vni->vrf_id = zvrf_id(zvrf);
8693 if (is_l3vni_oper_up(zl3vni))
8694 zebra_vxlan_process_l3vni_oper_up(zl3vni);
8695 return 0;
8696 }
8697
8698 int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
8699 {
8700 zebra_l3vni_t *zl3vni = NULL;
8701
8702 if (zvrf->l3vni)
8703 zl3vni = zl3vni_lookup(zvrf->l3vni);
8704 if (!zl3vni)
8705 return 0;
8706
8707 zl3vni->vrf_id = VRF_UNKNOWN;
8708 zebra_vxlan_process_l3vni_oper_down(zl3vni);
8709 return 0;
8710 }
8711
8712 int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
8713 {
8714 zebra_l3vni_t *zl3vni = NULL;
8715 vni_t vni;
8716
8717 if (zvrf->l3vni)
8718 zl3vni = zl3vni_lookup(zvrf->l3vni);
8719 if (!zl3vni)
8720 return 0;
8721
8722 vni = zl3vni->vni;
8723 zl3vni_del(zl3vni);
8724 zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
8725
8726 return 0;
8727 }
8728
8729 /*
8730 * Handle message from client to specify the flooding mechanism for
8731 * BUM packets. The default is to do head-end (ingress) replication
8732 * and the other supported option is to disable it. This applies to
8733 * all BUM traffic and disabling it applies to both the transmit and
8734 * receive direction.
8735 */
8736 void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS)
8737 {
8738 struct stream *s;
8739 enum vxlan_flood_control flood_ctrl;
8740
8741 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8742 zlog_err("EVPN flood control for non-default VRF %u",
8743 zvrf_id(zvrf));
8744 return;
8745 }
8746
8747 s = msg;
8748 STREAM_GETC(s, flood_ctrl);
8749
8750 if (IS_ZEBRA_DEBUG_VXLAN)
8751 zlog_debug("EVPN flood control %u, currently %u",
8752 flood_ctrl, zvrf->vxlan_flood_ctrl);
8753
8754 if (zvrf->vxlan_flood_ctrl == flood_ctrl)
8755 return;
8756
8757 zvrf->vxlan_flood_ctrl = flood_ctrl;
8758
8759 /* Install or uninstall flood entries corresponding to
8760 * remote VTEPs.
8761 */
8762 hash_iterate(zvrf->vni_table, zvni_handle_flooding_remote_vteps,
8763 zvrf);
8764
8765 stream_failure:
8766 return;
8767 }
8768
8769 /*
8770 * Handle message from client to enable/disable advertisement of svi macip
8771 * routes
8772 */
8773 void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
8774 {
8775 struct stream *s;
8776 int advertise;
8777 vni_t vni = 0;
8778 zebra_vni_t *zvni = NULL;
8779 struct interface *ifp = NULL;
8780
8781 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8782 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8783 zvrf_id(zvrf));
8784 return;
8785 }
8786
8787 s = msg;
8788 STREAM_GETC(s, advertise);
8789 STREAM_GETL(s, vni);
8790
8791 if (!vni) {
8792 if (IS_ZEBRA_DEBUG_VXLAN)
8793 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8794 advertise ? "enabled" : "disabled",
8795 advertise_gw_macip_enabled(NULL)
8796 ? "enabled"
8797 : "disabled");
8798
8799 if (zvrf->advertise_svi_macip == advertise)
8800 return;
8801
8802
8803 if (advertise) {
8804 zvrf->advertise_svi_macip = advertise;
8805 hash_iterate(zvrf->vni_table,
8806 zvni_gw_macip_add_for_vni_hash, NULL);
8807 } else {
8808 hash_iterate(zvrf->vni_table,
8809 zvni_svi_macip_del_for_vni_hash, NULL);
8810 zvrf->advertise_svi_macip = advertise;
8811 }
8812
8813 } else {
8814 struct zebra_if *zif = NULL;
8815 struct zebra_l2info_vxlan zl2_info;
8816 struct interface *vlan_if = NULL;
8817
8818 zvni = zvni_lookup(vni);
8819 if (!zvni)
8820 return;
8821
8822 if (IS_ZEBRA_DEBUG_VXLAN)
8823 zlog_debug(
8824 "EVPN SVI macip Adv %s on VNI %d , currently %s",
8825 advertise ? "enabled" : "disabled", vni,
8826 advertise_svi_macip_enabled(zvni)
8827 ? "enabled"
8828 : "disabled");
8829
8830 if (zvni->advertise_svi_macip == advertise)
8831 return;
8832
8833 ifp = zvni->vxlan_if;
8834 if (!ifp)
8835 return;
8836
8837 zif = ifp->info;
8838
8839 /* If down or not mapped to a bridge, we're done. */
8840 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8841 return;
8842
8843 zl2_info = zif->l2info.vxl;
8844
8845 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
8846 zif->brslave_info.br_if);
8847 if (!vlan_if)
8848 return;
8849
8850 if (advertise) {
8851 zvni->advertise_svi_macip = advertise;
8852 /* Add primary SVI MAC-IP */
8853 zvni_add_macip_for_intf(vlan_if, zvni);
8854 } else {
8855 /* Del primary MAC-IP */
8856 zvni_del_macip_for_intf(vlan_if, zvni);
8857 zvni->advertise_svi_macip = advertise;
8858 }
8859 }
8860
8861 stream_failure:
8862 return;
8863 }
8864
8865 /*
8866 * Handle message from client to enable/disable advertisement of g/w macip
8867 * routes
8868 */
8869 void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
8870 {
8871 struct stream *s;
8872 int advertise;
8873 vni_t vni = 0;
8874 zebra_vni_t *zvni = NULL;
8875 struct interface *ifp = NULL;
8876 struct zebra_if *zif = NULL;
8877 struct zebra_l2info_vxlan zl2_info;
8878 struct interface *vlan_if = NULL;
8879
8880 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8881 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8882 zvrf_id(zvrf));
8883 return;
8884 }
8885
8886 s = msg;
8887 STREAM_GETC(s, advertise);
8888 vni = stream_get3(s);
8889
8890 zvni = zvni_lookup(vni);
8891 if (!zvni)
8892 return;
8893
8894 if (zvni->advertise_subnet == advertise)
8895 return;
8896
8897 if (IS_ZEBRA_DEBUG_VXLAN)
8898 zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
8899 advertise ? "enabled" : "disabled", vni,
8900 zvni->advertise_subnet ? "enabled" : "disabled");
8901
8902
8903 zvni->advertise_subnet = advertise;
8904
8905 ifp = zvni->vxlan_if;
8906 if (!ifp)
8907 return;
8908
8909 zif = ifp->info;
8910
8911 /* If down or not mapped to a bridge, we're done. */
8912 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
8913 return;
8914
8915 zl2_info = zif->l2info.vxl;
8916
8917 vlan_if =
8918 zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
8919 if (!vlan_if)
8920 return;
8921
8922 if (zvni->advertise_subnet)
8923 zvni_advertise_subnet(zvni, vlan_if, 1);
8924 else
8925 zvni_advertise_subnet(zvni, vlan_if, 0);
8926
8927 stream_failure:
8928 return;
8929 }
8930
8931 /*
8932 * Handle message from client to enable/disable advertisement of g/w macip
8933 * routes
8934 */
8935 void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
8936 {
8937 struct stream *s;
8938 int advertise;
8939 vni_t vni = 0;
8940 zebra_vni_t *zvni = NULL;
8941 struct interface *ifp = NULL;
8942
8943 if (zvrf_id(zvrf) != VRF_DEFAULT) {
8944 zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
8945 zvrf_id(zvrf));
8946 return;
8947 }
8948
8949 s = msg;
8950 STREAM_GETC(s, advertise);
8951 STREAM_GETL(s, vni);
8952
8953 if (!vni) {
8954 if (IS_ZEBRA_DEBUG_VXLAN)
8955 zlog_debug("EVPN gateway macip Adv %s, currently %s",
8956 advertise ? "enabled" : "disabled",
8957 advertise_gw_macip_enabled(NULL)
8958 ? "enabled"
8959 : "disabled");
8960
8961 if (zvrf->advertise_gw_macip == advertise)
8962 return;
8963
8964 zvrf->advertise_gw_macip = advertise;
8965
8966 if (advertise_gw_macip_enabled(zvni))
8967 hash_iterate(zvrf->vni_table,
8968 zvni_gw_macip_add_for_vni_hash, NULL);
8969 else
8970 hash_iterate(zvrf->vni_table,
8971 zvni_gw_macip_del_for_vni_hash, NULL);
8972
8973 } else {
8974 struct zebra_if *zif = NULL;
8975 struct zebra_l2info_vxlan zl2_info;
8976 struct interface *vlan_if = NULL;
8977 struct interface *vrr_if = NULL;
8978
8979 zvni = zvni_lookup(vni);
8980 if (!zvni)
8981 return;
8982
8983 if (IS_ZEBRA_DEBUG_VXLAN)
8984 zlog_debug(
8985 "EVPN gateway macip Adv %s on VNI %d , currently %s",
8986 advertise ? "enabled" : "disabled", vni,
8987 advertise_gw_macip_enabled(zvni) ? "enabled"
8988 : "disabled");
8989
8990 if (zvni->advertise_gw_macip == advertise)
8991 return;
8992
8993 zvni->advertise_gw_macip = advertise;
8994
8995 ifp = zvni->vxlan_if;
8996 if (!ifp)
8997 return;
8998
8999 zif = ifp->info;
9000
9001 /* If down or not mapped to a bridge, we're done. */
9002 if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
9003 return;
9004
9005 zl2_info = zif->l2info.vxl;
9006
9007 vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
9008 zif->brslave_info.br_if);
9009 if (!vlan_if)
9010 return;
9011
9012 if (advertise_gw_macip_enabled(zvni)) {
9013 /* Add primary SVI MAC-IP */
9014 zvni_add_macip_for_intf(vlan_if, zvni);
9015
9016 /* Add VRR MAC-IP - if any*/
9017 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
9018 if (vrr_if)
9019 zvni_add_macip_for_intf(vrr_if, zvni);
9020 } else {
9021 /* Del primary MAC-IP */
9022 zvni_del_macip_for_intf(vlan_if, zvni);
9023
9024 /* Del VRR MAC-IP - if any*/
9025 vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
9026 if (vrr_if)
9027 zvni_del_macip_for_intf(vrr_if, zvni);
9028 }
9029 }
9030
9031 stream_failure:
9032 return;
9033 }
9034
9035
9036 /*
9037 * Handle message from client to learn (or stop learning) about VNIs and MACs.
9038 * When enabled, the VNI hash table will be built and MAC FDB table read;
9039 * when disabled, the entries should be deleted and remote VTEPs and MACs
9040 * uninstalled from the kernel.
9041 * This also informs the setting for BUM handling at the time this change
9042 * occurs; it is relevant only when specifying "learn".
9043 */
9044 void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
9045 {
9046 struct stream *s = NULL;
9047 int advertise = 0;
9048 enum vxlan_flood_control flood_ctrl;
9049
9050 if (zvrf_id(zvrf) != VRF_DEFAULT) {
9051 zlog_debug("EVPN VNI Adv for non-default VRF %u",
9052 zvrf_id(zvrf));
9053 return;
9054 }
9055
9056 s = msg;
9057 STREAM_GETC(s, advertise);
9058 STREAM_GETC(s, flood_ctrl);
9059
9060 if (IS_ZEBRA_DEBUG_VXLAN)
9061 zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u",
9062 advertise ? "enabled" : "disabled",
9063 is_evpn_enabled() ? "enabled" : "disabled",
9064 flood_ctrl);
9065
9066 if (zvrf->advertise_all_vni == advertise)
9067 return;
9068
9069 zvrf->advertise_all_vni = advertise;
9070 if (is_evpn_enabled()) {
9071 /* Note BUM handling */
9072 zvrf->vxlan_flood_ctrl = flood_ctrl;
9073
9074 /* Build VNI hash table and inform BGP. */
9075 zvni_build_hash_table();
9076
9077 /* Add all SVI (L3 GW) MACs to BGP*/
9078 hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash,
9079 NULL);
9080
9081 /* Read the MAC FDB */
9082 macfdb_read(zvrf->zns);
9083
9084 /* Read neighbors */
9085 neigh_read(zvrf->zns);
9086 } else {
9087 /* Cleanup VTEPs for all VNIs - uninstall from
9088 * kernel and free entries.
9089 */
9090 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9091
9092 /* cleanup all l3vnis */
9093 hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL);
9094 }
9095
9096 stream_failure:
9097 return;
9098 }
9099
9100 /*
9101 * Allocate VNI hash table for this VRF and do other initialization.
9102 * NOTE: Currently supported only for default VRF.
9103 */
9104 void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
9105 {
9106 if (!zvrf)
9107 return;
9108 zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp,
9109 "Zebra VRF VNI Table");
9110 }
9111
9112 /* Cleanup VNI info, but don't free the table. */
9113 void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
9114 {
9115 if (!zvrf)
9116 return;
9117 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9118 }
9119
9120 /* Close all VNI handling */
9121 void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
9122 {
9123 if (!zvrf)
9124 return;
9125 hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
9126 hash_free(zvrf->vni_table);
9127 }
9128
9129 /* init the l3vni table */
9130 void zebra_vxlan_init(void)
9131 {
9132 zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
9133 "Zebra VRF L3 VNI table");
9134 }
9135
9136 /* free l3vni table */
9137 void zebra_vxlan_disable(void)
9138 {
9139 hash_free(zrouter.l3vni_table);
9140 }
9141
9142 /* get the l3vni svi ifindex */
9143 ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id)
9144 {
9145 zebra_l3vni_t *zl3vni = NULL;
9146
9147 zl3vni = zl3vni_from_vrf(vrf_id);
9148 if (!zl3vni || !is_l3vni_oper_up(zl3vni))
9149 return 0;
9150
9151 return zl3vni->svi_if->ifindex;
9152 }
9153
9154 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
9155 {
9156 struct zebra_vrf *zvrf = NULL;
9157 zebra_neigh_t *nbr = NULL;
9158 zebra_vni_t *zvni = NULL;
9159 char buf1[INET6_ADDRSTRLEN];
9160 char buf2[ETHER_ADDR_STRLEN];
9161
9162 nbr = THREAD_ARG(t);
9163
9164 /* since this is asynchronous we need sanity checks*/
9165 nbr = zvni_neigh_lookup(zvni, &nbr->ip);
9166 if (!nbr)
9167 return 0;
9168
9169 zvni = zvni_lookup(nbr->zvni->vni);
9170 if (!zvni)
9171 return 0;
9172
9173 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
9174 if (!zvrf)
9175 return 0;
9176
9177 if (IS_ZEBRA_DEBUG_VXLAN)
9178 zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
9179 __PRETTY_FUNCTION__,
9180 prefix_mac2str(&nbr->emac, buf1, sizeof(buf1)),
9181 ipaddr2str(&nbr->ip, buf2, sizeof(buf2)),
9182 nbr->flags,
9183 nbr->dad_count, zvni->vni);
9184
9185 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
9186 nbr->dad_count = 0;
9187 nbr->detect_start_time.tv_sec = 0;
9188 nbr->detect_start_time.tv_usec = 0;
9189 nbr->dad_dup_detect_time = 0;
9190 nbr->dad_ip_auto_recovery_timer = NULL;
9191
9192 /* Send to BGP */
9193 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
9194 zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip, &nbr->emac,
9195 nbr->flags, nbr->loc_seq);
9196 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
9197 zvni_neigh_install(zvni, nbr);
9198 }
9199
9200 return 0;
9201 }
9202
9203 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
9204 {
9205 struct zebra_vrf *zvrf = NULL;
9206 zebra_mac_t *mac = NULL;
9207 zebra_vni_t *zvni = NULL;
9208 struct listnode *node = NULL;
9209 zebra_neigh_t *nbr = NULL;
9210 char buf[ETHER_ADDR_STRLEN];
9211
9212 mac = THREAD_ARG(t);
9213
9214 /* since this is asynchronous we need sanity checks*/
9215 mac = zvni_mac_lookup(zvni, &mac->macaddr);
9216 if (!mac)
9217 return 0;
9218
9219 zvni = zvni_lookup(mac->zvni->vni);
9220 if (!zvni)
9221 return 0;
9222
9223 zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
9224 if (!zvrf)
9225 return 0;
9226
9227 if (IS_ZEBRA_DEBUG_VXLAN)
9228 zlog_debug("%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired",
9229 __PRETTY_FUNCTION__,
9230 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
9231 mac->flags,
9232 mac->dad_count,
9233 listcount(mac->neigh_list));
9234
9235 /* Remove all IPs as duplicate associcated with this MAC */
9236 for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
9237 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
9238 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
9239 ZEBRA_NEIGH_SET_INACTIVE(nbr);
9240 else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
9241 zvni_neigh_install(zvni, nbr);
9242 }
9243
9244 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
9245 nbr->dad_count = 0;
9246 nbr->detect_start_time.tv_sec = 0;
9247 nbr->dad_dup_detect_time = 0;
9248 }
9249
9250 UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
9251 mac->dad_count = 0;
9252 mac->detect_start_time.tv_sec = 0;
9253 mac->detect_start_time.tv_usec = 0;
9254 mac->dad_dup_detect_time = 0;
9255 mac->dad_mac_auto_recovery_timer = NULL;
9256
9257 if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
9258 /* Inform to BGP */
9259 if (zvni_mac_send_add_to_client(zvni->vni, &mac->macaddr,
9260 mac->flags, mac->loc_seq))
9261 return -1;
9262
9263 /* Process all neighbors associated with this MAC. */
9264 zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
9265
9266 } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
9267 zvni_process_neigh_on_remote_mac_add(zvni, mac);
9268
9269 /* Install the entry. */
9270 zvni_mac_install(zvni, mac);
9271 }
9272
9273 return 0;
9274 }