1 /*
2 * Zebra EVPN Neighbor 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 "interface.h"
27 #include "jhash.h"
28 #include "memory.h"
29 #include "prefix.h"
30 #include "vlan.h"
31 #include "json.h"
32
33 #include "zebra/zserv.h"
34 #include "zebra/debug.h"
35 #include "zebra/zebra_router.h"
36 #include "zebra/rt.h"
37 #include "zebra/zebra_memory.h"
38 #include "zebra/zebra_errors.h"
39 #include "zebra/zebra_vrf.h"
40 #include "zebra/zebra_evpn.h"
41 #include "zebra/zebra_evpn_mh.h"
42 #include "zebra/zebra_evpn_neigh.h"
43 #include "zebra/zebra_evpn_mac.h"
44
45 DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "EVI Neighbor");
46
47 /*
48 * Make hash key for neighbors.
49 */
neigh_hash_keymake(const void * p)50 static unsigned int neigh_hash_keymake(const void *p)
51 {
52 const zebra_neigh_t *n = p;
53 const struct ipaddr *ip = &n->ip;
54
55 if (IS_IPADDR_V4(ip))
56 return jhash_1word(ip->ipaddr_v4.s_addr, 0);
57
58 return jhash2(ip->ipaddr_v6.s6_addr32,
59 array_size(ip->ipaddr_v6.s6_addr32), 0);
60 }
61
62 /*
63 * Compare two neighbor hash structures.
64 */
neigh_cmp(const void * p1,const void * p2)65 static bool neigh_cmp(const void *p1, const void *p2)
66 {
67 const zebra_neigh_t *n1 = p1;
68 const zebra_neigh_t *n2 = p2;
69
70 if (n1 == NULL && n2 == NULL)
71 return true;
72
73 if (n1 == NULL || n2 == NULL)
74 return false;
75
76 return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0);
77 }
78
neigh_list_cmp(void * p1,void * p2)79 int neigh_list_cmp(void *p1, void *p2)
80 {
81 const zebra_neigh_t *n1 = p1;
82 const zebra_neigh_t *n2 = p2;
83
84 return memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr));
85 }
86
zebra_neigh_db_create(const char * desc)87 struct hash *zebra_neigh_db_create(const char *desc)
88 {
89 return hash_create(neigh_hash_keymake, neigh_cmp, desc);
90 }
91
num_dup_detected_neighs(zebra_evpn_t * zevpn)92 uint32_t num_dup_detected_neighs(zebra_evpn_t *zevpn)
93 {
94 unsigned int i;
95 uint32_t num_neighs = 0;
96 struct hash *hash;
97 struct hash_bucket *hb;
98 zebra_neigh_t *nbr;
99
100 hash = zevpn->neigh_table;
101 if (!hash)
102 return num_neighs;
103 for (i = 0; i < hash->size; i++) {
104 for (hb = hash->index[i]; hb; hb = hb->next) {
105 nbr = (zebra_neigh_t *)hb->data;
106 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
107 num_neighs++;
108 }
109 }
110
111 return num_neighs;
112 }
113
114 /*
115 * Helper function to determine maximum width of neighbor IP address for
116 * display - just because we're dealing with IPv6 addresses that can
117 * widely vary.
118 */
zebra_evpn_find_neigh_addr_width(struct hash_bucket * bucket,void * ctxt)119 void zebra_evpn_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt)
120 {
121 zebra_neigh_t *n;
122 char buf[INET6_ADDRSTRLEN];
123 struct neigh_walk_ctx *wctx = ctxt;
124 int width;
125
126 n = (zebra_neigh_t *)bucket->data;
127
128 ipaddr2str(&n->ip, buf, sizeof(buf));
129 width = strlen(buf);
130 if (width > wctx->addr_width)
131 wctx->addr_width = width;
132 }
133
134 /*
135 * Count of remote neighbors referencing this MAC.
136 */
remote_neigh_count(zebra_mac_t * zmac)137 int remote_neigh_count(zebra_mac_t *zmac)
138 {
139 zebra_neigh_t *n = NULL;
140 struct listnode *node = NULL;
141 int count = 0;
142
143 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
144 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
145 count++;
146 }
147
148 return count;
149 }
150
151 /*
152 * Install remote neighbor into the kernel.
153 */
zebra_evpn_rem_neigh_install(zebra_evpn_t * zevpn,zebra_neigh_t * n,bool was_static)154 int zebra_evpn_rem_neigh_install(zebra_evpn_t *zevpn, zebra_neigh_t *n,
155 bool was_static)
156 {
157 struct interface *vlan_if;
158 int flags;
159 int ret = 0;
160
161 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
162 return 0;
163
164 vlan_if = zevpn_map_to_svi(zevpn);
165 if (!vlan_if)
166 return -1;
167
168 flags = DPLANE_NTF_EXT_LEARNED;
169 if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG)
170 flags |= DPLANE_NTF_ROUTER;
171 ZEBRA_NEIGH_SET_ACTIVE(n);
172
173 dplane_rem_neigh_add(vlan_if, &n->ip, &n->emac, flags, was_static);
174
175 return ret;
176 }
177
178 /*
179 * Install neighbor hash entry - called upon access VLAN change.
180 */
zebra_evpn_install_neigh_hash(struct hash_bucket * bucket,void * ctxt)181 void zebra_evpn_install_neigh_hash(struct hash_bucket *bucket, void *ctxt)
182 {
183 zebra_neigh_t *n;
184 struct neigh_walk_ctx *wctx = ctxt;
185
186 n = (zebra_neigh_t *)bucket->data;
187
188 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
189 zebra_evpn_rem_neigh_install(wctx->zevpn, n,
190 false /*was_static*/);
191 }
192
193 /*
194 * Callback to allocate neighbor hash entry.
195 */
zebra_evpn_neigh_alloc(void * p)196 static void *zebra_evpn_neigh_alloc(void *p)
197 {
198 const zebra_neigh_t *tmp_n = p;
199 zebra_neigh_t *n;
200
201 n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t));
202 *n = *tmp_n;
203
204 return ((void *)n);
205 }
206
zebra_evpn_local_neigh_ref_mac(zebra_neigh_t * n,struct ethaddr * macaddr,zebra_mac_t * mac,bool send_mac_update)207 static void zebra_evpn_local_neigh_ref_mac(zebra_neigh_t *n,
208 struct ethaddr *macaddr,
209 zebra_mac_t *mac,
210 bool send_mac_update)
211 {
212 char macbuf[ETHER_ADDR_STRLEN];
213 char ipbuf[INET6_ADDRSTRLEN];
214 bool old_static;
215 bool new_static;
216
217 memcpy(&n->emac, macaddr, ETH_ALEN);
218 n->mac = mac;
219
220 /* Link to new MAC */
221 if (!mac)
222 return;
223
224 listnode_add_sort(mac->neigh_list, n);
225 if (n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) {
226 old_static = zebra_evpn_mac_is_static(mac);
227 ++mac->sync_neigh_cnt;
228 new_static = zebra_evpn_mac_is_static(mac);
229 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
230 zlog_debug(
231 "sync-neigh ref mac vni %u ip %s mac %s ref %d",
232 n->zevpn->vni,
233 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
234 prefix_mac2str(&n->emac, macbuf,
235 sizeof(macbuf)),
236 mac->sync_neigh_cnt);
237 if ((old_static != new_static) && send_mac_update)
238 /* program the local mac in the kernel */
239 zebra_evpn_sync_mac_dp_install(
240 mac, false /*set_inactive*/,
241 false /*force_clear_static*/, __func__);
242 }
243 }
244
245 /* sync-path that is active on an ES peer */
zebra_evpn_sync_neigh_dp_install(zebra_neigh_t * n,bool set_inactive,bool force_clear_static,const char * caller)246 static void zebra_evpn_sync_neigh_dp_install(zebra_neigh_t *n,
247 bool set_inactive,
248 bool force_clear_static,
249 const char *caller)
250 {
251 char macbuf[ETHER_ADDR_STRLEN];
252 char ipbuf[INET6_ADDRSTRLEN];
253 struct zebra_ns *zns;
254 struct interface *ifp;
255 bool set_static;
256 bool set_router;
257
258 zns = zebra_ns_lookup(NS_DEFAULT);
259 ifp = if_lookup_by_index_per_ns(zns, n->ifindex);
260 if (!ifp) {
261 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
262 zlog_debug(
263 "%s: dp-install sync-neigh vni %u ip %s mac %s if %d f 0x%x skipped",
264 caller, n->zevpn->vni,
265 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
266 prefix_mac2str(&n->emac, macbuf,
267 sizeof(macbuf)),
268 n->ifindex, n->flags);
269 return;
270 }
271
272 if (force_clear_static)
273 set_static = false;
274 else
275 set_static = zebra_evpn_neigh_is_static(n);
276
277 set_router = !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
278
279 /* XXX - this will change post integration with the new kernel */
280 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
281 set_inactive = true;
282
283 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
284 zlog_debug(
285 "%s: dp-install sync-neigh vni %u ip %s mac %s if %s(%d) f 0x%x%s%s%s",
286 caller, n->zevpn->vni,
287 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
288 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
289 ifp->name, n->ifindex, n->flags,
290 set_router ? " router" : "",
291 set_static ? " static" : "",
292 set_inactive ? " inactive" : "");
293 dplane_local_neigh_add(ifp, &n->ip, &n->emac, set_router, set_static,
294 set_inactive);
295 }
296
297 /*
298 * Inform BGP about local neighbor addition.
299 */
zebra_evpn_neigh_send_add_to_client(vni_t vni,struct ipaddr * ip,struct ethaddr * macaddr,zebra_mac_t * zmac,uint32_t neigh_flags,uint32_t seq)300 int zebra_evpn_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
301 struct ethaddr *macaddr,
302 zebra_mac_t *zmac, uint32_t neigh_flags,
303 uint32_t seq)
304 {
305 uint8_t flags = 0;
306
307 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_LOCAL_INACTIVE)) {
308 /* host reachability has not been verified locally */
309
310 /* if no ES peer is claiming reachability we can't advertise
311 * the entry
312 */
313 if (!CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
314 return 0;
315
316 /* ES peers are claiming reachability; we will
317 * advertise the entry but with a proxy flag
318 */
319 SET_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT);
320 }
321
322 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
323 SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
324 /* Set router flag (R-bit) based on local neigh entry add */
325 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG))
326 SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
327 if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_SVI_IP))
328 SET_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP);
329
330 return zebra_evpn_macip_send_msg_to_client(
331 vni, macaddr, ip, flags, seq, ZEBRA_NEIGH_ACTIVE,
332 zmac ? zmac->es : NULL, ZEBRA_MACIP_ADD);
333 }
334
335 /*
336 * Inform BGP about local neighbor deletion.
337 */
zebra_evpn_neigh_send_del_to_client(vni_t vni,struct ipaddr * ip,struct ethaddr * macaddr,uint32_t flags,int state,bool force)338 int zebra_evpn_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
339 struct ethaddr *macaddr, uint32_t flags,
340 int state, bool force)
341 {
342 if (!force) {
343 if (CHECK_FLAG(flags, ZEBRA_NEIGH_LOCAL_INACTIVE)
344 && !CHECK_FLAG(flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
345 /* the neigh was not advertised - nothing to delete */
346 return 0;
347 }
348
349 return zebra_evpn_macip_send_msg_to_client(
350 vni, macaddr, ip, flags, 0, state, NULL, ZEBRA_MACIP_DEL);
351 }
352
zebra_evpn_neigh_send_add_del_to_client(zebra_neigh_t * n,bool old_bgp_ready,bool new_bgp_ready)353 static void zebra_evpn_neigh_send_add_del_to_client(zebra_neigh_t *n,
354 bool old_bgp_ready,
355 bool new_bgp_ready)
356 {
357 if (new_bgp_ready)
358 zebra_evpn_neigh_send_add_to_client(n->zevpn->vni, &n->ip,
359 &n->emac, n->mac, n->flags,
360 n->loc_seq);
361 else if (old_bgp_ready)
362 zebra_evpn_neigh_send_del_to_client(n->zevpn->vni, &n->ip,
363 &n->emac, n->flags,
364 n->state, true /*force*/);
365 }
366
367 /* if the static flag associated with the neigh changes we need
368 * to update the sync-neigh references against the MAC
369 * and inform the dataplane about the static flag changes.
370 */
zebra_evpn_sync_neigh_static_chg(zebra_neigh_t * n,bool old_n_static,bool new_n_static,bool defer_n_dp,bool defer_mac_dp,const char * caller)371 void zebra_evpn_sync_neigh_static_chg(zebra_neigh_t *n, bool old_n_static,
372 bool new_n_static, bool defer_n_dp,
373 bool defer_mac_dp, const char *caller)
374 {
375 zebra_mac_t *mac = n->mac;
376 bool old_mac_static;
377 bool new_mac_static;
378 char macbuf[ETHER_ADDR_STRLEN];
379 char ipbuf[INET6_ADDRSTRLEN];
380
381 if (old_n_static == new_n_static)
382 return;
383
384 /* update the neigh sync references in the dataplane. if
385 * the neigh is in the middle of updates the caller can
386 * request for a defer
387 */
388 if (!defer_n_dp)
389 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
390 false /* force_clear_static */,
391 __func__);
392
393 if (!mac)
394 return;
395
396 /* update the mac sync ref cnt */
397 old_mac_static = zebra_evpn_mac_is_static(mac);
398 if (new_n_static) {
399 ++mac->sync_neigh_cnt;
400 } else if (old_n_static) {
401 if (mac->sync_neigh_cnt)
402 --mac->sync_neigh_cnt;
403 }
404 new_mac_static = zebra_evpn_mac_is_static(mac);
405
406 /* update the mac sync references in the dataplane */
407 if ((old_mac_static != new_mac_static) && !defer_mac_dp)
408 zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
409 false /* force_clear_static */,
410 __func__);
411
412 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
413 zlog_debug(
414 "sync-neigh ref-chg vni %u ip %s mac %s f 0x%x %d%s%s%s%s by %s",
415 n->zevpn->vni, ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
416 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
417 n->flags, mac->sync_neigh_cnt,
418 old_n_static ? " old_n_static" : "",
419 new_n_static ? " new_n_static" : "",
420 old_mac_static ? " old_mac_static" : "",
421 new_mac_static ? " new_mac_static" : "", caller);
422 }
423
424 /* Neigh hold timer is used to age out peer-active flag.
425 *
426 * During this wait time we expect the dataplane component or an
427 * external neighmgr daemon to probe existing hosts to independently
428 * establish their presence on the ES.
429 */
zebra_evpn_neigh_hold_exp_cb(struct thread * t)430 static int zebra_evpn_neigh_hold_exp_cb(struct thread *t)
431 {
432 zebra_neigh_t *n;
433 bool old_bgp_ready;
434 bool new_bgp_ready;
435 bool old_n_static;
436 bool new_n_static;
437 char macbuf[ETHER_ADDR_STRLEN];
438 char ipbuf[INET6_ADDRSTRLEN];
439
440 n = THREAD_ARG(t);
441 /* the purpose of the hold timer is to age out the peer-active
442 * flag
443 */
444 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
445 return 0;
446
447 old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
448 old_n_static = zebra_evpn_neigh_is_static(n);
449 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
450 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
451 new_n_static = zebra_evpn_neigh_is_static(n);
452
453 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
454 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold expired",
455 n->zevpn->vni,
456 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
457 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
458 n->flags);
459
460 /* re-program the local neigh in the dataplane if the neigh is no
461 * longer static
462 */
463 if (old_n_static != new_n_static)
464 zebra_evpn_sync_neigh_static_chg(
465 n, old_n_static, new_n_static, false /*defer_n_dp*/,
466 false /*defer_mac_dp*/, __func__);
467
468 /* inform bgp if needed */
469 if (old_bgp_ready != new_bgp_ready)
470 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
471 new_bgp_ready);
472
473 return 0;
474 }
475
zebra_evpn_neigh_start_hold_timer(zebra_neigh_t * n)476 static inline void zebra_evpn_neigh_start_hold_timer(zebra_neigh_t *n)
477 {
478 char macbuf[ETHER_ADDR_STRLEN];
479 char ipbuf[INET6_ADDRSTRLEN];
480
481 if (n->hold_timer)
482 return;
483
484 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
485 zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold start",
486 n->zevpn->vni,
487 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
488 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
489 n->flags);
490 thread_add_timer(zrouter.master, zebra_evpn_neigh_hold_exp_cb, n,
491 zmh_info->neigh_hold_time, &n->hold_timer);
492 }
493
zebra_evpn_local_neigh_deref_mac(zebra_neigh_t * n,bool send_mac_update)494 static void zebra_evpn_local_neigh_deref_mac(zebra_neigh_t *n,
495 bool send_mac_update)
496 {
497 zebra_mac_t *mac = n->mac;
498 zebra_evpn_t *zevpn = n->zevpn;
499 char macbuf[ETHER_ADDR_STRLEN];
500 char ipbuf[INET6_ADDRSTRLEN];
501 bool old_static;
502 bool new_static;
503
504 n->mac = NULL;
505 if (!mac)
506 return;
507
508 if ((n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) && mac->sync_neigh_cnt) {
509 old_static = zebra_evpn_mac_is_static(mac);
510 --mac->sync_neigh_cnt;
511 new_static = zebra_evpn_mac_is_static(mac);
512 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
513 zlog_debug(
514 "sync-neigh deref mac vni %u ip %s mac %s ref %d",
515 n->zevpn->vni,
516 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
517 prefix_mac2str(&n->emac, macbuf,
518 sizeof(macbuf)),
519 mac->sync_neigh_cnt);
520 if ((old_static != new_static) && send_mac_update)
521 /* program the local mac in the kernel */
522 zebra_evpn_sync_mac_dp_install(
523 mac, false /* set_inactive */,
524 false /* force_clear_static */, __func__);
525 }
526
527 listnode_delete(mac->neigh_list, n);
528 zebra_evpn_deref_ip2mac(zevpn, mac);
529 }
530
zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t * zevpn,zebra_neigh_t * n,struct ethaddr * macaddr,uint32_t seq)531 bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
532 struct ethaddr *macaddr, uint32_t seq)
533 {
534 char macbuf[ETHER_ADDR_STRLEN];
535 char ipbuf[INET6_ADDRSTRLEN];
536 uint32_t tmp_seq;
537
538 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
539 tmp_seq = n->loc_seq;
540 else
541 tmp_seq = n->rem_seq;
542
543 if (seq < tmp_seq) {
544 /* if the neigh was never advertised to bgp we must accept
545 * whatever sequence number bgp sends
546 * XXX - check with Vivek
547 */
548 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)
549 && !zebra_evpn_neigh_is_ready_for_bgp(n)) {
550 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
551 zlog_debug(
552 "sync-macip accept vni %u mac %s IP %s lower seq %u f 0x%x",
553 zevpn->vni,
554 prefix_mac2str(macaddr, macbuf,
555 sizeof(macbuf)),
556 ipaddr2str(&n->ip, ipbuf,
557 sizeof(ipbuf)),
558 tmp_seq, n->flags);
559 return true;
560 }
561
562 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
563 zlog_debug(
564 "sync-macip ignore vni %u mac %s IP %s as existing has higher seq %u f 0x%x",
565 zevpn->vni,
566 prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
567 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
568 tmp_seq, n->flags);
569 return false;
570 }
571
572 return true;
573 }
574
575 /*
576 * Add neighbor entry.
577 */
zebra_evpn_neigh_add(zebra_evpn_t * zevpn,struct ipaddr * ip,struct ethaddr * mac,zebra_mac_t * zmac,uint32_t n_flags)578 static zebra_neigh_t *zebra_evpn_neigh_add(zebra_evpn_t *zevpn,
579 struct ipaddr *ip,
580 struct ethaddr *mac,
581 zebra_mac_t *zmac, uint32_t n_flags)
582 {
583 zebra_neigh_t tmp_n;
584 zebra_neigh_t *n = NULL;
585
586 memset(&tmp_n, 0, sizeof(zebra_neigh_t));
587 memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
588 n = hash_get(zevpn->neigh_table, &tmp_n, zebra_evpn_neigh_alloc);
589 assert(n);
590
591 n->state = ZEBRA_NEIGH_INACTIVE;
592 n->zevpn = zevpn;
593 n->dad_ip_auto_recovery_timer = NULL;
594 n->flags = n_flags;
595
596 if (!zmac)
597 zmac = zebra_evpn_mac_lookup(zevpn, mac);
598 zebra_evpn_local_neigh_ref_mac(n, mac, zmac,
599 false /* send_mac_update */);
600
601 return n;
602 }
603
604 /*
605 * Delete neighbor entry.
606 */
zebra_evpn_neigh_del(zebra_evpn_t * zevpn,zebra_neigh_t * n)607 int zebra_evpn_neigh_del(zebra_evpn_t *zevpn, zebra_neigh_t *n)
608 {
609 zebra_neigh_t *tmp_n;
610
611 if (n->mac)
612 listnode_delete(n->mac->neigh_list, n);
613
614 /* Cancel auto recovery */
615 THREAD_OFF(n->dad_ip_auto_recovery_timer);
616
617 /* Cancel proxy hold timer */
618 zebra_evpn_neigh_stop_hold_timer(n);
619
620 /* Free the VNI hash entry and allocated memory. */
621 tmp_n = hash_release(zevpn->neigh_table, n);
622 XFREE(MTYPE_NEIGH, tmp_n);
623
624 return 0;
625 }
626
zebra_evpn_sync_neigh_del(zebra_neigh_t * n)627 void zebra_evpn_sync_neigh_del(zebra_neigh_t *n)
628 {
629 bool old_n_static;
630 bool new_n_static;
631 char macbuf[ETHER_ADDR_STRLEN];
632 char ipbuf[INET6_ADDRSTRLEN];
633
634 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
635 zlog_debug("sync-neigh del vni %u ip %s mac %s f 0x%x",
636 n->zevpn->vni,
637 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
638 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
639 n->flags);
640
641 old_n_static = zebra_evpn_neigh_is_static(n);
642 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
643 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
644 zebra_evpn_neigh_start_hold_timer(n);
645 new_n_static = zebra_evpn_neigh_is_static(n);
646
647 if (old_n_static != new_n_static)
648 zebra_evpn_sync_neigh_static_chg(
649 n, old_n_static, new_n_static, false /*defer-dp*/,
650 false /*defer_mac_dp*/, __func__);
651 }
652
653 zebra_neigh_t *
zebra_evpn_proc_sync_neigh_update(zebra_evpn_t * zevpn,zebra_neigh_t * n,uint16_t ipa_len,struct ipaddr * ipaddr,uint8_t flags,uint32_t seq,esi_t * esi,struct sync_mac_ip_ctx * ctx)654 zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
655 uint16_t ipa_len, struct ipaddr *ipaddr,
656 uint8_t flags, uint32_t seq, esi_t *esi,
657 struct sync_mac_ip_ctx *ctx)
658 {
659 struct interface *ifp = NULL;
660 bool is_router;
661 zebra_mac_t *mac = ctx->mac;
662 uint32_t tmp_seq;
663 bool old_router = false;
664 bool old_bgp_ready = false;
665 bool new_bgp_ready;
666 bool inform_dataplane = false;
667 bool inform_bgp = false;
668 bool old_mac_static;
669 bool new_mac_static;
670 bool set_dp_inactive = false;
671 char macbuf[ETHER_ADDR_STRLEN];
672 char ipbuf[INET6_ADDRSTRLEN];
673 bool created;
674 ifindex_t ifindex = 0;
675
676 /* locate l3-svi */
677 ifp = zevpn_map_to_svi(zevpn);
678 if (ifp)
679 ifindex = ifp->ifindex;
680
681 is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
682 old_mac_static = zebra_evpn_mac_is_static(mac);
683
684 if (!n) {
685 uint32_t n_flags = 0;
686
687 /* New neighbor - create */
688 SET_FLAG(n_flags, ZEBRA_NEIGH_LOCAL);
689 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
690 SET_FLAG(n_flags, ZEBRA_NEIGH_ES_PEER_PROXY);
691 else
692 SET_FLAG(n_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
693 SET_FLAG(n_flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
694
695 n = zebra_evpn_neigh_add(zevpn, ipaddr, &mac->macaddr, mac,
696 n_flags);
697 n->ifindex = ifindex;
698 ZEBRA_NEIGH_SET_ACTIVE(n);
699
700 created = true;
701 inform_dataplane = true;
702 inform_bgp = true;
703 set_dp_inactive = true;
704 } else {
705 bool mac_change;
706 uint32_t old_flags = n->flags;
707 bool old_n_static;
708 bool new_n_static;
709
710 created = false;
711 old_n_static = zebra_evpn_neigh_is_static(n);
712 old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
713 old_router = !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
714
715 mac_change = !!memcmp(&n->emac, &mac->macaddr, ETH_ALEN);
716
717 /* deref and clear old info */
718 if (mac_change) {
719 if (old_bgp_ready) {
720 zebra_evpn_neigh_send_del_to_client(
721 zevpn->vni, &n->ip, &n->emac, n->flags,
722 n->state, false /*force*/);
723 old_bgp_ready = false;
724 }
725 if (n->mac)
726 zebra_evpn_local_neigh_deref_mac(
727 n, false /*send_mac_update*/);
728 }
729 /* clear old fwd info */
730 n->rem_seq = 0;
731 n->r_vtep_ip.s_addr = 0;
732
733 /* setup new flags */
734 n->flags = 0;
735 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
736 /* retain activity flag if the neigh was
737 * previously local
738 */
739 if (old_flags & ZEBRA_NEIGH_LOCAL) {
740 n->flags |= (old_flags & ZEBRA_NEIGH_LOCAL_INACTIVE);
741 } else {
742 inform_dataplane = true;
743 set_dp_inactive = true;
744 n->flags |= ZEBRA_NEIGH_LOCAL_INACTIVE;
745 }
746
747 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT))
748 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
749 else
750 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
751
752 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
753 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
754 /* if the neigh was peer-active previously we
755 * need to keep the flag and start the
756 * holdtimer on it. the peer-active flag is
757 * cleared on holdtimer expiry.
758 */
759 if (CHECK_FLAG(old_flags, ZEBRA_NEIGH_ES_PEER_ACTIVE)) {
760 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
761 zebra_evpn_neigh_start_hold_timer(n);
762 }
763 } else {
764 SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE);
765 /* stop hold timer if a peer has verified
766 * reachability
767 */
768 zebra_evpn_neigh_stop_hold_timer(n);
769 }
770 ZEBRA_NEIGH_SET_ACTIVE(n);
771
772 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH && (old_flags != n->flags))
773 zlog_debug(
774 "sync-neigh vni %u ip %s mac %s old_f 0x%x new_f 0x%x",
775 n->zevpn->vni,
776 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
777 prefix_mac2str(&n->emac, macbuf,
778 sizeof(macbuf)),
779 old_flags, n->flags);
780
781 new_n_static = zebra_evpn_neigh_is_static(n);
782 if (mac_change) {
783 set_dp_inactive = true;
784 n->flags |= ZEBRA_NEIGH_LOCAL_INACTIVE;
785 inform_dataplane = true;
786 zebra_evpn_local_neigh_ref_mac(
787 n, &mac->macaddr, mac,
788 false /*send_mac_update*/);
789 } else if (old_n_static != new_n_static) {
790 inform_dataplane = true;
791 /* if static flags have changed without a mac change
792 * we need to create the correct sync-refs against
793 * the existing mac
794 */
795 zebra_evpn_sync_neigh_static_chg(
796 n, old_n_static, new_n_static,
797 true /*defer_dp*/, true /*defer_mac_dp*/,
798 __func__);
799 }
800
801 /* Update the forwarding info. */
802 if (n->ifindex != ifindex) {
803 n->ifindex = ifindex;
804 inform_dataplane = true;
805 }
806 }
807
808 /* update the neigh seq. we don't bother with the mac seq as
809 * sync_mac_update already took care of that
810 */
811 tmp_seq = MAX(n->loc_seq, seq);
812 if (tmp_seq != n->loc_seq) {
813 n->loc_seq = tmp_seq;
814 inform_bgp = true;
815 }
816
817 /* Mark Router flag (R-bit) */
818 if (is_router)
819 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
820 else
821 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
822
823 if (old_router != is_router)
824 inform_dataplane = true;
825
826 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
827 if (old_bgp_ready != new_bgp_ready)
828 inform_bgp = true;
829
830 new_mac_static = zebra_evpn_mac_is_static(mac);
831 if ((old_mac_static != new_mac_static) || ctx->mac_dp_update_deferred)
832 zebra_evpn_sync_mac_dp_install(mac, ctx->mac_inactive,
833 false /* force_clear_static */,
834 __func__);
835
836 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
837 zlog_debug(
838 "sync-neigh %s vni %u ip %s mac %s if %s(%d) seq %d f 0x%x%s%s",
839 created ? "created" : "updated", n->zevpn->vni,
840 ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
841 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
842 ifp ? ifp->name : "", ifindex, n->loc_seq, n->flags,
843 inform_bgp ? " inform_bgp" : "",
844 inform_dataplane ? " inform_dp" : "");
845
846 if (inform_dataplane)
847 zebra_evpn_sync_neigh_dp_install(n, set_dp_inactive,
848 false /* force_clear_static */,
849 __func__);
850
851 if (inform_bgp)
852 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
853 new_bgp_ready);
854
855 return n;
856 }
857
858 /*
859 * Uninstall remote neighbor from the kernel.
860 */
zebra_evpn_neigh_uninstall(zebra_evpn_t * zevpn,zebra_neigh_t * n)861 static int zebra_evpn_neigh_uninstall(zebra_evpn_t *zevpn, zebra_neigh_t *n)
862 {
863 struct interface *vlan_if;
864
865 if (!(n->flags & ZEBRA_NEIGH_REMOTE))
866 return 0;
867
868 vlan_if = zevpn_map_to_svi(zevpn);
869 if (!vlan_if)
870 return -1;
871
872 ZEBRA_NEIGH_SET_INACTIVE(n);
873 n->loc_seq = 0;
874
875 dplane_rem_neigh_delete(vlan_if, &n->ip);
876
877 return 0;
878 }
879
880 /*
881 * Free neighbor hash entry (callback)
882 */
zebra_evpn_neigh_del_hash_entry(struct hash_bucket * bucket,void * arg)883 static void zebra_evpn_neigh_del_hash_entry(struct hash_bucket *bucket,
884 void *arg)
885 {
886 struct neigh_walk_ctx *wctx = arg;
887 zebra_neigh_t *n = bucket->data;
888
889 if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL))
890 || ((wctx->flags & DEL_REMOTE_NEIGH)
891 && (n->flags & ZEBRA_NEIGH_REMOTE))
892 || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP)
893 && (n->flags & ZEBRA_NEIGH_REMOTE)
894 && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
895 if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
896 zebra_evpn_neigh_send_del_to_client(
897 wctx->zevpn->vni, &n->ip, &n->emac, n->flags,
898 n->state, false /*force*/);
899
900 if (wctx->uninstall) {
901 if (zebra_evpn_neigh_is_static(n))
902 zebra_evpn_sync_neigh_dp_install(
903 n, false /* set_inactive */,
904 true /* force_clear_static */,
905 __func__);
906 if ((n->flags & ZEBRA_NEIGH_REMOTE))
907 zebra_evpn_neigh_uninstall(wctx->zevpn, n);
908 }
909
910 zebra_evpn_neigh_del(wctx->zevpn, n);
911 }
912
913 return;
914 }
915
916 /*
917 * Delete all neighbor entries for this EVPN.
918 */
zebra_evpn_neigh_del_all(zebra_evpn_t * zevpn,int uninstall,int upd_client,uint32_t flags)919 void zebra_evpn_neigh_del_all(zebra_evpn_t *zevpn, int uninstall,
920 int upd_client, uint32_t flags)
921 {
922 struct neigh_walk_ctx wctx;
923
924 if (!zevpn->neigh_table)
925 return;
926
927 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
928 wctx.zevpn = zevpn;
929 wctx.uninstall = uninstall;
930 wctx.upd_client = upd_client;
931 wctx.flags = flags;
932
933 hash_iterate(zevpn->neigh_table, zebra_evpn_neigh_del_hash_entry,
934 &wctx);
935 }
936
937 /*
938 * Look up neighbor hash entry.
939 */
zebra_evpn_neigh_lookup(zebra_evpn_t * zevpn,struct ipaddr * ip)940 zebra_neigh_t *zebra_evpn_neigh_lookup(zebra_evpn_t *zevpn, struct ipaddr *ip)
941 {
942 zebra_neigh_t tmp;
943 zebra_neigh_t *n;
944
945 memset(&tmp, 0, sizeof(tmp));
946 memcpy(&tmp.ip, ip, sizeof(struct ipaddr));
947 n = hash_lookup(zevpn->neigh_table, &tmp);
948
949 return n;
950 }
951
952 /*
953 * Process all neighbors associated with a MAC upon the MAC being learnt
954 * locally or undergoing any other change (such as sequence number).
955 */
zebra_evpn_process_neigh_on_local_mac_change(zebra_evpn_t * zevpn,zebra_mac_t * zmac,bool seq_change,bool es_change)956 void zebra_evpn_process_neigh_on_local_mac_change(zebra_evpn_t *zevpn,
957 zebra_mac_t *zmac,
958 bool seq_change,
959 bool es_change)
960 {
961 zebra_neigh_t *n = NULL;
962 struct listnode *node = NULL;
963 struct zebra_vrf *zvrf = NULL;
964 char buf[ETHER_ADDR_STRLEN];
965
966 zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
967
968 if (IS_ZEBRA_DEBUG_VXLAN)
969 zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
970 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
971 seq_change ? "CHANGE" : "ADD", zevpn->vni);
972
973 /* Walk all neighbors and mark any inactive local neighbors as
974 * active and/or update sequence number upon a move, and inform BGP.
975 * The action for remote neighbors is TBD.
976 * NOTE: We can't simply uninstall remote neighbors as the kernel may
977 * accidentally end up deleting a just-learnt local neighbor.
978 */
979 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
980 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
981 if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change
982 || es_change) {
983 ZEBRA_NEIGH_SET_ACTIVE(n);
984 n->loc_seq = zmac->loc_seq;
985 if (!(zvrf->dup_addr_detect && zvrf->dad_freeze
986 && !!CHECK_FLAG(n->flags,
987 ZEBRA_NEIGH_DUPLICATE)))
988 zebra_evpn_neigh_send_add_to_client(
989 zevpn->vni, &n->ip, &n->emac,
990 n->mac, n->flags, n->loc_seq);
991 }
992 }
993 }
994 }
995
996 /*
997 * Process all neighbors associated with a local MAC upon the MAC being
998 * deleted.
999 */
zebra_evpn_process_neigh_on_local_mac_del(zebra_evpn_t * zevpn,zebra_mac_t * zmac)1000 void zebra_evpn_process_neigh_on_local_mac_del(zebra_evpn_t *zevpn,
1001 zebra_mac_t *zmac)
1002 {
1003 zebra_neigh_t *n = NULL;
1004 struct listnode *node = NULL;
1005 char buf[ETHER_ADDR_STRLEN];
1006
1007 if (IS_ZEBRA_DEBUG_VXLAN)
1008 zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
1009 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
1010 zevpn->vni);
1011
1012 /* Walk all local neighbors and mark as inactive and inform
1013 * BGP, if needed.
1014 * TBD: There is currently no handling for remote neighbors. We
1015 * don't expect them to exist, if they do, do we install the MAC
1016 * as a remote MAC and the neighbor as remote?
1017 */
1018 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1019 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1020 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1021 ZEBRA_NEIGH_SET_INACTIVE(n);
1022 n->loc_seq = 0;
1023 zebra_evpn_neigh_send_del_to_client(
1024 zevpn->vni, &n->ip, &n->emac, n->flags,
1025 ZEBRA_NEIGH_ACTIVE, false /*force*/);
1026 }
1027 }
1028 }
1029 }
1030
1031 /*
1032 * Process all neighbors associated with a MAC upon the MAC being remotely
1033 * learnt.
1034 */
zebra_evpn_process_neigh_on_remote_mac_add(zebra_evpn_t * zevpn,zebra_mac_t * zmac)1035 void zebra_evpn_process_neigh_on_remote_mac_add(zebra_evpn_t *zevpn,
1036 zebra_mac_t *zmac)
1037 {
1038 zebra_neigh_t *n = NULL;
1039 struct listnode *node = NULL;
1040 char buf[ETHER_ADDR_STRLEN];
1041
1042 if (IS_ZEBRA_DEBUG_VXLAN)
1043 zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
1044 prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
1045 zevpn->vni);
1046
1047 /* Walk all local neighbors and mark as inactive and inform
1048 * BGP, if needed.
1049 */
1050 for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
1051 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1052 if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
1053 ZEBRA_NEIGH_SET_INACTIVE(n);
1054 n->loc_seq = 0;
1055 zebra_evpn_neigh_send_del_to_client(
1056 zevpn->vni, &n->ip, &n->emac, n->flags,
1057 ZEBRA_NEIGH_ACTIVE, false /* force */);
1058 }
1059 }
1060 }
1061 }
1062
1063 /*
1064 * Process all neighbors associated with a remote MAC upon the MAC being
1065 * deleted.
1066 */
zebra_evpn_process_neigh_on_remote_mac_del(zebra_evpn_t * zevpn,zebra_mac_t * zmac)1067 void zebra_evpn_process_neigh_on_remote_mac_del(zebra_evpn_t *zevpn,
1068 zebra_mac_t *zmac)
1069 {
1070 /* NOTE: Currently a NO-OP. */
1071 }
1072
zebra_evpn_local_neigh_update_log(const char * pfx,zebra_neigh_t * n,bool is_router,bool local_inactive,bool old_bgp_ready,bool new_bgp_ready,bool inform_dataplane,bool inform_bgp,const char * sfx)1073 static inline void zebra_evpn_local_neigh_update_log(
1074 const char *pfx, zebra_neigh_t *n, bool is_router, bool local_inactive,
1075 bool old_bgp_ready, bool new_bgp_ready, bool inform_dataplane,
1076 bool inform_bgp, const char *sfx)
1077 {
1078 char macbuf[ETHER_ADDR_STRLEN];
1079 char ipbuf[INET6_ADDRSTRLEN];
1080
1081 if (!IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
1082 return;
1083
1084 zlog_debug("%s neigh vni %u ip %s mac %s f 0x%x%s%s%s%s%s%s %s", pfx,
1085 n->zevpn->vni, ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
1086 prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)), n->flags,
1087 is_router ? " router" : "",
1088 local_inactive ? " local-inactive" : "",
1089 old_bgp_ready ? " old_bgp_ready" : "",
1090 new_bgp_ready ? " new_bgp_ready" : "",
1091 inform_dataplane ? " inform_dp" : "",
1092 inform_bgp ? " inform_bgp" : "", sfx);
1093 }
1094
1095 /* As part Duplicate Address Detection (DAD) for IP mobility
1096 * MAC binding changes, ensure to inherit duplicate flag
1097 * from MAC.
1098 */
zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf * zvrf,zebra_mac_t * old_zmac,zebra_mac_t * new_zmac,zebra_neigh_t * nbr)1099 static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
1100 zebra_mac_t *old_zmac,
1101 zebra_mac_t *new_zmac,
1102 zebra_neigh_t *nbr)
1103 {
1104 bool is_old_mac_dup = false;
1105 bool is_new_mac_dup = false;
1106
1107 if (!zvrf->dup_addr_detect)
1108 return 0;
1109 /* Check old or new MAC is detected as duplicate
1110 * mark this neigh as duplicate
1111 */
1112 if (old_zmac)
1113 is_old_mac_dup =
1114 CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE);
1115 if (new_zmac)
1116 is_new_mac_dup =
1117 CHECK_FLAG(new_zmac->flags, ZEBRA_MAC_DUPLICATE);
1118 /* Old and/or new MAC can be in duplicate state,
1119 * based on that IP/Neigh Inherits the flag.
1120 * If New MAC is marked duplicate, inherit to the IP.
1121 * If old MAC is duplicate but new MAC is not, clear
1122 * duplicate flag for IP and reset detection params
1123 * and let IP DAD retrigger.
1124 */
1125 if (is_new_mac_dup && !CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
1126 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
1127 /* Capture Duplicate detection time */
1128 nbr->dad_dup_detect_time = monotime(NULL);
1129 /* Mark neigh inactive */
1130 ZEBRA_NEIGH_SET_INACTIVE(nbr);
1131
1132 return 1;
1133 } else if (is_old_mac_dup && !is_new_mac_dup) {
1134 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
1135 nbr->dad_count = 0;
1136 nbr->detect_start_time.tv_sec = 0;
1137 nbr->detect_start_time.tv_usec = 0;
1138 }
1139 return 0;
1140 }
1141
zebra_evpn_dad_ip_auto_recovery_exp(struct thread * t)1142 static int zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t)
1143 {
1144 struct zebra_vrf *zvrf = NULL;
1145 zebra_neigh_t *nbr = NULL;
1146 zebra_evpn_t *zevpn = NULL;
1147 char buf1[INET6_ADDRSTRLEN];
1148 char buf2[ETHER_ADDR_STRLEN];
1149
1150 nbr = THREAD_ARG(t);
1151
1152 /* since this is asynchronous we need sanity checks*/
1153 zvrf = vrf_info_lookup(nbr->zevpn->vrf_id);
1154 if (!zvrf)
1155 return 0;
1156
1157 zevpn = zebra_evpn_lookup(nbr->zevpn->vni);
1158 if (!zevpn)
1159 return 0;
1160
1161 nbr = zebra_evpn_neigh_lookup(zevpn, &nbr->ip);
1162 if (!nbr)
1163 return 0;
1164
1165 if (IS_ZEBRA_DEBUG_VXLAN)
1166 zlog_debug(
1167 "%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
1168 __func__,
1169 prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)),
1170 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), nbr->flags,
1171 nbr->dad_count, zevpn->vni);
1172
1173 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
1174 nbr->dad_count = 0;
1175 nbr->detect_start_time.tv_sec = 0;
1176 nbr->detect_start_time.tv_usec = 0;
1177 nbr->dad_dup_detect_time = 0;
1178 nbr->dad_ip_auto_recovery_timer = NULL;
1179 ZEBRA_NEIGH_SET_ACTIVE(nbr);
1180
1181 /* Send to BGP */
1182 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
1183 zebra_evpn_neigh_send_add_to_client(zevpn->vni, &nbr->ip,
1184 &nbr->emac, nbr->mac,
1185 nbr->flags, nbr->loc_seq);
1186 } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
1187 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
1188 }
1189
1190 return 0;
1191 }
1192
1193 static void
zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf * zvrf,zebra_neigh_t * nbr,struct in_addr vtep_ip,bool do_dad,bool * is_dup_detect,bool is_local)1194 zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
1195 struct in_addr vtep_ip, bool do_dad,
1196 bool *is_dup_detect, bool is_local)
1197 {
1198
1199 struct timeval elapsed = {0, 0};
1200 char buf[ETHER_ADDR_STRLEN];
1201 char buf1[INET6_ADDRSTRLEN];
1202 bool reset_params = false;
1203
1204 if (!zvrf->dup_addr_detect)
1205 return;
1206
1207 /* IP is detected as duplicate or inherit dup
1208 * state, hold on to install as remote entry
1209 * only if freeze is enabled.
1210 */
1211 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
1212 if (IS_ZEBRA_DEBUG_VXLAN)
1213 zlog_debug(
1214 "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
1215 __func__,
1216 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
1217 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
1218 nbr->flags, nbr->dad_count,
1219 zvrf->dad_freeze_time);
1220
1221 if (zvrf->dad_freeze)
1222 *is_dup_detect = true;
1223
1224 /* warn-only action, neigh will be installed.
1225 * freeze action, it wil not be installed.
1226 */
1227 return;
1228 }
1229
1230 if (!do_dad)
1231 return;
1232
1233 /* Check if detection time (M-secs) expired.
1234 * Reset learn count and detection start time.
1235 * During remote mac add, count should already be 1
1236 * via local learning.
1237 */
1238 monotime_since(&nbr->detect_start_time, &elapsed);
1239 reset_params = (elapsed.tv_sec > zvrf->dad_time);
1240
1241 if (is_local && !reset_params) {
1242 /* RFC-7432: A PE/VTEP that detects a MAC mobility
1243 * event via LOCAL learning starts an M-second timer.
1244 *
1245 * NOTE: This is the START of the probe with count is
1246 * 0 during LOCAL learn event.
1247 */
1248 reset_params = !nbr->dad_count;
1249 }
1250
1251 if (reset_params) {
1252 if (IS_ZEBRA_DEBUG_VXLAN)
1253 zlog_debug(
1254 "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
1255 __func__,
1256 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
1257 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
1258 nbr->flags, nbr->dad_count);
1259 /* Reset learn count but do not start detection
1260 * during REMOTE learn event.
1261 */
1262 nbr->dad_count = 0;
1263 /* Start dup. addr detection (DAD) start time,
1264 * ONLY during LOCAL learn.
1265 */
1266 if (is_local)
1267 monotime(&nbr->detect_start_time);
1268
1269 } else if (!is_local) {
1270 /* For REMOTE IP/Neigh, increment detection count
1271 * ONLY while in probe window, once window passed,
1272 * next local learn event should trigger DAD.
1273 */
1274 nbr->dad_count++;
1275 }
1276
1277 /* For LOCAL IP/Neigh learn event, once count is reset above via either
1278 * initial/start detection time or passed the probe time, the count
1279 * needs to be incremented.
1280 */
1281 if (is_local)
1282 nbr->dad_count++;
1283
1284 if (nbr->dad_count >= zvrf->dad_max_moves) {
1285 flog_warn(
1286 EC_ZEBRA_DUP_IP_DETECTED,
1287 "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
1288 nbr->zevpn->vni,
1289 prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
1290 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
1291 is_local ? "local update, last" : "remote update, from",
1292 inet_ntoa(vtep_ip));
1293
1294 SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
1295
1296 /* Capture Duplicate detection time */
1297 nbr->dad_dup_detect_time = monotime(NULL);
1298
1299 /* Start auto recovery timer for this IP */
1300 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
1301 if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
1302 if (IS_ZEBRA_DEBUG_VXLAN)
1303 zlog_debug(
1304 "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
1305 __func__,
1306 prefix_mac2str(&nbr->emac, buf,
1307 sizeof(buf)),
1308 ipaddr2str(&nbr->ip, buf1,
1309 sizeof(buf1)),
1310 nbr->flags, zvrf->dad_freeze_time);
1311
1312 thread_add_timer(zrouter.master,
1313 zebra_evpn_dad_ip_auto_recovery_exp,
1314 nbr, zvrf->dad_freeze_time,
1315 &nbr->dad_ip_auto_recovery_timer);
1316 }
1317 if (zvrf->dad_freeze)
1318 *is_dup_detect = true;
1319 }
1320 }
1321
zebra_evpn_local_neigh_update(zebra_evpn_t * zevpn,struct interface * ifp,struct ipaddr * ip,struct ethaddr * macaddr,bool is_router,bool local_inactive,bool dp_static)1322 int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
1323 struct ipaddr *ip, struct ethaddr *macaddr,
1324 bool is_router, bool local_inactive,
1325 bool dp_static)
1326 {
1327 char buf[ETHER_ADDR_STRLEN];
1328 char buf2[INET6_ADDRSTRLEN];
1329 struct zebra_vrf *zvrf;
1330 zebra_neigh_t *n = NULL;
1331 zebra_mac_t *zmac = NULL, *old_zmac = NULL;
1332 uint32_t old_mac_seq = 0, mac_new_seq = 0;
1333 bool upd_mac_seq = false;
1334 bool neigh_mac_change = false;
1335 bool neigh_on_hold = false;
1336 bool neigh_was_remote = false;
1337 bool do_dad = false;
1338 struct in_addr vtep_ip = {.s_addr = 0};
1339 bool inform_dataplane = false;
1340 bool created = false;
1341 bool new_static = false;
1342 bool old_bgp_ready = false;
1343 bool new_bgp_ready;
1344
1345 /* Check if the MAC exists. */
1346 zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
1347 if (!zmac) {
1348 /* create a dummy MAC if the MAC is not already present */
1349 if (IS_ZEBRA_DEBUG_VXLAN)
1350 zlog_debug("AUTO MAC %s created for neigh %s on VNI %u",
1351 prefix_mac2str(macaddr, buf, sizeof(buf)),
1352 ipaddr2str(ip, buf2, sizeof(buf2)),
1353 zevpn->vni);
1354
1355 zmac = zebra_evpn_mac_add(zevpn, macaddr);
1356 if (!zmac) {
1357 zlog_debug("Failed to add MAC %s VNI %u",
1358 prefix_mac2str(macaddr, buf, sizeof(buf)),
1359 zevpn->vni);
1360 return -1;
1361 }
1362
1363 memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
1364 memset(&zmac->flags, 0, sizeof(uint32_t));
1365 SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
1366 } else {
1367 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
1368 /*
1369 * We don't change the MAC to local upon a neighbor
1370 * learn event, we wait for the explicit local MAC
1371 * learn. However, we have to compute its sequence
1372 * number in preparation for when it actually turns
1373 * local.
1374 */
1375 upd_mac_seq = true;
1376 }
1377 }
1378
1379 zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
1380 if (!zvrf) {
1381 if (IS_ZEBRA_DEBUG_VXLAN)
1382 zlog_debug(" Unable to find vrf for: %d",
1383 zevpn->vxlan_if->vrf_id);
1384 return -1;
1385 }
1386
1387 /* Check if the neighbor exists. */
1388 n = zebra_evpn_neigh_lookup(zevpn, ip);
1389 if (!n) {
1390 /* New neighbor - create */
1391 n = zebra_evpn_neigh_add(zevpn, ip, macaddr, zmac, 0);
1392 if (!n) {
1393 flog_err(
1394 EC_ZEBRA_MAC_ADD_FAILED,
1395 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
1396 ipaddr2str(ip, buf2, sizeof(buf2)),
1397 prefix_mac2str(macaddr, buf, sizeof(buf)),
1398 ifp->name, ifp->ifindex, zevpn->vni);
1399 return -1;
1400 }
1401 /* Set "local" forwarding info. */
1402 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
1403 n->ifindex = ifp->ifindex;
1404 created = true;
1405 } else {
1406 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1407 bool mac_different;
1408 bool cur_is_router;
1409 bool old_local_inactive;
1410
1411 old_local_inactive = !!CHECK_FLAG(
1412 n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
1413
1414 old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
1415
1416 /* Note any changes and see if of interest to BGP. */
1417 mac_different = !!memcmp(&n->emac, macaddr, ETH_ALEN);
1418 cur_is_router =
1419 !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
1420 new_static = zebra_evpn_neigh_is_static(n);
1421 if (!mac_different && is_router == cur_is_router
1422 && old_local_inactive == local_inactive
1423 && dp_static != new_static) {
1424 if (IS_ZEBRA_DEBUG_VXLAN)
1425 zlog_debug(
1426 " Ignoring entry mac is the same and is_router == cur_is_router");
1427 n->ifindex = ifp->ifindex;
1428 return 0;
1429 }
1430
1431 old_zmac = n->mac;
1432 if (!mac_different) {
1433 /* XXX - cleanup this code duplication */
1434 bool is_neigh_freezed = false;
1435
1436 /* Only the router flag has changed. */
1437 if (is_router)
1438 SET_FLAG(n->flags,
1439 ZEBRA_NEIGH_ROUTER_FLAG);
1440 else
1441 UNSET_FLAG(n->flags,
1442 ZEBRA_NEIGH_ROUTER_FLAG);
1443
1444 if (local_inactive)
1445 SET_FLAG(n->flags,
1446 ZEBRA_NEIGH_LOCAL_INACTIVE);
1447 else
1448 UNSET_FLAG(n->flags,
1449 ZEBRA_NEIGH_LOCAL_INACTIVE);
1450 new_bgp_ready =
1451 zebra_evpn_neigh_is_ready_for_bgp(n);
1452
1453 /* Neigh is in freeze state and freeze action
1454 * is enabled, do not send update to client.
1455 */
1456 is_neigh_freezed =
1457 (zvrf->dup_addr_detect
1458 && zvrf->dad_freeze
1459 && CHECK_FLAG(n->flags,
1460 ZEBRA_NEIGH_DUPLICATE));
1461
1462 zebra_evpn_local_neigh_update_log(
1463 "local", n, is_router, local_inactive,
1464 old_bgp_ready, new_bgp_ready, false,
1465 false, "flag-update");
1466
1467 /* if the neigh can no longer be advertised
1468 * remove it from bgp
1469 */
1470 if (!is_neigh_freezed) {
1471 zebra_evpn_neigh_send_add_del_to_client(
1472 n, old_bgp_ready,
1473 new_bgp_ready);
1474 } else {
1475 if (IS_ZEBRA_DEBUG_VXLAN
1476 && IS_ZEBRA_NEIGH_ACTIVE(n))
1477 zlog_debug(
1478 " Neighbor active and frozen");
1479 }
1480 return 0;
1481 }
1482
1483 /* The MAC has changed, need to issue a delete
1484 * first as this means a different MACIP route.
1485 * Also, need to do some unlinking/relinking.
1486 * We also need to update the MAC's sequence number
1487 * in different situations.
1488 */
1489 if (old_bgp_ready) {
1490 zebra_evpn_neigh_send_del_to_client(
1491 zevpn->vni, &n->ip, &n->emac, n->flags,
1492 n->state, false /*force*/);
1493 old_bgp_ready = false;
1494 }
1495 if (old_zmac) {
1496 old_mac_seq = CHECK_FLAG(old_zmac->flags,
1497 ZEBRA_MAC_REMOTE)
1498 ? old_zmac->rem_seq
1499 : old_zmac->loc_seq;
1500 neigh_mac_change = upd_mac_seq = true;
1501 zebra_evpn_local_neigh_deref_mac(
1502 n, true /* send_mac_update */);
1503 }
1504
1505 /* if mac changes abandon peer flags and tell
1506 * dataplane to clear the static flag
1507 */
1508 if (zebra_evpn_neigh_clear_sync_info(n))
1509 inform_dataplane = true;
1510 /* Update the forwarding info. */
1511 n->ifindex = ifp->ifindex;
1512
1513 /* Link to new MAC */
1514 zebra_evpn_local_neigh_ref_mac(
1515 n, macaddr, zmac, true /* send_mac_update */);
1516 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1517 /*
1518 * Neighbor has moved from remote to local. Its
1519 * MAC could have also changed as part of the move.
1520 */
1521 if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN)
1522 != 0) {
1523 old_zmac = n->mac;
1524 if (old_zmac) {
1525 old_mac_seq =
1526 CHECK_FLAG(old_zmac->flags,
1527 ZEBRA_MAC_REMOTE)
1528 ? old_zmac->rem_seq
1529 : old_zmac->loc_seq;
1530 neigh_mac_change = upd_mac_seq = true;
1531 zebra_evpn_local_neigh_deref_mac(
1532 n, true /* send_update */);
1533 }
1534
1535 /* Link to new MAC */
1536 zebra_evpn_local_neigh_ref_mac(
1537 n, macaddr, zmac, true /*send_update*/);
1538 }
1539 /* Based on Mobility event Scenario-B from the
1540 * draft, neigh's previous state was remote treat this
1541 * event for DAD.
1542 */
1543 neigh_was_remote = true;
1544 vtep_ip = n->r_vtep_ip;
1545 /* Mark appropriately */
1546 UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
1547 n->r_vtep_ip.s_addr = INADDR_ANY;
1548 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
1549 n->ifindex = ifp->ifindex;
1550 }
1551 }
1552
1553 /* If MAC was previously remote, or the neighbor had a different
1554 * MAC earlier, recompute the sequence number.
1555 */
1556 if (upd_mac_seq) {
1557 uint32_t seq1, seq2;
1558
1559 seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)
1560 ? zmac->rem_seq + 1
1561 : zmac->loc_seq;
1562 seq2 = neigh_mac_change ? old_mac_seq + 1 : 0;
1563 mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ? MAX(seq1, seq2)
1564 : zmac->loc_seq;
1565 }
1566
1567 if (local_inactive)
1568 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
1569 else
1570 UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
1571
1572 /* Mark Router flag (R-bit) */
1573 if (is_router)
1574 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
1575 else
1576 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
1577
1578 /* if the dataplane thinks that this is a sync entry but
1579 * zebra doesn't we need to re-concile the diff
1580 * by re-installing the dataplane entry
1581 */
1582 if (dp_static) {
1583 new_static = zebra_evpn_neigh_is_static(n);
1584 if (!new_static)
1585 inform_dataplane = true;
1586 }
1587
1588 /* Check old and/or new MAC detected as duplicate mark
1589 * the neigh as duplicate
1590 */
1591 if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
1592 flog_warn(
1593 EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
1594 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
1595 zevpn->vni, prefix_mac2str(macaddr, buf, sizeof(buf)),
1596 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1597 }
1598
1599 /* For IP Duplicate Address Detection (DAD) is trigger,
1600 * when the event is extended mobility based on scenario-B
1601 * from the draft, IP/Neigh's MAC binding changed and
1602 * neigh's previous state was remote.
1603 */
1604 if (neigh_mac_change && neigh_was_remote)
1605 do_dad = true;
1606
1607 zebra_evpn_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad,
1608 &neigh_on_hold, true);
1609
1610 if (inform_dataplane)
1611 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
1612 false /* force_clear_static */,
1613 __func__);
1614
1615 /* Before we program this in BGP, we need to check if MAC is locally
1616 * learnt. If not, force neighbor to be inactive and reset its seq.
1617 */
1618 if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
1619 zebra_evpn_local_neigh_update_log(
1620 "local", n, is_router, local_inactive, false, false,
1621 inform_dataplane, false, "auto-mac");
1622 ZEBRA_NEIGH_SET_INACTIVE(n);
1623 n->loc_seq = 0;
1624 zmac->loc_seq = mac_new_seq;
1625 return 0;
1626 }
1627
1628 zebra_evpn_local_neigh_update_log("local", n, is_router, local_inactive,
1629 false, false, inform_dataplane, true,
1630 created ? "created" : "updated");
1631
1632 /* If the MAC's sequence number has changed, inform the MAC and all
1633 * neighbors associated with the MAC to BGP, else just inform this
1634 * neighbor.
1635 */
1636 if (upd_mac_seq && zmac->loc_seq != mac_new_seq) {
1637 if (IS_ZEBRA_DEBUG_VXLAN)
1638 zlog_debug(
1639 "Seq changed for MAC %s VNI %u - old %u new %u",
1640 prefix_mac2str(macaddr, buf, sizeof(buf)),
1641 zevpn->vni, zmac->loc_seq, mac_new_seq);
1642 zmac->loc_seq = mac_new_seq;
1643 if (zebra_evpn_mac_send_add_to_client(zevpn->vni, macaddr,
1644 zmac->flags,
1645 zmac->loc_seq, zmac->es))
1646 return -1;
1647 zebra_evpn_process_neigh_on_local_mac_change(zevpn, zmac, 1,
1648 0 /*es_change*/);
1649 return 0;
1650 }
1651
1652 n->loc_seq = zmac->loc_seq;
1653
1654 if (!neigh_on_hold) {
1655 ZEBRA_NEIGH_SET_ACTIVE(n);
1656 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
1657 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
1658 new_bgp_ready);
1659 } else {
1660 if (IS_ZEBRA_DEBUG_VXLAN)
1661 zlog_debug(" Neighbor on hold not sending");
1662 }
1663 return 0;
1664 }
1665
zebra_evpn_remote_neigh_update(zebra_evpn_t * zevpn,struct interface * ifp,struct ipaddr * ip,struct ethaddr * macaddr,uint16_t state)1666 int zebra_evpn_remote_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
1667 struct ipaddr *ip, struct ethaddr *macaddr,
1668 uint16_t state)
1669 {
1670 char buf[ETHER_ADDR_STRLEN];
1671 char buf2[INET6_ADDRSTRLEN];
1672 zebra_neigh_t *n = NULL;
1673 zebra_mac_t *zmac = NULL;
1674
1675 /* If the neighbor is unknown, there is no further action. */
1676 n = zebra_evpn_neigh_lookup(zevpn, ip);
1677 if (!n)
1678 return 0;
1679
1680 /* If a remote entry, see if it needs to be refreshed */
1681 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1682 #ifdef GNU_LINUX
1683 if (state & NUD_STALE)
1684 zebra_evpn_rem_neigh_install(zevpn, n,
1685 false /*was_static*/);
1686 #endif
1687 } else {
1688 /* We got a "remote" neighbor notification for an entry
1689 * we think is local. This can happen in a multihoming
1690 * scenario - but only if the MAC is already "remote".
1691 * Just mark our entry as "remote".
1692 */
1693 zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
1694 if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
1695 zlog_debug(
1696 "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
1697 ipaddr2str(&n->ip, buf2, sizeof(buf2)),
1698 prefix_mac2str(macaddr, buf, sizeof(buf)),
1699 zevpn->vni);
1700 return -1;
1701 }
1702
1703 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS);
1704 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
1705 ZEBRA_NEIGH_SET_ACTIVE(n);
1706 n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
1707 }
1708
1709 return 0;
1710 }
1711
1712 /* Notify Neighbor entries to the Client, skips the GW entry */
1713 static void
zebra_evpn_send_neigh_hash_entry_to_client(struct hash_bucket * bucket,void * arg)1714 zebra_evpn_send_neigh_hash_entry_to_client(struct hash_bucket *bucket,
1715 void *arg)
1716 {
1717 struct mac_walk_ctx *wctx = arg;
1718 zebra_neigh_t *zn = bucket->data;
1719 zebra_mac_t *zmac = NULL;
1720
1721 if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_DEF_GW))
1722 return;
1723
1724 if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_LOCAL)
1725 && IS_ZEBRA_NEIGH_ACTIVE(zn)) {
1726 zmac = zebra_evpn_mac_lookup(wctx->zevpn, &zn->emac);
1727 if (!zmac)
1728 return;
1729
1730 zebra_evpn_neigh_send_add_to_client(wctx->zevpn->vni, &zn->ip,
1731 &zn->emac, zn->mac,
1732 zn->flags, zn->loc_seq);
1733 }
1734 }
1735
1736 /* Iterator of a specific EVPN */
zebra_evpn_send_neigh_to_client(zebra_evpn_t * zevpn)1737 void zebra_evpn_send_neigh_to_client(zebra_evpn_t *zevpn)
1738 {
1739 struct neigh_walk_ctx wctx;
1740
1741 memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
1742 wctx.zevpn = zevpn;
1743
1744 hash_iterate(zevpn->neigh_table,
1745 zebra_evpn_send_neigh_hash_entry_to_client, &wctx);
1746 }
1747
zebra_evpn_clear_dup_neigh_hash(struct hash_bucket * bucket,void * ctxt)1748 void zebra_evpn_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt)
1749 {
1750 struct neigh_walk_ctx *wctx = ctxt;
1751 zebra_neigh_t *nbr;
1752 zebra_evpn_t *zevpn;
1753 char buf[INET6_ADDRSTRLEN];
1754
1755 nbr = (zebra_neigh_t *)bucket->data;
1756 if (!nbr)
1757 return;
1758
1759 zevpn = wctx->zevpn;
1760
1761 if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
1762 return;
1763
1764 if (IS_ZEBRA_DEBUG_VXLAN) {
1765 ipaddr2str(&nbr->ip, buf, sizeof(buf));
1766 zlog_debug("%s: clear neigh %s dup state, flags 0x%x seq %u",
1767 __func__, buf, nbr->flags, nbr->loc_seq);
1768 }
1769
1770 UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
1771 nbr->dad_count = 0;
1772 nbr->detect_start_time.tv_sec = 0;
1773 nbr->detect_start_time.tv_usec = 0;
1774 nbr->dad_dup_detect_time = 0;
1775 THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
1776
1777 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
1778 zebra_evpn_neigh_send_add_to_client(zevpn->vni, &nbr->ip,
1779 &nbr->emac, nbr->mac,
1780 nbr->flags, nbr->loc_seq);
1781 } else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
1782 zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
1783 }
1784 }
1785
1786 /*
1787 * Print a specific neighbor entry.
1788 */
zebra_evpn_print_neigh(zebra_neigh_t * n,void * ctxt,json_object * json)1789 void zebra_evpn_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
1790 {
1791 struct vty *vty;
1792 char buf1[ETHER_ADDR_STRLEN];
1793 char buf2[INET6_ADDRSTRLEN];
1794 const char *type_str;
1795 const char *state_str;
1796 bool flags_present = false;
1797 struct zebra_vrf *zvrf = NULL;
1798 struct timeval detect_start_time = {0, 0};
1799 char timebuf[MONOTIME_STRLEN];
1800 char thread_buf[THREAD_TIMER_STRLEN];
1801
1802 zvrf = zebra_vrf_get_evpn();
1803 if (!zvrf)
1804 return;
1805
1806 ipaddr2str(&n->ip, buf2, sizeof(buf2));
1807 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
1808 type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? "local" : "remote";
1809 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
1810 vty = (struct vty *)ctxt;
1811 if (json == NULL) {
1812 bool sync_info = false;
1813
1814 vty_out(vty, "IP: %s\n",
1815 ipaddr2str(&n->ip, buf2, sizeof(buf2)));
1816 vty_out(vty, " Type: %s\n", type_str);
1817 vty_out(vty, " State: %s\n", state_str);
1818 vty_out(vty, " MAC: %s\n",
1819 prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
1820 vty_out(vty, " Sync-info:");
1821 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE)) {
1822 vty_out(vty, " local-inactive");
1823 sync_info = true;
1824 }
1825 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY)) {
1826 vty_out(vty, " peer-proxy");
1827 sync_info = true;
1828 }
1829 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE)) {
1830 vty_out(vty, " peer-active");
1831 sync_info = true;
1832 }
1833 if (n->hold_timer) {
1834 vty_out(vty, " (ht: %s)",
1835 thread_timer_to_hhmmss(thread_buf,
1836 sizeof(thread_buf),
1837 n->hold_timer));
1838 sync_info = true;
1839 }
1840 if (!sync_info)
1841 vty_out(vty, " -");
1842 vty_out(vty, "\n");
1843 } else {
1844 json_object_string_add(json, "ip", buf2);
1845 json_object_string_add(json, "type", type_str);
1846 json_object_string_add(json, "state", state_str);
1847 json_object_string_add(json, "mac", buf1);
1848 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
1849 json_object_boolean_true_add(json, "localInactive");
1850 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY))
1851 json_object_boolean_true_add(json, "peerProxy");
1852 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE))
1853 json_object_boolean_true_add(json, "peerActive");
1854 if (n->hold_timer)
1855 json_object_string_add(
1856 json, "peerActiveHold",
1857 thread_timer_to_hhmmss(thread_buf,
1858 sizeof(thread_buf),
1859 n->hold_timer));
1860 }
1861 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
1862 if (n->mac->es) {
1863 if (json)
1864 json_object_string_add(json, "remoteEs",
1865 n->mac->es->esi_str);
1866 else
1867 vty_out(vty, " Remote ES: %s\n",
1868 n->mac->es->esi_str);
1869 } else {
1870 if (json)
1871 json_object_string_add(json, "remoteVtep",
1872 inet_ntoa(n->r_vtep_ip));
1873 else
1874 vty_out(vty, " Remote VTEP: %s\n",
1875 inet_ntoa(n->r_vtep_ip));
1876 }
1877 }
1878 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
1879 if (!json) {
1880 vty_out(vty, " Flags: Default-gateway");
1881 flags_present = true;
1882 } else
1883 json_object_boolean_true_add(json, "defaultGateway");
1884 }
1885 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) {
1886 if (!json) {
1887 vty_out(vty,
1888 flags_present ? " ,Router" : " Flags: Router");
1889 flags_present = true;
1890 }
1891 }
1892 if (json == NULL) {
1893 if (flags_present)
1894 vty_out(vty, "\n");
1895 vty_out(vty, " Local Seq: %u Remote Seq: %u\n", n->loc_seq,
1896 n->rem_seq);
1897
1898 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
1899 vty_out(vty, " Duplicate, detected at %s",
1900 time_to_string(n->dad_dup_detect_time,
1901 timebuf));
1902 } else if (n->dad_count) {
1903 monotime_since(&n->detect_start_time,
1904 &detect_start_time);
1905 if (detect_start_time.tv_sec <= zvrf->dad_time) {
1906 time_to_string(n->detect_start_time.tv_sec,
1907 timebuf);
1908 vty_out(vty,
1909 " Duplicate detection started at %s, detection count %u\n",
1910 timebuf, n->dad_count);
1911 }
1912 }
1913 } else {
1914 json_object_int_add(json, "localSequence", n->loc_seq);
1915 json_object_int_add(json, "remoteSequence", n->rem_seq);
1916 json_object_int_add(json, "detectionCount", n->dad_count);
1917 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
1918 json_object_boolean_true_add(json, "isDuplicate");
1919 else
1920 json_object_boolean_false_add(json, "isDuplicate");
1921 }
1922 }
1923
zebra_evpn_print_neigh_hdr(struct vty * vty,struct neigh_walk_ctx * wctx)1924 void zebra_evpn_print_neigh_hdr(struct vty *vty, struct neigh_walk_ctx *wctx)
1925 {
1926 vty_out(vty, "Flags: I=local-inactive, P=peer-active, X=peer-proxy\n");
1927 vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %s\n", -wctx->addr_width,
1928 "Neighbor", "Type", "Flags", "State", "MAC", "Remote ES/VTEP",
1929 "Seq #'s");
1930 }
1931
zebra_evpn_print_neigh_flags(zebra_neigh_t * n,char * flags_buf,uint32_t flags_buf_sz)1932 static char *zebra_evpn_print_neigh_flags(zebra_neigh_t *n, char *flags_buf,
1933 uint32_t flags_buf_sz)
1934 {
1935 snprintf(flags_buf, flags_buf_sz, "%s%s%s",
1936 (n->flags & ZEBRA_NEIGH_ES_PEER_ACTIVE) ?
1937 "P" : "",
1938 (n->flags & ZEBRA_NEIGH_ES_PEER_PROXY) ?
1939 "X" : "",
1940 (n->flags & ZEBRA_NEIGH_LOCAL_INACTIVE) ?
1941 "I" : "");
1942
1943 return flags_buf;
1944 }
1945
1946 /*
1947 * Print neighbor hash entry - called for display of all neighbors.
1948 */
zebra_evpn_print_neigh_hash(struct hash_bucket * bucket,void * ctxt)1949 void zebra_evpn_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
1950 {
1951 struct vty *vty;
1952 json_object *json_evpn = NULL, *json_row = NULL;
1953 zebra_neigh_t *n;
1954 char buf1[ETHER_ADDR_STRLEN];
1955 char buf2[INET6_ADDRSTRLEN];
1956 struct neigh_walk_ctx *wctx = ctxt;
1957 const char *state_str;
1958 char flags_buf[6];
1959
1960 vty = wctx->vty;
1961 json_evpn = wctx->json;
1962 n = (zebra_neigh_t *)bucket->data;
1963
1964 if (json_evpn)
1965 json_row = json_object_new_object();
1966
1967 prefix_mac2str(&n->emac, buf1, sizeof(buf1));
1968 ipaddr2str(&n->ip, buf2, sizeof(buf2));
1969 state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive";
1970 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
1971 if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
1972 return;
1973
1974 if (json_evpn == NULL) {
1975 vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
1976 -wctx->addr_width, buf2, "local",
1977 zebra_evpn_print_neigh_flags(n, flags_buf,
1978 sizeof(flags_buf)), state_str, buf1,
1979 "", n->loc_seq, n->rem_seq);
1980 } else {
1981 json_object_string_add(json_row, "type", "local");
1982 json_object_string_add(json_row, "state", state_str);
1983 json_object_string_add(json_row, "mac", buf1);
1984 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
1985 json_object_boolean_true_add(json_row,
1986 "defaultGateway");
1987 json_object_int_add(json_row, "localSequence",
1988 n->loc_seq);
1989 json_object_int_add(json_row, "remoteSequence",
1990 n->rem_seq);
1991 json_object_int_add(json_row, "detectionCount",
1992 n->dad_count);
1993 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
1994 json_object_boolean_true_add(json_row,
1995 "isDuplicate");
1996 else
1997 json_object_boolean_false_add(json_row,
1998 "isDuplicate");
1999 }
2000 wctx->count++;
2001 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2002 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
2003 && !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))
2004 return;
2005
2006 if (json_evpn == NULL) {
2007 if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP)
2008 && (wctx->count == 0))
2009 zebra_evpn_print_neigh_hdr(vty, wctx);
2010 vty_out(vty, "%*s %-6s %-5s %-8s %-17s %-30s %u/%u\n",
2011 -wctx->addr_width, buf2, "remote",
2012 zebra_evpn_print_neigh_flags(n, flags_buf,
2013 sizeof(flags_buf)), state_str, buf1,
2014 n->mac->es ? n->mac->es->esi_str
2015 : inet_ntoa(n->r_vtep_ip),
2016 n->loc_seq, n->rem_seq);
2017 } else {
2018 json_object_string_add(json_row, "type", "remote");
2019 json_object_string_add(json_row, "state", state_str);
2020 json_object_string_add(json_row, "mac", buf1);
2021 if (n->mac->es)
2022 json_object_string_add(json_row, "remoteEs",
2023 n->mac->es->esi_str);
2024 else
2025 json_object_string_add(json_row, "remoteVtep",
2026 inet_ntoa(n->r_vtep_ip));
2027 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW))
2028 json_object_boolean_true_add(json_row,
2029 "defaultGateway");
2030 json_object_int_add(json_row, "localSequence",
2031 n->loc_seq);
2032 json_object_int_add(json_row, "remoteSequence",
2033 n->rem_seq);
2034 json_object_int_add(json_row, "detectionCount",
2035 n->dad_count);
2036 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
2037 json_object_boolean_true_add(json_row,
2038 "isDuplicate");
2039 else
2040 json_object_boolean_false_add(json_row,
2041 "isDuplicate");
2042 }
2043 wctx->count++;
2044 }
2045
2046 if (json_evpn)
2047 json_object_object_add(json_evpn, buf2, json_row);
2048 }
2049
2050 /*
2051 * Print neighbor hash entry in detail - called for display of all neighbors.
2052 */
zebra_evpn_print_neigh_hash_detail(struct hash_bucket * bucket,void * ctxt)2053 void zebra_evpn_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt)
2054 {
2055 struct vty *vty;
2056 json_object *json_evpn = NULL, *json_row = NULL;
2057 zebra_neigh_t *n;
2058 char buf[INET6_ADDRSTRLEN];
2059 struct neigh_walk_ctx *wctx = ctxt;
2060
2061 vty = wctx->vty;
2062 json_evpn = wctx->json;
2063 n = (zebra_neigh_t *)bucket->data;
2064 if (!n)
2065 return;
2066
2067 ipaddr2str(&n->ip, buf, sizeof(buf));
2068 if (json_evpn)
2069 json_row = json_object_new_object();
2070
2071 zebra_evpn_print_neigh(n, vty, json_row);
2072
2073 if (json_evpn)
2074 json_object_object_add(json_evpn, buf, json_row);
2075 }
2076
zebra_evpn_print_dad_neigh_hash(struct hash_bucket * bucket,void * ctxt)2077 void zebra_evpn_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt)
2078 {
2079 zebra_neigh_t *nbr;
2080
2081 nbr = (zebra_neigh_t *)bucket->data;
2082 if (!nbr)
2083 return;
2084
2085 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
2086 zebra_evpn_print_neigh_hash(bucket, ctxt);
2087 }
2088
zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket * bucket,void * ctxt)2089 void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket,
2090 void *ctxt)
2091 {
2092 zebra_neigh_t *nbr;
2093
2094 nbr = (zebra_neigh_t *)bucket->data;
2095 if (!nbr)
2096 return;
2097
2098 if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
2099 zebra_evpn_print_neigh_hash_detail(bucket, ctxt);
2100 }
2101
process_neigh_remote_macip_add(zebra_evpn_t * zevpn,struct zebra_vrf * zvrf,struct ipaddr * ipaddr,zebra_mac_t * mac,struct in_addr vtep_ip,uint8_t flags,uint32_t seq)2102 void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
2103 struct ipaddr *ipaddr, zebra_mac_t *mac,
2104 struct in_addr vtep_ip, uint8_t flags,
2105 uint32_t seq)
2106 {
2107 zebra_neigh_t *n;
2108 int update_neigh = 0;
2109 uint32_t tmp_seq;
2110 char buf[ETHER_ADDR_STRLEN];
2111 char buf1[INET6_ADDRSTRLEN];
2112 zebra_mac_t *old_mac = NULL;
2113 bool old_static = false;
2114 bool do_dad = false;
2115 bool is_dup_detect = false;
2116 bool is_router;
2117
2118 assert(mac);
2119 is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
2120
2121 /* Check if the remote neighbor itself is unknown or has a
2122 * change. If so, create or update and then install the entry.
2123 */
2124 n = zebra_evpn_neigh_lookup(zevpn, ipaddr);
2125 if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
2126 || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)
2127 || (memcmp(&n->emac, &mac->macaddr, sizeof(struct ethaddr)) != 0)
2128 || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) || seq != n->rem_seq)
2129 update_neigh = 1;
2130
2131 if (update_neigh) {
2132 if (!n) {
2133 n = zebra_evpn_neigh_add(zevpn, ipaddr, &mac->macaddr,
2134 mac, 0);
2135 if (!n) {
2136 zlog_warn(
2137 "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
2138 ipaddr2str(ipaddr, buf1, sizeof(buf1)),
2139 prefix_mac2str(&mac->macaddr, buf,
2140 sizeof(buf)),
2141 zevpn->vni, inet_ntoa(vtep_ip));
2142 return;
2143 }
2144
2145 } else {
2146 const char *n_type;
2147
2148 /* When host moves but changes its (MAC,IP)
2149 * binding, BGP may install a MACIP entry that
2150 * corresponds to "older" location of the host
2151 * in transient situations (because {IP1,M1}
2152 * is a different route from {IP1,M2}). Check
2153 * the sequence number and ignore this update
2154 * if appropriate.
2155 */
2156 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2157 tmp_seq = n->loc_seq;
2158 n_type = "local";
2159 } else {
2160 tmp_seq = n->rem_seq;
2161 n_type = "remote";
2162 }
2163 if (seq < tmp_seq) {
2164 if (IS_ZEBRA_DEBUG_VXLAN)
2165 zlog_debug(
2166 "Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
2167 zevpn->vni,
2168 prefix_mac2str(&mac->macaddr,
2169 buf,
2170 sizeof(buf)),
2171 " IP ",
2172 ipaddr2str(ipaddr, buf1,
2173 sizeof(buf1)),
2174 n_type, tmp_seq);
2175 return;
2176 }
2177 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2178 old_static = zebra_evpn_neigh_is_static(n);
2179 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
2180 zlog_debug(
2181 "sync->remote neigh vni %u ip %s mac %s seq %d f0x%x",
2182 n->zevpn->vni,
2183 ipaddr2str(&n->ip, buf1,
2184 sizeof(buf1)),
2185 prefix_mac2str(&n->emac, buf,
2186 sizeof(buf)),
2187 seq, n->flags);
2188 zebra_evpn_neigh_clear_sync_info(n);
2189 if (IS_ZEBRA_NEIGH_ACTIVE(n))
2190 zebra_evpn_neigh_send_del_to_client(
2191 zevpn->vni, &n->ip, &n->emac,
2192 n->flags, n->state,
2193 false /*force*/);
2194 }
2195 if (memcmp(&n->emac, &mac->macaddr,
2196 sizeof(struct ethaddr))
2197 != 0) {
2198 /* update neigh list for macs */
2199 old_mac =
2200 zebra_evpn_mac_lookup(zevpn, &n->emac);
2201 if (old_mac) {
2202 listnode_delete(old_mac->neigh_list, n);
2203 n->mac = NULL;
2204 zebra_evpn_deref_ip2mac(zevpn, old_mac);
2205 }
2206 n->mac = mac;
2207 listnode_add_sort(mac->neigh_list, n);
2208 memcpy(&n->emac, &mac->macaddr, ETH_ALEN);
2209
2210 /* Check Neigh's curent state is local
2211 * (this is the case where neigh/host has moved
2212 * from L->R) and check previous detction
2213 * started via local learning.
2214 *
2215 * RFC-7432: A PE/VTEP that detects a MAC
2216 * mobilit event via local learning starts
2217 * an M-second timer.
2218 * VTEP-IP or seq. change along is not
2219 * considered for dup. detection.
2220 *
2221 * Mobilty event scenario-B IP-MAC binding
2222 * changed.
2223 */
2224 if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE))
2225 && n->dad_count)
2226 do_dad = true;
2227 }
2228 }
2229
2230 /* Set "remote" forwarding info. */
2231 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS);
2232 n->r_vtep_ip = vtep_ip;
2233 SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
2234
2235 /* Set router flag (R-bit) to this Neighbor entry */
2236 if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG))
2237 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
2238 else
2239 UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
2240
2241 /* Check old or new MAC detected as duplicate,
2242 * inherit duplicate flag to this neigh.
2243 */
2244 if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) {
2245 flog_warn(
2246 EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
2247 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
2248 zevpn->vni,
2249 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
2250 ipaddr2str(&n->ip, buf1, sizeof(buf1)));
2251 }
2252
2253 /* Check duplicate address detection for IP */
2254 zebra_evpn_dup_addr_detect_for_neigh(
2255 zvrf, n, n->r_vtep_ip, do_dad, &is_dup_detect, false);
2256 /* Install the entry. */
2257 if (!is_dup_detect)
2258 zebra_evpn_rem_neigh_install(zevpn, n, old_static);
2259 }
2260
2261 /* Update seq number. */
2262 n->rem_seq = seq;
2263 }
2264
zebra_evpn_neigh_gw_macip_add(struct interface * ifp,zebra_evpn_t * zevpn,struct ipaddr * ip,zebra_mac_t * mac)2265 int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
2266 struct ipaddr *ip, zebra_mac_t *mac)
2267 {
2268 zebra_neigh_t *n;
2269 char buf[ETHER_ADDR_STRLEN];
2270 char buf2[INET6_ADDRSTRLEN];
2271
2272 assert(mac);
2273
2274 n = zebra_evpn_neigh_lookup(zevpn, ip);
2275 if (!n) {
2276 n = zebra_evpn_neigh_add(zevpn, ip, &mac->macaddr, mac, 0);
2277 if (!n) {
2278 flog_err(
2279 EC_ZEBRA_MAC_ADD_FAILED,
2280 "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
2281 ipaddr2str(ip, buf2, sizeof(buf2)),
2282 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
2283 ifp->name, ifp->ifindex, zevpn->vni);
2284 return -1;
2285 }
2286 }
2287
2288 /* Set "local" forwarding info. */
2289 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
2290 ZEBRA_NEIGH_SET_ACTIVE(n);
2291 memcpy(&n->emac, &mac->macaddr, ETH_ALEN);
2292 n->ifindex = ifp->ifindex;
2293
2294 /* Only advertise in BGP if the knob is enabled */
2295 if (advertise_gw_macip_enabled(zevpn)) {
2296
2297 SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
2298 SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
2299 /* Set Router flag (R-bit) */
2300 if (ip->ipa_type == IPADDR_V6)
2301 SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG);
2302
2303 if (IS_ZEBRA_DEBUG_VXLAN)
2304 zlog_debug(
2305 "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
2306 ifp->name, ifp->ifindex, zevpn->vni,
2307 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
2308 ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
2309
2310 zebra_evpn_neigh_send_add_to_client(
2311 zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
2312 } else if (advertise_svi_macip_enabled(zevpn)) {
2313
2314 SET_FLAG(n->flags, ZEBRA_NEIGH_SVI_IP);
2315 if (IS_ZEBRA_DEBUG_VXLAN)
2316 zlog_debug(
2317 "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
2318 ifp->name, ifp->ifindex, zevpn->vni,
2319 prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
2320 ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
2321
2322 zebra_evpn_neigh_send_add_to_client(
2323 zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
2324 }
2325
2326 return 0;
2327 }
2328
zebra_evpn_neigh_remote_uninstall(zebra_evpn_t * zevpn,struct zebra_vrf * zvrf,zebra_neigh_t * n,zebra_mac_t * mac,struct ipaddr * ipaddr)2329 void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
2330 struct zebra_vrf *zvrf, zebra_neigh_t *n,
2331 zebra_mac_t *mac, struct ipaddr *ipaddr)
2332 {
2333 char buf1[INET6_ADDRSTRLEN];
2334
2335 if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)
2336 && CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
2337 && (memcmp(n->emac.octet, mac->macaddr.octet, ETH_ALEN) == 0)) {
2338 struct interface *vlan_if;
2339
2340 vlan_if = zevpn_map_to_svi(zevpn);
2341 if (IS_ZEBRA_DEBUG_VXLAN)
2342 zlog_debug(
2343 "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
2344 __func__,
2345 ipaddr2str(ipaddr, buf1, sizeof(buf1)),
2346 n->flags, vlan_if ? vlan_if->name : "Unknown");
2347 if (vlan_if)
2348 neigh_read_specific_ip(ipaddr, vlan_if);
2349 }
2350
2351 /* When the MAC changes for an IP, it is possible the
2352 * client may update the new MAC before trying to delete the
2353 * "old" neighbor (as these are two different MACIP routes).
2354 * Do the delete only if the MAC matches.
2355 */
2356 if (!memcmp(n->emac.octet, mac->macaddr.octet, ETH_ALEN)) {
2357 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
2358 zebra_evpn_sync_neigh_del(n);
2359 } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2360 zebra_evpn_neigh_uninstall(zevpn, n);
2361 zebra_evpn_neigh_del(zevpn, n);
2362 zebra_evpn_deref_ip2mac(zevpn, mac);
2363 }
2364 }
2365 }
2366
zebra_evpn_neigh_del_ip(zebra_evpn_t * zevpn,struct ipaddr * ip)2367 int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
2368 {
2369 zebra_neigh_t *n;
2370 zebra_mac_t *zmac;
2371 bool old_bgp_ready;
2372 bool new_bgp_ready;
2373 char buf[INET6_ADDRSTRLEN];
2374 char buf2[ETHER_ADDR_STRLEN];
2375 struct zebra_vrf *zvrf;
2376
2377 /* If entry doesn't exist, nothing to do. */
2378 n = zebra_evpn_neigh_lookup(zevpn, ip);
2379 if (!n)
2380 return 0;
2381
2382 zmac = zebra_evpn_mac_lookup(zevpn, &n->emac);
2383 if (!zmac) {
2384 if (IS_ZEBRA_DEBUG_VXLAN)
2385 zlog_debug(
2386 "Trying to del a neigh %s without a mac %s on VNI %u",
2387 ipaddr2str(ip, buf, sizeof(buf)),
2388 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
2389 zevpn->vni);
2390
2391 return 0;
2392 }
2393
2394 /* If it is a remote entry, the kernel has aged this out or someone has
2395 * deleted it, it needs to be re-installed as Quagga is the owner.
2396 */
2397 if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
2398 zebra_evpn_rem_neigh_install(zevpn, n, false /*was_static*/);
2399 return 0;
2400 }
2401
2402 /* if this is a sync entry it cannot be dropped re-install it in
2403 * the dataplane
2404 */
2405 old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
2406 if (zebra_evpn_neigh_is_static(n)) {
2407 if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
2408 zlog_debug("re-add sync neigh vni %u ip %s mac %s 0x%x",
2409 n->zevpn->vni,
2410 ipaddr2str(&n->ip, buf, sizeof(buf)),
2411 prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
2412 n->flags);
2413
2414 if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
2415 SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE);
2416 /* inform-bgp about change in local-activity if any */
2417 new_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
2418 zebra_evpn_neigh_send_add_del_to_client(n, old_bgp_ready,
2419 new_bgp_ready);
2420
2421 /* re-install the entry in the kernel */
2422 zebra_evpn_sync_neigh_dp_install(n, false /* set_inactive */,
2423 false /* force_clear_static */,
2424 __func__);
2425
2426 return 0;
2427 }
2428
2429 zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
2430 if (!zvrf) {
2431 zlog_debug("%s: VNI %u vrf lookup failed.", __func__,
2432 zevpn->vni);
2433 return -1;
2434 }
2435
2436 /* In case of feeze action, if local neigh is in duplicate state,
2437 * Mark the Neigh as inactive before sending delete request to BGPd,
2438 * If BGPd has remote entry, it will re-install
2439 */
2440 if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
2441 ZEBRA_NEIGH_SET_INACTIVE(n);
2442
2443 /* Remove neighbor from BGP. */
2444 zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac,
2445 n->flags, n->state,
2446 false /* force */);
2447
2448 /* Delete this neighbor entry. */
2449 zebra_evpn_neigh_del(zevpn, n);
2450
2451 /* see if the AUTO mac needs to be deleted */
2452 if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
2453 && !listcount(zmac->neigh_list))
2454 zebra_evpn_mac_del(zevpn, zmac);
2455
2456 return 0;
2457 }
2458