]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_nexthop.c
bfdd: Fix malformed session with vrf
[mirror_frr.git] / bgpd / bgp_nexthop.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP nexthop scan
3 * Copyright (C) 2000 Kunihiro Ishiguro
4 */
5
6 #include <zebra.h>
7
8 #include "command.h"
9 #include "frrevent.h"
10 #include "prefix.h"
11 #include "lib/json.h"
12 #include "zclient.h"
13 #include "stream.h"
14 #include "network.h"
15 #include "log.h"
16 #include "memory.h"
17 #include "hash.h"
18 #include "jhash.h"
19 #include "nexthop.h"
20 #include "queue.h"
21 #include "filter.h"
22 #include "printfrr.h"
23
24 #include "bgpd/bgpd.h"
25 #include "bgpd/bgp_route.h"
26 #include "bgpd/bgp_attr.h"
27 #include "bgpd/bgp_nexthop.h"
28 #include "bgpd/bgp_nht.h"
29 #include "bgpd/bgp_debug.h"
30 #include "bgpd/bgp_damp.h"
31 #include "bgpd/bgp_fsm.h"
32 #include "bgpd/bgp_vty.h"
33 #include "bgpd/bgp_rd.h"
34
35 DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
36
37 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
38 const struct bgp_nexthop_cache *b)
39 {
40 if (a->srte_color < b->srte_color)
41 return -1;
42 if (a->srte_color > b->srte_color)
43 return 1;
44
45 if (a->ifindex < b->ifindex)
46 return -1;
47 if (a->ifindex > b->ifindex)
48 return 1;
49
50 return prefix_cmp(&a->prefix, &b->prefix);
51 }
52
53 void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
54 {
55 nexthops_free(bnc->nexthop);
56 }
57
58 struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
59 struct prefix *prefix, uint32_t srte_color,
60 ifindex_t ifindex)
61 {
62 struct bgp_nexthop_cache *bnc;
63
64 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
65 sizeof(struct bgp_nexthop_cache));
66 bnc->prefix = *prefix;
67 bnc->ifindex = ifindex;
68 bnc->srte_color = srte_color;
69 bnc->tree = tree;
70 LIST_INIT(&(bnc->paths));
71 bgp_nexthop_cache_add(tree, bnc);
72
73 return bnc;
74 }
75
76 bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc)
77 {
78 struct bgp_nexthop_cache *bnc_tmp;
79
80 frr_each (bgp_nexthop_cache, bnc->tree, bnc_tmp) {
81 if (bnc_tmp == bnc)
82 continue;
83 if (prefix_cmp(&bnc->prefix, &bnc_tmp->prefix) == 0)
84 return true;
85 }
86 return false;
87 }
88
89 void bnc_free(struct bgp_nexthop_cache *bnc)
90 {
91 bnc_nexthop_free(bnc);
92 bgp_nexthop_cache_del(bnc->tree, bnc);
93 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
94 }
95
96 struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
97 struct prefix *prefix, uint32_t srte_color,
98 ifindex_t ifindex)
99 {
100 struct bgp_nexthop_cache bnc = {};
101
102 if (!tree)
103 return NULL;
104
105 bnc.prefix = *prefix;
106 bnc.srte_color = srte_color;
107 bnc.ifindex = ifindex;
108 return bgp_nexthop_cache_find(tree, &bnc);
109 }
110
111 /* Reset and free all BGP nexthop cache. */
112 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head *tree)
113 {
114 struct bgp_nexthop_cache *bnc;
115
116 while (bgp_nexthop_cache_count(tree) > 0) {
117 bnc = bgp_nexthop_cache_first(tree);
118
119 while (!LIST_EMPTY(&(bnc->paths))) {
120 struct bgp_path_info *path = LIST_FIRST(&(bnc->paths));
121
122 path_nh_map(path, bnc, false);
123 }
124
125 bnc_free(bnc);
126 }
127 }
128
129 static void *bgp_tip_hash_alloc(void *p)
130 {
131 const struct in_addr *val = (const struct in_addr *)p;
132 struct tip_addr *addr;
133
134 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
135 addr->refcnt = 0;
136 addr->addr.s_addr = val->s_addr;
137
138 return addr;
139 }
140
141 static void bgp_tip_hash_free(void *addr)
142 {
143 XFREE(MTYPE_TIP_ADDR, addr);
144 }
145
146 static unsigned int bgp_tip_hash_key_make(const void *p)
147 {
148 const struct tip_addr *addr = p;
149
150 return jhash_1word(addr->addr.s_addr, 0);
151 }
152
153 static bool bgp_tip_hash_cmp(const void *p1, const void *p2)
154 {
155 const struct tip_addr *addr1 = p1;
156 const struct tip_addr *addr2 = p2;
157
158 return addr1->addr.s_addr == addr2->addr.s_addr;
159 }
160
161 void bgp_tip_hash_init(struct bgp *bgp)
162 {
163 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
164 "BGP TIP hash");
165 }
166
167 void bgp_tip_hash_destroy(struct bgp *bgp)
168 {
169 hash_clean_and_free(&bgp->tip_hash, bgp_tip_hash_free);
170 }
171
172 /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
173 *
174 * Returns true only if we add a _new_ TIP so the caller knows that an
175 * actionable change has occurred. If we find an existing TIP then we
176 * only need to update the refcnt, since the collection of known TIPs
177 * has not changed.
178 */
179 bool bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
180 {
181 struct tip_addr tmp;
182 struct tip_addr *addr;
183 bool tip_added = false;
184
185 tmp.addr = *tip;
186
187 addr = hash_lookup(bgp->tip_hash, &tmp);
188 if (!addr) {
189 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
190 tip_added = true;
191 }
192
193 addr->refcnt++;
194
195 return tip_added;
196 }
197
198 void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
199 {
200 struct tip_addr tmp;
201 struct tip_addr *addr;
202
203 tmp.addr = *tip;
204
205 addr = hash_lookup(bgp->tip_hash, &tmp);
206 /* may have been deleted earlier by bgp_interface_down() */
207 if (addr == NULL)
208 return;
209
210 addr->refcnt--;
211
212 if (addr->refcnt == 0) {
213 hash_release(bgp->tip_hash, addr);
214 XFREE(MTYPE_TIP_ADDR, addr);
215 }
216 }
217
218 /* BGP own address structure */
219 struct bgp_addr {
220 struct prefix p;
221 struct list *ifp_name_list;
222 };
223
224 static void show_address_entry(struct hash_bucket *bucket, void *args)
225 {
226 struct vty *vty = (struct vty *)args;
227 struct bgp_addr *addr = (struct bgp_addr *)bucket->data;
228 char *name;
229 struct listnode *node;
230 char str[INET6_ADDRSTRLEN] = {0};
231
232 vty_out(vty, "addr: %s, count: %d : ",
233 inet_ntop(addr->p.family, &(addr->p.u.prefix),
234 str, INET6_ADDRSTRLEN),
235 addr->ifp_name_list->count);
236
237 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
238 vty_out(vty, " %s,", name);
239 }
240
241 vty_out(vty, "\n");
242 }
243
244 void bgp_nexthop_show_address_hash(struct vty *vty, struct bgp *bgp)
245 {
246 hash_iterate(bgp->address_hash,
247 (void (*)(struct hash_bucket *, void *))show_address_entry,
248 vty);
249 }
250
251 static void bgp_address_hash_string_del(void *val)
252 {
253 char *data = val;
254
255 XFREE(MTYPE_MARTIAN_STRING, data);
256 }
257
258 static void *bgp_address_hash_alloc(void *p)
259 {
260 struct bgp_addr *copy_addr = p;
261 struct bgp_addr *addr = NULL;
262
263 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
264 prefix_copy(&addr->p, &copy_addr->p);
265
266 addr->ifp_name_list = list_new();
267 addr->ifp_name_list->del = bgp_address_hash_string_del;
268
269 return addr;
270 }
271
272 static void bgp_address_hash_free(void *data)
273 {
274 struct bgp_addr *addr = data;
275
276 list_delete(&addr->ifp_name_list);
277 XFREE(MTYPE_BGP_ADDR, addr);
278 }
279
280 static unsigned int bgp_address_hash_key_make(const void *p)
281 {
282 const struct bgp_addr *addr = p;
283
284 return prefix_hash_key(&addr->p);
285 }
286
287 static bool bgp_address_hash_cmp(const void *p1, const void *p2)
288 {
289 const struct bgp_addr *addr1 = p1;
290 const struct bgp_addr *addr2 = p2;
291
292 return prefix_same(&addr1->p, &addr2->p);
293 }
294
295 void bgp_address_init(struct bgp *bgp)
296 {
297 bgp->address_hash =
298 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
299 "BGP Connected Address Hash");
300 }
301
302 void bgp_address_destroy(struct bgp *bgp)
303 {
304 hash_clean_and_free(&bgp->address_hash, bgp_address_hash_free);
305 }
306
307 static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
308 struct prefix *p)
309 {
310 struct bgp_addr tmp;
311 struct bgp_addr *addr;
312 struct listnode *node;
313 char *name;
314
315 tmp.p = *p;
316
317 if (tmp.p.family == AF_INET)
318 tmp.p.prefixlen = IPV4_MAX_BITLEN;
319 else if (tmp.p.family == AF_INET6)
320 tmp.p.prefixlen = IPV6_MAX_BITLEN;
321
322 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
323
324 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
325 if (strcmp(ifc->ifp->name, name) == 0)
326 break;
327 }
328 if (!node) {
329 name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name);
330 listnode_add(addr->ifp_name_list, name);
331 }
332 }
333
334 static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
335 struct prefix *p)
336 {
337 struct bgp_addr tmp;
338 struct bgp_addr *addr;
339 struct listnode *node;
340 char *name;
341
342 tmp.p = *p;
343
344 if (tmp.p.family == AF_INET)
345 tmp.p.prefixlen = IPV4_MAX_BITLEN;
346 else if (tmp.p.family == AF_INET6)
347 tmp.p.prefixlen = IPV6_MAX_BITLEN;
348
349 addr = hash_lookup(bgp->address_hash, &tmp);
350 /* may have been deleted earlier by bgp_interface_down() */
351 if (addr == NULL)
352 return;
353
354 for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
355 if (strcmp(ifc->ifp->name, name) == 0)
356 break;
357 }
358
359 if (node) {
360 list_delete_node(addr->ifp_name_list, node);
361 XFREE(MTYPE_MARTIAN_STRING, name);
362 }
363
364 if (addr->ifp_name_list->count == 0) {
365 hash_release(bgp->address_hash, addr);
366 list_delete(&addr->ifp_name_list);
367 XFREE(MTYPE_BGP_ADDR, addr);
368 }
369 }
370
371
372 struct bgp_connected_ref {
373 unsigned int refcnt;
374 };
375
376 void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
377 {
378 struct prefix p;
379 struct prefix *addr;
380 struct bgp_dest *dest;
381 struct bgp_connected_ref *bc;
382 struct listnode *node, *nnode;
383 struct peer *peer;
384
385 addr = ifc->address;
386
387 p = *(CONNECTED_PREFIX(ifc));
388 if (addr->family == AF_INET) {
389 apply_mask_ipv4((struct prefix_ipv4 *)&p);
390
391 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
392 return;
393
394 bgp_address_add(bgp, ifc, addr);
395
396 dest = bgp_node_get(bgp->connected_table[AFI_IP], &p);
397 bc = bgp_dest_get_bgp_connected_ref_info(dest);
398 if (bc)
399 bc->refcnt++;
400 else {
401 bc = XCALLOC(MTYPE_BGP_CONN,
402 sizeof(struct bgp_connected_ref));
403 bc->refcnt = 1;
404 bgp_dest_set_bgp_connected_ref_info(dest, bc);
405 }
406
407 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
408 if (peer->conf_if
409 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
410 && !peer_established(peer)
411 && !CHECK_FLAG(peer->flags,
412 PEER_FLAG_IFPEER_V6ONLY)) {
413 if (peer_active(peer))
414 BGP_EVENT_ADD(peer, BGP_Stop);
415 BGP_EVENT_ADD(peer, BGP_Start);
416 }
417 }
418 } else if (addr->family == AF_INET6) {
419 apply_mask_ipv6((struct prefix_ipv6 *)&p);
420
421 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
422 return;
423
424 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
425 return;
426
427 bgp_address_add(bgp, ifc, addr);
428
429 dest = bgp_node_get(bgp->connected_table[AFI_IP6], &p);
430
431 bc = bgp_dest_get_bgp_connected_ref_info(dest);
432 if (bc)
433 bc->refcnt++;
434 else {
435 bc = XCALLOC(MTYPE_BGP_CONN,
436 sizeof(struct bgp_connected_ref));
437 bc->refcnt = 1;
438 bgp_dest_set_bgp_connected_ref_info(dest, bc);
439 }
440 }
441 }
442
443 void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
444 {
445 struct prefix p;
446 struct prefix *addr;
447 struct bgp_dest *dest = NULL;
448 struct bgp_connected_ref *bc;
449
450 addr = ifc->address;
451
452 p = *(CONNECTED_PREFIX(ifc));
453 apply_mask(&p);
454 if (addr->family == AF_INET) {
455 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
456 return;
457
458 bgp_address_del(bgp, ifc, addr);
459
460 dest = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
461 } else if (addr->family == AF_INET6) {
462 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
463 return;
464
465 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
466 return;
467
468 bgp_address_del(bgp, ifc, addr);
469
470 dest = bgp_node_lookup(bgp->connected_table[AFI_IP6], &p);
471 }
472
473 if (!dest)
474 return;
475
476 bc = bgp_dest_get_bgp_connected_ref_info(dest);
477 bc->refcnt--;
478 if (bc->refcnt == 0) {
479 XFREE(MTYPE_BGP_CONN, bc);
480 bgp_dest_set_bgp_connected_ref_info(dest, NULL);
481 }
482 bgp_dest_unlock_node(dest);
483 bgp_dest_unlock_node(dest);
484 }
485
486 static void bgp_connected_cleanup(struct route_table *table,
487 struct route_node *rn)
488 {
489 struct bgp_connected_ref *bc;
490 struct bgp_dest *bn = bgp_dest_from_rnode(rn);
491
492 bc = bgp_dest_get_bgp_connected_ref_info(bn);
493 if (!bc)
494 return;
495
496 XFREE(MTYPE_BGP_CONN, bc);
497 bgp_dest_set_bgp_connected_ref_info(bn, NULL);
498 }
499
500 bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
501 uint8_t sub_type, struct attr *attr,
502 struct bgp_dest *dest)
503 {
504 uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
505 struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
506 struct tip_addr tmp_tip, *tip = NULL;
507 const struct prefix *p = bgp_dest_get_prefix(dest);
508 bool is_bgp_static_route =
509 ((type == ZEBRA_ROUTE_BGP) && (sub_type == BGP_ROUTE_STATIC))
510 ? true
511 : false;
512
513 if (!is_bgp_static_route)
514 new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AF_INET6 : AF_INET;
515
516 tmp_addr.p.family = new_afi;
517 switch (new_afi) {
518 case AF_INET:
519 if (is_bgp_static_route) {
520 tmp_addr.p.u.prefix4 = p->u.prefix4;
521 tmp_addr.p.prefixlen = p->prefixlen;
522 } else {
523 /* Here we need to find out which nexthop to be used*/
524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
525 tmp_addr.p.u.prefix4 = attr->nexthop;
526 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
527 } else if ((attr->mp_nexthop_len)
528 && ((attr->mp_nexthop_len
529 == BGP_ATTR_NHLEN_IPV4)
530 || (attr->mp_nexthop_len
531 == BGP_ATTR_NHLEN_VPNV4))) {
532 tmp_addr.p.u.prefix4 =
533 attr->mp_nexthop_global_in;
534 tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
535 } else
536 return false;
537 }
538 break;
539 case AF_INET6:
540 if (is_bgp_static_route) {
541 tmp_addr.p.u.prefix6 = p->u.prefix6;
542 tmp_addr.p.prefixlen = p->prefixlen;
543 } else {
544 tmp_addr.p.u.prefix6 = attr->mp_nexthop_global;
545 tmp_addr.p.prefixlen = IPV6_MAX_BITLEN;
546 }
547 break;
548 default:
549 break;
550 }
551
552 addr = hash_lookup(bgp->address_hash, &tmp_addr);
553 if (addr)
554 return true;
555
556 if (new_afi == AF_INET && hashcount(bgp->tip_hash)) {
557 memset(&tmp_tip, 0, sizeof(tmp_tip));
558 tmp_tip.addr = attr->nexthop;
559
560 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
561 tmp_tip.addr = attr->nexthop;
562 } else if ((attr->mp_nexthop_len) &&
563 ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
564 || (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4))) {
565 tmp_tip.addr = attr->mp_nexthop_global_in;
566 }
567
568 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
569 if (tip)
570 return true;
571 }
572
573 return false;
574 }
575
576 bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
577 {
578 struct bgp_dest *dest1;
579 struct bgp_dest *dest2;
580 struct prefix p;
581 int ret;
582
583 p.family = AF_INET;
584 p.prefixlen = IPV4_MAX_BITLEN;
585 p.u.prefix4 = nexthop;
586
587 dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
588 if (!dest1)
589 return false;
590
591 p.family = AF_INET;
592 p.prefixlen = IPV4_MAX_BITLEN;
593 p.u.prefix4 = peer->su.sin.sin_addr;
594
595 dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
596 if (!dest2) {
597 bgp_dest_unlock_node(dest1);
598 return false;
599 }
600
601 ret = (dest1 == dest2);
602
603 bgp_dest_unlock_node(dest1);
604 bgp_dest_unlock_node(dest2);
605
606 return ret;
607 }
608
609 bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
610 {
611 struct bgp_dest *dest1;
612 struct bgp_dest *dest2;
613 struct prefix p;
614 int ret;
615
616 p.family = AF_INET6;
617 p.prefixlen = IPV6_MAX_BITLEN;
618 p.u.prefix6 = nexthop;
619
620 dest1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
621 if (!dest1)
622 return false;
623
624 p.family = AF_INET6;
625 p.prefixlen = IPV6_MAX_BITLEN;
626 p.u.prefix6 = peer->su.sin6.sin6_addr;
627
628 dest2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p);
629 if (!dest2) {
630 bgp_dest_unlock_node(dest1);
631 return false;
632 }
633
634 ret = (dest1 == dest2);
635
636 bgp_dest_unlock_node(dest1);
637 bgp_dest_unlock_node(dest2);
638
639 return ret;
640 }
641
642 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
643 struct update_subgroup *subgrp,
644 struct peer *exclude)
645 {
646 struct bgp_dest *dest1 = NULL, *dest2 = NULL;
647 struct peer_af *paf = NULL;
648 struct prefix p = {0}, np = {0};
649 struct bgp *bgp = NULL;
650
651 np.family = AF_INET6;
652 np.prefixlen = IPV6_MAX_BITLEN;
653 np.u.prefix6 = nexthop;
654
655 p.family = AF_INET;
656 p.prefixlen = IPV6_MAX_BITLEN;
657
658 bgp = SUBGRP_INST(subgrp);
659 dest1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np);
660 if (!dest1)
661 return false;
662
663 SUBGRP_FOREACH_PEER (subgrp, paf) {
664 /* Skip peer we're told to exclude - e.g., source of route. */
665 if (paf->peer == exclude)
666 continue;
667
668 p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
669 dest2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
670 if (dest1 == dest2) {
671 bgp_dest_unlock_node(dest1);
672 bgp_dest_unlock_node(dest2);
673 return true;
674 }
675
676 if (dest2)
677 bgp_dest_unlock_node(dest2);
678 }
679
680 bgp_dest_unlock_node(dest1);
681 return false;
682 }
683
684 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
685 struct update_subgroup *subgrp,
686 struct peer *exclude)
687 {
688 struct bgp_dest *dest1, *dest2;
689 struct peer_af *paf;
690 struct prefix p, np;
691 struct bgp *bgp;
692
693 np.family = AF_INET;
694 np.prefixlen = IPV4_MAX_BITLEN;
695 np.u.prefix4 = nexthop;
696
697 p.family = AF_INET;
698 p.prefixlen = IPV4_MAX_BITLEN;
699
700 bgp = SUBGRP_INST(subgrp);
701 dest1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
702 if (!dest1)
703 return false;
704
705 SUBGRP_FOREACH_PEER (subgrp, paf) {
706 /* Skip peer we're told to exclude - e.g., source of route. */
707 if (paf->peer == exclude)
708 continue;
709
710 p.u.prefix4 = paf->peer->su.sin.sin_addr;
711
712 dest2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
713 if (dest1 == dest2) {
714 bgp_dest_unlock_node(dest1);
715 bgp_dest_unlock_node(dest2);
716 return true;
717 }
718
719 if (dest2)
720 bgp_dest_unlock_node(dest2);
721 }
722
723 bgp_dest_unlock_node(dest1);
724 return false;
725 }
726
727 static void bgp_show_bgp_path_info_flags(uint32_t flags, json_object *json)
728 {
729 json_object *json_flags = NULL;
730
731 if (!json)
732 return;
733
734 json_flags = json_object_new_object();
735 json_object_boolean_add(json_flags, "igpChanged",
736 CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED));
737 json_object_boolean_add(json_flags, "damped",
738 CHECK_FLAG(flags, BGP_PATH_DAMPED));
739 json_object_boolean_add(json_flags, "history",
740 CHECK_FLAG(flags, BGP_PATH_HISTORY));
741 json_object_boolean_add(json_flags, "bestpath",
742 CHECK_FLAG(flags, BGP_PATH_SELECTED));
743 json_object_boolean_add(json_flags, "valid",
744 CHECK_FLAG(flags, BGP_PATH_VALID));
745 json_object_boolean_add(json_flags, "attrChanged",
746 CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED));
747 json_object_boolean_add(json_flags, "deterministicMedCheck",
748 CHECK_FLAG(flags, BGP_PATH_DMED_CHECK));
749 json_object_boolean_add(json_flags, "deterministicMedSelected",
750 CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED));
751 json_object_boolean_add(json_flags, "stale",
752 CHECK_FLAG(flags, BGP_PATH_STALE));
753 json_object_boolean_add(json_flags, "removed",
754 CHECK_FLAG(flags, BGP_PATH_REMOVED));
755 json_object_boolean_add(json_flags, "counted",
756 CHECK_FLAG(flags, BGP_PATH_COUNTED));
757 json_object_boolean_add(json_flags, "multipath",
758 CHECK_FLAG(flags, BGP_PATH_MULTIPATH));
759 json_object_boolean_add(json_flags, "multipathChanged",
760 CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG));
761 json_object_boolean_add(json_flags, "ribAttributeChanged",
762 CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG));
763 json_object_boolean_add(json_flags, "nexthopSelf",
764 CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF));
765 json_object_boolean_add(json_flags, "linkBandwidthChanged",
766 CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG));
767 json_object_boolean_add(json_flags, "acceptOwn",
768 CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN));
769 json_object_object_add(json, "flags", json_flags);
770 }
771
772 static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
773 struct bgp_nexthop_cache *bnc,
774 json_object *json)
775 {
776 struct bgp_dest *dest;
777 struct bgp_path_info *path;
778 afi_t afi;
779 safi_t safi;
780 struct bgp_table *table;
781 struct bgp *bgp_path;
782 json_object *paths = NULL;
783 json_object *json_path = NULL;
784
785 if (json)
786 paths = json_object_new_array();
787 else
788 vty_out(vty, " Paths:\n");
789 LIST_FOREACH (path, &(bnc->paths), nh_thread) {
790 dest = path->net;
791 assert(dest && bgp_dest_table(dest));
792 afi = family2afi(bgp_dest_get_prefix(dest)->family);
793 table = bgp_dest_table(dest);
794 safi = table->safi;
795 bgp_path = table->bgp;
796
797
798 if (json) {
799 json_path = json_object_new_object();
800 json_object_string_add(json_path, "afi", afi2str(afi));
801 json_object_string_add(json_path, "safi",
802 safi2str(safi));
803 json_object_string_addf(json_path, "prefix", "%pBD",
804 dest);
805 if (dest->pdest)
806 json_object_string_addf(
807 json_path, "rd",
808 BGP_RD_AS_FORMAT(bgp->asnotation),
809 (struct prefix_rd *)bgp_dest_get_prefix(
810 dest->pdest));
811 json_object_string_add(
812 json_path, "vrf",
813 vrf_id_to_name(bgp_path->vrf_id));
814 bgp_show_bgp_path_info_flags(path->flags, json_path);
815 json_object_array_add(paths, json_path);
816 continue;
817 }
818 if (dest->pdest) {
819 vty_out(vty, " %d/%d %pBD RD ", afi, safi, dest);
820 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
821 (struct prefix_rd *)bgp_dest_get_prefix(
822 dest->pdest));
823 vty_out(vty, " %s flags 0x%x\n", bgp_path->name_pretty,
824 path->flags);
825 } else
826 vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
827 afi, safi, dest, bgp_path->name_pretty, path->flags);
828 }
829 if (json)
830 json_object_object_add(json, "paths", paths);
831 }
832
833 static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
834 struct bgp_nexthop_cache *bnc,
835 json_object *json)
836 {
837 struct nexthop *nexthop;
838 json_object *json_gates = NULL;
839 json_object *json_gate = NULL;
840
841 if (json)
842 json_gates = json_object_new_array();
843 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
844 if (json) {
845 json_gate = json_object_new_object();
846 switch (nexthop->type) {
847 case NEXTHOP_TYPE_IPV6:
848 json_object_string_addf(json_gate, "ip", "%pI6",
849 &nexthop->gate.ipv6);
850 break;
851 case NEXTHOP_TYPE_IPV6_IFINDEX:
852 json_object_string_addf(json_gate, "ip", "%pI6",
853 &nexthop->gate.ipv6);
854 json_object_string_add(
855 json_gate, "interfaceName",
856 ifindex2ifname(
857 bnc->ifindex ? bnc->ifindex
858 : nexthop->ifindex,
859 bgp->vrf_id));
860 break;
861 case NEXTHOP_TYPE_IPV4:
862 json_object_string_addf(json_gate, "ip", "%pI4",
863 &nexthop->gate.ipv4);
864 break;
865 case NEXTHOP_TYPE_IFINDEX:
866 json_object_string_add(
867 json_gate, "interfaceName",
868 ifindex2ifname(
869 bnc->ifindex ? bnc->ifindex
870 : nexthop->ifindex,
871 bgp->vrf_id));
872 break;
873 case NEXTHOP_TYPE_IPV4_IFINDEX:
874 json_object_string_addf(json_gate, "ip", "%pI4",
875 &nexthop->gate.ipv4);
876 json_object_string_add(
877 json_gate, "interfaceName",
878 ifindex2ifname(
879 bnc->ifindex ? bnc->ifindex
880 : nexthop->ifindex,
881 bgp->vrf_id));
882 break;
883 case NEXTHOP_TYPE_BLACKHOLE:
884 json_object_boolean_true_add(json_gate,
885 "unreachable");
886 switch (nexthop->bh_type) {
887 case BLACKHOLE_REJECT:
888 json_object_boolean_true_add(json_gate,
889 "reject");
890 break;
891 case BLACKHOLE_ADMINPROHIB:
892 json_object_boolean_true_add(
893 json_gate, "adminProhibited");
894 break;
895 case BLACKHOLE_NULL:
896 json_object_boolean_true_add(
897 json_gate, "blackhole");
898 break;
899 case BLACKHOLE_UNSPEC:
900 break;
901 }
902 break;
903 default:
904 break;
905 }
906 json_object_array_add(json_gates, json_gate);
907 continue;
908 }
909 switch (nexthop->type) {
910 case NEXTHOP_TYPE_IPV6:
911 case NEXTHOP_TYPE_IPV6_IFINDEX:
912 vty_out(vty, " gate %pI6", &nexthop->gate.ipv6);
913 if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX &&
914 bnc->ifindex)
915 vty_out(vty, ", if %s\n",
916 ifindex2ifname(bnc->ifindex,
917 bgp->vrf_id));
918 else if (nexthop->ifindex)
919 vty_out(vty, ", if %s\n",
920 ifindex2ifname(nexthop->ifindex,
921 bgp->vrf_id));
922 else
923 vty_out(vty, "\n");
924 break;
925 case NEXTHOP_TYPE_IPV4:
926 case NEXTHOP_TYPE_IPV4_IFINDEX:
927 vty_out(vty, " gate %pI4", &nexthop->gate.ipv4);
928 if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX &&
929 bnc->ifindex)
930 vty_out(vty, ", if %s\n",
931 ifindex2ifname(bnc->ifindex,
932 bgp->vrf_id));
933 else if (nexthop->ifindex)
934 vty_out(vty, ", if %s\n",
935 ifindex2ifname(nexthop->ifindex,
936 bgp->vrf_id));
937 else
938 vty_out(vty, "\n");
939 break;
940 case NEXTHOP_TYPE_IFINDEX:
941 vty_out(vty, " if %s\n",
942 ifindex2ifname(bnc->ifindex ? bnc->ifindex
943 : nexthop->ifindex,
944 bgp->vrf_id));
945 break;
946 case NEXTHOP_TYPE_BLACKHOLE:
947 vty_out(vty, " blackhole\n");
948 break;
949 default:
950 vty_out(vty, " invalid nexthop type %u\n",
951 nexthop->type);
952 }
953 }
954 if (json)
955 json_object_object_add(json, "nexthops", json_gates);
956 }
957
958 static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
959 struct bgp_nexthop_cache *bnc, bool specific,
960 json_object *json)
961 {
962 char buf[PREFIX2STR_BUFFER];
963 time_t tbuf;
964 struct peer *peer;
965 json_object *json_last_update = NULL;
966 json_object *json_nexthop = NULL;
967
968 peer = (struct peer *)bnc->nht_info;
969
970 if (json)
971 json_nexthop = json_object_new_object();
972 if (bnc->srte_color) {
973 if (json)
974 json_object_int_add(json_nexthop, "srteColor",
975 bnc->srte_color);
976 else
977 vty_out(vty, " SR-TE color %u -", bnc->srte_color);
978 }
979 inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix, buf, sizeof(buf));
980 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
981 if (json) {
982 json_object_boolean_true_add(json_nexthop, "valid");
983 json_object_boolean_true_add(json_nexthop, "complete");
984 json_object_int_add(json_nexthop, "igpMetric",
985 bnc->metric);
986 json_object_int_add(json_nexthop, "pathCount",
987 bnc->path_count);
988 if (peer)
989 json_object_string_add(json_nexthop, "peer",
990 peer->host);
991 if (bnc->is_evpn_gwip_nexthop)
992 json_object_boolean_true_add(json_nexthop,
993 "isEvpnGatewayIp");
994 } else {
995 vty_out(vty, " %s valid [IGP metric %d], #paths %d",
996 buf, bnc->metric, bnc->path_count);
997 if (peer)
998 vty_out(vty, ", peer %s", peer->host);
999 if (bnc->is_evpn_gwip_nexthop)
1000 vty_out(vty, " EVPN Gateway IP");
1001 vty_out(vty, "\n");
1002 }
1003 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
1004 } else if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
1005 if (json) {
1006 json_object_boolean_true_add(json_nexthop, "valid");
1007 json_object_boolean_false_add(json_nexthop, "complete");
1008 json_object_int_add(json_nexthop, "igpMetric",
1009 bnc->metric);
1010 json_object_int_add(json_nexthop, "pathCount",
1011 bnc->path_count);
1012 if (bnc->is_evpn_gwip_nexthop)
1013 json_object_boolean_true_add(json_nexthop,
1014 "isEvpnGatewayIp");
1015 } else {
1016 vty_out(vty,
1017 " %s overlay index unresolved [IGP metric %d], #paths %d",
1018 buf, bnc->metric, bnc->path_count);
1019 if (bnc->is_evpn_gwip_nexthop)
1020 vty_out(vty, " EVPN Gateway IP");
1021 vty_out(vty, "\n");
1022 }
1023 bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
1024 } else {
1025 if (json) {
1026 json_object_boolean_false_add(json_nexthop, "valid");
1027 json_object_boolean_false_add(json_nexthop, "complete");
1028 json_object_int_add(json_nexthop, "pathCount",
1029 bnc->path_count);
1030 if (peer)
1031 json_object_string_add(json_nexthop, "peer",
1032 peer->host);
1033 if (bnc->is_evpn_gwip_nexthop)
1034 json_object_boolean_true_add(json_nexthop,
1035 "isEvpnGatewayIp");
1036 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
1037 json_object_boolean_false_add(json_nexthop,
1038 "isConnected");
1039 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
1040 json_object_boolean_false_add(json_nexthop,
1041 "isRegistered");
1042 } else {
1043 vty_out(vty, " %s invalid, #paths %d", buf,
1044 bnc->path_count);
1045 if (peer)
1046 vty_out(vty, ", peer %s", peer->host);
1047 if (bnc->is_evpn_gwip_nexthop)
1048 vty_out(vty, " EVPN Gateway IP");
1049 vty_out(vty, "\n");
1050 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
1051 vty_out(vty, " Must be Connected\n");
1052 if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
1053 vty_out(vty, " Is not Registered\n");
1054 }
1055 }
1056 tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
1057 if (json) {
1058 if (!specific) {
1059 json_last_update = json_object_new_object();
1060 json_object_int_add(json_last_update, "epoch", tbuf);
1061 json_object_string_add(json_last_update, "string",
1062 ctime(&tbuf));
1063 json_object_object_add(json_nexthop, "lastUpdate",
1064 json_last_update);
1065 } else {
1066 json_object_int_add(json_nexthop, "lastUpdate", tbuf);
1067 }
1068 } else {
1069 vty_out(vty, " Last update: %s", ctime(&tbuf));
1070 }
1071
1072 /* show paths dependent on nexthop, if needed. */
1073 if (specific)
1074 bgp_show_nexthop_paths(vty, bgp, bnc, json_nexthop);
1075 if (json)
1076 json_object_object_add(json, buf, json_nexthop);
1077 }
1078
1079 static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
1080 bool import_table, json_object *json, afi_t afi,
1081 bool detail)
1082 {
1083 struct bgp_nexthop_cache *bnc;
1084 struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
1085 json_object *json_afi = NULL;
1086 bool found = false;
1087
1088 if (!json) {
1089 if (import_table)
1090 vty_out(vty, "Current BGP import check cache:\n");
1091 else
1092 vty_out(vty, "Current BGP nexthop cache:\n");
1093 }
1094 if (import_table)
1095 tree = &bgp->import_check_table;
1096 else
1097 tree = &bgp->nexthop_cache_table;
1098
1099 if (afi == AFI_IP || afi == AFI_IP6) {
1100 if (json)
1101 json_afi = json_object_new_object();
1102 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc) {
1103 bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
1104 found = true;
1105 }
1106 if (found && json)
1107 json_object_object_add(
1108 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
1109 json_afi);
1110 return;
1111 }
1112
1113 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1114 if (json && (afi == AFI_IP || afi == AFI_IP6))
1115 json_afi = json_object_new_object();
1116 frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
1117 bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
1118 if (json && (afi == AFI_IP || afi == AFI_IP6))
1119 json_object_object_add(
1120 json, (afi == AFI_IP) ? "ipv4" : "ipv6",
1121 json_afi);
1122 }
1123 }
1124
1125 static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
1126 const char *nhopip_str, bool import_table,
1127 json_object *json, afi_t afi, bool detail)
1128 {
1129 struct bgp *bgp;
1130
1131 if (name && !strmatch(name, VRF_DEFAULT_NAME))
1132 bgp = bgp_lookup_by_name(name);
1133 else
1134 bgp = bgp_get_default();
1135 if (!bgp) {
1136 if (!json)
1137 vty_out(vty, "%% No such BGP instance exist\n");
1138 return CMD_WARNING;
1139 }
1140
1141 if (nhopip_str) {
1142 struct prefix nhop;
1143 struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
1144 struct bgp_nexthop_cache *bnc;
1145 bool found = false;
1146 json_object *json_afi = NULL;
1147
1148 if (!str2prefix(nhopip_str, &nhop)) {
1149 if (!json)
1150 vty_out(vty, "nexthop address is malformed\n");
1151 return CMD_WARNING;
1152 }
1153 tree = import_table ? &bgp->import_check_table
1154 : &bgp->nexthop_cache_table;
1155 if (json)
1156 json_afi = json_object_new_object();
1157 frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
1158 bnc) {
1159 if (prefix_cmp(&bnc->prefix, &nhop))
1160 continue;
1161 bgp_show_nexthop(vty, bgp, bnc, true, json_afi);
1162 found = true;
1163 }
1164 if (json)
1165 json_object_object_add(
1166 json,
1167 (family2afi(nhop.family) == AFI_IP) ? "ipv4"
1168 : "ipv6",
1169 json_afi);
1170 if (!found && !json)
1171 vty_out(vty, "nexthop %s does not have entry\n",
1172 nhopip_str);
1173 } else
1174 bgp_show_nexthops(vty, bgp, import_table, json, afi, detail);
1175
1176 return CMD_SUCCESS;
1177 }
1178
1179 static void bgp_show_all_instances_nexthops_vty(struct vty *vty,
1180 json_object *json, afi_t afi,
1181 bool detail)
1182 {
1183 struct listnode *node, *nnode;
1184 struct bgp *bgp;
1185 const char *inst_name;
1186 json_object *json_instance = NULL;
1187
1188 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
1189 inst_name = (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
1190 ? VRF_DEFAULT_NAME
1191 : bgp->name;
1192 if (json)
1193 json_instance = json_object_new_object();
1194 else
1195 vty_out(vty, "\nInstance %s:\n", inst_name);
1196
1197 bgp_show_nexthops(vty, bgp, false, json_instance, afi, detail);
1198
1199 if (json)
1200 json_object_object_add(json, inst_name, json_instance);
1201 }
1202 }
1203
1204 #include "bgpd/bgp_nexthop_clippy.c"
1205
1206 DEFPY (show_ip_bgp_nexthop,
1207 show_ip_bgp_nexthop_cmd,
1208 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] nexthop [<A.B.C.D|X:X::X:X>$nhop] [<ipv4$afi [A.B.C.D$nhop]|ipv6$afi [X:X::X:X$nhop]>] [detail$detail] [json$uj]",
1209 SHOW_STR
1210 IP_STR
1211 BGP_STR
1212 BGP_INSTANCE_HELP_STR
1213 "BGP nexthop table\n"
1214 "IPv4 nexthop address\n"
1215 "IPv6 nexthop address\n"
1216 "BGP nexthop IPv4 table\n"
1217 "IPv4 nexthop address\n"
1218 "BGP nexthop IPv6 table\n"
1219 "IPv6 nexthop address\n"
1220 "Show detailed information\n"
1221 JSON_STR)
1222 {
1223 int rc = 0;
1224 json_object *json = NULL;
1225 afi_t afiz = AFI_UNSPEC;
1226
1227 if (uj)
1228 json = json_object_new_object();
1229
1230 if (afi)
1231 afiz = bgp_vty_afi_from_str(afi);
1232
1233 rc = show_ip_bgp_nexthop_table(vty, vrf, nhop_str, false, json, afiz,
1234 detail);
1235
1236 if (uj)
1237 vty_json(vty, json);
1238
1239 return rc;
1240 }
1241
1242 DEFPY (show_ip_bgp_import_check,
1243 show_ip_bgp_import_check_cmd,
1244 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1245 SHOW_STR
1246 IP_STR
1247 BGP_STR
1248 BGP_INSTANCE_HELP_STR
1249 "BGP import check table\n"
1250 "Show detailed information\n"
1251 JSON_STR)
1252 {
1253 int rc = 0;
1254 json_object *json = NULL;
1255
1256 if (uj)
1257 json = json_object_new_object();
1258
1259 rc = show_ip_bgp_nexthop_table(vty, vrf, NULL, true, json, AFI_UNSPEC,
1260 detail);
1261
1262 if (uj)
1263 vty_json(vty, json);
1264
1265 return rc;
1266 }
1267
1268 DEFPY (show_ip_bgp_instance_all_nexthop,
1269 show_ip_bgp_instance_all_nexthop_cmd,
1270 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1271 SHOW_STR
1272 IP_STR
1273 BGP_STR
1274 BGP_INSTANCE_ALL_HELP_STR
1275 "BGP nexthop table\n"
1276 "BGP IPv4 nexthop table\n"
1277 "BGP IPv6 nexthop table\n"
1278 "Show detailed information\n"
1279 JSON_STR)
1280 {
1281 json_object *json = NULL;
1282 afi_t afiz = AFI_UNSPEC;
1283
1284 if (uj)
1285 json = json_object_new_object();
1286
1287 if (afi)
1288 afiz = bgp_vty_afi_from_str(afi);
1289
1290 bgp_show_all_instances_nexthops_vty(vty, json, afiz, detail);
1291
1292 if (uj)
1293 vty_json(vty, json);
1294
1295 return CMD_SUCCESS;
1296 }
1297
1298 void bgp_scan_init(struct bgp *bgp)
1299 {
1300 afi_t afi;
1301
1302 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1303 bgp_nexthop_cache_init(&bgp->nexthop_cache_table[afi]);
1304 bgp_nexthop_cache_init(&bgp->import_check_table[afi]);
1305 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
1306 SAFI_UNICAST);
1307 }
1308 }
1309
1310 void bgp_scan_vty_init(void)
1311 {
1312 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
1313 install_element(VIEW_NODE, &show_ip_bgp_import_check_cmd);
1314 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
1315 }
1316
1317 void bgp_scan_finish(struct bgp *bgp)
1318 {
1319 afi_t afi;
1320
1321 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
1322 /* Only the current one needs to be reset. */
1323 bgp_nexthop_cache_reset(&bgp->nexthop_cache_table[afi]);
1324 bgp_nexthop_cache_reset(&bgp->import_check_table[afi]);
1325
1326 bgp->connected_table[afi]->route_table->cleanup =
1327 bgp_connected_cleanup;
1328 bgp_table_unlock(bgp->connected_table[afi]);
1329 bgp->connected_table[afi] = NULL;
1330 }
1331 }
1332
1333 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache *bnc, char *buf,
1334 size_t len)
1335 {
1336 if (bnc->flags == 0) {
1337 snprintfrr(buf, len, "None ");
1338 return buf;
1339 }
1340
1341 snprintfrr(buf, len, "%s%s%s%s%s%s%s",
1342 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) ? "Valid " : "",
1343 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED) ? "Reg " : "",
1344 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED) ? "Conn " : "",
1345 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED) ? "Notify "
1346 : "",
1347 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE) ? "Static " : "",
1348 CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)
1349 ? "Static Exact "
1350 : "",
1351 CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
1352 ? "Label Valid "
1353 : "");
1354
1355 return buf;
1356 }
1357
1358 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
1359 char *buf, size_t len)
1360 {
1361 if (bnc->flags == 0) {
1362 snprintfrr(buf, len, "None ");
1363 return buf;
1364 }
1365
1366 snprintfrr(buf, len, "%s%s%s",
1367 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
1368 ? "Changed "
1369 : "",
1370 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
1371 ? "Metric "
1372 : "",
1373 CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
1374 ? "Connected "
1375 : "");
1376
1377 return buf;
1378 }