1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2000 Kunihiro Ishiguro
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"
35 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Addr Intf String");
37 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache
*a
,
38 const struct bgp_nexthop_cache
*b
)
40 if (a
->srte_color
< b
->srte_color
)
42 if (a
->srte_color
> b
->srte_color
)
45 if (a
->ifindex
< b
->ifindex
)
47 if (a
->ifindex
> b
->ifindex
)
50 return prefix_cmp(&a
->prefix
, &b
->prefix
);
53 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
55 nexthops_free(bnc
->nexthop
);
58 struct bgp_nexthop_cache
*bnc_new(struct bgp_nexthop_cache_head
*tree
,
59 struct prefix
*prefix
, uint32_t srte_color
,
62 struct bgp_nexthop_cache
*bnc
;
64 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
65 sizeof(struct bgp_nexthop_cache
));
66 bnc
->prefix
= *prefix
;
67 bnc
->ifindex
= ifindex
;
68 bnc
->srte_color
= srte_color
;
70 LIST_INIT(&(bnc
->paths
));
71 bgp_nexthop_cache_add(tree
, bnc
);
76 bool bnc_existing_for_prefix(struct bgp_nexthop_cache
*bnc
)
78 struct bgp_nexthop_cache
*bnc_tmp
;
80 frr_each (bgp_nexthop_cache
, bnc
->tree
, bnc_tmp
) {
83 if (prefix_cmp(&bnc
->prefix
, &bnc_tmp
->prefix
) == 0)
89 void bnc_free(struct bgp_nexthop_cache
*bnc
)
91 bnc_nexthop_free(bnc
);
92 bgp_nexthop_cache_del(bnc
->tree
, bnc
);
93 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
96 struct bgp_nexthop_cache
*bnc_find(struct bgp_nexthop_cache_head
*tree
,
97 struct prefix
*prefix
, uint32_t srte_color
,
100 struct bgp_nexthop_cache bnc
= {};
105 bnc
.prefix
= *prefix
;
106 bnc
.srte_color
= srte_color
;
107 bnc
.ifindex
= ifindex
;
108 return bgp_nexthop_cache_find(tree
, &bnc
);
111 /* Reset and free all BGP nexthop cache. */
112 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head
*tree
)
114 struct bgp_nexthop_cache
*bnc
;
116 while (bgp_nexthop_cache_count(tree
) > 0) {
117 bnc
= bgp_nexthop_cache_first(tree
);
119 while (!LIST_EMPTY(&(bnc
->paths
))) {
120 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
122 path_nh_map(path
, bnc
, false);
129 static void *bgp_tip_hash_alloc(void *p
)
131 const struct in_addr
*val
= (const struct in_addr
*)p
;
132 struct tip_addr
*addr
;
134 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
136 addr
->addr
.s_addr
= val
->s_addr
;
141 static void bgp_tip_hash_free(void *addr
)
143 XFREE(MTYPE_TIP_ADDR
, addr
);
146 static unsigned int bgp_tip_hash_key_make(const void *p
)
148 const struct tip_addr
*addr
= p
;
150 return jhash_1word(addr
->addr
.s_addr
, 0);
153 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
155 const struct tip_addr
*addr1
= p1
;
156 const struct tip_addr
*addr2
= p2
;
158 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
161 void bgp_tip_hash_init(struct bgp
*bgp
)
163 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
167 void bgp_tip_hash_destroy(struct bgp
*bgp
)
169 if (bgp
->tip_hash
== NULL
)
171 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
172 hash_free(bgp
->tip_hash
);
173 bgp
->tip_hash
= NULL
;
176 /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
178 * Returns true only if we add a _new_ TIP so the caller knows that an
179 * actionable change has occurred. If we find an existing TIP then we
180 * only need to update the refcnt, since the collection of known TIPs
183 bool bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
186 struct tip_addr
*addr
;
187 bool tip_added
= false;
191 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
193 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
202 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
205 struct tip_addr
*addr
;
209 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
210 /* may have been deleted earlier by bgp_interface_down() */
216 if (addr
->refcnt
== 0) {
217 hash_release(bgp
->tip_hash
, addr
);
218 XFREE(MTYPE_TIP_ADDR
, addr
);
222 /* BGP own address structure */
225 struct list
*ifp_name_list
;
228 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
230 struct vty
*vty
= (struct vty
*)args
;
231 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
233 struct listnode
*node
;
234 char str
[INET6_ADDRSTRLEN
] = {0};
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
);
241 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
242 vty_out(vty
, " %s,", name
);
248 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
250 hash_iterate(bgp
->address_hash
,
251 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
255 static void bgp_address_hash_string_del(void *val
)
259 XFREE(MTYPE_MARTIAN_STRING
, data
);
262 static void *bgp_address_hash_alloc(void *p
)
264 struct bgp_addr
*copy_addr
= p
;
265 struct bgp_addr
*addr
= NULL
;
267 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
268 prefix_copy(&addr
->p
, ©_addr
->p
);
270 addr
->ifp_name_list
= list_new();
271 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
276 static void bgp_address_hash_free(void *data
)
278 struct bgp_addr
*addr
= data
;
280 list_delete(&addr
->ifp_name_list
);
281 XFREE(MTYPE_BGP_ADDR
, addr
);
284 static unsigned int bgp_address_hash_key_make(const void *p
)
286 const struct bgp_addr
*addr
= p
;
288 return prefix_hash_key(&addr
->p
);
291 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
293 const struct bgp_addr
*addr1
= p1
;
294 const struct bgp_addr
*addr2
= p2
;
296 return prefix_same(&addr1
->p
, &addr2
->p
);
299 void bgp_address_init(struct bgp
*bgp
)
302 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
303 "BGP Connected Address Hash");
306 void bgp_address_destroy(struct bgp
*bgp
)
308 if (bgp
->address_hash
== NULL
)
310 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
311 hash_free(bgp
->address_hash
);
312 bgp
->address_hash
= NULL
;
315 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
319 struct bgp_addr
*addr
;
320 struct listnode
*node
;
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
;
330 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
332 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
333 if (strcmp(ifc
->ifp
->name
, name
) == 0)
337 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
338 listnode_add(addr
->ifp_name_list
, name
);
342 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
346 struct bgp_addr
*addr
;
347 struct listnode
*node
;
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
;
357 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
358 /* may have been deleted earlier by bgp_interface_down() */
362 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
363 if (strcmp(ifc
->ifp
->name
, name
) == 0)
368 list_delete_node(addr
->ifp_name_list
, node
);
369 XFREE(MTYPE_MARTIAN_STRING
, name
);
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
);
380 struct bgp_connected_ref
{
384 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
388 struct bgp_dest
*dest
;
389 struct bgp_connected_ref
*bc
;
390 struct listnode
*node
, *nnode
;
395 p
= *(CONNECTED_PREFIX(ifc
));
396 if (addr
->family
== AF_INET
) {
397 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
399 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
402 bgp_address_add(bgp
, ifc
, addr
);
404 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP
], &p
);
405 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
409 bc
= XCALLOC(MTYPE_BGP_CONN
,
410 sizeof(struct bgp_connected_ref
));
412 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
415 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
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
);
426 } else if (addr
->family
== AF_INET6
) {
427 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
429 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
432 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
435 bgp_address_add(bgp
, ifc
, addr
);
437 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP6
], &p
);
439 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
443 bc
= XCALLOC(MTYPE_BGP_CONN
,
444 sizeof(struct bgp_connected_ref
));
446 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
451 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
455 struct bgp_dest
*dest
= NULL
;
456 struct bgp_connected_ref
*bc
;
460 p
= *(CONNECTED_PREFIX(ifc
));
462 if (addr
->family
== AF_INET
) {
463 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
466 bgp_address_del(bgp
, ifc
, addr
);
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
))
473 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
476 bgp_address_del(bgp
, ifc
, addr
);
478 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
484 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
486 if (bc
->refcnt
== 0) {
487 XFREE(MTYPE_BGP_CONN
, bc
);
488 bgp_dest_set_bgp_connected_ref_info(dest
, NULL
);
490 bgp_dest_unlock_node(dest
);
491 bgp_dest_unlock_node(dest
);
494 static void bgp_connected_cleanup(struct route_table
*table
,
495 struct route_node
*rn
)
497 struct bgp_connected_ref
*bc
;
498 struct bgp_dest
*bn
= bgp_dest_from_rnode(rn
);
500 bc
= bgp_dest_get_bgp_connected_ref_info(bn
);
504 XFREE(MTYPE_BGP_CONN
, bc
);
505 bgp_dest_set_bgp_connected_ref_info(bn
, NULL
);
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
)
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
))
521 if (!is_bgp_static_route
)
522 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
524 tmp_addr
.p
.family
= new_afi
;
527 if (is_bgp_static_route
) {
528 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
529 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
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
;
548 if (is_bgp_static_route
) {
549 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
550 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
552 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
553 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
560 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
564 if (new_afi
== AF_INET
&& hashcount(bgp
->tip_hash
)) {
565 memset(&tmp_tip
, 0, sizeof(tmp_tip
));
566 tmp_tip
.addr
= attr
->nexthop
;
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
;
576 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
584 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
586 struct bgp_dest
*dest1
;
587 struct bgp_dest
*dest2
;
592 p
.prefixlen
= IPV4_MAX_BITLEN
;
593 p
.u
.prefix4
= nexthop
;
595 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
600 p
.prefixlen
= IPV4_MAX_BITLEN
;
601 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
603 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
605 bgp_dest_unlock_node(dest1
);
609 ret
= (dest1
== dest2
);
611 bgp_dest_unlock_node(dest1
);
612 bgp_dest_unlock_node(dest2
);
617 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
619 struct bgp_dest
*dest1
;
620 struct bgp_dest
*dest2
;
625 p
.prefixlen
= IPV6_MAX_BITLEN
;
626 p
.u
.prefix6
= nexthop
;
628 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
633 p
.prefixlen
= IPV6_MAX_BITLEN
;
634 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
636 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
638 bgp_dest_unlock_node(dest1
);
642 ret
= (dest1
== dest2
);
644 bgp_dest_unlock_node(dest1
);
645 bgp_dest_unlock_node(dest2
);
650 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
651 struct update_subgroup
*subgrp
,
652 struct peer
*exclude
)
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
;
659 np
.family
= AF_INET6
;
660 np
.prefixlen
= IPV6_MAX_BITLEN
;
661 np
.u
.prefix6
= nexthop
;
664 p
.prefixlen
= IPV6_MAX_BITLEN
;
666 bgp
= SUBGRP_INST(subgrp
);
667 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
671 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
672 /* Skip peer we're told to exclude - e.g., source of route. */
673 if (paf
->peer
== exclude
)
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
);
685 bgp_dest_unlock_node(dest2
);
688 bgp_dest_unlock_node(dest1
);
692 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
693 struct update_subgroup
*subgrp
,
694 struct peer
*exclude
)
696 struct bgp_dest
*dest1
, *dest2
;
702 np
.prefixlen
= IPV4_MAX_BITLEN
;
703 np
.u
.prefix4
= nexthop
;
706 p
.prefixlen
= IPV4_MAX_BITLEN
;
708 bgp
= SUBGRP_INST(subgrp
);
709 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
713 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
714 /* Skip peer we're told to exclude - e.g., source of route. */
715 if (paf
->peer
== exclude
)
718 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
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
);
728 bgp_dest_unlock_node(dest2
);
731 bgp_dest_unlock_node(dest1
);
735 static void bgp_show_bgp_path_info_flags(uint32_t flags
, json_object
*json
)
737 json_object
*json_flags
= NULL
;
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
);
780 static void bgp_show_nexthop_paths(struct vty
*vty
, struct bgp
*bgp
,
781 struct bgp_nexthop_cache
*bnc
,
784 struct bgp_dest
*dest
;
785 struct bgp_path_info
*path
;
788 struct bgp_table
*table
;
789 struct bgp
*bgp_path
;
790 json_object
*paths
= NULL
;
791 json_object
*json_path
= NULL
;
794 paths
= json_object_new_array();
796 vty_out(vty
, " Paths:\n");
797 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
799 assert(dest
&& bgp_dest_table(dest
));
800 afi
= family2afi(bgp_dest_get_prefix(dest
)->family
);
801 table
= bgp_dest_table(dest
);
803 bgp_path
= table
->bgp
;
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",
810 json_object_string_addf(json_path
, "prefix", "%pBD",
813 json_object_string_addf(
814 json_path
, "rd", "%pRD",
815 (struct prefix_rd
*)bgp_dest_get_prefix(
817 json_object_string_add(
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
);
825 vty_out(vty
, " %d/%d %pBD RD %pRD %s flags 0x%x\n",
827 (struct prefix_rd
*)bgp_dest_get_prefix(
829 bgp_path
->name_pretty
, path
->flags
);
831 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
832 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
835 json_object_object_add(json
, "paths", paths
);
838 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
839 struct bgp_nexthop_cache
*bnc
,
842 struct nexthop
*nexthop
;
843 json_object
*json_gates
= NULL
;
844 json_object
*json_gate
= NULL
;
847 json_gates
= json_object_new_array();
848 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
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
);
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",
862 bnc
->ifindex
? bnc
->ifindex
866 case NEXTHOP_TYPE_IPV4
:
867 json_object_string_addf(json_gate
, "ip", "%pI4",
868 &nexthop
->gate
.ipv4
);
870 case NEXTHOP_TYPE_IFINDEX
:
871 json_object_string_add(
872 json_gate
, "interfaceName",
874 bnc
->ifindex
? bnc
->ifindex
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",
884 bnc
->ifindex
? bnc
->ifindex
888 case NEXTHOP_TYPE_BLACKHOLE
:
889 json_object_boolean_true_add(json_gate
,
891 switch (nexthop
->bh_type
) {
892 case BLACKHOLE_REJECT
:
893 json_object_boolean_true_add(json_gate
,
896 case BLACKHOLE_ADMINPROHIB
:
897 json_object_boolean_true_add(
898 json_gate
, "adminProhibited");
901 json_object_boolean_true_add(
902 json_gate
, "blackhole");
904 case BLACKHOLE_UNSPEC
:
911 json_object_array_add(json_gates
, json_gate
);
914 switch (nexthop
->type
) {
915 case NEXTHOP_TYPE_IPV6
:
916 vty_out(vty
, " gate %pI6\n", &nexthop
->gate
.ipv6
);
918 case NEXTHOP_TYPE_IPV6_IFINDEX
:
919 vty_out(vty
, " gate %pI6, if %s\n",
921 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
925 case NEXTHOP_TYPE_IPV4
:
926 vty_out(vty
, " gate %pI4\n", &nexthop
->gate
.ipv4
);
928 case NEXTHOP_TYPE_IFINDEX
:
929 vty_out(vty
, " if %s\n",
930 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
934 case NEXTHOP_TYPE_IPV4_IFINDEX
:
935 vty_out(vty
, " gate %pI4, if %s\n",
937 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
941 case NEXTHOP_TYPE_BLACKHOLE
:
942 vty_out(vty
, " blackhole\n");
945 vty_out(vty
, " invalid nexthop type %u\n",
950 json_object_object_add(json
, "nexthops", json_gates
);
953 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
954 struct bgp_nexthop_cache
*bnc
, bool specific
,
957 char buf
[PREFIX2STR_BUFFER
];
960 json_object
*json_last_update
= NULL
;
961 json_object
*json_nexthop
= NULL
;
963 peer
= (struct peer
*)bnc
->nht_info
;
966 json_nexthop
= json_object_new_object();
967 if (bnc
->srte_color
) {
969 json_object_int_add(json_nexthop
, "srteColor",
972 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
974 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
975 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
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",
981 json_object_int_add(json_nexthop
, "pathCount",
984 json_object_string_add(json_nexthop
, "peer",
986 if (bnc
->is_evpn_gwip_nexthop
)
987 json_object_boolean_true_add(json_nexthop
,
990 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
991 buf
, bnc
->metric
, bnc
->path_count
);
993 vty_out(vty
, ", peer %s", peer
->host
);
994 if (bnc
->is_evpn_gwip_nexthop
)
995 vty_out(vty
, " EVPN Gateway IP");
998 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
999 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
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",
1005 json_object_int_add(json_nexthop
, "pathCount",
1007 if (bnc
->is_evpn_gwip_nexthop
)
1008 json_object_boolean_true_add(json_nexthop
,
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");
1018 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
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",
1026 json_object_string_add(json_nexthop
, "peer",
1028 if (bnc
->is_evpn_gwip_nexthop
)
1029 json_object_boolean_true_add(json_nexthop
,
1031 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1032 json_object_boolean_false_add(json_nexthop
,
1034 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1035 json_object_boolean_false_add(json_nexthop
,
1038 vty_out(vty
, " %s invalid, #paths %d", buf
,
1041 vty_out(vty
, ", peer %s", peer
->host
);
1042 if (bnc
->is_evpn_gwip_nexthop
)
1043 vty_out(vty
, " EVPN Gateway IP");
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");
1051 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
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",
1058 json_object_object_add(json_nexthop
, "lastUpdate",
1061 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1064 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1067 /* show paths dependent on nexthop, if needed. */
1069 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1071 json_object_object_add(json
, buf
, json_nexthop
);
1074 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1075 bool import_table
, json_object
*json
, afi_t afi
,
1078 struct bgp_nexthop_cache
*bnc
;
1079 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1080 json_object
*json_afi
= NULL
;
1085 vty_out(vty
, "Current BGP import check cache:\n");
1087 vty_out(vty
, "Current BGP nexthop cache:\n");
1090 tree
= &bgp
->import_check_table
;
1092 tree
= &bgp
->nexthop_cache_table
;
1094 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
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
);
1102 json_object_object_add(
1103 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
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",
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
)
1126 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1127 bgp
= bgp_lookup_by_name(name
);
1129 bgp
= bgp_get_default();
1132 vty_out(vty
, "%% No such BGP instance exist\n");
1138 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1139 struct bgp_nexthop_cache
*bnc
;
1141 json_object
*json_afi
= NULL
;
1143 if (!str2prefix(nhopip_str
, &nhop
)) {
1145 vty_out(vty
, "nexthop address is malformed\n");
1148 tree
= import_table
? &bgp
->import_check_table
1149 : &bgp
->nexthop_cache_table
;
1151 json_afi
= json_object_new_object();
1152 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1154 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1156 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1160 json_object_object_add(
1162 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1165 if (!found
&& !json
)
1166 vty_out(vty
, "nexthop %s does not have entry\n",
1169 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1174 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1175 json_object
*json
, afi_t afi
,
1178 struct listnode
*node
, *nnode
;
1180 const char *inst_name
;
1181 json_object
*json_instance
= NULL
;
1183 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1184 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1188 json_instance
= json_object_new_object();
1190 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1192 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1195 json_object_object_add(json
, inst_name
, json_instance
);
1199 #include "bgpd/bgp_nexthop_clippy.c"
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]",
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"
1219 json_object
*json
= NULL
;
1220 afi_t afiz
= AFI_UNSPEC
;
1223 json
= json_object_new_object();
1226 afiz
= bgp_vty_afi_from_str(afi
);
1228 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1232 vty_json(vty
, json
);
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]",
1243 BGP_INSTANCE_HELP_STR
1244 "BGP import check table\n"
1245 "Show detailed information\n"
1249 json_object
*json
= NULL
;
1252 json
= json_object_new_object();
1254 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1258 vty_json(vty
, json
);
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]",
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"
1276 json_object
*json
= NULL
;
1277 afi_t afiz
= AFI_UNSPEC
;
1280 json
= json_object_new_object();
1283 afiz
= bgp_vty_afi_from_str(afi
);
1285 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1288 vty_json(vty
, json
);
1293 void bgp_scan_init(struct bgp
*bgp
)
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
,
1305 void bgp_scan_vty_init(void)
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
);
1312 void bgp_scan_finish(struct bgp
*bgp
)
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
]);
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
;
1328 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1331 if (bnc
->flags
== 0) {
1332 snprintfrr(buf
, len
, "None ");
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 "
1342 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1343 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1346 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1353 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1354 char *buf
, size_t len
)
1356 if (bnc
->flags
== 0) {
1357 snprintfrr(buf
, len
, "None ");
1361 snprintfrr(buf
, len
, "%s%s%s",
1362 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1365 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1368 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)