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"
34 #include "bgpd/bgp_mplsvpn.h"
36 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Addr Intf String");
38 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache
*a
,
39 const struct bgp_nexthop_cache
*b
)
41 if (a
->srte_color
< b
->srte_color
)
43 if (a
->srte_color
> b
->srte_color
)
46 if (a
->ifindex
< b
->ifindex
)
48 if (a
->ifindex
> b
->ifindex
)
51 return prefix_cmp(&a
->prefix
, &b
->prefix
);
54 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
56 nexthops_free(bnc
->nexthop
);
59 struct bgp_nexthop_cache
*bnc_new(struct bgp_nexthop_cache_head
*tree
,
60 struct prefix
*prefix
, uint32_t srte_color
,
63 struct bgp_nexthop_cache
*bnc
;
65 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
66 sizeof(struct bgp_nexthop_cache
));
67 bnc
->prefix
= *prefix
;
68 bnc
->ifindex
= ifindex
;
69 bnc
->srte_color
= srte_color
;
71 LIST_INIT(&(bnc
->paths
));
72 bgp_nexthop_cache_add(tree
, bnc
);
77 bool bnc_existing_for_prefix(struct bgp_nexthop_cache
*bnc
)
79 struct bgp_nexthop_cache
*bnc_tmp
;
81 frr_each (bgp_nexthop_cache
, bnc
->tree
, bnc_tmp
) {
84 if (prefix_cmp(&bnc
->prefix
, &bnc_tmp
->prefix
) == 0)
90 void bnc_free(struct bgp_nexthop_cache
*bnc
)
92 bnc_nexthop_free(bnc
);
93 bgp_nexthop_cache_del(bnc
->tree
, bnc
);
94 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
97 struct bgp_nexthop_cache
*bnc_find(struct bgp_nexthop_cache_head
*tree
,
98 struct prefix
*prefix
, uint32_t srte_color
,
101 struct bgp_nexthop_cache bnc
= {};
106 bnc
.prefix
= *prefix
;
107 bnc
.srte_color
= srte_color
;
108 bnc
.ifindex
= ifindex
;
109 return bgp_nexthop_cache_find(tree
, &bnc
);
112 /* Reset and free all BGP nexthop cache. */
113 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head
*tree
)
115 struct bgp_nexthop_cache
*bnc
;
117 while (bgp_nexthop_cache_count(tree
) > 0) {
118 bnc
= bgp_nexthop_cache_first(tree
);
120 while (!LIST_EMPTY(&(bnc
->paths
))) {
121 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
123 bgp_mplsvpn_path_nh_label_unlink(path
);
125 path_nh_map(path
, bnc
, false);
132 static void *bgp_tip_hash_alloc(void *p
)
134 const struct in_addr
*val
= (const struct in_addr
*)p
;
135 struct tip_addr
*addr
;
137 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
139 addr
->addr
.s_addr
= val
->s_addr
;
144 static void bgp_tip_hash_free(void *addr
)
146 XFREE(MTYPE_TIP_ADDR
, addr
);
149 static unsigned int bgp_tip_hash_key_make(const void *p
)
151 const struct tip_addr
*addr
= p
;
153 return jhash_1word(addr
->addr
.s_addr
, 0);
156 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
158 const struct tip_addr
*addr1
= p1
;
159 const struct tip_addr
*addr2
= p2
;
161 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
164 void bgp_tip_hash_init(struct bgp
*bgp
)
166 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
170 void bgp_tip_hash_destroy(struct bgp
*bgp
)
172 hash_clean_and_free(&bgp
->tip_hash
, bgp_tip_hash_free
);
175 /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
177 * Returns true only if we add a _new_ TIP so the caller knows that an
178 * actionable change has occurred. If we find an existing TIP then we
179 * only need to update the refcnt, since the collection of known TIPs
182 bool bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
185 struct tip_addr
*addr
;
186 bool tip_added
= false;
190 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
192 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
201 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
204 struct tip_addr
*addr
;
208 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
209 /* may have been deleted earlier by bgp_interface_down() */
215 if (addr
->refcnt
== 0) {
216 hash_release(bgp
->tip_hash
, addr
);
217 XFREE(MTYPE_TIP_ADDR
, addr
);
221 /* BGP own address structure */
224 struct list
*ifp_name_list
;
227 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
229 struct vty
*vty
= (struct vty
*)args
;
230 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
232 struct listnode
*node
;
233 char str
[INET6_ADDRSTRLEN
] = {0};
235 vty_out(vty
, "addr: %s, count: %d : ",
236 inet_ntop(addr
->p
.family
, &(addr
->p
.u
.prefix
),
237 str
, INET6_ADDRSTRLEN
),
238 addr
->ifp_name_list
->count
);
240 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
241 vty_out(vty
, " %s,", name
);
247 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
249 hash_iterate(bgp
->address_hash
,
250 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
254 static void bgp_address_hash_string_del(void *val
)
258 XFREE(MTYPE_MARTIAN_STRING
, data
);
261 static void *bgp_address_hash_alloc(void *p
)
263 struct bgp_addr
*copy_addr
= p
;
264 struct bgp_addr
*addr
= NULL
;
266 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
267 prefix_copy(&addr
->p
, ©_addr
->p
);
269 addr
->ifp_name_list
= list_new();
270 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
275 static void bgp_address_hash_free(void *data
)
277 struct bgp_addr
*addr
= data
;
279 list_delete(&addr
->ifp_name_list
);
280 XFREE(MTYPE_BGP_ADDR
, addr
);
283 static unsigned int bgp_address_hash_key_make(const void *p
)
285 const struct bgp_addr
*addr
= p
;
287 return prefix_hash_key(&addr
->p
);
290 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
292 const struct bgp_addr
*addr1
= p1
;
293 const struct bgp_addr
*addr2
= p2
;
295 return prefix_same(&addr1
->p
, &addr2
->p
);
298 void bgp_address_init(struct bgp
*bgp
)
301 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
302 "BGP Connected Address Hash");
305 void bgp_address_destroy(struct bgp
*bgp
)
307 hash_clean_and_free(&bgp
->address_hash
, bgp_address_hash_free
);
310 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
314 struct bgp_addr
*addr
;
315 struct listnode
*node
;
320 if (tmp
.p
.family
== AF_INET
)
321 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
322 else if (tmp
.p
.family
== AF_INET6
)
323 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
325 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
327 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
328 if (strcmp(ifc
->ifp
->name
, name
) == 0)
332 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
333 listnode_add(addr
->ifp_name_list
, name
);
337 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
341 struct bgp_addr
*addr
;
342 struct listnode
*node
;
347 if (tmp
.p
.family
== AF_INET
)
348 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
349 else if (tmp
.p
.family
== AF_INET6
)
350 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
352 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
353 /* may have been deleted earlier by bgp_interface_down() */
357 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
358 if (strcmp(ifc
->ifp
->name
, name
) == 0)
363 list_delete_node(addr
->ifp_name_list
, node
);
364 XFREE(MTYPE_MARTIAN_STRING
, name
);
367 if (addr
->ifp_name_list
->count
== 0) {
368 hash_release(bgp
->address_hash
, addr
);
369 list_delete(&addr
->ifp_name_list
);
370 XFREE(MTYPE_BGP_ADDR
, addr
);
375 struct bgp_connected_ref
{
379 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
383 struct bgp_dest
*dest
;
384 struct bgp_connected_ref
*bc
;
385 struct listnode
*node
, *nnode
;
390 p
= *(CONNECTED_PREFIX(ifc
));
391 if (addr
->family
== AF_INET
) {
392 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
394 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
397 bgp_address_add(bgp
, ifc
, addr
);
399 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP
], &p
);
400 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
404 bc
= XCALLOC(MTYPE_BGP_CONN
,
405 sizeof(struct bgp_connected_ref
));
407 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
410 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
412 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
413 && !peer_established(peer
)
414 && !CHECK_FLAG(peer
->flags
,
415 PEER_FLAG_IFPEER_V6ONLY
)) {
416 if (peer_active(peer
))
417 BGP_EVENT_ADD(peer
, BGP_Stop
);
418 BGP_EVENT_ADD(peer
, BGP_Start
);
421 } else if (addr
->family
== AF_INET6
) {
422 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
424 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
427 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
430 bgp_address_add(bgp
, ifc
, addr
);
432 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP6
], &p
);
434 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
438 bc
= XCALLOC(MTYPE_BGP_CONN
,
439 sizeof(struct bgp_connected_ref
));
441 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
446 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
450 struct bgp_dest
*dest
= NULL
;
451 struct bgp_connected_ref
*bc
;
455 p
= *(CONNECTED_PREFIX(ifc
));
457 if (addr
->family
== AF_INET
) {
458 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
461 bgp_address_del(bgp
, ifc
, addr
);
463 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
464 } else if (addr
->family
== AF_INET6
) {
465 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
468 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
471 bgp_address_del(bgp
, ifc
, addr
);
473 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
479 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
481 if (bc
->refcnt
== 0) {
482 XFREE(MTYPE_BGP_CONN
, bc
);
483 bgp_dest_set_bgp_connected_ref_info(dest
, NULL
);
485 bgp_dest_unlock_node(dest
);
486 bgp_dest_unlock_node(dest
);
489 static void bgp_connected_cleanup(struct route_table
*table
,
490 struct route_node
*rn
)
492 struct bgp_connected_ref
*bc
;
493 struct bgp_dest
*bn
= bgp_dest_from_rnode(rn
);
495 bc
= bgp_dest_get_bgp_connected_ref_info(bn
);
499 XFREE(MTYPE_BGP_CONN
, bc
);
500 bgp_dest_set_bgp_connected_ref_info(bn
, NULL
);
503 bool bgp_nexthop_self(struct bgp
*bgp
, afi_t afi
, uint8_t type
,
504 uint8_t sub_type
, struct attr
*attr
,
505 struct bgp_dest
*dest
)
507 uint8_t new_afi
= afi
== AFI_IP
? AF_INET
: AF_INET6
;
508 struct bgp_addr tmp_addr
= {{0}}, *addr
= NULL
;
509 struct tip_addr tmp_tip
, *tip
= NULL
;
510 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
511 bool is_bgp_static_route
=
512 ((type
== ZEBRA_ROUTE_BGP
) && (sub_type
== BGP_ROUTE_STATIC
))
516 if (!is_bgp_static_route
)
517 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
519 tmp_addr
.p
.family
= new_afi
;
522 if (is_bgp_static_route
) {
523 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
524 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
526 /* Here we need to find out which nexthop to be used*/
527 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
528 tmp_addr
.p
.u
.prefix4
= attr
->nexthop
;
529 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
530 } else if ((attr
->mp_nexthop_len
)
531 && ((attr
->mp_nexthop_len
532 == BGP_ATTR_NHLEN_IPV4
)
533 || (attr
->mp_nexthop_len
534 == BGP_ATTR_NHLEN_VPNV4
))) {
535 tmp_addr
.p
.u
.prefix4
=
536 attr
->mp_nexthop_global_in
;
537 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
543 if (is_bgp_static_route
) {
544 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
545 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
547 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
548 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
555 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
559 if (new_afi
== AF_INET
&& hashcount(bgp
->tip_hash
)) {
560 memset(&tmp_tip
, 0, sizeof(tmp_tip
));
561 tmp_tip
.addr
= attr
->nexthop
;
563 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
564 tmp_tip
.addr
= attr
->nexthop
;
565 } else if ((attr
->mp_nexthop_len
) &&
566 ((attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV4
)
567 || (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
))) {
568 tmp_tip
.addr
= attr
->mp_nexthop_global_in
;
571 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
579 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
581 struct bgp_dest
*dest1
;
582 struct bgp_dest
*dest2
;
587 p
.prefixlen
= IPV4_MAX_BITLEN
;
588 p
.u
.prefix4
= nexthop
;
590 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
595 p
.prefixlen
= IPV4_MAX_BITLEN
;
596 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
598 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
600 bgp_dest_unlock_node(dest1
);
604 ret
= (dest1
== dest2
);
606 bgp_dest_unlock_node(dest1
);
607 bgp_dest_unlock_node(dest2
);
612 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
614 struct bgp_dest
*dest1
;
615 struct bgp_dest
*dest2
;
620 p
.prefixlen
= IPV6_MAX_BITLEN
;
621 p
.u
.prefix6
= nexthop
;
623 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
628 p
.prefixlen
= IPV6_MAX_BITLEN
;
629 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
631 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
633 bgp_dest_unlock_node(dest1
);
637 ret
= (dest1
== dest2
);
639 bgp_dest_unlock_node(dest1
);
640 bgp_dest_unlock_node(dest2
);
645 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
646 struct update_subgroup
*subgrp
,
647 struct peer
*exclude
)
649 struct bgp_dest
*dest1
= NULL
, *dest2
= NULL
;
650 struct peer_af
*paf
= NULL
;
651 struct prefix p
= {0}, np
= {0};
652 struct bgp
*bgp
= NULL
;
654 np
.family
= AF_INET6
;
655 np
.prefixlen
= IPV6_MAX_BITLEN
;
656 np
.u
.prefix6
= nexthop
;
659 p
.prefixlen
= IPV6_MAX_BITLEN
;
661 bgp
= SUBGRP_INST(subgrp
);
662 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
666 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
667 /* Skip peer we're told to exclude - e.g., source of route. */
668 if (paf
->peer
== exclude
)
671 p
.u
.prefix6
= paf
->peer
->su
.sin6
.sin6_addr
;
672 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &p
);
673 if (dest1
== dest2
) {
674 bgp_dest_unlock_node(dest1
);
675 bgp_dest_unlock_node(dest2
);
680 bgp_dest_unlock_node(dest2
);
683 bgp_dest_unlock_node(dest1
);
687 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
688 struct update_subgroup
*subgrp
,
689 struct peer
*exclude
)
691 struct bgp_dest
*dest1
, *dest2
;
697 np
.prefixlen
= IPV4_MAX_BITLEN
;
698 np
.u
.prefix4
= nexthop
;
701 p
.prefixlen
= IPV4_MAX_BITLEN
;
703 bgp
= SUBGRP_INST(subgrp
);
704 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
708 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
709 /* Skip peer we're told to exclude - e.g., source of route. */
710 if (paf
->peer
== exclude
)
713 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
715 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
716 if (dest1
== dest2
) {
717 bgp_dest_unlock_node(dest1
);
718 bgp_dest_unlock_node(dest2
);
723 bgp_dest_unlock_node(dest2
);
726 bgp_dest_unlock_node(dest1
);
730 static void bgp_show_bgp_path_info_flags(uint32_t flags
, json_object
*json
)
732 json_object
*json_flags
= NULL
;
737 json_flags
= json_object_new_object();
738 json_object_boolean_add(json_flags
, "igpChanged",
739 CHECK_FLAG(flags
, BGP_PATH_IGP_CHANGED
));
740 json_object_boolean_add(json_flags
, "damped",
741 CHECK_FLAG(flags
, BGP_PATH_DAMPED
));
742 json_object_boolean_add(json_flags
, "history",
743 CHECK_FLAG(flags
, BGP_PATH_HISTORY
));
744 json_object_boolean_add(json_flags
, "bestpath",
745 CHECK_FLAG(flags
, BGP_PATH_SELECTED
));
746 json_object_boolean_add(json_flags
, "valid",
747 CHECK_FLAG(flags
, BGP_PATH_VALID
));
748 json_object_boolean_add(json_flags
, "attrChanged",
749 CHECK_FLAG(flags
, BGP_PATH_ATTR_CHANGED
));
750 json_object_boolean_add(json_flags
, "deterministicMedCheck",
751 CHECK_FLAG(flags
, BGP_PATH_DMED_CHECK
));
752 json_object_boolean_add(json_flags
, "deterministicMedSelected",
753 CHECK_FLAG(flags
, BGP_PATH_DMED_SELECTED
));
754 json_object_boolean_add(json_flags
, "stale",
755 CHECK_FLAG(flags
, BGP_PATH_STALE
));
756 json_object_boolean_add(json_flags
, "removed",
757 CHECK_FLAG(flags
, BGP_PATH_REMOVED
));
758 json_object_boolean_add(json_flags
, "counted",
759 CHECK_FLAG(flags
, BGP_PATH_COUNTED
));
760 json_object_boolean_add(json_flags
, "multipath",
761 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH
));
762 json_object_boolean_add(json_flags
, "multipathChanged",
763 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH_CHG
));
764 json_object_boolean_add(json_flags
, "ribAttributeChanged",
765 CHECK_FLAG(flags
, BGP_PATH_RIB_ATTR_CHG
));
766 json_object_boolean_add(json_flags
, "nexthopSelf",
767 CHECK_FLAG(flags
, BGP_PATH_ANNC_NH_SELF
));
768 json_object_boolean_add(json_flags
, "linkBandwidthChanged",
769 CHECK_FLAG(flags
, BGP_PATH_LINK_BW_CHG
));
770 json_object_boolean_add(json_flags
, "acceptOwn",
771 CHECK_FLAG(flags
, BGP_PATH_ACCEPT_OWN
));
772 json_object_object_add(json
, "flags", json_flags
);
775 static void bgp_show_nexthop_paths(struct vty
*vty
, struct bgp
*bgp
,
776 struct bgp_nexthop_cache
*bnc
,
779 struct bgp_dest
*dest
;
780 struct bgp_path_info
*path
;
783 struct bgp_table
*table
;
784 struct bgp
*bgp_path
;
785 json_object
*paths
= NULL
;
786 json_object
*json_path
= NULL
;
789 paths
= json_object_new_array();
791 vty_out(vty
, " Paths:\n");
792 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
794 assert(dest
&& bgp_dest_table(dest
));
795 afi
= family2afi(bgp_dest_get_prefix(dest
)->family
);
796 table
= bgp_dest_table(dest
);
798 bgp_path
= table
->bgp
;
802 json_path
= json_object_new_object();
803 json_object_string_add(json_path
, "afi", afi2str(afi
));
804 json_object_string_add(json_path
, "safi",
806 json_object_string_addf(json_path
, "prefix", "%pBD",
809 json_object_string_addf(
811 BGP_RD_AS_FORMAT(bgp
->asnotation
),
812 (struct prefix_rd
*)bgp_dest_get_prefix(
814 json_object_string_add(
816 vrf_id_to_name(bgp_path
->vrf_id
));
817 bgp_show_bgp_path_info_flags(path
->flags
, json_path
);
818 json_object_array_add(paths
, json_path
);
822 vty_out(vty
, " %d/%d %pBD RD ", afi
, safi
, dest
);
823 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
824 (struct prefix_rd
*)bgp_dest_get_prefix(
826 vty_out(vty
, " %s flags 0x%x\n", bgp_path
->name_pretty
,
829 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
830 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
833 json_object_object_add(json
, "paths", paths
);
836 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
837 struct bgp_nexthop_cache
*bnc
,
840 struct nexthop
*nexthop
;
841 json_object
*json_gates
= NULL
;
842 json_object
*json_gate
= NULL
;
845 json_gates
= json_object_new_array();
846 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
848 json_gate
= json_object_new_object();
849 switch (nexthop
->type
) {
850 case NEXTHOP_TYPE_IPV6
:
851 json_object_string_addf(json_gate
, "ip", "%pI6",
852 &nexthop
->gate
.ipv6
);
854 case NEXTHOP_TYPE_IPV6_IFINDEX
:
855 json_object_string_addf(json_gate
, "ip", "%pI6",
856 &nexthop
->gate
.ipv6
);
857 json_object_string_add(
858 json_gate
, "interfaceName",
860 bnc
->ifindex
? bnc
->ifindex
864 case NEXTHOP_TYPE_IPV4
:
865 json_object_string_addf(json_gate
, "ip", "%pI4",
866 &nexthop
->gate
.ipv4
);
868 case NEXTHOP_TYPE_IFINDEX
:
869 json_object_string_add(
870 json_gate
, "interfaceName",
872 bnc
->ifindex
? bnc
->ifindex
876 case NEXTHOP_TYPE_IPV4_IFINDEX
:
877 json_object_string_addf(json_gate
, "ip", "%pI4",
878 &nexthop
->gate
.ipv4
);
879 json_object_string_add(
880 json_gate
, "interfaceName",
882 bnc
->ifindex
? bnc
->ifindex
886 case NEXTHOP_TYPE_BLACKHOLE
:
887 json_object_boolean_true_add(json_gate
,
889 switch (nexthop
->bh_type
) {
890 case BLACKHOLE_REJECT
:
891 json_object_boolean_true_add(json_gate
,
894 case BLACKHOLE_ADMINPROHIB
:
895 json_object_boolean_true_add(
896 json_gate
, "adminProhibited");
899 json_object_boolean_true_add(
900 json_gate
, "blackhole");
902 case BLACKHOLE_UNSPEC
:
909 json_object_array_add(json_gates
, json_gate
);
912 switch (nexthop
->type
) {
913 case NEXTHOP_TYPE_IPV6
:
914 case NEXTHOP_TYPE_IPV6_IFINDEX
:
915 vty_out(vty
, " gate %pI6", &nexthop
->gate
.ipv6
);
916 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
&&
918 vty_out(vty
, ", if %s\n",
919 ifindex2ifname(bnc
->ifindex
,
921 else if (nexthop
->ifindex
)
922 vty_out(vty
, ", if %s\n",
923 ifindex2ifname(nexthop
->ifindex
,
928 case NEXTHOP_TYPE_IPV4
:
929 case NEXTHOP_TYPE_IPV4_IFINDEX
:
930 vty_out(vty
, " gate %pI4", &nexthop
->gate
.ipv4
);
931 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
&&
933 vty_out(vty
, ", if %s\n",
934 ifindex2ifname(bnc
->ifindex
,
936 else if (nexthop
->ifindex
)
937 vty_out(vty
, ", if %s\n",
938 ifindex2ifname(nexthop
->ifindex
,
943 case NEXTHOP_TYPE_IFINDEX
:
944 vty_out(vty
, " if %s\n",
945 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
949 case NEXTHOP_TYPE_BLACKHOLE
:
950 vty_out(vty
, " blackhole\n");
953 vty_out(vty
, " invalid nexthop type %u\n",
958 json_object_object_add(json
, "nexthops", json_gates
);
961 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
962 struct bgp_nexthop_cache
*bnc
, bool specific
,
965 char buf
[PREFIX2STR_BUFFER
];
968 json_object
*json_last_update
= NULL
;
969 json_object
*json_nexthop
= NULL
;
971 peer
= (struct peer
*)bnc
->nht_info
;
974 json_nexthop
= json_object_new_object();
975 if (bnc
->srte_color
) {
977 json_object_int_add(json_nexthop
, "srteColor",
980 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
982 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
983 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
985 json_object_boolean_true_add(json_nexthop
, "valid");
986 json_object_boolean_true_add(json_nexthop
, "complete");
987 json_object_int_add(json_nexthop
, "igpMetric",
989 json_object_int_add(json_nexthop
, "pathCount",
992 json_object_string_add(json_nexthop
, "peer",
994 if (bnc
->is_evpn_gwip_nexthop
)
995 json_object_boolean_true_add(json_nexthop
,
998 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
999 buf
, bnc
->metric
, bnc
->path_count
);
1001 vty_out(vty
, ", peer %s", peer
->host
);
1002 if (bnc
->is_evpn_gwip_nexthop
)
1003 vty_out(vty
, " EVPN Gateway IP");
1006 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1007 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
1009 json_object_boolean_true_add(json_nexthop
, "valid");
1010 json_object_boolean_false_add(json_nexthop
, "complete");
1011 json_object_int_add(json_nexthop
, "igpMetric",
1013 json_object_int_add(json_nexthop
, "pathCount",
1015 if (bnc
->is_evpn_gwip_nexthop
)
1016 json_object_boolean_true_add(json_nexthop
,
1020 " %s overlay index unresolved [IGP metric %d], #paths %d",
1021 buf
, bnc
->metric
, bnc
->path_count
);
1022 if (bnc
->is_evpn_gwip_nexthop
)
1023 vty_out(vty
, " EVPN Gateway IP");
1026 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1029 json_object_boolean_false_add(json_nexthop
, "valid");
1030 json_object_boolean_false_add(json_nexthop
, "complete");
1031 json_object_int_add(json_nexthop
, "pathCount",
1034 json_object_string_add(json_nexthop
, "peer",
1036 if (bnc
->is_evpn_gwip_nexthop
)
1037 json_object_boolean_true_add(json_nexthop
,
1039 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1040 json_object_boolean_false_add(json_nexthop
,
1042 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1043 json_object_boolean_false_add(json_nexthop
,
1046 vty_out(vty
, " %s invalid, #paths %d", buf
,
1049 vty_out(vty
, ", peer %s", peer
->host
);
1050 if (bnc
->is_evpn_gwip_nexthop
)
1051 vty_out(vty
, " EVPN Gateway IP");
1053 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1054 vty_out(vty
, " Must be Connected\n");
1055 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1056 vty_out(vty
, " Is not Registered\n");
1059 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
1062 json_last_update
= json_object_new_object();
1063 json_object_int_add(json_last_update
, "epoch", tbuf
);
1064 json_object_string_add(json_last_update
, "string",
1066 json_object_object_add(json_nexthop
, "lastUpdate",
1069 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1072 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1075 /* show paths dependent on nexthop, if needed. */
1077 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1079 json_object_object_add(json
, buf
, json_nexthop
);
1082 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1083 bool import_table
, json_object
*json
, afi_t afi
,
1086 struct bgp_nexthop_cache
*bnc
;
1087 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1088 json_object
*json_afi
= NULL
;
1093 vty_out(vty
, "Current BGP import check cache:\n");
1095 vty_out(vty
, "Current BGP nexthop cache:\n");
1098 tree
= &bgp
->import_check_table
;
1100 tree
= &bgp
->nexthop_cache_table
;
1102 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1104 json_afi
= json_object_new_object();
1105 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
) {
1106 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1110 json_object_object_add(
1111 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1116 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1117 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1118 json_afi
= json_object_new_object();
1119 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
1120 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1121 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1122 json_object_object_add(
1123 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1128 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
1129 const char *nhopip_str
, bool import_table
,
1130 json_object
*json
, afi_t afi
, bool detail
)
1134 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1135 bgp
= bgp_lookup_by_name(name
);
1137 bgp
= bgp_get_default();
1140 vty_out(vty
, "%% No such BGP instance exist\n");
1146 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1147 struct bgp_nexthop_cache
*bnc
;
1149 json_object
*json_afi
= NULL
;
1151 if (!str2prefix(nhopip_str
, &nhop
)) {
1153 vty_out(vty
, "nexthop address is malformed\n");
1156 tree
= import_table
? &bgp
->import_check_table
1157 : &bgp
->nexthop_cache_table
;
1159 json_afi
= json_object_new_object();
1160 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1162 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1164 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1168 json_object_object_add(
1170 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1173 if (!found
&& !json
)
1174 vty_out(vty
, "nexthop %s does not have entry\n",
1177 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1182 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1183 json_object
*json
, afi_t afi
,
1186 struct listnode
*node
, *nnode
;
1188 const char *inst_name
;
1189 json_object
*json_instance
= NULL
;
1191 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1192 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1196 json_instance
= json_object_new_object();
1198 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1200 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1203 json_object_object_add(json
, inst_name
, json_instance
);
1207 #include "bgpd/bgp_nexthop_clippy.c"
1209 DEFPY (show_ip_bgp_nexthop
,
1210 show_ip_bgp_nexthop_cmd
,
1211 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] nexthop [<A.B.C.D|X:X::X:X>$nhop] [<ipv4$afi [A.B.C.D$nhop]|ipv6$afi [X:X::X:X$nhop]>] [detail$detail] [json$uj]",
1215 BGP_INSTANCE_HELP_STR
1216 "BGP nexthop table\n"
1217 "IPv4 nexthop address\n"
1218 "IPv6 nexthop address\n"
1219 "BGP nexthop IPv4 table\n"
1220 "IPv4 nexthop address\n"
1221 "BGP nexthop IPv6 table\n"
1222 "IPv6 nexthop address\n"
1223 "Show detailed information\n"
1227 json_object
*json
= NULL
;
1228 afi_t afiz
= AFI_UNSPEC
;
1231 json
= json_object_new_object();
1234 afiz
= bgp_vty_afi_from_str(afi
);
1236 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1240 vty_json(vty
, json
);
1245 DEFPY (show_ip_bgp_import_check
,
1246 show_ip_bgp_import_check_cmd
,
1247 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1251 BGP_INSTANCE_HELP_STR
1252 "BGP import check table\n"
1253 "Show detailed information\n"
1257 json_object
*json
= NULL
;
1260 json
= json_object_new_object();
1262 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1266 vty_json(vty
, json
);
1271 DEFPY (show_ip_bgp_instance_all_nexthop
,
1272 show_ip_bgp_instance_all_nexthop_cmd
,
1273 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1277 BGP_INSTANCE_ALL_HELP_STR
1278 "BGP nexthop table\n"
1279 "BGP IPv4 nexthop table\n"
1280 "BGP IPv6 nexthop table\n"
1281 "Show detailed information\n"
1284 json_object
*json
= NULL
;
1285 afi_t afiz
= AFI_UNSPEC
;
1288 json
= json_object_new_object();
1291 afiz
= bgp_vty_afi_from_str(afi
);
1293 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1296 vty_json(vty
, json
);
1301 void bgp_scan_init(struct bgp
*bgp
)
1305 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1306 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1307 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1308 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1313 void bgp_scan_vty_init(void)
1315 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1316 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1317 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1320 void bgp_scan_finish(struct bgp
*bgp
)
1324 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1325 /* Only the current one needs to be reset. */
1326 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1327 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1329 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1330 bgp_connected_cleanup
;
1331 bgp_table_unlock(bgp
->connected_table
[afi
]);
1332 bgp
->connected_table
[afi
] = NULL
;
1336 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1339 if (bnc
->flags
== 0) {
1340 snprintfrr(buf
, len
, "None ");
1344 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1345 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1346 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1347 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1348 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1350 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1351 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1354 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1361 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1362 char *buf
, size_t len
)
1364 if (bnc
->flags
== 0) {
1365 snprintfrr(buf
, len
, "None ");
1369 snprintfrr(buf
, len
, "%s%s%s",
1370 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1373 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1376 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)