2 * Copyright (C) 2000 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
39 #include "bgpd/bgpd.h"
40 #include "bgpd/bgp_route.h"
41 #include "bgpd/bgp_attr.h"
42 #include "bgpd/bgp_nexthop.h"
43 #include "bgpd/bgp_nht.h"
44 #include "bgpd/bgp_debug.h"
45 #include "bgpd/bgp_damp.h"
46 #include "bgpd/bgp_fsm.h"
47 #include "bgpd/bgp_vty.h"
48 #include "bgpd/bgp_rd.h"
50 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Addr Intf String");
52 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache
*a
,
53 const struct bgp_nexthop_cache
*b
)
55 if (a
->srte_color
< b
->srte_color
)
57 if (a
->srte_color
> b
->srte_color
)
60 if (a
->ifindex
< b
->ifindex
)
62 if (a
->ifindex
> b
->ifindex
)
65 return prefix_cmp(&a
->prefix
, &b
->prefix
);
68 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
70 nexthops_free(bnc
->nexthop
);
73 struct bgp_nexthop_cache
*bnc_new(struct bgp_nexthop_cache_head
*tree
,
74 struct prefix
*prefix
, uint32_t srte_color
,
77 struct bgp_nexthop_cache
*bnc
;
79 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
80 sizeof(struct bgp_nexthop_cache
));
81 bnc
->prefix
= *prefix
;
82 bnc
->ifindex
= ifindex
;
83 bnc
->srte_color
= srte_color
;
85 LIST_INIT(&(bnc
->paths
));
86 bgp_nexthop_cache_add(tree
, bnc
);
91 bool bnc_existing_for_prefix(struct bgp_nexthop_cache
*bnc
)
93 struct bgp_nexthop_cache
*bnc_tmp
;
95 frr_each (bgp_nexthop_cache
, bnc
->tree
, bnc_tmp
) {
98 if (prefix_cmp(&bnc
->prefix
, &bnc_tmp
->prefix
) == 0)
104 void bnc_free(struct bgp_nexthop_cache
*bnc
)
106 bnc_nexthop_free(bnc
);
107 bgp_nexthop_cache_del(bnc
->tree
, bnc
);
108 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
111 struct bgp_nexthop_cache
*bnc_find(struct bgp_nexthop_cache_head
*tree
,
112 struct prefix
*prefix
, uint32_t srte_color
,
115 struct bgp_nexthop_cache bnc
= {};
120 bnc
.prefix
= *prefix
;
121 bnc
.srte_color
= srte_color
;
122 bnc
.ifindex
= ifindex
;
123 return bgp_nexthop_cache_find(tree
, &bnc
);
126 /* Reset and free all BGP nexthop cache. */
127 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head
*tree
)
129 struct bgp_nexthop_cache
*bnc
;
131 while (bgp_nexthop_cache_count(tree
) > 0) {
132 bnc
= bgp_nexthop_cache_first(tree
);
134 while (!LIST_EMPTY(&(bnc
->paths
))) {
135 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
137 path_nh_map(path
, bnc
, false);
144 static void *bgp_tip_hash_alloc(void *p
)
146 const struct in_addr
*val
= (const struct in_addr
*)p
;
147 struct tip_addr
*addr
;
149 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
151 addr
->addr
.s_addr
= val
->s_addr
;
156 static void bgp_tip_hash_free(void *addr
)
158 XFREE(MTYPE_TIP_ADDR
, addr
);
161 static unsigned int bgp_tip_hash_key_make(const void *p
)
163 const struct tip_addr
*addr
= p
;
165 return jhash_1word(addr
->addr
.s_addr
, 0);
168 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
170 const struct tip_addr
*addr1
= p1
;
171 const struct tip_addr
*addr2
= p2
;
173 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
176 void bgp_tip_hash_init(struct bgp
*bgp
)
178 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
182 void bgp_tip_hash_destroy(struct bgp
*bgp
)
184 if (bgp
->tip_hash
== NULL
)
186 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
187 hash_free(bgp
->tip_hash
);
188 bgp
->tip_hash
= NULL
;
191 /* Add/Update Tunnel-IP entry of bgp martian next-hop table.
193 * Returns true only if we add a _new_ TIP so the caller knows that an
194 * actionable change has occurred. If we find an existing TIP then we
195 * only need to update the refcnt, since the collection of known TIPs
198 bool bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
201 struct tip_addr
*addr
;
202 bool tip_added
= false;
206 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
208 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
217 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
220 struct tip_addr
*addr
;
224 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
225 /* may have been deleted earlier by bgp_interface_down() */
231 if (addr
->refcnt
== 0) {
232 hash_release(bgp
->tip_hash
, addr
);
233 XFREE(MTYPE_TIP_ADDR
, addr
);
237 /* BGP own address structure */
240 struct list
*ifp_name_list
;
243 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
245 struct vty
*vty
= (struct vty
*)args
;
246 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
248 struct listnode
*node
;
249 char str
[INET6_ADDRSTRLEN
] = {0};
251 vty_out(vty
, "addr: %s, count: %d : ",
252 inet_ntop(addr
->p
.family
, &(addr
->p
.u
.prefix
),
253 str
, INET6_ADDRSTRLEN
),
254 addr
->ifp_name_list
->count
);
256 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
257 vty_out(vty
, " %s,", name
);
263 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
265 hash_iterate(bgp
->address_hash
,
266 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
270 static void bgp_address_hash_string_del(void *val
)
274 XFREE(MTYPE_MARTIAN_STRING
, data
);
277 static void *bgp_address_hash_alloc(void *p
)
279 struct bgp_addr
*copy_addr
= p
;
280 struct bgp_addr
*addr
= NULL
;
282 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
283 prefix_copy(&addr
->p
, ©_addr
->p
);
285 addr
->ifp_name_list
= list_new();
286 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
291 static void bgp_address_hash_free(void *data
)
293 struct bgp_addr
*addr
= data
;
295 list_delete(&addr
->ifp_name_list
);
296 XFREE(MTYPE_BGP_ADDR
, addr
);
299 static unsigned int bgp_address_hash_key_make(const void *p
)
301 const struct bgp_addr
*addr
= p
;
303 return prefix_hash_key(&addr
->p
);
306 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
308 const struct bgp_addr
*addr1
= p1
;
309 const struct bgp_addr
*addr2
= p2
;
311 return prefix_same(&addr1
->p
, &addr2
->p
);
314 void bgp_address_init(struct bgp
*bgp
)
317 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
318 "BGP Connected Address Hash");
321 void bgp_address_destroy(struct bgp
*bgp
)
323 if (bgp
->address_hash
== NULL
)
325 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
326 hash_free(bgp
->address_hash
);
327 bgp
->address_hash
= NULL
;
330 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
334 struct bgp_addr
*addr
;
335 struct listnode
*node
;
340 if (tmp
.p
.family
== AF_INET
)
341 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
342 else if (tmp
.p
.family
== AF_INET6
)
343 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
345 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
347 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
348 if (strcmp(ifc
->ifp
->name
, name
) == 0)
352 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
353 listnode_add(addr
->ifp_name_list
, name
);
357 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
361 struct bgp_addr
*addr
;
362 struct listnode
*node
;
367 if (tmp
.p
.family
== AF_INET
)
368 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
369 else if (tmp
.p
.family
== AF_INET6
)
370 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
372 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
373 /* may have been deleted earlier by bgp_interface_down() */
377 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
378 if (strcmp(ifc
->ifp
->name
, name
) == 0)
383 list_delete_node(addr
->ifp_name_list
, node
);
384 XFREE(MTYPE_MARTIAN_STRING
, name
);
387 if (addr
->ifp_name_list
->count
== 0) {
388 hash_release(bgp
->address_hash
, addr
);
389 list_delete(&addr
->ifp_name_list
);
390 XFREE(MTYPE_BGP_ADDR
, addr
);
395 struct bgp_connected_ref
{
399 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
403 struct bgp_dest
*dest
;
404 struct bgp_connected_ref
*bc
;
405 struct listnode
*node
, *nnode
;
410 p
= *(CONNECTED_PREFIX(ifc
));
411 if (addr
->family
== AF_INET
) {
412 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
414 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
417 bgp_address_add(bgp
, ifc
, addr
);
419 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP
], &p
);
420 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
424 bc
= XCALLOC(MTYPE_BGP_CONN
,
425 sizeof(struct bgp_connected_ref
));
427 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
430 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
432 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
433 && !peer_established(peer
)
434 && !CHECK_FLAG(peer
->flags
,
435 PEER_FLAG_IFPEER_V6ONLY
)) {
436 if (peer_active(peer
))
437 BGP_EVENT_ADD(peer
, BGP_Stop
);
438 BGP_EVENT_ADD(peer
, BGP_Start
);
441 } else if (addr
->family
== AF_INET6
) {
442 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
444 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
447 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
450 bgp_address_add(bgp
, ifc
, addr
);
452 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP6
], &p
);
454 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
458 bc
= XCALLOC(MTYPE_BGP_CONN
,
459 sizeof(struct bgp_connected_ref
));
461 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
466 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
470 struct bgp_dest
*dest
= NULL
;
471 struct bgp_connected_ref
*bc
;
475 p
= *(CONNECTED_PREFIX(ifc
));
477 if (addr
->family
== AF_INET
) {
478 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
481 bgp_address_del(bgp
, ifc
, addr
);
483 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
484 } else if (addr
->family
== AF_INET6
) {
485 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
488 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
491 bgp_address_del(bgp
, ifc
, addr
);
493 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
499 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
501 if (bc
->refcnt
== 0) {
502 XFREE(MTYPE_BGP_CONN
, bc
);
503 bgp_dest_set_bgp_connected_ref_info(dest
, NULL
);
505 bgp_dest_unlock_node(dest
);
506 bgp_dest_unlock_node(dest
);
509 static void bgp_connected_cleanup(struct route_table
*table
,
510 struct route_node
*rn
)
512 struct bgp_connected_ref
*bc
;
513 struct bgp_dest
*bn
= bgp_dest_from_rnode(rn
);
515 bc
= bgp_dest_get_bgp_connected_ref_info(bn
);
519 XFREE(MTYPE_BGP_CONN
, bc
);
520 bgp_dest_set_bgp_connected_ref_info(bn
, NULL
);
523 bool bgp_nexthop_self(struct bgp
*bgp
, afi_t afi
, uint8_t type
,
524 uint8_t sub_type
, struct attr
*attr
,
525 struct bgp_dest
*dest
)
527 uint8_t new_afi
= afi
== AFI_IP
? AF_INET
: AF_INET6
;
528 struct bgp_addr tmp_addr
= {{0}}, *addr
= NULL
;
529 struct tip_addr tmp_tip
, *tip
= NULL
;
530 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
531 bool is_bgp_static_route
=
532 ((type
== ZEBRA_ROUTE_BGP
) && (sub_type
== BGP_ROUTE_STATIC
))
536 if (!is_bgp_static_route
)
537 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
539 tmp_addr
.p
.family
= new_afi
;
542 if (is_bgp_static_route
) {
543 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
544 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
546 /* Here we need to find out which nexthop to be used*/
547 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
548 tmp_addr
.p
.u
.prefix4
= attr
->nexthop
;
549 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
550 } else if ((attr
->mp_nexthop_len
)
551 && ((attr
->mp_nexthop_len
552 == BGP_ATTR_NHLEN_IPV4
)
553 || (attr
->mp_nexthop_len
554 == BGP_ATTR_NHLEN_VPNV4
))) {
555 tmp_addr
.p
.u
.prefix4
=
556 attr
->mp_nexthop_global_in
;
557 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
563 if (is_bgp_static_route
) {
564 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
565 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
567 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
568 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
575 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
579 if (new_afi
== AF_INET
&& hashcount(bgp
->tip_hash
)) {
580 memset(&tmp_tip
, 0, sizeof(tmp_tip
));
581 tmp_tip
.addr
= attr
->nexthop
;
583 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
584 tmp_tip
.addr
= attr
->nexthop
;
585 } else if ((attr
->mp_nexthop_len
) &&
586 ((attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV4
)
587 || (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
))) {
588 tmp_tip
.addr
= attr
->mp_nexthop_global_in
;
591 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
599 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
601 struct bgp_dest
*dest1
;
602 struct bgp_dest
*dest2
;
607 p
.prefixlen
= IPV4_MAX_BITLEN
;
608 p
.u
.prefix4
= nexthop
;
610 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
615 p
.prefixlen
= IPV4_MAX_BITLEN
;
616 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
618 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
620 bgp_dest_unlock_node(dest1
);
624 ret
= (dest1
== dest2
);
626 bgp_dest_unlock_node(dest1
);
627 bgp_dest_unlock_node(dest2
);
632 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
634 struct bgp_dest
*dest1
;
635 struct bgp_dest
*dest2
;
640 p
.prefixlen
= IPV6_MAX_BITLEN
;
641 p
.u
.prefix6
= nexthop
;
643 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
648 p
.prefixlen
= IPV6_MAX_BITLEN
;
649 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
651 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
653 bgp_dest_unlock_node(dest1
);
657 ret
= (dest1
== dest2
);
659 bgp_dest_unlock_node(dest1
);
660 bgp_dest_unlock_node(dest2
);
665 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
666 struct update_subgroup
*subgrp
,
667 struct peer
*exclude
)
669 struct bgp_dest
*dest1
= NULL
, *dest2
= NULL
;
670 struct peer_af
*paf
= NULL
;
671 struct prefix p
= {0}, np
= {0};
672 struct bgp
*bgp
= NULL
;
674 np
.family
= AF_INET6
;
675 np
.prefixlen
= IPV6_MAX_BITLEN
;
676 np
.u
.prefix6
= nexthop
;
679 p
.prefixlen
= IPV6_MAX_BITLEN
;
681 bgp
= SUBGRP_INST(subgrp
);
682 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
686 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
687 /* Skip peer we're told to exclude - e.g., source of route. */
688 if (paf
->peer
== exclude
)
691 p
.u
.prefix6
= paf
->peer
->su
.sin6
.sin6_addr
;
692 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &p
);
693 if (dest1
== dest2
) {
694 bgp_dest_unlock_node(dest1
);
695 bgp_dest_unlock_node(dest2
);
700 bgp_dest_unlock_node(dest2
);
703 bgp_dest_unlock_node(dest1
);
707 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
708 struct update_subgroup
*subgrp
,
709 struct peer
*exclude
)
711 struct bgp_dest
*dest1
, *dest2
;
717 np
.prefixlen
= IPV4_MAX_BITLEN
;
718 np
.u
.prefix4
= nexthop
;
721 p
.prefixlen
= IPV4_MAX_BITLEN
;
723 bgp
= SUBGRP_INST(subgrp
);
724 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
728 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
729 /* Skip peer we're told to exclude - e.g., source of route. */
730 if (paf
->peer
== exclude
)
733 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
735 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
736 if (dest1
== dest2
) {
737 bgp_dest_unlock_node(dest1
);
738 bgp_dest_unlock_node(dest2
);
743 bgp_dest_unlock_node(dest2
);
746 bgp_dest_unlock_node(dest1
);
750 static void bgp_show_bgp_path_info_flags(uint32_t flags
, json_object
*json
)
752 json_object
*json_flags
= NULL
;
757 json_flags
= json_object_new_object();
758 json_object_boolean_add(json_flags
, "igpChanged",
759 CHECK_FLAG(flags
, BGP_PATH_IGP_CHANGED
));
760 json_object_boolean_add(json_flags
, "damped",
761 CHECK_FLAG(flags
, BGP_PATH_DAMPED
));
762 json_object_boolean_add(json_flags
, "history",
763 CHECK_FLAG(flags
, BGP_PATH_HISTORY
));
764 json_object_boolean_add(json_flags
, "bestpath",
765 CHECK_FLAG(flags
, BGP_PATH_SELECTED
));
766 json_object_boolean_add(json_flags
, "valid",
767 CHECK_FLAG(flags
, BGP_PATH_VALID
));
768 json_object_boolean_add(json_flags
, "attrChanged",
769 CHECK_FLAG(flags
, BGP_PATH_ATTR_CHANGED
));
770 json_object_boolean_add(json_flags
, "deterministicMedCheck",
771 CHECK_FLAG(flags
, BGP_PATH_DMED_CHECK
));
772 json_object_boolean_add(json_flags
, "deterministicMedSelected",
773 CHECK_FLAG(flags
, BGP_PATH_DMED_SELECTED
));
774 json_object_boolean_add(json_flags
, "stale",
775 CHECK_FLAG(flags
, BGP_PATH_STALE
));
776 json_object_boolean_add(json_flags
, "removed",
777 CHECK_FLAG(flags
, BGP_PATH_REMOVED
));
778 json_object_boolean_add(json_flags
, "counted",
779 CHECK_FLAG(flags
, BGP_PATH_COUNTED
));
780 json_object_boolean_add(json_flags
, "multipath",
781 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH
));
782 json_object_boolean_add(json_flags
, "multipathChanged",
783 CHECK_FLAG(flags
, BGP_PATH_MULTIPATH_CHG
));
784 json_object_boolean_add(json_flags
, "ribAttributeChanged",
785 CHECK_FLAG(flags
, BGP_PATH_RIB_ATTR_CHG
));
786 json_object_boolean_add(json_flags
, "nexthopSelf",
787 CHECK_FLAG(flags
, BGP_PATH_ANNC_NH_SELF
));
788 json_object_boolean_add(json_flags
, "linkBandwidthChanged",
789 CHECK_FLAG(flags
, BGP_PATH_LINK_BW_CHG
));
790 json_object_boolean_add(json_flags
, "acceptOwn",
791 CHECK_FLAG(flags
, BGP_PATH_ACCEPT_OWN
));
792 json_object_object_add(json
, "flags", json_flags
);
795 static void bgp_show_nexthop_paths(struct vty
*vty
, struct bgp
*bgp
,
796 struct bgp_nexthop_cache
*bnc
,
799 struct bgp_dest
*dest
;
800 struct bgp_path_info
*path
;
803 struct bgp_table
*table
;
804 struct bgp
*bgp_path
;
805 json_object
*paths
= NULL
;
806 json_object
*json_path
= NULL
;
809 paths
= json_object_new_array();
811 vty_out(vty
, " Paths:\n");
812 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
814 assert(dest
&& bgp_dest_table(dest
));
815 afi
= family2afi(bgp_dest_get_prefix(dest
)->family
);
816 table
= bgp_dest_table(dest
);
818 bgp_path
= table
->bgp
;
821 json_path
= json_object_new_object();
822 json_object_string_add(json_path
, "afi", afi2str(afi
));
823 json_object_string_add(json_path
, "safi",
825 json_object_string_addf(json_path
, "prefix", "%pBD",
828 json_object_string_addf(
829 json_path
, "rd", "%pRD",
830 (struct prefix_rd
*)bgp_dest_get_prefix(
832 json_object_string_add(
834 vrf_id_to_name(bgp_path
->vrf_id
));
835 bgp_show_bgp_path_info_flags(path
->flags
, json_path
);
836 json_object_array_add(paths
, json_path
);
840 vty_out(vty
, " %d/%d %pBD RD %pRD %s flags 0x%x\n",
842 (struct prefix_rd
*)bgp_dest_get_prefix(
844 bgp_path
->name_pretty
, path
->flags
);
846 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
847 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
850 json_object_object_add(json
, "paths", paths
);
853 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
854 struct bgp_nexthop_cache
*bnc
,
857 struct nexthop
*nexthop
;
858 json_object
*json_gates
= NULL
;
859 json_object
*json_gate
= NULL
;
862 json_gates
= json_object_new_array();
863 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
865 json_gate
= json_object_new_object();
866 switch (nexthop
->type
) {
867 case NEXTHOP_TYPE_IPV6
:
868 json_object_string_addf(json_gate
, "ip", "%pI6",
869 &nexthop
->gate
.ipv6
);
871 case NEXTHOP_TYPE_IPV6_IFINDEX
:
872 json_object_string_addf(json_gate
, "ip", "%pI6",
873 &nexthop
->gate
.ipv6
);
874 json_object_string_add(
875 json_gate
, "interfaceName",
877 bnc
->ifindex
? bnc
->ifindex
881 case NEXTHOP_TYPE_IPV4
:
882 json_object_string_addf(json_gate
, "ip", "%pI4",
883 &nexthop
->gate
.ipv4
);
885 case NEXTHOP_TYPE_IFINDEX
:
886 json_object_string_add(
887 json_gate
, "interfaceName",
889 bnc
->ifindex
? bnc
->ifindex
893 case NEXTHOP_TYPE_IPV4_IFINDEX
:
894 json_object_string_addf(json_gate
, "ip", "%pI4",
895 &nexthop
->gate
.ipv4
);
896 json_object_string_add(
897 json_gate
, "interfaceName",
899 bnc
->ifindex
? bnc
->ifindex
903 case NEXTHOP_TYPE_BLACKHOLE
:
904 json_object_boolean_true_add(json_gate
,
906 switch (nexthop
->bh_type
) {
907 case BLACKHOLE_REJECT
:
908 json_object_boolean_true_add(json_gate
,
911 case BLACKHOLE_ADMINPROHIB
:
912 json_object_boolean_true_add(
913 json_gate
, "adminProhibited");
916 json_object_boolean_true_add(
917 json_gate
, "blackhole");
919 case BLACKHOLE_UNSPEC
:
926 json_object_array_add(json_gates
, json_gate
);
929 switch (nexthop
->type
) {
930 case NEXTHOP_TYPE_IPV6
:
931 vty_out(vty
, " gate %pI6\n", &nexthop
->gate
.ipv6
);
933 case NEXTHOP_TYPE_IPV6_IFINDEX
:
934 vty_out(vty
, " gate %pI6, if %s\n",
936 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
940 case NEXTHOP_TYPE_IPV4
:
941 vty_out(vty
, " gate %pI4\n", &nexthop
->gate
.ipv4
);
943 case NEXTHOP_TYPE_IFINDEX
:
944 vty_out(vty
, " if %s\n",
945 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
949 case NEXTHOP_TYPE_IPV4_IFINDEX
:
950 vty_out(vty
, " gate %pI4, if %s\n",
952 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
956 case NEXTHOP_TYPE_BLACKHOLE
:
957 vty_out(vty
, " blackhole\n");
960 vty_out(vty
, " invalid nexthop type %u\n",
965 json_object_object_add(json
, "nexthops", json_gates
);
968 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
969 struct bgp_nexthop_cache
*bnc
, bool specific
,
972 char buf
[PREFIX2STR_BUFFER
];
975 json_object
*json_last_update
= NULL
;
976 json_object
*json_nexthop
= NULL
;
978 peer
= (struct peer
*)bnc
->nht_info
;
981 json_nexthop
= json_object_new_object();
982 if (bnc
->srte_color
) {
984 json_object_int_add(json_nexthop
, "srteColor",
987 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
989 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
, buf
, sizeof(buf
));
990 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
992 json_object_boolean_true_add(json_nexthop
, "valid");
993 json_object_boolean_true_add(json_nexthop
, "complete");
994 json_object_int_add(json_nexthop
, "igpMetric",
996 json_object_int_add(json_nexthop
, "pathCount",
999 json_object_string_add(json_nexthop
, "peer",
1001 if (bnc
->is_evpn_gwip_nexthop
)
1002 json_object_boolean_true_add(json_nexthop
,
1005 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
1006 buf
, bnc
->metric
, bnc
->path_count
);
1008 vty_out(vty
, ", peer %s", peer
->host
);
1009 if (bnc
->is_evpn_gwip_nexthop
)
1010 vty_out(vty
, " EVPN Gateway IP");
1013 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1014 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
1016 json_object_boolean_true_add(json_nexthop
, "valid");
1017 json_object_boolean_false_add(json_nexthop
, "complete");
1018 json_object_int_add(json_nexthop
, "igpMetric",
1020 json_object_int_add(json_nexthop
, "pathCount",
1022 if (bnc
->is_evpn_gwip_nexthop
)
1023 json_object_boolean_true_add(json_nexthop
,
1027 " %s overlay index unresolved [IGP metric %d], #paths %d",
1028 buf
, bnc
->metric
, bnc
->path_count
);
1029 if (bnc
->is_evpn_gwip_nexthop
)
1030 vty_out(vty
, " EVPN Gateway IP");
1033 bgp_show_nexthops_detail(vty
, bgp
, bnc
, json_nexthop
);
1036 json_object_boolean_false_add(json_nexthop
, "valid");
1037 json_object_boolean_false_add(json_nexthop
, "complete");
1038 json_object_int_add(json_nexthop
, "pathCount",
1041 json_object_string_add(json_nexthop
, "peer",
1043 if (bnc
->is_evpn_gwip_nexthop
)
1044 json_object_boolean_true_add(json_nexthop
,
1046 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1047 json_object_boolean_false_add(json_nexthop
,
1049 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1050 json_object_boolean_false_add(json_nexthop
,
1053 vty_out(vty
, " %s invalid, #paths %d", buf
,
1056 vty_out(vty
, ", peer %s", peer
->host
);
1057 if (bnc
->is_evpn_gwip_nexthop
)
1058 vty_out(vty
, " EVPN Gateway IP");
1060 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
1061 vty_out(vty
, " Must be Connected\n");
1062 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
1063 vty_out(vty
, " Is not Registered\n");
1066 tbuf
= time(NULL
) - (monotime(NULL
) - bnc
->last_update
);
1069 json_last_update
= json_object_new_object();
1070 json_object_int_add(json_last_update
, "epoch", tbuf
);
1071 json_object_string_add(json_last_update
, "string",
1073 json_object_object_add(json_nexthop
, "lastUpdate",
1076 json_object_int_add(json_nexthop
, "lastUpdate", tbuf
);
1079 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
1082 /* show paths dependent on nexthop, if needed. */
1084 bgp_show_nexthop_paths(vty
, bgp
, bnc
, json_nexthop
);
1086 json_object_object_add(json
, buf
, json_nexthop
);
1089 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
1090 bool import_table
, json_object
*json
, afi_t afi
,
1093 struct bgp_nexthop_cache
*bnc
;
1094 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
1095 json_object
*json_afi
= NULL
;
1100 vty_out(vty
, "Current BGP import check cache:\n");
1102 vty_out(vty
, "Current BGP nexthop cache:\n");
1105 tree
= &bgp
->import_check_table
;
1107 tree
= &bgp
->nexthop_cache_table
;
1109 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1111 json_afi
= json_object_new_object();
1112 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
) {
1113 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1117 json_object_object_add(
1118 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1123 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1124 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1125 json_afi
= json_object_new_object();
1126 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
1127 bgp_show_nexthop(vty
, bgp
, bnc
, detail
, json_afi
);
1128 if (json
&& (afi
== AFI_IP
|| afi
== AFI_IP6
))
1129 json_object_object_add(
1130 json
, (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1135 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
1136 const char *nhopip_str
, bool import_table
,
1137 json_object
*json
, afi_t afi
, bool detail
)
1141 if (name
&& !strmatch(name
, VRF_DEFAULT_NAME
))
1142 bgp
= bgp_lookup_by_name(name
);
1144 bgp
= bgp_get_default();
1147 vty_out(vty
, "%% No such BGP instance exist\n");
1153 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
1154 struct bgp_nexthop_cache
*bnc
;
1156 json_object
*json_afi
= NULL
;
1158 if (!str2prefix(nhopip_str
, &nhop
)) {
1160 vty_out(vty
, "nexthop address is malformed\n");
1163 tree
= import_table
? &bgp
->import_check_table
1164 : &bgp
->nexthop_cache_table
;
1166 json_afi
= json_object_new_object();
1167 frr_each (bgp_nexthop_cache
, &(*tree
)[family2afi(nhop
.family
)],
1169 if (prefix_cmp(&bnc
->prefix
, &nhop
))
1171 bgp_show_nexthop(vty
, bgp
, bnc
, true, json_afi
);
1175 json_object_object_add(
1177 (family2afi(nhop
.family
) == AFI_IP
) ? "ipv4"
1180 if (!found
&& !json
)
1181 vty_out(vty
, "nexthop %s does not have entry\n",
1184 bgp_show_nexthops(vty
, bgp
, import_table
, json
, afi
, detail
);
1189 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
,
1190 json_object
*json
, afi_t afi
,
1193 struct listnode
*node
, *nnode
;
1195 const char *inst_name
;
1196 json_object
*json_instance
= NULL
;
1198 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
1199 inst_name
= (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
1203 json_instance
= json_object_new_object();
1205 vty_out(vty
, "\nInstance %s:\n", inst_name
);
1207 bgp_show_nexthops(vty
, bgp
, false, json_instance
, afi
, detail
);
1210 json_object_object_add(json
, inst_name
, json_instance
);
1214 #include "bgpd/bgp_nexthop_clippy.c"
1216 DEFPY (show_ip_bgp_nexthop
,
1217 show_ip_bgp_nexthop_cmd
,
1218 "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]",
1222 BGP_INSTANCE_HELP_STR
1223 "BGP nexthop table\n"
1224 "IPv4 nexthop address\n"
1225 "IPv6 nexthop address\n"
1226 "BGP nexthop IPv4 table\n"
1227 "IPv4 nexthop address\n"
1228 "BGP nexthop IPv6 table\n"
1229 "IPv6 nexthop address\n"
1230 "Show detailed information\n"
1234 json_object
*json
= NULL
;
1235 afi_t afiz
= AFI_UNSPEC
;
1238 json
= json_object_new_object();
1241 afiz
= bgp_vty_afi_from_str(afi
);
1243 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, nhop_str
, false, json
, afiz
,
1247 vty_json(vty
, json
);
1252 DEFPY (show_ip_bgp_import_check
,
1253 show_ip_bgp_import_check_cmd
,
1254 "show [ip] bgp [<view|vrf> VIEWVRFNAME$vrf] import-check-table [detail$detail] [json$uj]",
1258 BGP_INSTANCE_HELP_STR
1259 "BGP import check table\n"
1260 "Show detailed information\n"
1264 json_object
*json
= NULL
;
1267 json
= json_object_new_object();
1269 rc
= show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true, json
, AFI_UNSPEC
,
1273 vty_json(vty
, json
);
1278 DEFPY (show_ip_bgp_instance_all_nexthop
,
1279 show_ip_bgp_instance_all_nexthop_cmd
,
1280 "show [ip] bgp <view|vrf> all nexthop [<ipv4|ipv6>$afi] [detail$detail] [json$uj]",
1284 BGP_INSTANCE_ALL_HELP_STR
1285 "BGP nexthop table\n"
1286 "BGP IPv4 nexthop table\n"
1287 "BGP IPv6 nexthop table\n"
1288 "Show detailed information\n"
1291 json_object
*json
= NULL
;
1292 afi_t afiz
= AFI_UNSPEC
;
1295 json
= json_object_new_object();
1298 afiz
= bgp_vty_afi_from_str(afi
);
1300 bgp_show_all_instances_nexthops_vty(vty
, json
, afiz
, detail
);
1303 vty_json(vty
, json
);
1308 void bgp_scan_init(struct bgp
*bgp
)
1312 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1313 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1314 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1315 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1320 void bgp_scan_vty_init(void)
1322 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1323 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1324 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1327 void bgp_scan_finish(struct bgp
*bgp
)
1331 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1332 /* Only the current one needs to be reset. */
1333 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1334 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1336 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1337 bgp_connected_cleanup
;
1338 bgp_table_unlock(bgp
->connected_table
[afi
]);
1339 bgp
->connected_table
[afi
] = NULL
;
1343 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1346 if (bnc
->flags
== 0) {
1347 snprintfrr(buf
, len
, "None ");
1351 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1352 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1353 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1354 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1355 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1357 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1358 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1361 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1368 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1369 char *buf
, size_t len
)
1371 if (bnc
->flags
== 0) {
1372 snprintfrr(buf
, len
, "None ");
1376 snprintfrr(buf
, len
, "%s%s%s",
1377 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1380 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1383 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)