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 hash_clean_and_free(&bgp
->tip_hash
, bgp_tip_hash_free
);
172 /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
174 * Returns true only if we add a _new_ TIP so the caller knows that an
175 * actionable change has occurred. If we find an existing TIP then we
176 * only need to update the refcnt, since the collection of known TIPs
179 bool bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
182 struct tip_addr
*addr
;
183 bool tip_added
= false;
187 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
189 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
198 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
201 struct tip_addr
*addr
;
205 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
206 /* may have been deleted earlier by bgp_interface_down() */
212 if (addr
->refcnt
== 0) {
213 hash_release(bgp
->tip_hash
, addr
);
214 XFREE(MTYPE_TIP_ADDR
, addr
);
218 /* BGP own address structure */
221 struct list
*ifp_name_list
;
224 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
226 struct vty
*vty
= (struct vty
*)args
;
227 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
229 struct listnode
*node
;
230 char str
[INET6_ADDRSTRLEN
] = {0};
232 vty_out(vty
, "addr: %s, count: %d : ",
233 inet_ntop(addr
->p
.family
, &(addr
->p
.u
.prefix
),
234 str
, INET6_ADDRSTRLEN
),
235 addr
->ifp_name_list
->count
);
237 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
238 vty_out(vty
, " %s,", name
);
244 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
246 hash_iterate(bgp
->address_hash
,
247 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
251 static void bgp_address_hash_string_del(void *val
)
255 XFREE(MTYPE_MARTIAN_STRING
, data
);
258 static void *bgp_address_hash_alloc(void *p
)
260 struct bgp_addr
*copy_addr
= p
;
261 struct bgp_addr
*addr
= NULL
;
263 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
264 prefix_copy(&addr
->p
, ©_addr
->p
);
266 addr
->ifp_name_list
= list_new();
267 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
272 static void bgp_address_hash_free(void *data
)
274 struct bgp_addr
*addr
= data
;
276 list_delete(&addr
->ifp_name_list
);
277 XFREE(MTYPE_BGP_ADDR
, addr
);
280 static unsigned int bgp_address_hash_key_make(const void *p
)
282 const struct bgp_addr
*addr
= p
;
284 return prefix_hash_key(&addr
->p
);
287 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
289 const struct bgp_addr
*addr1
= p1
;
290 const struct bgp_addr
*addr2
= p2
;
292 return prefix_same(&addr1
->p
, &addr2
->p
);
295 void bgp_address_init(struct bgp
*bgp
)
298 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
299 "BGP Connected Address Hash");
302 void bgp_address_destroy(struct bgp
*bgp
)
304 hash_clean_and_free(&bgp
->address_hash
, bgp_address_hash_free
);
307 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
311 struct bgp_addr
*addr
;
312 struct listnode
*node
;
317 if (tmp
.p
.family
== AF_INET
)
318 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
319 else if (tmp
.p
.family
== AF_INET6
)
320 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
322 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
324 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
325 if (strcmp(ifc
->ifp
->name
, name
) == 0)
329 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
330 listnode_add(addr
->ifp_name_list
, name
);
334 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
338 struct bgp_addr
*addr
;
339 struct listnode
*node
;
344 if (tmp
.p
.family
== AF_INET
)
345 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
346 else if (tmp
.p
.family
== AF_INET6
)
347 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
349 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
350 /* may have been deleted earlier by bgp_interface_down() */
354 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
355 if (strcmp(ifc
->ifp
->name
, name
) == 0)
360 list_delete_node(addr
->ifp_name_list
, node
);
361 XFREE(MTYPE_MARTIAN_STRING
, name
);
364 if (addr
->ifp_name_list
->count
== 0) {
365 hash_release(bgp
->address_hash
, addr
);
366 list_delete(&addr
->ifp_name_list
);
367 XFREE(MTYPE_BGP_ADDR
, addr
);
372 struct bgp_connected_ref
{
376 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
380 struct bgp_dest
*dest
;
381 struct bgp_connected_ref
*bc
;
382 struct listnode
*node
, *nnode
;
387 p
= *(CONNECTED_PREFIX(ifc
));
388 if (addr
->family
== AF_INET
) {
389 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
391 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
394 bgp_address_add(bgp
, ifc
, addr
);
396 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP
], &p
);
397 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
401 bc
= XCALLOC(MTYPE_BGP_CONN
,
402 sizeof(struct bgp_connected_ref
));
404 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
407 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
409 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
410 && !peer_established(peer
)
411 && !CHECK_FLAG(peer
->flags
,
412 PEER_FLAG_IFPEER_V6ONLY
)) {
413 if (peer_active(peer
))
414 BGP_EVENT_ADD(peer
, BGP_Stop
);
415 BGP_EVENT_ADD(peer
, BGP_Start
);
418 } else if (addr
->family
== AF_INET6
) {
419 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
421 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
424 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
427 bgp_address_add(bgp
, ifc
, addr
);
429 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP6
], &p
);
431 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
435 bc
= XCALLOC(MTYPE_BGP_CONN
,
436 sizeof(struct bgp_connected_ref
));
438 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
443 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
447 struct bgp_dest
*dest
= NULL
;
448 struct bgp_connected_ref
*bc
;
452 p
= *(CONNECTED_PREFIX(ifc
));
454 if (addr
->family
== AF_INET
) {
455 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
458 bgp_address_del(bgp
, ifc
, addr
);
460 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
461 } else if (addr
->family
== AF_INET6
) {
462 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
465 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
468 bgp_address_del(bgp
, ifc
, addr
);
470 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
476 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
478 if (bc
->refcnt
== 0) {
479 XFREE(MTYPE_BGP_CONN
, bc
);
480 bgp_dest_set_bgp_connected_ref_info(dest
, NULL
);
482 bgp_dest_unlock_node(dest
);
483 bgp_dest_unlock_node(dest
);
486 static void bgp_connected_cleanup(struct route_table
*table
,
487 struct route_node
*rn
)
489 struct bgp_connected_ref
*bc
;
490 struct bgp_dest
*bn
= bgp_dest_from_rnode(rn
);
492 bc
= bgp_dest_get_bgp_connected_ref_info(bn
);
496 XFREE(MTYPE_BGP_CONN
, bc
);
497 bgp_dest_set_bgp_connected_ref_info(bn
, NULL
);
500 bool bgp_nexthop_self(struct bgp
*bgp
, afi_t afi
, uint8_t type
,
501 uint8_t sub_type
, struct attr
*attr
,
502 struct bgp_dest
*dest
)
504 uint8_t new_afi
= afi
== AFI_IP
? AF_INET
: AF_INET6
;
505 struct bgp_addr tmp_addr
= {{0}}, *addr
= NULL
;
506 struct tip_addr tmp_tip
, *tip
= NULL
;
507 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
508 bool is_bgp_static_route
=
509 ((type
== ZEBRA_ROUTE_BGP
) && (sub_type
== BGP_ROUTE_STATIC
))
513 if (!is_bgp_static_route
)
514 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
516 tmp_addr
.p
.family
= new_afi
;
519 if (is_bgp_static_route
) {
520 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
521 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
523 /* Here we need to find out which nexthop to be used*/
524 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
525 tmp_addr
.p
.u
.prefix4
= attr
->nexthop
;
526 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
527 } else if ((attr
->mp_nexthop_len
)
528 && ((attr
->mp_nexthop_len
529 == BGP_ATTR_NHLEN_IPV4
)
530 || (attr
->mp_nexthop_len
531 == BGP_ATTR_NHLEN_VPNV4
))) {
532 tmp_addr
.p
.u
.prefix4
=
533 attr
->mp_nexthop_global_in
;
534 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
540 if (is_bgp_static_route
) {
541 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
542 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
544 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
545 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
552 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
556 if (new_afi
== AF_INET
&& hashcount(bgp
->tip_hash
)) {
557 memset(&tmp_tip
, 0, sizeof(tmp_tip
));
558 tmp_tip
.addr
= attr
->nexthop
;
560 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
561 tmp_tip
.addr
= attr
->nexthop
;
562 } else if ((attr
->mp_nexthop_len
) &&
563 ((attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV4
)
564 || (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
))) {
565 tmp_tip
.addr
= attr
->mp_nexthop_global_in
;
568 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
576 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
578 struct bgp_dest
*dest1
;
579 struct bgp_dest
*dest2
;
584 p
.prefixlen
= IPV4_MAX_BITLEN
;
585 p
.u
.prefix4
= nexthop
;
587 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
592 p
.prefixlen
= IPV4_MAX_BITLEN
;
593 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
595 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
597 bgp_dest_unlock_node(dest1
);
601 ret
= (dest1
== dest2
);
603 bgp_dest_unlock_node(dest1
);
604 bgp_dest_unlock_node(dest2
);
609 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
611 struct bgp_dest
*dest1
;
612 struct bgp_dest
*dest2
;
617 p
.prefixlen
= IPV6_MAX_BITLEN
;
618 p
.u
.prefix6
= nexthop
;
620 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
625 p
.prefixlen
= IPV6_MAX_BITLEN
;
626 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
628 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
630 bgp_dest_unlock_node(dest1
);
634 ret
= (dest1
== dest2
);
636 bgp_dest_unlock_node(dest1
);
637 bgp_dest_unlock_node(dest2
);
642 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
643 struct update_subgroup
*subgrp
,
644 struct peer
*exclude
)
646 struct bgp_dest
*dest1
= NULL
, *dest2
= NULL
;
647 struct peer_af
*paf
= NULL
;
648 struct prefix p
= {0}, np
= {0};
649 struct bgp
*bgp
= NULL
;
651 np
.family
= AF_INET6
;
652 np
.prefixlen
= IPV6_MAX_BITLEN
;
653 np
.u
.prefix6
= nexthop
;
656 p
.prefixlen
= IPV6_MAX_BITLEN
;
658 bgp
= SUBGRP_INST(subgrp
);
659 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
663 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
664 /* Skip peer we're told to exclude - e.g., source of route. */
665 if (paf
->peer
== exclude
)
668 p
.u
.prefix6
= paf
->peer
->su
.sin6
.sin6_addr
;
669 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &p
);
670 if (dest1
== dest2
) {
671 bgp_dest_unlock_node(dest1
);
672 bgp_dest_unlock_node(dest2
);
677 bgp_dest_unlock_node(dest2
);
680 bgp_dest_unlock_node(dest1
);
684 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
685 struct update_subgroup
*subgrp
,
686 struct peer
*exclude
)
688 struct bgp_dest
*dest1
, *dest2
;
694 np
.prefixlen
= IPV4_MAX_BITLEN
;
695 np
.u
.prefix4
= nexthop
;
698 p
.prefixlen
= IPV4_MAX_BITLEN
;
700 bgp
= SUBGRP_INST(subgrp
);
701 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
705 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
706 /* Skip peer we're told to exclude - e.g., source of route. */
707 if (paf
->peer
== exclude
)
710 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
712 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
713 if (dest1
== dest2
) {
714 bgp_dest_unlock_node(dest1
);
715 bgp_dest_unlock_node(dest2
);
720 bgp_dest_unlock_node(dest2
);
723 bgp_dest_unlock_node(dest1
);
727 static void bgp_show_bgp_path_info_flags(uint32_t flags
, json_object
*json
)
729 json_object
*json_flags
= NULL
;
734 json_flags
= json_object_new_object();
735 json_object_boolean_add(json_flags
, "igpChanged",
736 CHECK_FLAG(flags
, BGP_PATH_IGP_CHANGED
));
737 json_object_boolean_add(json_flags
, "damped",
738 CHECK_FLAG(flags
, BGP_PATH_DAMPED
));
739 json_object_boolean_add(json_flags
, "history",
740 CHECK_FLAG(flags
, BGP_PATH_HISTORY
));
741 json_object_boolean_add(json_flags
, "bestpath",
742 CHECK_FLAG(flags
, BGP_PATH_SELECTED
));
743 json_object_boolean_add(json_flags
, "valid",
744 CHECK_FLAG(flags
, BGP_PATH_VALID
));
745 json_object_boolean_add(json_flags
, "attrChanged",
746 CHECK_FLAG(flags
, BGP_PATH_ATTR_CHANGED
));
747 json_object_boolean_add(json_flags
, "deterministicMedCheck",
748 CHECK_FLAG(flags
, BGP_PATH_DMED_CHECK
));
749 json_object_boolean_add(json_flags
, "deterministicMedSelected",
750 CHECK_FLAG(flags
, BGP_PATH_DMED_SELECTED
));
751 json_object_boolean_add(json_flags
, "stale",
752 CHECK_FLAG(flags
, BGP_PATH_STALE
));
753 json_object_boolean_add(json_flags
, "removed",
754 CHECK_FLAG(flags
, BGP_PATH_REMOVED
));
755 json_object_boolean_add(json_flags
, "counted",
756 CHECK_FLAG(flags
, BGP_PATH_COUNTED
));
757 json_object_boolean_add(json_flags
, "multipath",
758 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH
));
759 json_object_boolean_add(json_flags
, "multipathChanged",
760 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH_CHG
));
761 json_object_boolean_add(json_flags
, "ribAttributeChanged",
762 CHECK_FLAG(flags
, BGP_PATH_RIB_ATTR_CHG
));
763 json_object_boolean_add(json_flags
, "nexthopSelf",
764 CHECK_FLAG(flags
, BGP_PATH_ANNC_NH_SELF
));
765 json_object_boolean_add(json_flags
, "linkBandwidthChanged",
766 CHECK_FLAG(flags
, BGP_PATH_LINK_BW_CHG
));
767 json_object_boolean_add(json_flags
, "acceptOwn",
768 CHECK_FLAG(flags
, BGP_PATH_ACCEPT_OWN
));
769 json_object_object_add(json
, "flags", json_flags
);
772 static void bgp_show_nexthop_paths(struct vty
*vty
, struct bgp
*bgp
,
773 struct bgp_nexthop_cache
*bnc
,
776 struct bgp_dest
*dest
;
777 struct bgp_path_info
*path
;
780 struct bgp_table
*table
;
781 struct bgp
*bgp_path
;
782 json_object
*paths
= NULL
;
783 json_object
*json_path
= NULL
;
786 paths
= json_object_new_array();
788 vty_out(vty
, " Paths:\n");
789 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
791 assert(dest
&& bgp_dest_table(dest
));
792 afi
= family2afi(bgp_dest_get_prefix(dest
)->family
);
793 table
= bgp_dest_table(dest
);
795 bgp_path
= table
->bgp
;
799 json_path
= json_object_new_object();
800 json_object_string_add(json_path
, "afi", afi2str(afi
));
801 json_object_string_add(json_path
, "safi",
803 json_object_string_addf(json_path
, "prefix", "%pBD",
806 json_object_string_addf(
808 BGP_RD_AS_FORMAT(bgp
->asnotation
),
809 (struct prefix_rd
*)bgp_dest_get_prefix(
811 json_object_string_add(
813 vrf_id_to_name(bgp_path
->vrf_id
));
814 bgp_show_bgp_path_info_flags(path
->flags
, json_path
);
815 json_object_array_add(paths
, json_path
);
819 vty_out(vty
, " %d/%d %pBD RD ", afi
, safi
, dest
);
820 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
),
821 (struct prefix_rd
*)bgp_dest_get_prefix(
823 vty_out(vty
, " %s flags 0x%x\n", bgp_path
->name_pretty
,
826 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
827 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
830 json_object_object_add(json
, "paths", paths
);
833 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
834 struct bgp_nexthop_cache
*bnc
,
837 struct nexthop
*nexthop
;
838 json_object
*json_gates
= NULL
;
839 json_object
*json_gate
= NULL
;
842 json_gates
= json_object_new_array();
843 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
845 json_gate
= json_object_new_object();
846 switch (nexthop
->type
) {
847 case NEXTHOP_TYPE_IPV6
:
848 json_object_string_addf(json_gate
, "ip", "%pI6",
849 &nexthop
->gate
.ipv6
);
851 case NEXTHOP_TYPE_IPV6_IFINDEX
:
852 json_object_string_addf(json_gate
, "ip", "%pI6",
853 &nexthop
->gate
.ipv6
);
854 json_object_string_add(
855 json_gate
, "interfaceName",
857 bnc
->ifindex
? bnc
->ifindex
861 case NEXTHOP_TYPE_IPV4
:
862 json_object_string_addf(json_gate
, "ip", "%pI4",
863 &nexthop
->gate
.ipv4
);
865 case NEXTHOP_TYPE_IFINDEX
:
866 json_object_string_add(
867 json_gate
, "interfaceName",
869 bnc
->ifindex
? bnc
->ifindex
873 case NEXTHOP_TYPE_IPV4_IFINDEX
:
874 json_object_string_addf(json_gate
, "ip", "%pI4",
875 &nexthop
->gate
.ipv4
);
876 json_object_string_add(
877 json_gate
, "interfaceName",
879 bnc
->ifindex
? bnc
->ifindex
883 case NEXTHOP_TYPE_BLACKHOLE
:
884 json_object_boolean_true_add(json_gate
,
886 switch (nexthop
->bh_type
) {
887 case BLACKHOLE_REJECT
:
888 json_object_boolean_true_add(json_gate
,
891 case BLACKHOLE_ADMINPROHIB
:
892 json_object_boolean_true_add(
893 json_gate
, "adminProhibited");
896 json_object_boolean_true_add(
897 json_gate
, "blackhole");
899 case BLACKHOLE_UNSPEC
:
906 json_object_array_add(json_gates
, json_gate
);
909 switch (nexthop
->type
) {
910 case NEXTHOP_TYPE_IPV6
:
911 case NEXTHOP_TYPE_IPV6_IFINDEX
:
912 vty_out(vty
, " gate %pI6", &nexthop
->gate
.ipv6
);
913 if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
&&
915 vty_out(vty
, ", if %s\n",
916 ifindex2ifname(bnc
->ifindex
,
918 else if (nexthop
->ifindex
)
919 vty_out(vty
, ", if %s\n",
920 ifindex2ifname(nexthop
->ifindex
,
925 case NEXTHOP_TYPE_IPV4
:
926 case NEXTHOP_TYPE_IPV4_IFINDEX
:
927 vty_out(vty
, " gate %pI4", &nexthop
->gate
.ipv4
);
928 if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
&&
930 vty_out(vty
, ", if %s\n",
931 ifindex2ifname(bnc
->ifindex
,
933 else if (nexthop
->ifindex
)
934 vty_out(vty
, ", if %s\n",
935 ifindex2ifname(nexthop
->ifindex
,
940 case NEXTHOP_TYPE_IFINDEX
:
941 vty_out(vty
, " if %s\n",
942 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
946 case NEXTHOP_TYPE_BLACKHOLE
:
947 vty_out(vty
, " blackhole\n");
950 vty_out(vty
, " invalid nexthop type %u\n",
955 json_object_object_add(json
, "nexthops", json_gates
);
958 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
959 struct bgp_nexthop_cache
*bnc
, bool specific
,
962 char buf
[PREFIX2STR_BUFFER
];
965 json_object
*json_last_update
= NULL
;
966 json_object
*json_nexthop
= NULL
;
968 peer
= (struct peer
*)bnc
->nht_info
;
971 json_nexthop
= json_object_new_object();
972 if (bnc
->srte_color
) {
974 json_object_int_add(json_nexthop
, "srteColor",
977 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
979 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
980 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
982 json_object_boolean_true_add(json_nexthop
, "valid");
983 json_object_boolean_true_add(json_nexthop
, "complete");
984 json_object_int_add(json_nexthop
, "igpMetric",
986 json_object_int_add(json_nexthop
, "pathCount",
989 json_object_string_add(json_nexthop
, "peer",
991 if (bnc
->is_evpn_gwip_nexthop
)
992 json_object_boolean_true_add(json_nexthop
,
995 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
996 buf
, bnc
->metric
, bnc
->path_count
);
998 vty_out(vty
, ", peer %s", peer
->host
);
999 if (bnc
->is_evpn_gwip_nexthop
)
1000 vty_out(vty
, " EVPN Gateway IP");
1003 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1004 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
1006 json_object_boolean_true_add(json_nexthop
, "valid");
1007 json_object_boolean_false_add(json_nexthop
, "complete");
1008 json_object_int_add(json_nexthop
, "igpMetric",
1010 json_object_int_add(json_nexthop
, "pathCount",
1012 if (bnc
->is_evpn_gwip_nexthop
)
1013 json_object_boolean_true_add(json_nexthop
,
1017 " %s overlay index unresolved [IGP metric %d], #paths %d",
1018 buf
, bnc
->metric
, bnc
->path_count
);
1019 if (bnc
->is_evpn_gwip_nexthop
)
1020 vty_out(vty
, " EVPN Gateway IP");
1023 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1026 json_object_boolean_false_add(json_nexthop
, "valid");
1027 json_object_boolean_false_add(json_nexthop
, "complete");
1028 json_object_int_add(json_nexthop
, "pathCount",
1031 json_object_string_add(json_nexthop
, "peer",
1033 if (bnc
->is_evpn_gwip_nexthop
)
1034 json_object_boolean_true_add(json_nexthop
,
1036 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1037 json_object_boolean_false_add(json_nexthop
,
1039 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1040 json_object_boolean_false_add(json_nexthop
,
1043 vty_out(vty
, " %s invalid, #paths %d", buf
,
1046 vty_out(vty
, ", peer %s", peer
->host
);
1047 if (bnc
->is_evpn_gwip_nexthop
)
1048 vty_out(vty
, " EVPN Gateway IP");
1050 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1051 vty_out(vty
, " Must be Connected\n");
1052 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1053 vty_out(vty
, " Is not Registered\n");
1056 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
1059 json_last_update
= json_object_new_object();
1060 json_object_int_add(json_last_update
, "epoch", tbuf
);
1061 json_object_string_add(json_last_update
, "string",
1063 json_object_object_add(json_nexthop
, "lastUpdate",
1066 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1069 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1072 /* show paths dependent on nexthop, if needed. */
1074 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1076 json_object_object_add(json
, buf
, json_nexthop
);
1079 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1080 bool import_table
, json_object
*json
, afi_t afi
,
1083 struct bgp_nexthop_cache
*bnc
;
1084 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1085 json_object
*json_afi
= NULL
;
1090 vty_out(vty
, "Current BGP import check cache:\n");
1092 vty_out(vty
, "Current BGP nexthop cache:\n");
1095 tree
= &bgp
->import_check_table
;
1097 tree
= &bgp
->nexthop_cache_table
;
1099 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1101 json_afi
= json_object_new_object();
1102 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
) {
1103 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1107 json_object_object_add(
1108 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1113 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1114 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1115 json_afi
= json_object_new_object();
1116 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
1117 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1118 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1119 json_object_object_add(
1120 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1125 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
1126 const char *nhopip_str
, bool import_table
,
1127 json_object
*json
, afi_t afi
, bool detail
)
1131 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1132 bgp
= bgp_lookup_by_name(name
);
1134 bgp
= bgp_get_default();
1137 vty_out(vty
, "%% No such BGP instance exist\n");
1143 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1144 struct bgp_nexthop_cache
*bnc
;
1146 json_object
*json_afi
= NULL
;
1148 if (!str2prefix(nhopip_str
, &nhop
)) {
1150 vty_out(vty
, "nexthop address is malformed\n");
1153 tree
= import_table
? &bgp
->import_check_table
1154 : &bgp
->nexthop_cache_table
;
1156 json_afi
= json_object_new_object();
1157 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1159 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1161 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1165 json_object_object_add(
1167 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1170 if (!found
&& !json
)
1171 vty_out(vty
, "nexthop %s does not have entry\n",
1174 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1179 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1180 json_object
*json
, afi_t afi
,
1183 struct listnode
*node
, *nnode
;
1185 const char *inst_name
;
1186 json_object
*json_instance
= NULL
;
1188 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1189 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1193 json_instance
= json_object_new_object();
1195 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1197 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1200 json_object_object_add(json
, inst_name
, json_instance
);
1204 #include "bgpd/bgp_nexthop_clippy.c"
1206 DEFPY (show_ip_bgp_nexthop
,
1207 show_ip_bgp_nexthop_cmd
,
1208 "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]",
1212 BGP_INSTANCE_HELP_STR
1213 "BGP nexthop table\n"
1214 "IPv4 nexthop address\n"
1215 "IPv6 nexthop address\n"
1216 "BGP nexthop IPv4 table\n"
1217 "IPv4 nexthop address\n"
1218 "BGP nexthop IPv6 table\n"
1219 "IPv6 nexthop address\n"
1220 "Show detailed information\n"
1224 json_object
*json
= NULL
;
1225 afi_t afiz
= AFI_UNSPEC
;
1228 json
= json_object_new_object();
1231 afiz
= bgp_vty_afi_from_str(afi
);
1233 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1237 vty_json(vty
, json
);
1242 DEFPY (show_ip_bgp_import_check
,
1243 show_ip_bgp_import_check_cmd
,
1244 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1248 BGP_INSTANCE_HELP_STR
1249 "BGP import check table\n"
1250 "Show detailed information\n"
1254 json_object
*json
= NULL
;
1257 json
= json_object_new_object();
1259 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1263 vty_json(vty
, json
);
1268 DEFPY (show_ip_bgp_instance_all_nexthop
,
1269 show_ip_bgp_instance_all_nexthop_cmd
,
1270 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1274 BGP_INSTANCE_ALL_HELP_STR
1275 "BGP nexthop table\n"
1276 "BGP IPv4 nexthop table\n"
1277 "BGP IPv6 nexthop table\n"
1278 "Show detailed information\n"
1281 json_object
*json
= NULL
;
1282 afi_t afiz
= AFI_UNSPEC
;
1285 json
= json_object_new_object();
1288 afiz
= bgp_vty_afi_from_str(afi
);
1290 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1293 vty_json(vty
, json
);
1298 void bgp_scan_init(struct bgp
*bgp
)
1302 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1303 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1304 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1305 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1310 void bgp_scan_vty_init(void)
1312 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1313 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1314 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1317 void bgp_scan_finish(struct bgp
*bgp
)
1321 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1322 /* Only the current one needs to be reset. */
1323 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1324 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1326 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1327 bgp_connected_cleanup
;
1328 bgp_table_unlock(bgp
->connected_table
[afi
]);
1329 bgp
->connected_table
[afi
] = NULL
;
1333 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1336 if (bnc
->flags
== 0) {
1337 snprintfrr(buf
, len
, "None ");
1341 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1342 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1343 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1344 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1345 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1347 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1348 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1351 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1358 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1359 char *buf
, size_t len
)
1361 if (bnc
->flags
== 0) {
1362 snprintfrr(buf
, len
, "None ");
1366 snprintfrr(buf
, len
, "%s%s%s",
1367 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1370 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1373 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)