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 char *bnc_str(struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
52 prefix2str(&(bnc
->node
->p
), 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 if ((bnc
= rn
->info
) != NULL
) {
91 static void *bgp_tip_hash_alloc(void *p
)
93 const struct in_addr
*val
= (const struct in_addr
*)p
;
94 struct tip_addr
*addr
;
96 addr
= XMALLOC(MTYPE_TIP_ADDR
, sizeof(struct tip_addr
));
98 addr
->addr
.s_addr
= val
->s_addr
;
103 static void bgp_tip_hash_free(void *addr
)
105 XFREE(MTYPE_TIP_ADDR
, addr
);
108 static unsigned int bgp_tip_hash_key_make(void *p
)
110 const struct tip_addr
*addr
= p
;
112 return jhash_1word(addr
->addr
.s_addr
, 0);
115 static int bgp_tip_hash_cmp(const void *p1
, const void *p2
)
117 const struct tip_addr
*addr1
= p1
;
118 const struct tip_addr
*addr2
= p2
;
120 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
123 void bgp_tip_hash_init(struct bgp
*bgp
)
125 bgp
->tip_hash
= hash_create(bgp_tip_hash_key_make
,
130 void bgp_tip_hash_destroy(struct bgp
*bgp
)
132 if (bgp
->tip_hash
== NULL
)
134 hash_clean(bgp
->tip_hash
, bgp_tip_hash_free
);
135 hash_free(bgp
->tip_hash
);
136 bgp
->tip_hash
= NULL
;
139 void bgp_tip_add(struct bgp
*bgp
, struct in_addr
*tip
)
142 struct tip_addr
*addr
;
146 addr
= hash_get(bgp
->tip_hash
, &tmp
, bgp_tip_hash_alloc
);
153 void bgp_tip_del(struct bgp
*bgp
, struct in_addr
*tip
)
156 struct tip_addr
*addr
;
160 addr
= hash_lookup(bgp
->tip_hash
, &tmp
);
161 /* may have been deleted earlier by bgp_interface_down() */
167 if (addr
->refcnt
== 0) {
168 hash_release(bgp
->tip_hash
, addr
);
169 XFREE(MTYPE_TIP_ADDR
, addr
);
173 static void *bgp_address_hash_alloc(void *p
)
175 const struct in_addr
*val
= (const struct in_addr
*)p
;
176 struct bgp_addr
*addr
;
178 addr
= XMALLOC(MTYPE_BGP_ADDR
, sizeof(struct bgp_addr
));
180 addr
->addr
.s_addr
= val
->s_addr
;
185 static void bgp_address_hash_free(void *addr
)
187 XFREE(MTYPE_BGP_ADDR
, addr
);
190 static unsigned int bgp_address_hash_key_make(void *p
)
192 const struct bgp_addr
*addr
= p
;
194 return jhash_1word(addr
->addr
.s_addr
, 0);
197 static int bgp_address_hash_cmp(const void *p1
, const void *p2
)
199 const struct bgp_addr
*addr1
= p1
;
200 const struct bgp_addr
*addr2
= p2
;
202 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
205 void bgp_address_init(struct bgp
*bgp
)
207 bgp
->address_hash
= hash_create(bgp_address_hash_key_make
,
208 bgp_address_hash_cmp
,
212 void bgp_address_destroy(struct bgp
*bgp
)
214 if (bgp
->address_hash
== NULL
)
216 hash_clean(bgp
->address_hash
, bgp_address_hash_free
);
217 hash_free(bgp
->address_hash
);
218 bgp
->address_hash
= NULL
;
221 static void bgp_address_add(struct bgp
*bgp
, struct prefix
*p
)
224 struct bgp_addr
*addr
;
226 tmp
.addr
= p
->u
.prefix4
;
228 addr
= hash_get(bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
235 static void bgp_address_del(struct bgp
*bgp
, struct prefix
*p
)
238 struct bgp_addr
*addr
;
240 tmp
.addr
= p
->u
.prefix4
;
242 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
243 /* may have been deleted earlier by bgp_interface_down() */
249 if (addr
->refcnt
== 0) {
250 hash_release(bgp
->address_hash
, addr
);
251 XFREE(MTYPE_BGP_ADDR
, addr
);
256 struct bgp_connected_ref
{
260 void bgp_connected_add(struct bgp
*bgp
, struct connected
*ifc
)
265 struct bgp_connected_ref
*bc
;
266 struct listnode
*node
, *nnode
;
271 p
= *(CONNECTED_PREFIX(ifc
));
272 if (addr
->family
== AF_INET
) {
273 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
275 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
278 bgp_address_add(bgp
, addr
);
280 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP
],
281 (struct prefix
*)&p
);
286 bc
= XCALLOC(MTYPE_BGP_CONN
,
287 sizeof(struct bgp_connected_ref
));
292 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
294 && (strcmp(peer
->conf_if
, ifc
->ifp
->name
) == 0)
295 && peer
->status
!= Established
296 && !CHECK_FLAG(peer
->flags
,
297 PEER_FLAG_IFPEER_V6ONLY
)) {
298 if (peer_active(peer
))
299 BGP_EVENT_ADD(peer
, BGP_Stop
);
300 BGP_EVENT_ADD(peer
, BGP_Start
);
303 } else if (addr
->family
== AF_INET6
) {
304 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
306 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
309 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
312 rn
= bgp_node_get(bgp
->connected_table
[AFI_IP6
],
313 (struct prefix
*)&p
);
318 bc
= XCALLOC(MTYPE_BGP_CONN
,
319 sizeof(struct bgp_connected_ref
));
326 void bgp_connected_delete(struct bgp
*bgp
, struct connected
*ifc
)
331 struct bgp_connected_ref
*bc
;
335 p
= *(CONNECTED_PREFIX(ifc
));
336 if (addr
->family
== AF_INET
) {
337 apply_mask_ipv4((struct prefix_ipv4
*)&p
);
339 if (prefix_ipv4_any((struct prefix_ipv4
*)&p
))
342 bgp_address_del(bgp
, addr
);
344 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP
], &p
);
350 if (bc
->refcnt
== 0) {
351 XFREE(MTYPE_BGP_CONN
, bc
);
356 } else if (addr
->family
== AF_INET6
) {
357 apply_mask_ipv6((struct prefix_ipv6
*)&p
);
359 if (IN6_IS_ADDR_UNSPECIFIED(&p
.u
.prefix6
))
362 if (IN6_IS_ADDR_LINKLOCAL(&p
.u
.prefix6
))
365 rn
= bgp_node_lookup(bgp
->connected_table
[AFI_IP6
],
366 (struct prefix
*)&p
);
372 if (bc
->refcnt
== 0) {
373 XFREE(MTYPE_BGP_CONN
, bc
);
381 int bgp_nexthop_self(struct bgp
*bgp
, struct in_addr nh_addr
)
383 struct bgp_addr tmp
, *addr
;
384 struct tip_addr tmp_tip
, *tip
;
388 addr
= hash_lookup(bgp
->address_hash
, &tmp
);
392 tmp_tip
.addr
= nh_addr
;
393 tip
= hash_lookup(bgp
->tip_hash
, &tmp_tip
);
400 int bgp_multiaccess_check_v4(struct in_addr nexthop
, struct peer
*peer
)
402 struct bgp_node
*rn1
;
403 struct bgp_node
*rn2
;
408 p
.prefixlen
= IPV4_MAX_BITLEN
;
409 p
.u
.prefix4
= nexthop
;
411 rn1
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
416 p
.prefixlen
= IPV4_MAX_BITLEN
;
417 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
419 rn2
= bgp_node_match(peer
->bgp
->connected_table
[AFI_IP
], &p
);
421 bgp_unlock_node(rn1
);
425 ret
= (rn1
== rn2
) ? 1 : 0;
427 bgp_unlock_node(rn1
);
428 bgp_unlock_node(rn2
);
433 static void bgp_show_nexthops(struct vty
*vty
, struct bgp
*bgp
, int detail
)
436 struct bgp_nexthop_cache
*bnc
;
437 char buf
[PREFIX2STR_BUFFER
];
438 struct nexthop
*nexthop
;
442 vty_out(vty
, "Current BGP nexthop cache:\n");
443 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
444 if (!bgp
->nexthop_cache_table
[afi
])
447 for (rn
= bgp_table_top(bgp
->nexthop_cache_table
[afi
]); rn
;
448 rn
= bgp_route_next(rn
)) {
449 if ((bnc
= rn
->info
) != NULL
) {
450 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
)) {
452 " %s valid [IGP metric %d], #paths %d\n",
453 inet_ntop(rn
->p
.family
,
454 &rn
->p
.u
.prefix
, buf
,
456 bnc
->metric
, bnc
->path_count
);
458 for (nexthop
= bnc
->nexthop
;
460 nexthop
= nexthop
->next
)
461 switch (nexthop
->type
) {
462 case NEXTHOP_TYPE_IPV6
:
472 case NEXTHOP_TYPE_IPV6_IFINDEX
:
485 case NEXTHOP_TYPE_IPV4
:
495 case NEXTHOP_TYPE_IFINDEX
:
502 case NEXTHOP_TYPE_IPV4_IFINDEX
:
517 " invalid nexthop type %u\n",
521 vty_out(vty
, " %s invalid\n",
522 inet_ntop(rn
->p
.family
,
523 &rn
->p
.u
.prefix
, buf
,
525 if (CHECK_FLAG(bnc
->flags
,
526 BGP_NEXTHOP_CONNECTED
))
528 " Must be Connected\n");
531 - (bgp_clock() - bnc
->last_update
);
532 vty_out(vty
, " Last update: %s", ctime(&tbuf
));
539 static int show_ip_bgp_nexthop_table(struct vty
*vty
, const char *name
,
545 bgp
= bgp_lookup_by_name(name
);
547 bgp
= bgp_get_default();
549 vty_out(vty
, "%% No such BGP instance exist\n");
553 bgp_show_nexthops(vty
, bgp
, detail
);
558 static void bgp_show_all_instances_nexthops_vty(struct vty
*vty
)
560 struct listnode
*node
, *nnode
;
563 for (ALL_LIST_ELEMENTS(bm
->bgp
, node
, nnode
, bgp
)) {
564 vty_out(vty
, "\nInstance %s:\n",
565 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
)
568 bgp_show_nexthops(vty
, bgp
, 0);
572 DEFUN (show_ip_bgp_nexthop
,
573 show_ip_bgp_nexthop_cmd
,
574 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
578 BGP_INSTANCE_HELP_STR
579 "BGP nexthop table\n"
580 "Show detailed information\n")
585 if (argv_find(argv
, argc
, "view", &idx
)
586 || argv_find(argv
, argc
, "vrf", &idx
))
587 vrf
= argv
[++idx
]->arg
;
588 int detail
= argv_find(argv
, argc
, "detail", &idx
) ? 1 : 0;
589 return show_ip_bgp_nexthop_table(vty
, vrf
, detail
);
592 DEFUN (show_ip_bgp_instance_all_nexthop
,
593 show_ip_bgp_instance_all_nexthop_cmd
,
594 "show [ip] bgp <view|vrf> all nexthop",
598 BGP_INSTANCE_ALL_HELP_STR
599 "BGP nexthop table\n")
601 bgp_show_all_instances_nexthops_vty(vty
);
605 void bgp_scan_init(struct bgp
*bgp
)
609 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
610 bgp
->nexthop_cache_table
[afi
] =
611 bgp_table_init(afi
, SAFI_UNICAST
);
612 bgp
->connected_table
[afi
] = bgp_table_init(afi
, SAFI_UNICAST
);
613 bgp
->import_check_table
[afi
] =
614 bgp_table_init(afi
, SAFI_UNICAST
);
618 void bgp_scan_vty_init(void)
620 install_element(VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
621 install_element(VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
624 void bgp_scan_finish(struct bgp
*bgp
)
628 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
629 /* Only the current one needs to be reset. */
630 bgp_nexthop_cache_reset(bgp
->nexthop_cache_table
[afi
]);
631 bgp_table_unlock(bgp
->nexthop_cache_table
[afi
]);
632 bgp
->nexthop_cache_table
[afi
] = NULL
;
634 bgp_table_unlock(bgp
->connected_table
[afi
]);
635 bgp
->connected_table
[afi
] = NULL
;
637 bgp_table_unlock(bgp
->import_check_table
[afi
]);
638 bgp
->import_check_table
[afi
] = NULL
;