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
;
807 json_path
= json_object_new_object();
808 json_object_string_add(json_path
, "afi", afi2str(afi
));
809 json_object_string_add(json_path
, "safi",
811 json_object_string_addf(json_path
, "prefix", "%pBD",
814 json_object_string_addf(
816 BGP_RD_AS_FORMAT(bgp
->asnotation
),
817 (struct prefix_rd
*)bgp_dest_get_prefix(
819 json_object_string_add(
821 vrf_id_to_name(bgp_path
->vrf_id
));
822 bgp_show_bgp_path_info_flags(path
->flags
, json_path
);
823 json_object_array_add(paths
, json_path
);
827 vty_out(vty
, " %d/%d %pBD RD ", afi
, safi
, dest
);
828 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
829 (struct prefix_rd
*)bgp_dest_get_prefix(
831 vty_out(vty
, " %s flags 0x%x\n", bgp_path
->name_pretty
,
834 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
835 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
838 json_object_object_add(json
, "paths", paths
);
841 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
842 struct bgp_nexthop_cache
*bnc
,
845 struct nexthop
*nexthop
;
846 json_object
*json_gates
= NULL
;
847 json_object
*json_gate
= NULL
;
850 json_gates
= json_object_new_array();
851 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
853 json_gate
= json_object_new_object();
854 switch (nexthop
->type
) {
855 case NEXTHOP_TYPE_IPV6
:
856 json_object_string_addf(json_gate
, "ip", "%pI6",
857 &nexthop
->gate
.ipv6
);
859 case NEXTHOP_TYPE_IPV6_IFINDEX
:
860 json_object_string_addf(json_gate
, "ip", "%pI6",
861 &nexthop
->gate
.ipv6
);
862 json_object_string_add(
863 json_gate
, "interfaceName",
865 bnc
->ifindex
? bnc
->ifindex
869 case NEXTHOP_TYPE_IPV4
:
870 json_object_string_addf(json_gate
, "ip", "%pI4",
871 &nexthop
->gate
.ipv4
);
873 case NEXTHOP_TYPE_IFINDEX
:
874 json_object_string_add(
875 json_gate
, "interfaceName",
877 bnc
->ifindex
? bnc
->ifindex
881 case NEXTHOP_TYPE_IPV4_IFINDEX
:
882 json_object_string_addf(json_gate
, "ip", "%pI4",
883 &nexthop
->gate
.ipv4
);
884 json_object_string_add(
885 json_gate
, "interfaceName",
887 bnc
->ifindex
? bnc
->ifindex
891 case NEXTHOP_TYPE_BLACKHOLE
:
892 json_object_boolean_true_add(json_gate
,
894 switch (nexthop
->bh_type
) {
895 case BLACKHOLE_REJECT
:
896 json_object_boolean_true_add(json_gate
,
899 case BLACKHOLE_ADMINPROHIB
:
900 json_object_boolean_true_add(
901 json_gate
, "adminProhibited");
904 json_object_boolean_true_add(
905 json_gate
, "blackhole");
907 case BLACKHOLE_UNSPEC
:
914 json_object_array_add(json_gates
, json_gate
);
917 switch (nexthop
->type
) {
918 case NEXTHOP_TYPE_IPV6
:
919 vty_out(vty
, " gate %pI6\n", &nexthop
->gate
.ipv6
);
921 case NEXTHOP_TYPE_IPV6_IFINDEX
:
922 vty_out(vty
, " gate %pI6, if %s\n",
924 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
928 case NEXTHOP_TYPE_IPV4
:
929 vty_out(vty
, " gate %pI4\n", &nexthop
->gate
.ipv4
);
931 case NEXTHOP_TYPE_IFINDEX
:
932 vty_out(vty
, " if %s\n",
933 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
937 case NEXTHOP_TYPE_IPV4_IFINDEX
:
938 vty_out(vty
, " gate %pI4, if %s\n",
940 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
944 case NEXTHOP_TYPE_BLACKHOLE
:
945 vty_out(vty
, " blackhole\n");
948 vty_out(vty
, " invalid nexthop type %u\n",
953 json_object_object_add(json
, "nexthops", json_gates
);
956 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
957 struct bgp_nexthop_cache
*bnc
, bool specific
,
960 char buf
[PREFIX2STR_BUFFER
];
963 json_object
*json_last_update
= NULL
;
964 json_object
*json_nexthop
= NULL
;
966 peer
= (struct peer
*)bnc
->nht_info
;
969 json_nexthop
= json_object_new_object();
970 if (bnc
->srte_color
) {
972 json_object_int_add(json_nexthop
, "srteColor",
975 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
977 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
978 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
980 json_object_boolean_true_add(json_nexthop
, "valid");
981 json_object_boolean_true_add(json_nexthop
, "complete");
982 json_object_int_add(json_nexthop
, "igpMetric",
984 json_object_int_add(json_nexthop
, "pathCount",
987 json_object_string_add(json_nexthop
, "peer",
989 if (bnc
->is_evpn_gwip_nexthop
)
990 json_object_boolean_true_add(json_nexthop
,
993 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
994 buf
, bnc
->metric
, bnc
->path_count
);
996 vty_out(vty
, ", peer %s", peer
->host
);
997 if (bnc
->is_evpn_gwip_nexthop
)
998 vty_out(vty
, " EVPN Gateway IP");
1001 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1002 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
1004 json_object_boolean_true_add(json_nexthop
, "valid");
1005 json_object_boolean_false_add(json_nexthop
, "complete");
1006 json_object_int_add(json_nexthop
, "igpMetric",
1008 json_object_int_add(json_nexthop
, "pathCount",
1010 if (bnc
->is_evpn_gwip_nexthop
)
1011 json_object_boolean_true_add(json_nexthop
,
1015 " %s overlay index unresolved [IGP metric %d], #paths %d",
1016 buf
, bnc
->metric
, bnc
->path_count
);
1017 if (bnc
->is_evpn_gwip_nexthop
)
1018 vty_out(vty
, " EVPN Gateway IP");
1021 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1024 json_object_boolean_false_add(json_nexthop
, "valid");
1025 json_object_boolean_false_add(json_nexthop
, "complete");
1026 json_object_int_add(json_nexthop
, "pathCount",
1029 json_object_string_add(json_nexthop
, "peer",
1031 if (bnc
->is_evpn_gwip_nexthop
)
1032 json_object_boolean_true_add(json_nexthop
,
1034 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1035 json_object_boolean_false_add(json_nexthop
,
1037 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1038 json_object_boolean_false_add(json_nexthop
,
1041 vty_out(vty
, " %s invalid, #paths %d", buf
,
1044 vty_out(vty
, ", peer %s", peer
->host
);
1045 if (bnc
->is_evpn_gwip_nexthop
)
1046 vty_out(vty
, " EVPN Gateway IP");
1048 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1049 vty_out(vty
, " Must be Connected\n");
1050 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1051 vty_out(vty
, " Is not Registered\n");
1054 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
1057 json_last_update
= json_object_new_object();
1058 json_object_int_add(json_last_update
, "epoch", tbuf
);
1059 json_object_string_add(json_last_update
, "string",
1061 json_object_object_add(json_nexthop
, "lastUpdate",
1064 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1067 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1070 /* show paths dependent on nexthop, if needed. */
1072 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1074 json_object_object_add(json
, buf
, json_nexthop
);
1077 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1078 bool import_table
, json_object
*json
, afi_t afi
,
1081 struct bgp_nexthop_cache
*bnc
;
1082 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1083 json_object
*json_afi
= NULL
;
1088 vty_out(vty
, "Current BGP import check cache:\n");
1090 vty_out(vty
, "Current BGP nexthop cache:\n");
1093 tree
= &bgp
->import_check_table
;
1095 tree
= &bgp
->nexthop_cache_table
;
1097 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1099 json_afi
= json_object_new_object();
1100 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
) {
1101 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1105 json_object_object_add(
1106 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1111 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1112 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1113 json_afi
= json_object_new_object();
1114 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
1115 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1116 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1117 json_object_object_add(
1118 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1123 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
1124 const char *nhopip_str
, bool import_table
,
1125 json_object
*json
, afi_t afi
, bool detail
)
1129 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1130 bgp
= bgp_lookup_by_name(name
);
1132 bgp
= bgp_get_default();
1135 vty_out(vty
, "%% No such BGP instance exist\n");
1141 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1142 struct bgp_nexthop_cache
*bnc
;
1144 json_object
*json_afi
= NULL
;
1146 if (!str2prefix(nhopip_str
, &nhop
)) {
1148 vty_out(vty
, "nexthop address is malformed\n");
1151 tree
= import_table
? &bgp
->import_check_table
1152 : &bgp
->nexthop_cache_table
;
1154 json_afi
= json_object_new_object();
1155 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1157 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1159 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1163 json_object_object_add(
1165 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1168 if (!found
&& !json
)
1169 vty_out(vty
, "nexthop %s does not have entry\n",
1172 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1177 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1178 json_object
*json
, afi_t afi
,
1181 struct listnode
*node
, *nnode
;
1183 const char *inst_name
;
1184 json_object
*json_instance
= NULL
;
1186 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1187 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1191 json_instance
= json_object_new_object();
1193 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1195 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1198 json_object_object_add(json
, inst_name
, json_instance
);
1202 #include "bgpd/bgp_nexthop_clippy.c"
1204 DEFPY (show_ip_bgp_nexthop
,
1205 show_ip_bgp_nexthop_cmd
,
1206 "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]",
1210 BGP_INSTANCE_HELP_STR
1211 "BGP nexthop table\n"
1212 "IPv4 nexthop address\n"
1213 "IPv6 nexthop address\n"
1214 "BGP nexthop IPv4 table\n"
1215 "IPv4 nexthop address\n"
1216 "BGP nexthop IPv6 table\n"
1217 "IPv6 nexthop address\n"
1218 "Show detailed information\n"
1222 json_object
*json
= NULL
;
1223 afi_t afiz
= AFI_UNSPEC
;
1226 json
= json_object_new_object();
1229 afiz
= bgp_vty_afi_from_str(afi
);
1231 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1235 vty_json(vty
, json
);
1240 DEFPY (show_ip_bgp_import_check
,
1241 show_ip_bgp_import_check_cmd
,
1242 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1246 BGP_INSTANCE_HELP_STR
1247 "BGP import check table\n"
1248 "Show detailed information\n"
1252 json_object
*json
= NULL
;
1255 json
= json_object_new_object();
1257 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1261 vty_json(vty
, json
);
1266 DEFPY (show_ip_bgp_instance_all_nexthop
,
1267 show_ip_bgp_instance_all_nexthop_cmd
,
1268 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1272 BGP_INSTANCE_ALL_HELP_STR
1273 "BGP nexthop table\n"
1274 "BGP IPv4 nexthop table\n"
1275 "BGP IPv6 nexthop table\n"
1276 "Show detailed information\n"
1279 json_object
*json
= NULL
;
1280 afi_t afiz
= AFI_UNSPEC
;
1283 json
= json_object_new_object();
1286 afiz
= bgp_vty_afi_from_str(afi
);
1288 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1291 vty_json(vty
, json
);
1296 void bgp_scan_init(struct bgp
*bgp
)
1300 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1301 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1302 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1303 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1308 void bgp_scan_vty_init(void)
1310 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1311 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1312 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1315 void bgp_scan_finish(struct bgp
*bgp
)
1319 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1320 /* Only the current one needs to be reset. */
1321 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1322 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1324 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1325 bgp_connected_cleanup
;
1326 bgp_table_unlock(bgp
->connected_table
[afi
]);
1327 bgp
->connected_table
[afi
] = NULL
;
1331 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1334 if (bnc
->flags
== 0) {
1335 snprintfrr(buf
, len
, "None ");
1339 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1340 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1341 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1342 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1343 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1345 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1346 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1349 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1356 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1357 char *buf
, size_t len
)
1359 if (bnc
->flags
== 0) {
1360 snprintfrr(buf
, len
, "None ");
1364 snprintfrr(buf
, len
, "%s%s%s",
1365 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1368 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1371 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)