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