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
38 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_route.h"
40 #include "bgpd/bgp_attr.h"
41 #include "bgpd/bgp_nexthop.h"
42 #include "bgpd/bgp_nht.h"
43 #include "bgpd/bgp_debug.h"
44 #include "bgpd/bgp_damp.h"
45 #include "bgpd/bgp_fsm.h"
46 #include "bgpd/bgp_vty.h"
47 #include "bgpd/bgp_rd.h"
49 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Addr Intf String");
51 int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache
*a
,
52 const struct bgp_nexthop_cache
*b
)
54 if (a
->srte_color
< b
->srte_color
)
56 if (a
->srte_color
> b
->srte_color
)
59 return prefix_cmp(&a
->prefix
, &b
->prefix
);
62 const char *bnc_str(struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
64 return prefix2str(&bnc
->prefix
, buf
, size
);
67 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
69 nexthops_free(bnc
->nexthop
);
72 struct bgp_nexthop_cache
*bnc_new(struct bgp_nexthop_cache_head
*tree
,
73 struct prefix
*prefix
, uint32_t srte_color
)
75 struct bgp_nexthop_cache
*bnc
;
77 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
78 sizeof(struct bgp_nexthop_cache
));
79 bnc
->prefix
= *prefix
;
80 bnc
->srte_color
= srte_color
;
82 LIST_INIT(&(bnc
->paths
));
83 bgp_nexthop_cache_add(tree
, bnc
);
88 bool bnc_existing_for_prefix(struct bgp_nexthop_cache
*bnc
)
90 struct bgp_nexthop_cache
*bnc_tmp
;
92 frr_each (bgp_nexthop_cache
, bnc
->tree
, bnc_tmp
) {
95 if (prefix_cmp(&bnc
->prefix
, &bnc_tmp
->prefix
) == 0)
101 void bnc_free(struct bgp_nexthop_cache
*bnc
)
103 bnc_nexthop_free(bnc
);
104 bgp_nexthop_cache_del(bnc
->tree
, bnc
);
105 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
108 struct bgp_nexthop_cache
*bnc_find(struct bgp_nexthop_cache_head
*tree
,
109 struct prefix
*prefix
, uint32_t srte_color
)
111 struct bgp_nexthop_cache bnc
= {};
116 bnc
.prefix
= *prefix
;
117 bnc
.srte_color
= srte_color
;
118 return bgp_nexthop_cache_find(tree
, &bnc
);
121 /* Reset and free all BGP nexthop cache. */
122 static void bgp_nexthop_cache_reset(struct bgp_nexthop_cache_head
*tree
)
124 struct bgp_nexthop_cache
*bnc
;
126 while (bgp_nexthop_cache_count(tree
) > 0) {
127 bnc
= bgp_nexthop_cache_first(tree
);
129 while (!LIST_EMPTY(&(bnc
->paths
))) {
130 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
132 path_nh_map(path
, bnc
, false);
139 static void *bgp_tip_hash_alloc(void *p
)
141 const struct in_addr
*val
= (const struct in_addr
*)p
;
142 struct tip_addr
*addr
;
144 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
146 addr
->addr
.s_addr
= val
->s_addr
;
151 static void bgp_tip_hash_free(void *addr
)
153 XFREE(MTYPE_TIP_ADDR
, addr
);
156 static unsigned int bgp_tip_hash_key_make(const void *p
)
158 const struct tip_addr
*addr
= p
;
160 return jhash_1word(addr
->addr
.s_addr
, 0);
163 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
165 const struct tip_addr
*addr1
= p1
;
166 const struct tip_addr
*addr2
= p2
;
168 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
171 void bgp_tip_hash_init(struct bgp
*bgp
)
173 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
177 void bgp_tip_hash_destroy(struct bgp
*bgp
)
179 if (bgp
->tip_hash
== NULL
)
181 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
182 hash_free(bgp
->tip_hash
);
183 bgp
->tip_hash
= NULL
;
186 void bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
189 struct tip_addr
*addr
;
193 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
197 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
200 struct tip_addr
*addr
;
204 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
205 /* may have been deleted earlier by bgp_interface_down() */
211 if (addr
->refcnt
== 0) {
212 hash_release(bgp
->tip_hash
, addr
);
213 XFREE(MTYPE_TIP_ADDR
, addr
);
217 /* BGP own address structure */
220 struct list
*ifp_name_list
;
223 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
225 struct vty
*vty
= (struct vty
*)args
;
226 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
228 struct listnode
*node
;
229 char str
[INET6_ADDRSTRLEN
] = {0};
231 vty_out(vty
, "addr: %s, count: %d : ",
232 inet_ntop(addr
->p
.family
, &(addr
->p
.u
.prefix
),
233 str
, INET6_ADDRSTRLEN
),
234 addr
->ifp_name_list
->count
);
236 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
237 vty_out(vty
, " %s,", name
);
243 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
245 hash_iterate(bgp
->address_hash
,
246 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
250 static void bgp_address_hash_string_del(void *val
)
254 XFREE(MTYPE_MARTIAN_STRING
, data
);
257 static void *bgp_address_hash_alloc(void *p
)
259 struct bgp_addr
*copy_addr
= p
;
260 struct bgp_addr
*addr
= NULL
;
262 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
263 prefix_copy(&addr
->p
, ©_addr
->p
);
265 addr
->ifp_name_list
= list_new();
266 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
271 static void bgp_address_hash_free(void *data
)
273 struct bgp_addr
*addr
= data
;
275 list_delete(&addr
->ifp_name_list
);
276 XFREE(MTYPE_BGP_ADDR
, addr
);
279 static unsigned int bgp_address_hash_key_make(const void *p
)
281 const struct bgp_addr
*addr
= p
;
283 return prefix_hash_key(&addr
->p
);
286 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
288 const struct bgp_addr
*addr1
= p1
;
289 const struct bgp_addr
*addr2
= p2
;
291 return prefix_same(&addr1
->p
, &addr2
->p
);
294 void bgp_address_init(struct bgp
*bgp
)
297 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
298 "BGP Connected Address Hash");
301 void bgp_address_destroy(struct bgp
*bgp
)
303 if (bgp
->address_hash
== NULL
)
305 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
306 hash_free(bgp
->address_hash
);
307 bgp
->address_hash
= NULL
;
310 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
314 struct bgp_addr
*addr
;
315 struct listnode
*node
;
320 if (tmp
.p
.family
== AF_INET
)
321 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
322 else if (tmp
.p
.family
== AF_INET6
)
323 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
325 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
327 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
328 if (strcmp(ifc
->ifp
->name
, name
) == 0)
332 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
333 listnode_add(addr
->ifp_name_list
, name
);
337 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
341 struct bgp_addr
*addr
;
342 struct listnode
*node
;
347 if (tmp
.p
.family
== AF_INET
)
348 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
349 else if (tmp
.p
.family
== AF_INET6
)
350 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
352 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
353 /* may have been deleted earlier by bgp_interface_down() */
357 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
358 if (strcmp(ifc
->ifp
->name
, name
) == 0)
363 list_delete_node(addr
->ifp_name_list
, node
);
364 XFREE(MTYPE_MARTIAN_STRING
, name
);
367 if (addr
->ifp_name_list
->count
== 0) {
368 hash_release(bgp
->address_hash
, addr
);
369 list_delete(&addr
->ifp_name_list
);
370 XFREE(MTYPE_BGP_ADDR
, addr
);
375 struct bgp_connected_ref
{
379 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
383 struct bgp_dest
*dest
;
384 struct bgp_connected_ref
*bc
;
385 struct listnode
*node
, *nnode
;
390 p
= *(CONNECTED_PREFIX(ifc
));
391 if (addr
->family
== AF_INET
) {
392 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
394 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
397 bgp_address_add(bgp
, ifc
, addr
);
399 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP
], &p
);
400 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
404 bc
= XCALLOC(MTYPE_BGP_CONN
,
405 sizeof(struct bgp_connected_ref
));
407 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
410 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
412 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
413 && !peer_established(peer
)
414 && !CHECK_FLAG(peer
->flags
,
415 PEER_FLAG_IFPEER_V6ONLY
)) {
416 if (peer_active(peer
))
417 BGP_EVENT_ADD(peer
, BGP_Stop
);
418 BGP_EVENT_ADD(peer
, BGP_Start
);
421 } else if (addr
->family
== AF_INET6
) {
422 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
424 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
427 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
430 bgp_address_add(bgp
, ifc
, addr
);
432 dest
= bgp_node_get(bgp
->connected_table
[AFI_IP6
], &p
);
434 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
438 bc
= XCALLOC(MTYPE_BGP_CONN
,
439 sizeof(struct bgp_connected_ref
));
441 bgp_dest_set_bgp_connected_ref_info(dest
, bc
);
446 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
450 struct bgp_dest
*dest
= NULL
;
451 struct bgp_connected_ref
*bc
;
455 p
= *(CONNECTED_PREFIX(ifc
));
457 if (addr
->family
== AF_INET
) {
458 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
461 bgp_address_del(bgp
, ifc
, addr
);
463 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
464 } else if (addr
->family
== AF_INET6
) {
465 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
468 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
471 bgp_address_del(bgp
, ifc
, addr
);
473 dest
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
479 bc
= bgp_dest_get_bgp_connected_ref_info(dest
);
481 if (bc
->refcnt
== 0) {
482 XFREE(MTYPE_BGP_CONN
, bc
);
483 bgp_dest_set_bgp_connected_ref_info(dest
, NULL
);
485 bgp_dest_unlock_node(dest
);
486 bgp_dest_unlock_node(dest
);
489 static void bgp_connected_cleanup(struct route_table
*table
,
490 struct route_node
*rn
)
492 struct bgp_connected_ref
*bc
;
493 struct bgp_dest
*bn
= bgp_dest_from_rnode(rn
);
495 bc
= bgp_dest_get_bgp_connected_ref_info(bn
);
500 if (bc
->refcnt
== 0) {
501 XFREE(MTYPE_BGP_CONN
, bc
);
502 bgp_dest_set_bgp_connected_ref_info(bn
, NULL
);
506 bool bgp_nexthop_self(struct bgp
*bgp
, afi_t afi
, uint8_t type
,
507 uint8_t sub_type
, struct attr
*attr
,
508 struct bgp_dest
*dest
)
510 uint8_t new_afi
= afi
== AFI_IP
? AF_INET
: AF_INET6
;
511 struct bgp_addr tmp_addr
= {{0}}, *addr
= NULL
;
512 struct tip_addr tmp_tip
, *tip
= NULL
;
513 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
514 bool is_bgp_static_route
=
515 ((type
== ZEBRA_ROUTE_BGP
) && (sub_type
== BGP_ROUTE_STATIC
))
519 if (!is_bgp_static_route
)
520 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
522 tmp_addr
.p
.family
= new_afi
;
525 if (is_bgp_static_route
) {
526 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
527 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
529 /* Here we need to find out which nexthop to be used*/
530 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
531 tmp_addr
.p
.u
.prefix4
= attr
->nexthop
;
532 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
533 } else if ((attr
->mp_nexthop_len
)
534 && ((attr
->mp_nexthop_len
535 == BGP_ATTR_NHLEN_IPV4
)
536 || (attr
->mp_nexthop_len
537 == BGP_ATTR_NHLEN_VPNV4
))) {
538 tmp_addr
.p
.u
.prefix4
=
539 attr
->mp_nexthop_global_in
;
540 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
546 if (is_bgp_static_route
) {
547 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
548 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
550 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
551 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
558 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
562 if (new_afi
== AF_INET
&& hashcount(bgp
->tip_hash
)) {
563 memset(&tmp_tip
, 0, sizeof(tmp_tip
));
564 tmp_tip
.addr
= attr
->nexthop
;
566 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
567 tmp_tip
.addr
= attr
->nexthop
;
568 } else if ((attr
->mp_nexthop_len
) &&
569 ((attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV4
)
570 || (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
))) {
571 tmp_tip
.addr
= attr
->mp_nexthop_global_in
;
574 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
582 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
584 struct bgp_dest
*dest1
;
585 struct bgp_dest
*dest2
;
590 p
.prefixlen
= IPV4_MAX_BITLEN
;
591 p
.u
.prefix4
= nexthop
;
593 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
598 p
.prefixlen
= IPV4_MAX_BITLEN
;
599 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
601 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
603 bgp_dest_unlock_node(dest1
);
607 ret
= (dest1
== dest2
);
609 bgp_dest_unlock_node(dest1
);
610 bgp_dest_unlock_node(dest2
);
615 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
617 struct bgp_dest
*dest1
;
618 struct bgp_dest
*dest2
;
623 p
.prefixlen
= IPV6_MAX_BITLEN
;
624 p
.u
.prefix6
= nexthop
;
626 dest1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
631 p
.prefixlen
= IPV6_MAX_BITLEN
;
632 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
634 dest2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
636 bgp_dest_unlock_node(dest1
);
640 ret
= (dest1
== dest2
);
642 bgp_dest_unlock_node(dest1
);
643 bgp_dest_unlock_node(dest2
);
648 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
649 struct update_subgroup
*subgrp
,
650 struct peer
*exclude
)
652 struct bgp_dest
*dest1
= NULL
, *dest2
= NULL
;
653 struct peer_af
*paf
= NULL
;
654 struct prefix p
= {0}, np
= {0};
655 struct bgp
*bgp
= NULL
;
657 np
.family
= AF_INET6
;
658 np
.prefixlen
= IPV6_MAX_BITLEN
;
659 np
.u
.prefix6
= nexthop
;
662 p
.prefixlen
= IPV6_MAX_BITLEN
;
664 bgp
= SUBGRP_INST(subgrp
);
665 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
669 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
670 /* Skip peer we're told to exclude - e.g., source of route. */
671 if (paf
->peer
== exclude
)
674 p
.u
.prefix6
= paf
->peer
->su
.sin6
.sin6_addr
;
675 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &p
);
676 if (dest1
== dest2
) {
677 bgp_dest_unlock_node(dest1
);
678 bgp_dest_unlock_node(dest2
);
683 bgp_dest_unlock_node(dest2
);
686 bgp_dest_unlock_node(dest1
);
690 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
691 struct update_subgroup
*subgrp
,
692 struct peer
*exclude
)
694 struct bgp_dest
*dest1
, *dest2
;
700 np
.prefixlen
= IPV4_MAX_BITLEN
;
701 np
.u
.prefix4
= nexthop
;
704 p
.prefixlen
= IPV4_MAX_BITLEN
;
706 bgp
= SUBGRP_INST(subgrp
);
707 dest1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
711 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
712 /* Skip peer we're told to exclude - e.g., source of route. */
713 if (paf
->peer
== exclude
)
716 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
718 dest2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
719 if (dest1
== dest2
) {
720 bgp_dest_unlock_node(dest1
);
721 bgp_dest_unlock_node(dest2
);
726 bgp_dest_unlock_node(dest2
);
729 bgp_dest_unlock_node(dest1
);
733 static void bgp_show_nexthop_paths(struct vty
*vty
, struct bgp
*bgp
,
734 struct bgp_nexthop_cache
*bnc
)
736 struct bgp_dest
*dest
;
737 struct bgp_path_info
*path
;
740 struct bgp_table
*table
;
741 struct bgp
*bgp_path
;
744 vty_out(vty
, " Paths:\n");
745 LIST_FOREACH (path
, &(bnc
->paths
), nh_thread
) {
747 assert(dest
&& bgp_dest_table(dest
));
748 afi
= family2afi(bgp_dest_get_prefix(dest
)->family
);
749 table
= bgp_dest_table(dest
);
751 bgp_path
= table
->bgp
;
754 prefix_rd2str((struct prefix_rd
*)bgp_dest_get_prefix(dest
->pdest
),
756 vty_out(vty
, " %d/%d %pBD RD %s %s flags 0x%x\n",
757 afi
, safi
, dest
, buf1
, bgp_path
->name_pretty
, path
->flags
);
759 vty_out(vty
, " %d/%d %pBD %s flags 0x%x\n",
760 afi
, safi
, dest
, bgp_path
->name_pretty
, path
->flags
);
764 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
765 struct bgp_nexthop_cache
*bnc
)
767 char buf
[PREFIX2STR_BUFFER
];
768 struct nexthop
*nexthop
;
770 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
) {
771 switch (nexthop
->type
) {
772 case NEXTHOP_TYPE_IPV6
:
773 vty_out(vty
, " gate %s\n",
774 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
777 case NEXTHOP_TYPE_IPV6_IFINDEX
:
778 vty_out(vty
, " gate %s, if %s\n",
779 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
781 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
785 case NEXTHOP_TYPE_IPV4
:
786 vty_out(vty
, " gate %s\n",
787 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
790 case NEXTHOP_TYPE_IFINDEX
:
791 vty_out(vty
, " if %s\n",
792 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
796 case NEXTHOP_TYPE_IPV4_IFINDEX
:
797 vty_out(vty
, " gate %s, if %s\n",
798 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
800 ifindex2ifname(bnc
->ifindex
? bnc
->ifindex
804 case NEXTHOP_TYPE_BLACKHOLE
:
805 vty_out(vty
, " blackhole\n");
808 vty_out(vty
, " invalid nexthop type %u\n",
814 static void bgp_show_nexthop(struct vty
*vty
, struct bgp
*bgp
,
815 struct bgp_nexthop_cache
*bnc
,
818 char buf
[PREFIX2STR_BUFFER
];
822 peer
= (struct peer
*)bnc
->nht_info
;
825 vty_out(vty
, " SR-TE color %u -", bnc
->srte_color
);
826 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
827 vty_out(vty
, " %s valid [IGP metric %d], #paths %d",
828 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
,
830 bnc
->metric
, bnc
->path_count
);
832 vty_out(vty
, ", peer %s", peer
->host
);
833 if (bnc
->is_evpn_gwip_nexthop
)
834 vty_out(vty
, " EVPN Gateway IP");
836 bgp_show_nexthops_detail(vty
, bgp
, bnc
);
837 } else if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_EVPN_INCOMPLETE
)) {
839 " %s overlay index unresolved [IGP metric %d], #paths %d",
840 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
,
842 bnc
->metric
, bnc
->path_count
);
843 if (bnc
->is_evpn_gwip_nexthop
)
844 vty_out(vty
, " EVPN Gateway IP");
846 bgp_show_nexthops_detail(vty
, bgp
, bnc
);
848 vty_out(vty
, " %s invalid, #paths %d",
849 inet_ntop(bnc
->prefix
.family
, &bnc
->prefix
.u
.prefix
,
853 vty_out(vty
, ", peer %s", peer
->host
);
854 if (bnc
->is_evpn_gwip_nexthop
)
855 vty_out(vty
, " EVPN Gateway IP");
857 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
858 vty_out(vty
, " Must be Connected\n");
859 if (!CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
))
860 vty_out(vty
, " Is not Registered\n");
862 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
863 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
866 /* show paths dependent on nexthop, if needed. */
868 bgp_show_nexthop_paths(vty
, bgp
, bnc
);
871 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
,
874 struct bgp_nexthop_cache
*bnc
;
876 struct bgp_nexthop_cache_head(*tree
)[AFI_MAX
];
879 vty_out(vty
, "Current BGP import check cache:\n");
881 vty_out(vty
, "Current BGP nexthop cache:\n");
883 tree
= &bgp
->import_check_table
;
885 tree
= &bgp
->nexthop_cache_table
;
886 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
887 frr_each (bgp_nexthop_cache
, &(*tree
)[afi
], bnc
)
888 bgp_show_nexthop(vty
, bgp
, bnc
, false);
892 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
893 const char *nhopip_str
,
899 bgp
= bgp_lookup_by_name(name
);
901 bgp
= bgp_get_default();
903 vty_out(vty
, "%% No such BGP instance exist\n");
909 struct bgp_nexthop_cache_head (*tree
)[AFI_MAX
];
910 struct bgp_nexthop_cache
*bnc
;
912 if (!str2prefix(nhopip_str
, &nhop
)) {
913 vty_out(vty
, "nexthop address is malformed\n");
916 tree
= import_table
? &bgp
->import_check_table
917 : &bgp
->nexthop_cache_table
;
918 bnc
= bnc_find(tree
[family2afi(nhop
.family
)], &nhop
, 0);
920 vty_out(vty
, "specified nexthop does not have entry\n");
923 bgp_show_nexthop(vty
, bgp
, bnc
, true);
925 bgp_show_nexthops(vty
, bgp
, import_table
);
930 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
)
932 struct listnode
*node
, *nnode
;
935 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
936 vty_out(vty
, "\nInstance %s:\n",
937 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
940 bgp_show_nexthops(vty
, bgp
, false);
944 DEFUN (show_ip_bgp_nexthop
,
945 show_ip_bgp_nexthop_cmd
,
946 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [<A.B.C.D|X:X::X:X>] [detail]",
950 BGP_INSTANCE_HELP_STR
951 "BGP nexthop table\n"
952 "IPv4 nexthop address\n"
953 "IPv6 nexthop address\n"
954 "Show detailed information\n")
959 char *nhop_ip
= NULL
;
961 if (argv_find(argv
, argc
, "view", &idx
)
962 || argv_find(argv
, argc
, "vrf", &idx
))
963 vrf
= argv
[++idx
]->arg
;
965 if (argv_find(argv
, argc
, "A.B.C.D", &nh_idx
)
966 || argv_find(argv
, argc
, "X:X::X:X", &nh_idx
))
967 nhop_ip
= argv
[nh_idx
]->arg
;
969 return show_ip_bgp_nexthop_table(vty
, vrf
, nhop_ip
, false);
972 DEFUN (show_ip_bgp_import_check
,
973 show_ip_bgp_import_check_cmd
,
974 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
978 BGP_INSTANCE_HELP_STR
979 "BGP import check table\n"
980 "Show detailed information\n")
985 if (argv_find(argv
, argc
, "view", &idx
)
986 || argv_find(argv
, argc
, "vrf", &idx
))
987 vrf
= argv
[++idx
]->arg
;
989 return show_ip_bgp_nexthop_table(vty
, vrf
, NULL
, true);
992 DEFUN (show_ip_bgp_instance_all_nexthop
,
993 show_ip_bgp_instance_all_nexthop_cmd
,
994 "show [ip] bgp <view|vrf> all nexthop",
998 BGP_INSTANCE_ALL_HELP_STR
999 "BGP nexthop table\n")
1001 bgp_show_all_instances_nexthops_vty(vty
);
1005 void bgp_scan_init(struct bgp
*bgp
)
1009 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1010 bgp_nexthop_cache_init(&bgp
->nexthop_cache_table
[afi
]);
1011 bgp_nexthop_cache_init(&bgp
->import_check_table
[afi
]);
1012 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
1017 void bgp_scan_vty_init(void)
1019 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
1020 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
1021 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
1024 void bgp_scan_finish(struct bgp
*bgp
)
1028 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
1029 /* Only the current one needs to be reset. */
1030 bgp_nexthop_cache_reset(&bgp
->nexthop_cache_table
[afi
]);
1031 bgp_nexthop_cache_reset(&bgp
->import_check_table
[afi
]);
1033 bgp
->connected_table
[afi
]->route_table
->cleanup
=
1034 bgp_connected_cleanup
;
1035 bgp_table_unlock(bgp
->connected_table
[afi
]);
1036 bgp
->connected_table
[afi
] = NULL
;
1040 char *bgp_nexthop_dump_bnc_flags(struct bgp_nexthop_cache
*bnc
, char *buf
,
1043 if (bnc
->flags
== 0) {
1044 snprintfrr(buf
, len
, "None ");
1048 snprintfrr(buf
, len
, "%s%s%s%s%s%s%s",
1049 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
) ? "Valid " : "",
1050 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_REGISTERED
) ? "Reg " : "",
1051 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
) ? "Conn " : "",
1052 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_PEER_NOTIFIED
) ? "Notify "
1054 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE
) ? "Static " : "",
1055 CHECK_FLAG(bnc
->flags
, BGP_STATIC_ROUTE_EXACT_MATCH
)
1058 CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_LABELED_VALID
)
1065 char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache
*bnc
,
1066 char *buf
, size_t len
)
1068 if (bnc
->flags
== 0) {
1069 snprintfrr(buf
, len
, "None ");
1073 snprintfrr(buf
, len
, "%s%s%s",
1074 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CHANGED
)
1077 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_METRIC_CHANGED
)
1080 CHECK_FLAG(bnc
->change_flags
, BGP_NEXTHOP_CONNECTED_CHANGED
)