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 vty_out(vty
, " gate %pI6\n", &nexthop
->gate
.ipv6
);
913 case NEXTHOP_TYPE_IPV6_IFINDEX
:
914 vty_out(vty
, " gate %pI6, if %s\n",
916 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
920 case NEXTHOP_TYPE_IPV4
:
921 vty_out(vty
, " gate %pI4\n", &nexthop
->gate
.ipv4
);
923 case NEXTHOP_TYPE_IFINDEX
:
924 vty_out(vty
, " if %s\n",
925 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
929 case NEXTHOP_TYPE_IPV4_IFINDEX
:
930 vty_out(vty
, " gate %pI4, if %s\n",
932 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
936 case NEXTHOP_TYPE_BLACKHOLE
:
937 vty_out(vty
, " blackhole\n");
940 vty_out(vty
, " invalid nexthop type %u\n",
945 json_object_object_add(json
, "nexthops", json_gates
);
948 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
949 struct bgp_nexthop_cache
*bnc
, bool specific
,
952 char buf
[PREFIX2STR_BUFFER
];
955 json_object
*json_last_update
= NULL
;
956 json_object
*json_nexthop
= NULL
;
958 peer
= (struct peer
*)bnc
->nht_info
;
961 json_nexthop
= json_object_new_object();
962 if (bnc
->srte_color
) {
964 json_object_int_add(json_nexthop
, "srteColor",
967 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
969 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
970 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
972 json_object_boolean_true_add(json_nexthop
, "valid");
973 json_object_boolean_true_add(json_nexthop
, "complete");
974 json_object_int_add(json_nexthop
, "igpMetric",
976 json_object_int_add(json_nexthop
, "pathCount",
979 json_object_string_add(json_nexthop
, "peer",
981 if (bnc
->is_evpn_gwip_nexthop
)
982 json_object_boolean_true_add(json_nexthop
,
985 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
986 buf
, bnc
->metric
, bnc
->path_count
);
988 vty_out(vty
, ", peer %s", peer
->host
);
989 if (bnc
->is_evpn_gwip_nexthop
)
990 vty_out(vty
, " EVPN Gateway IP");
993 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
994 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
996 json_object_boolean_true_add(json_nexthop
, "valid");
997 json_object_boolean_false_add(json_nexthop
, "complete");
998 json_object_int_add(json_nexthop
, "igpMetric",
1000 json_object_int_add(json_nexthop
, "pathCount",
1002 if (bnc
->is_evpn_gwip_nexthop
)
1003 json_object_boolean_true_add(json_nexthop
,
1007 " %s overlay index unresolved [IGP metric %d], #paths %d",
1008 buf
, bnc
->metric
, bnc
->path_count
);
1009 if (bnc
->is_evpn_gwip_nexthop
)
1010 vty_out(vty
, " EVPN Gateway IP");
1013 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1016 json_object_boolean_false_add(json_nexthop
, "valid");
1017 json_object_boolean_false_add(json_nexthop
, "complete");
1018 json_object_int_add(json_nexthop
, "pathCount",
1021 json_object_string_add(json_nexthop
, "peer",
1023 if (bnc
->is_evpn_gwip_nexthop
)
1024 json_object_boolean_true_add(json_nexthop
,
1026 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1027 json_object_boolean_false_add(json_nexthop
,
1029 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1030 json_object_boolean_false_add(json_nexthop
,
1033 vty_out(vty
, " %s invalid, #paths %d", buf
,
1036 vty_out(vty
, ", peer %s", peer
->host
);
1037 if (bnc
->is_evpn_gwip_nexthop
)
1038 vty_out(vty
, " EVPN Gateway IP");
1040 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1041 vty_out(vty
, " Must be Connected\n");
1042 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1043 vty_out(vty
, " Is not Registered\n");
1046 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
1049 json_last_update
= json_object_new_object();
1050 json_object_int_add(json_last_update
, "epoch", tbuf
);
1051 json_object_string_add(json_last_update
, "string",
1053 json_object_object_add(json_nexthop
, "lastUpdate",
1056 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1059 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1062 /* show paths dependent on nexthop, if needed. */
1064 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1066 json_object_object_add(json
, buf
, json_nexthop
);
1069 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1070 bool import_table
, json_object
*json
, afi_t afi
,
1073 struct bgp_nexthop_cache
*bnc
;
1074 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1075 json_object
*json_afi
= NULL
;
1080 vty_out(vty
, "Current BGP import check cache:\n");
1082 vty_out(vty
, "Current BGP nexthop cache:\n");
1085 tree
= &bgp
->import_check_table
;
1087 tree
= &bgp
->nexthop_cache_table
;
1089 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1091 json_afi
= json_object_new_object();
1092 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
) {
1093 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1097 json_object_object_add(
1098 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1103 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1104 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1105 json_afi
= json_object_new_object();
1106 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
1107 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1108 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1109 json_object_object_add(
1110 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1115 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
1116 const char *nhopip_str
, bool import_table
,
1117 json_object
*json
, afi_t afi
, bool detail
)
1121 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1122 bgp
= bgp_lookup_by_name(name
);
1124 bgp
= bgp_get_default();
1127 vty_out(vty
, "%% No such BGP instance exist\n");
1133 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1134 struct bgp_nexthop_cache
*bnc
;
1136 json_object
*json_afi
= NULL
;
1138 if (!str2prefix(nhopip_str
, &nhop
)) {
1140 vty_out(vty
, "nexthop address is malformed\n");
1143 tree
= import_table
? &bgp
->import_check_table
1144 : &bgp
->nexthop_cache_table
;
1146 json_afi
= json_object_new_object();
1147 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1149 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1151 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1155 json_object_object_add(
1157 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1160 if (!found
&& !json
)
1161 vty_out(vty
, "nexthop %s does not have entry\n",
1164 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1169 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1170 json_object
*json
, afi_t afi
,
1173 struct listnode
*node
, *nnode
;
1175 const char *inst_name
;
1176 json_object
*json_instance
= NULL
;
1178 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1179 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1183 json_instance
= json_object_new_object();
1185 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1187 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1190 json_object_object_add(json
, inst_name
, json_instance
);
1194 #include "bgpd/bgp_nexthop_clippy.c"
1196 DEFPY (show_ip_bgp_nexthop
,
1197 show_ip_bgp_nexthop_cmd
,
1198 "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]",
1202 BGP_INSTANCE_HELP_STR
1203 "BGP nexthop table\n"
1204 "IPv4 nexthop address\n"
1205 "IPv6 nexthop address\n"
1206 "BGP nexthop IPv4 table\n"
1207 "IPv4 nexthop address\n"
1208 "BGP nexthop IPv6 table\n"
1209 "IPv6 nexthop address\n"
1210 "Show detailed information\n"
1214 json_object
*json
= NULL
;
1215 afi_t afiz
= AFI_UNSPEC
;
1218 json
= json_object_new_object();
1221 afiz
= bgp_vty_afi_from_str(afi
);
1223 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1227 vty_json(vty
, json
);
1232 DEFPY (show_ip_bgp_import_check
,
1233 show_ip_bgp_import_check_cmd
,
1234 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1238 BGP_INSTANCE_HELP_STR
1239 "BGP import check table\n"
1240 "Show detailed information\n"
1244 json_object
*json
= NULL
;
1247 json
= json_object_new_object();
1249 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1253 vty_json(vty
, json
);
1258 DEFPY (show_ip_bgp_instance_all_nexthop
,
1259 show_ip_bgp_instance_all_nexthop_cmd
,
1260 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1264 BGP_INSTANCE_ALL_HELP_STR
1265 "BGP nexthop table\n"
1266 "BGP IPv4 nexthop table\n"
1267 "BGP IPv6 nexthop table\n"
1268 "Show detailed information\n"
1271 json_object
*json
= NULL
;
1272 afi_t afiz
= AFI_UNSPEC
;
1275 json
= json_object_new_object();
1278 afiz
= bgp_vty_afi_from_str(afi
);
1280 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1283 vty_json(vty
, json
);
1288 void bgp_scan_init(struct bgp
*bgp
)
1292 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1293 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1294 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1295 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1300 void bgp_scan_vty_init(void)
1302 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1303 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1304 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1307 void bgp_scan_finish(struct bgp
*bgp
)
1311 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1312 /* Only the current one needs to be reset. */
1313 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1314 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1316 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1317 bgp_connected_cleanup
;
1318 bgp_table_unlock(bgp
->connected_table
[afi
]);
1319 bgp
->connected_table
[afi
] = NULL
;
1323 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1326 if (bnc
->flags
== 0) {
1327 snprintfrr(buf
, len
, "None ");
1331 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1332 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1333 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1334 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1335 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1337 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1338 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1341 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1348 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1349 char *buf
, size_t len
)
1351 if (bnc
->flags
== 0) {
1352 snprintfrr(buf
, len
, "None ");
1356 snprintfrr(buf
, len
, "%s%s%s",
1357 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1360 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1363 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)