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