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"
47 #include "zebra/rib.h"
48 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
50 DEFINE_MTYPE_STATIC(BGPD
, MARTIAN_STRING
, "BGP Martian Address Intf String");
52 char *bnc_str(struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
54 prefix2str(&(bnc
->node
->p
), buf
, size
);
58 void bnc_nexthop_free(struct bgp_nexthop_cache
*bnc
)
60 nexthops_free(bnc
->nexthop
);
63 struct bgp_nexthop_cache
*bnc_new(void)
65 struct bgp_nexthop_cache
*bnc
;
67 bnc
= XCALLOC(MTYPE_BGP_NEXTHOP_CACHE
,
68 sizeof(struct bgp_nexthop_cache
));
69 LIST_INIT(&(bnc
->paths
));
73 void bnc_free(struct bgp_nexthop_cache
*bnc
)
75 bnc_nexthop_free(bnc
);
76 XFREE(MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
79 /* Reset and free all BGP nexthop cache. */
80 static void bgp_nexthop_cache_reset(struct bgp_table
*table
)
83 struct bgp_nexthop_cache
*bnc
;
85 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
86 bnc
= bgp_nexthop_get_node_info(rn
);
90 while (!LIST_EMPTY(&(bnc
->paths
))) {
91 struct bgp_path_info
*path
= LIST_FIRST(&(bnc
->paths
));
93 path_nh_map(path
, bnc
, false);
97 bgp_nexthop_set_node_info(rn
, NULL
);
102 static void *bgp_tip_hash_alloc(void *p
)
104 const struct in_addr
*val
= (const struct in_addr
*)p
;
105 struct tip_addr
*addr
;
107 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
109 addr
->addr
.s_addr
= val
->s_addr
;
114 static void bgp_tip_hash_free(void *addr
)
116 XFREE(MTYPE_TIP_ADDR
, addr
);
119 static unsigned int bgp_tip_hash_key_make(void *p
)
121 const struct tip_addr
*addr
= p
;
123 return jhash_1word(addr
->addr
.s_addr
, 0);
126 static bool bgp_tip_hash_cmp(const void *p1
, const void *p2
)
128 const struct tip_addr
*addr1
= p1
;
129 const struct tip_addr
*addr2
= p2
;
131 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
134 void bgp_tip_hash_init(struct bgp
*bgp
)
136 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
, bgp_tip_hash_cmp
,
140 void bgp_tip_hash_destroy(struct bgp
*bgp
)
142 if (bgp
->tip_hash
== NULL
)
144 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
145 hash_free(bgp
->tip_hash
);
146 bgp
->tip_hash
= NULL
;
149 void bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
152 struct tip_addr
*addr
;
156 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
163 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
166 struct tip_addr
*addr
;
170 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
171 /* may have been deleted earlier by bgp_interface_down() */
177 if (addr
->refcnt
== 0) {
178 hash_release(bgp
->tip_hash
, addr
);
179 XFREE(MTYPE_TIP_ADDR
, addr
);
183 /* BGP own address structure */
186 struct list
*ifp_name_list
;
189 static void show_address_entry(struct hash_backet
*backet
, void *args
)
191 struct vty
*vty
= (struct vty
*)args
;
192 struct bgp_addr
*addr
= (struct bgp_addr
*)backet
->data
;
194 struct listnode
*node
;
196 vty_out(vty
, "addr: %s, count: %d : ", inet_ntoa(addr
->addr
),
197 addr
->ifp_name_list
->count
);
199 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
200 vty_out(vty
, " %s,", name
);
206 void bgp_nexthop_show_address_hash(struct vty
*vty
, struct bgp
*bgp
)
208 hash_iterate(bgp
->address_hash
,
209 (void (*)(struct hash_backet
*, void *))show_address_entry
,
213 static void bgp_address_hash_string_del(void *val
)
217 XFREE(MTYPE_MARTIAN_STRING
, data
);
220 static void *bgp_address_hash_alloc(void *p
)
222 const struct in_addr
*val
= (const struct in_addr
*)p
;
223 struct bgp_addr
*addr
;
225 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
226 addr
->addr
.s_addr
= val
->s_addr
;
228 addr
->ifp_name_list
= list_new();
229 addr
->ifp_name_list
->del
= bgp_address_hash_string_del
;
234 static void bgp_address_hash_free(void *data
)
236 struct bgp_addr
*addr
= data
;
238 list_delete(&addr
->ifp_name_list
);
239 XFREE(MTYPE_BGP_ADDR
, addr
);
242 static unsigned int bgp_address_hash_key_make(void *p
)
244 const struct bgp_addr
*addr
= p
;
246 return jhash_1word(addr
->addr
.s_addr
, 0);
249 static bool bgp_address_hash_cmp(const void *p1
, const void *p2
)
251 const struct bgp_addr
*addr1
= p1
;
252 const struct bgp_addr
*addr2
= p2
;
254 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
257 void bgp_address_init(struct bgp
*bgp
)
260 hash_create(bgp_address_hash_key_make
, bgp_address_hash_cmp
,
264 void bgp_address_destroy(struct bgp
*bgp
)
266 if (bgp
->address_hash
== NULL
)
268 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
269 hash_free(bgp
->address_hash
);
270 bgp
->address_hash
= NULL
;
273 static void bgp_address_add(struct bgp
*bgp
, struct connected
*ifc
,
277 struct bgp_addr
*addr
;
278 struct listnode
*node
;
281 tmp
.addr
= p
->u
.prefix4
;
283 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
285 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
286 if (strcmp(ifc
->ifp
->name
, name
) == 0)
290 name
= XSTRDUP(MTYPE_MARTIAN_STRING
, ifc
->ifp
->name
);
291 listnode_add(addr
->ifp_name_list
, name
);
295 static void bgp_address_del(struct bgp
*bgp
, struct connected
*ifc
,
299 struct bgp_addr
*addr
;
300 struct listnode
*node
;
303 tmp
.addr
= p
->u
.prefix4
;
305 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
306 /* may have been deleted earlier by bgp_interface_down() */
310 for (ALL_LIST_ELEMENTS_RO(addr
->ifp_name_list
, node
, name
)) {
311 if (strcmp(ifc
->ifp
->name
, name
) == 0)
316 list_delete_node(addr
->ifp_name_list
, node
);
317 XFREE(MTYPE_MARTIAN_STRING
, name
);
320 if (addr
->ifp_name_list
->count
== 0) {
321 hash_release(bgp
->address_hash
, addr
);
322 list_delete(&addr
->ifp_name_list
);
323 XFREE(MTYPE_BGP_ADDR
, addr
);
328 struct bgp_connected_ref
{
332 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
337 struct bgp_connected_ref
*bc
;
338 struct listnode
*node
, *nnode
;
343 p
= *(CONNECTED_PREFIX(ifc
));
344 if (addr
->family
== AF_INET
) {
345 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
347 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
350 bgp_address_add(bgp
, ifc
, addr
);
352 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP
],
353 (struct prefix
*)&p
);
354 bc
= bgp_connected_get_node_info(rn
);
358 bc
= XCALLOC(MTYPE_BGP_CONN
,
359 sizeof(struct bgp_connected_ref
));
361 bgp_connected_set_node_info(rn
, bc
);
364 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
366 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
367 && peer
->status
!= Established
368 && !CHECK_FLAG(peer
->flags
,
369 PEER_FLAG_IFPEER_V6ONLY
)) {
370 if (peer_active(peer
))
371 BGP_EVENT_ADD(peer
, BGP_Stop
);
372 BGP_EVENT_ADD(peer
, BGP_Start
);
375 } else if (addr
->family
== AF_INET6
) {
376 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
378 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
381 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
384 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP6
],
385 (struct prefix
*)&p
);
387 bc
= bgp_connected_get_node_info(rn
);
391 bc
= XCALLOC(MTYPE_BGP_CONN
,
392 sizeof(struct bgp_connected_ref
));
394 bgp_connected_set_node_info(rn
, bc
);
399 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
403 struct bgp_node
*rn
= NULL
;
404 struct bgp_connected_ref
*bc
;
408 p
= *(CONNECTED_PREFIX(ifc
));
410 if (addr
->family
== AF_INET
) {
411 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
414 bgp_address_del(bgp
, ifc
, addr
);
416 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
417 } else if (addr
->family
== AF_INET6
) {
418 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
421 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
424 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
],
425 (struct prefix
*)&p
);
431 bc
= bgp_connected_get_node_info(rn
);
433 if (bc
->refcnt
== 0) {
434 XFREE(MTYPE_BGP_CONN
, bc
);
435 bgp_connected_set_node_info(rn
, NULL
);
441 static void bgp_connected_cleanup(struct route_table
*table
,
442 struct route_node
*rn
)
444 struct bgp_connected_ref
*bc
;
445 struct bgp_node
*bn
= bgp_node_from_rnode(rn
);
447 bc
= bgp_connected_get_node_info(bn
);
452 if (bc
->refcnt
== 0) {
453 XFREE(MTYPE_BGP_CONN
, bc
);
454 bgp_connected_set_node_info(bn
, NULL
);
458 int bgp_nexthop_self(struct bgp
*bgp
, struct in_addr nh_addr
)
460 struct bgp_addr tmp
, *addr
;
461 struct tip_addr tmp_tip
, *tip
;
465 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
469 tmp_tip
.addr
= nh_addr
;
470 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
477 int bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
479 struct bgp_node
*rn1
;
480 struct bgp_node
*rn2
;
485 p
.prefixlen
= IPV4_MAX_BITLEN
;
486 p
.u
.prefix4
= nexthop
;
488 rn1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
493 p
.prefixlen
= IPV4_MAX_BITLEN
;
494 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
496 rn2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
498 bgp_unlock_node(rn1
);
502 ret
= (rn1
== rn2
) ? 1 : 0;
504 bgp_unlock_node(rn1
);
505 bgp_unlock_node(rn2
);
510 int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop
,
511 struct update_subgroup
*subgrp
)
513 struct bgp_node
*rn1
, *rn2
;
519 np
.prefixlen
= IPV4_MAX_BITLEN
;
520 np
.u
.prefix4
= nexthop
;
523 p
.prefixlen
= IPV4_MAX_BITLEN
;
525 bgp
= SUBGRP_INST(subgrp
);
526 rn1
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &np
);
530 SUBGRP_FOREACH_PEER (subgrp
, paf
) {
531 p
.u
.prefix4
= paf
->peer
->su
.sin
.sin_addr
;
533 rn2
= bgp_node_match(bgp
->connected_table
[AFI_IP
], &p
);
535 bgp_unlock_node(rn1
);
536 bgp_unlock_node(rn2
);
541 bgp_unlock_node(rn2
);
544 bgp_unlock_node(rn1
);
548 static void bgp_show_nexthops_detail(struct vty
*vty
, struct bgp
*bgp
,
549 struct bgp_nexthop_cache
*bnc
)
551 char buf
[PREFIX2STR_BUFFER
];
552 struct nexthop
*nexthop
;
554 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
555 switch (nexthop
->type
) {
556 case NEXTHOP_TYPE_IPV6
:
557 vty_out(vty
, " gate %s\n",
558 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
561 case NEXTHOP_TYPE_IPV6_IFINDEX
:
562 vty_out(vty
, " gate %s, if %s\n",
563 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
565 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
567 case NEXTHOP_TYPE_IPV4
:
568 vty_out(vty
, " gate %s\n",
569 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
572 case NEXTHOP_TYPE_IFINDEX
:
573 vty_out(vty
, " if %s\n",
574 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
576 case NEXTHOP_TYPE_IPV4_IFINDEX
:
577 vty_out(vty
, " gate %s, if %s\n",
578 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
580 ifindex2ifname(nexthop
->ifindex
, bgp
->vrf_id
));
582 case NEXTHOP_TYPE_BLACKHOLE
:
583 vty_out(vty
, " blackhole\n");
586 vty_out(vty
, " invalid nexthop type %u\n",
591 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
, int detail
)
594 struct bgp_nexthop_cache
*bnc
;
595 char buf
[PREFIX2STR_BUFFER
];
599 vty_out(vty
, "Current BGP nexthop cache:\n");
600 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
601 if (!bgp
->nexthop_cache_table
[afi
])
604 for (rn
= bgp_table_top(bgp
->nexthop_cache_table
[afi
]); rn
;
605 rn
= bgp_route_next(rn
)) {
606 bnc
= bgp_nexthop_get_node_info(rn
);
610 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
612 " %s valid [IGP metric %d], #paths %d\n",
613 inet_ntop(rn
->p
.family
,
614 &rn
->p
.u
.prefix
, buf
,
616 bnc
->metric
, bnc
->path_count
);
621 bgp_show_nexthops_detail(vty
, bgp
, bnc
);
624 vty_out(vty
, " %s invalid\n",
625 inet_ntop(rn
->p
.family
,
626 &rn
->p
.u
.prefix
, buf
,
628 if (CHECK_FLAG(bnc
->flags
,
629 BGP_NEXTHOP_CONNECTED
))
630 vty_out(vty
, " Must be Connected\n");
631 if (!CHECK_FLAG(bnc
->flags
,
632 BGP_NEXTHOP_REGISTERED
))
633 vty_out(vty
, " Is not Registered\n");
635 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
636 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
642 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
648 bgp
= bgp_lookup_by_name(name
);
650 bgp
= bgp_get_default();
652 vty_out(vty
, "%% No such BGP instance exist\n");
656 bgp_show_nexthops(vty
, bgp
, detail
);
661 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
)
663 struct listnode
*node
, *nnode
;
666 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
667 vty_out(vty
, "\nInstance %s:\n",
668 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
671 bgp_show_nexthops(vty
, bgp
, 0);
675 DEFUN (show_ip_bgp_nexthop
,
676 show_ip_bgp_nexthop_cmd
,
677 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
681 BGP_INSTANCE_HELP_STR
682 "BGP nexthop table\n"
683 "Show detailed information\n")
688 if (argv_find(argv
, argc
, "view", &idx
)
689 || argv_find(argv
, argc
, "vrf", &idx
))
690 vrf
= argv
[++idx
]->arg
;
691 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
692 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
);
695 DEFUN (show_ip_bgp_instance_all_nexthop
,
696 show_ip_bgp_instance_all_nexthop_cmd
,
697 "show [ip] bgp <view|vrf> all nexthop",
701 BGP_INSTANCE_ALL_HELP_STR
702 "BGP nexthop table\n")
704 bgp_show_all_instances_nexthops_vty(vty
);
708 void bgp_scan_init(struct bgp
*bgp
)
712 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
713 bgp
->nexthop_cache_table
[afi
] =
714 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
715 bgp
->connected_table
[afi
] = bgp_table_init(bgp
, afi
,
717 bgp
->import_check_table
[afi
] =
718 bgp_table_init(bgp
, afi
, SAFI_UNICAST
);
722 void bgp_scan_vty_init(void)
724 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
725 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
728 void bgp_scan_finish(struct bgp
*bgp
)
732 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
733 /* Only the current one needs to be reset. */
734 bgp_nexthop_cache_reset(bgp
->nexthop_cache_table
[afi
]);
735 bgp_table_unlock(bgp
->nexthop_cache_table
[afi
]);
736 bgp
->nexthop_cache_table
[afi
] = NULL
;
738 bgp
->connected_table
[afi
]->route_table
->cleanup
=
739 bgp_connected_cleanup
;
740 bgp_table_unlock(bgp
->connected_table
[afi
]);
741 bgp
->connected_table
[afi
] = NULL
;
743 bgp_table_unlock(bgp
->import_check_table
[afi
]);
744 bgp
->import_check_table
[afi
] = NULL
;