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