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