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
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_table.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"
48 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Address Intf String");
50 char *bnc_str(struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
52 prefix2str(bgp_node_get_prefix(bnc
->node
), buf
, size
);
56 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
58 nexthops_free(bnc
->nexthop
);
61 struct bgp_nexthop_cache
*bnc_new(void)
63 struct bgp_nexthop_cache
*bnc
;
65 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
66 sizeof(struct bgp_nexthop_cache
));
67 LIST_INIT(&(bnc
->paths
));
71 void bnc_free(struct bgp_nexthop_cache
*bnc
)
73 bnc_nexthop_free(bnc
);
74 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
77 /* Reset and free all BGP nexthop cache. */
78 static void bgp_nexthop_cache_reset(struct bgp_table
*table
)
81 struct bgp_nexthop_cache
*bnc
;
83 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
84 bnc
= bgp_node_get_bgp_nexthop_info(rn
);
88 while (!LIST_EMPTY(&(bnc
->paths
))) {
89 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
91 path_nh_map(path
, bnc
, false);
95 bgp_node_set_bgp_nexthop_info(rn
, NULL
);
100 static void *bgp_tip_hash_alloc(void *p
)
102 const struct in_addr
*val
= (const struct in_addr
*)p
;
103 struct tip_addr
*addr
;
105 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
107 addr
->addr
.s_addr
= val
->s_addr
;
112 static void bgp_tip_hash_free(void *addr
)
114 XFREE(MTYPE_TIP_ADDR
, addr
);
117 static unsigned int bgp_tip_hash_key_make(const void *p
)
119 const struct tip_addr
*addr
= p
;
121 return jhash_1word(addr
->addr
.s_addr
, 0);
124 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
126 const struct tip_addr
*addr1
= p1
;
127 const struct tip_addr
*addr2
= p2
;
129 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
132 void bgp_tip_hash_init(struct bgp
*bgp
)
134 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
138 void bgp_tip_hash_destroy(struct bgp
*bgp
)
140 if (bgp
->tip_hash
== NULL
)
142 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
143 hash_free(bgp
->tip_hash
);
144 bgp
->tip_hash
= NULL
;
147 void bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
150 struct tip_addr
*addr
;
154 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
161 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
164 struct tip_addr
*addr
;
168 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
169 /* may have been deleted earlier by bgp_interface_down() */
175 if (addr
->refcnt
== 0) {
176 hash_release(bgp
->tip_hash
, addr
);
177 XFREE(MTYPE_TIP_ADDR
, addr
);
181 /* BGP own address structure */
184 struct list
*ifp_name_list
;
187 static void show_address_entry(struct hash_bucket
*bucket
, void *args
)
189 struct vty
*vty
= (struct vty
*)args
;
190 struct bgp_addr
*addr
= (struct bgp_addr
*)bucket
->data
;
192 struct listnode
*node
;
193 char str
[INET6_ADDRSTRLEN
] = {0};
195 vty_out(vty
, "addr: %s, count: %d : ",
196 inet_ntop(addr
->p
.family
, &(addr
->p
.u
.prefix
),
197 str
, INET6_ADDRSTRLEN
),
198 addr
->ifp_name_list
->count
);
200 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
201 vty_out(vty
, " %s,", name
);
207 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
209 hash_iterate(bgp
->address_hash
,
210 (void (*)(struct hash_bucket
*, void *))show_address_entry
,
214 static void bgp_address_hash_string_del(void *val
)
218 XFREE(MTYPE_MARTIAN_STRING
, data
);
221 static void *bgp_address_hash_alloc(void *p
)
223 struct bgp_addr
*copy_addr
= p
;
224 struct bgp_addr
*addr
= NULL
;
226 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
227 prefix_copy(&addr
->p
, ©_addr
->p
);
229 addr
->ifp_name_list
= list_new();
230 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
235 static void bgp_address_hash_free(void *data
)
237 struct bgp_addr
*addr
= data
;
239 list_delete(&addr
->ifp_name_list
);
240 XFREE(MTYPE_BGP_ADDR
, addr
);
243 static unsigned int bgp_address_hash_key_make(const void *p
)
245 const struct bgp_addr
*addr
= p
;
247 return prefix_hash_key(&addr
->p
);
250 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
252 const struct bgp_addr
*addr1
= p1
;
253 const struct bgp_addr
*addr2
= p2
;
255 return prefix_same(&addr1
->p
, &addr2
->p
);
258 void bgp_address_init(struct bgp
*bgp
)
261 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
262 "BGP Connected Address Hash");
265 void bgp_address_destroy(struct bgp
*bgp
)
267 if (bgp
->address_hash
== NULL
)
269 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
270 hash_free(bgp
->address_hash
);
271 bgp
->address_hash
= NULL
;
274 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
278 struct bgp_addr
*addr
;
279 struct listnode
*node
;
284 if (tmp
.p
.family
== AF_INET
)
285 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
286 else if (tmp
.p
.family
== AF_INET6
)
287 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
289 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
291 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
292 if (strcmp(ifc
->ifp
->name
, name
) == 0)
296 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
297 listnode_add(addr
->ifp_name_list
, name
);
301 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
305 struct bgp_addr
*addr
;
306 struct listnode
*node
;
311 if (tmp
.p
.family
== AF_INET
)
312 tmp
.p
.prefixlen
= IPV4_MAX_BITLEN
;
313 else if (tmp
.p
.family
== AF_INET6
)
314 tmp
.p
.prefixlen
= IPV6_MAX_BITLEN
;
316 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
317 /* may have been deleted earlier by bgp_interface_down() */
321 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
322 if (strcmp(ifc
->ifp
->name
, name
) == 0)
327 list_delete_node(addr
->ifp_name_list
, node
);
328 XFREE(MTYPE_MARTIAN_STRING
, name
);
331 if (addr
->ifp_name_list
->count
== 0) {
332 hash_release(bgp
->address_hash
, addr
);
333 list_delete(&addr
->ifp_name_list
);
334 XFREE(MTYPE_BGP_ADDR
, addr
);
339 struct bgp_connected_ref
{
343 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
348 struct bgp_connected_ref
*bc
;
349 struct listnode
*node
, *nnode
;
354 p
= *(CONNECTED_PREFIX(ifc
));
355 if (addr
->family
== AF_INET
) {
356 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
358 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
361 bgp_address_add(bgp
, ifc
, addr
);
363 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP
],
364 (struct prefix
*)&p
);
365 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
369 bc
= XCALLOC(MTYPE_BGP_CONN
,
370 sizeof(struct bgp_connected_ref
));
372 bgp_node_set_bgp_connected_ref_info(rn
, bc
);
375 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
377 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
378 && peer
->status
!= Established
379 && !CHECK_FLAG(peer
->flags
,
380 PEER_FLAG_IFPEER_V6ONLY
)) {
381 if (peer_active(peer
))
382 BGP_EVENT_ADD(peer
, BGP_Stop
);
383 BGP_EVENT_ADD(peer
, BGP_Start
);
386 } else if (addr
->family
== AF_INET6
) {
387 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
389 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
392 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
395 bgp_address_add(bgp
, ifc
, addr
);
397 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP6
],
398 (struct prefix
*)&p
);
400 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
404 bc
= XCALLOC(MTYPE_BGP_CONN
,
405 sizeof(struct bgp_connected_ref
));
407 bgp_node_set_bgp_connected_ref_info(rn
, bc
);
412 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
416 struct bgp_node
*rn
= NULL
;
417 struct bgp_connected_ref
*bc
;
421 p
= *(CONNECTED_PREFIX(ifc
));
423 if (addr
->family
== AF_INET
) {
424 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
427 bgp_address_del(bgp
, ifc
, addr
);
429 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
430 } else if (addr
->family
== AF_INET6
) {
431 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
434 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
437 bgp_address_del(bgp
, ifc
, addr
);
439 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
], &p
);
445 bc
= bgp_node_get_bgp_connected_ref_info(rn
);
447 if (bc
->refcnt
== 0) {
448 XFREE(MTYPE_BGP_CONN
, bc
);
449 bgp_node_set_bgp_connected_ref_info(rn
, NULL
);
455 static void bgp_connected_cleanup(struct route_table
*table
,
456 struct route_node
*rn
)
458 struct bgp_connected_ref
*bc
;
459 struct bgp_node
*bn
= bgp_node_from_rnode(rn
);
461 bc
= bgp_node_get_bgp_connected_ref_info(bn
);
466 if (bc
->refcnt
== 0) {
467 XFREE(MTYPE_BGP_CONN
, bc
);
468 bgp_node_set_bgp_connected_ref_info(bn
, NULL
);
472 bool bgp_nexthop_self(struct bgp
*bgp
, afi_t afi
, uint8_t type
,
473 uint8_t sub_type
, struct attr
*attr
, struct bgp_node
*rn
)
475 uint8_t new_afi
= afi
== AFI_IP
? AF_INET
: AF_INET6
;
476 struct bgp_addr tmp_addr
= {{0}}, *addr
= NULL
;
477 struct tip_addr tmp_tip
, *tip
= NULL
;
478 const struct prefix
*p
= bgp_node_get_prefix(rn
);
479 bool is_bgp_static_route
=
480 ((type
== ZEBRA_ROUTE_BGP
) && (sub_type
== BGP_ROUTE_STATIC
))
484 if (!is_bgp_static_route
)
485 new_afi
= BGP_ATTR_NEXTHOP_AFI_IP6(attr
) ? AF_INET6
: AF_INET
;
487 tmp_addr
.p
.family
= new_afi
;
490 if (is_bgp_static_route
) {
491 tmp_addr
.p
.u
.prefix4
= p
->u
.prefix4
;
492 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
494 /* Here we need to find out which nexthop to be used*/
495 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
496 tmp_addr
.p
.u
.prefix4
= attr
->nexthop
;
497 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
498 } else if ((attr
->mp_nexthop_len
)
499 && ((attr
->mp_nexthop_len
500 == BGP_ATTR_NHLEN_IPV4
)
501 || (attr
->mp_nexthop_len
502 == BGP_ATTR_NHLEN_VPNV4
))) {
503 tmp_addr
.p
.u
.prefix4
=
504 attr
->mp_nexthop_global_in
;
505 tmp_addr
.p
.prefixlen
= IPV4_MAX_BITLEN
;
511 if (is_bgp_static_route
) {
512 tmp_addr
.p
.u
.prefix6
= p
->u
.prefix6
;
513 tmp_addr
.p
.prefixlen
= p
->prefixlen
;
515 tmp_addr
.p
.u
.prefix6
= attr
->mp_nexthop_global
;
516 tmp_addr
.p
.prefixlen
= IPV6_MAX_BITLEN
;
523 addr
= hash_lookup(bgp
->address_hash
, &tmp_addr
);
527 if (new_afi
== AF_INET
) {
528 memset(&tmp_tip
, 0, sizeof(struct tip_addr
));
529 tmp_tip
.addr
= attr
->nexthop
;
531 if (attr
->flag
& ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
)) {
532 tmp_tip
.addr
= attr
->nexthop
;
533 } else if ((attr
->mp_nexthop_len
) &&
534 ((attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_IPV4
)
535 || (attr
->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV4
))) {
536 tmp_tip
.addr
= attr
->mp_nexthop_global_in
;
539 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
547 bool bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
549 struct bgp_node
*rn1
;
550 struct bgp_node
*rn2
;
555 p
.prefixlen
= IPV4_MAX_BITLEN
;
556 p
.u
.prefix4
= nexthop
;
558 rn1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
563 p
.prefixlen
= IPV4_MAX_BITLEN
;
564 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
566 rn2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
568 bgp_unlock_node(rn1
);
574 bgp_unlock_node(rn1
);
575 bgp_unlock_node(rn2
);
580 bool bgp_multiaccess_check_v6(struct in6_addr nexthop
, struct peer
*peer
)
582 struct bgp_node
*rn1
;
583 struct bgp_node
*rn2
;
588 p
.prefixlen
= IPV6_MAX_BITLEN
;
589 p
.u
.prefix6
= nexthop
;
591 rn1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
596 p
.prefixlen
= IPV6_MAX_BITLEN
;
597 p
.u
.prefix6
= peer
->su
.sin6
.sin6_addr
;
599 rn2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP6
], &p
);
601 bgp_unlock_node(rn1
);
607 bgp_unlock_node(rn1
);
608 bgp_unlock_node(rn2
);
613 bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop
,
614 struct update_subgroup
*subgrp
,
615 struct peer
*exclude
)
617 struct bgp_node
*rn1
= NULL
, *rn2
= NULL
;
618 struct peer_af
*paf
= NULL
;
619 struct prefix p
= {0}, np
= {0};
620 struct bgp
*bgp
= NULL
;
622 np
.family
= AF_INET6
;
623 np
.prefixlen
= IPV6_MAX_BITLEN
;
624 np
.u
.prefix6
= nexthop
;
627 p
.prefixlen
= IPV6_MAX_BITLEN
;
629 bgp
= SUBGRP_INST(subgrp
);
630 rn1
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &np
);
634 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
635 /* Skip peer we're told to exclude - e.g., source of route. */
636 if (paf
->peer
== exclude
)
639 p
.u
.prefix6
= paf
->peer
->su
.sin6
.sin6_addr
;
640 rn2
= bgp_node_match(bgp
->connected_table
[AFI_IP6
], &p
);
642 bgp_unlock_node(rn1
);
643 bgp_unlock_node(rn2
);
648 bgp_unlock_node(rn2
);
651 bgp_unlock_node(rn1
);
655 bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
656 struct update_subgroup
*subgrp
,
657 struct peer
*exclude
)
659 struct bgp_node
*rn1
, *rn2
;
665 np
.prefixlen
= IPV4_MAX_BITLEN
;
666 np
.u
.prefix4
= nexthop
;
669 p
.prefixlen
= IPV4_MAX_BITLEN
;
671 bgp
= SUBGRP_INST(subgrp
);
672 rn1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
676 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
677 /* Skip peer we're told to exclude - e.g., source of route. */
678 if (paf
->peer
== exclude
)
681 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
683 rn2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
685 bgp_unlock_node(rn1
);
686 bgp_unlock_node(rn2
);
691 bgp_unlock_node(rn2
);
694 bgp_unlock_node(rn1
);
698 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
699 struct bgp_nexthop_cache
*bnc
)
701 char buf
[PREFIX2STR_BUFFER
];
702 struct nexthop
*nexthop
;
704 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
705 switch (nexthop
->type
) {
706 case NEXTHOP_TYPE_IPV6
:
707 vty_out(vty
, " gate %s\n",
708 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
711 case NEXTHOP_TYPE_IPV6_IFINDEX
:
712 vty_out(vty
, " gate %s, if %s\n",
713 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
715 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
717 case NEXTHOP_TYPE_IPV4
:
718 vty_out(vty
, " gate %s\n",
719 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
722 case NEXTHOP_TYPE_IFINDEX
:
723 vty_out(vty
, " if %s\n",
724 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
726 case NEXTHOP_TYPE_IPV4_IFINDEX
:
727 vty_out(vty
, " gate %s, if %s\n",
728 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
730 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
732 case NEXTHOP_TYPE_BLACKHOLE
:
733 vty_out(vty
, " blackhole\n");
736 vty_out(vty
, " invalid nexthop type %u\n",
741 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
, int detail
,
745 struct bgp_nexthop_cache
*bnc
;
746 char buf
[PREFIX2STR_BUFFER
];
749 struct bgp_table
**table
;
752 vty_out(vty
, "Current BGP import check cache:\n");
754 vty_out(vty
, "Current BGP nexthop cache:\n");
756 table
= bgp
->import_check_table
;
758 table
= bgp
->nexthop_cache_table
;
759 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
760 if (!table
|| !table
[afi
])
762 for (rn
= bgp_table_top(table
[afi
]); rn
;
763 rn
= bgp_route_next(rn
)) {
765 const struct prefix
*p
= bgp_node_get_prefix(rn
);
767 bnc
= bgp_node_get_bgp_nexthop_info(rn
);
770 peer
= (struct peer
*)bnc
->nht_info
;
772 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
774 " %s valid [IGP metric %d], #paths %d",
775 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
777 bnc
->metric
, bnc
->path_count
);
779 vty_out(vty
, ", peer %s", peer
->host
);
785 bgp_show_nexthops_detail(vty
, bgp
, bnc
);
788 vty_out(vty
, " %s invalid",
789 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
792 vty_out(vty
, ", peer %s", peer
->host
);
794 if (CHECK_FLAG(bnc
->flags
,
795 BGP_NEXTHOP_CONNECTED
))
796 vty_out(vty
, " Must be Connected\n");
797 if (!CHECK_FLAG(bnc
->flags
,
798 BGP_NEXTHOP_REGISTERED
))
799 vty_out(vty
, " Is not Registered\n");
801 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
802 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
808 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
809 int detail
, bool import_table
)
814 bgp
= bgp_lookup_by_name(name
);
816 bgp
= bgp_get_default();
818 vty_out(vty
, "%% No such BGP instance exist\n");
822 bgp_show_nexthops(vty
, bgp
, detail
, import_table
);
827 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
)
829 struct listnode
*node
, *nnode
;
832 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
833 vty_out(vty
, "\nInstance %s:\n",
834 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
837 bgp_show_nexthops(vty
, bgp
, 0, false);
841 DEFUN (show_ip_bgp_nexthop
,
842 show_ip_bgp_nexthop_cmd
,
843 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
847 BGP_INSTANCE_HELP_STR
848 "BGP nexthop table\n"
849 "Show detailed information\n")
854 if (argv_find(argv
, argc
, "view", &idx
)
855 || argv_find(argv
, argc
, "vrf", &idx
))
856 vrf
= argv
[++idx
]->arg
;
857 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
859 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
, false);
862 DEFUN (show_ip_bgp_import_check
,
863 show_ip_bgp_import_check_cmd
,
864 "show [ip] bgp [<view|vrf> VIEWVRFNAME] import-check-table [detail]",
868 BGP_INSTANCE_HELP_STR
869 "BGP import check table\n"
870 "Show detailed information\n")
875 if (argv_find(argv
, argc
, "view", &idx
)
876 || argv_find(argv
, argc
, "vrf", &idx
))
877 vrf
= argv
[++idx
]->arg
;
878 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
879 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
, true);
882 DEFUN (show_ip_bgp_instance_all_nexthop
,
883 show_ip_bgp_instance_all_nexthop_cmd
,
884 "show [ip] bgp <view|vrf> all nexthop",
888 BGP_INSTANCE_ALL_HELP_STR
889 "BGP nexthop table\n")
891 bgp_show_all_instances_nexthops_vty(vty
);
895 void bgp_scan_init(struct bgp
*bgp
)
899 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
900 bgp
->nexthop_cache_table
[afi
] =
901 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
902 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
904 bgp
->import_check_table
[afi
] =
905 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
909 void bgp_scan_vty_init(void)
911 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
912 install_element(VIEW_NODE
, &show_ip_bgp_import_check_cmd
);
913 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
916 void bgp_scan_finish(struct bgp
*bgp
)
920 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
921 /* Only the current one needs to be reset. */
922 bgp_nexthop_cache_reset(bgp
->nexthop_cache_table
[afi
]);
923 bgp_table_unlock(bgp
->nexthop_cache_table
[afi
]);
924 bgp
->nexthop_cache_table
[afi
] = NULL
;
926 bgp
->connected_table
[afi
]->route_table
->cleanup
=
927 bgp_connected_cleanup
;
928 bgp_table_unlock(bgp
->connected_table
[afi
]);
929 bgp
->connected_table
[afi
] = NULL
;
931 bgp_table_unlock(bgp
->import_check_table
[afi
]);
932 bgp
->import_check_table
[afi
] = NULL
;