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
17 along with GNU Zebra; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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. */
51 bnc_str (struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
53 prefix2str(&(bnc
->node
->p
), buf
, size
);
58 bnc_nexthop_free (struct bgp_nexthop_cache
*bnc
)
60 nexthops_free(bnc
->nexthop
);
63 struct bgp_nexthop_cache
*
66 struct bgp_nexthop_cache
*bnc
;
68 bnc
= XCALLOC (MTYPE_BGP_NEXTHOP_CACHE
, sizeof (struct bgp_nexthop_cache
));
69 LIST_INIT(&(bnc
->paths
));
74 bnc_free (struct bgp_nexthop_cache
*bnc
)
76 bnc_nexthop_free (bnc
);
77 XFREE (MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
80 /* Reset and free all BGP nexthop cache. */
82 bgp_nexthop_cache_reset (struct bgp_table
*table
)
85 struct bgp_nexthop_cache
*bnc
;
87 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
88 if ((bnc
= rn
->info
) != NULL
)
96 /* BGP own address structure */
104 bgp_address_hash_alloc (void *p
)
106 const struct in_addr
*val
= (const struct in_addr
*)p
;
107 struct bgp_addr
*addr
;
109 addr
= XMALLOC (MTYPE_BGP_ADDR
, sizeof (struct bgp_addr
));
111 addr
->addr
.s_addr
= val
->s_addr
;
117 bgp_address_hash_key_make (void *p
)
119 const struct bgp_addr
*addr
= p
;
121 return jhash_1word(addr
->addr
.s_addr
, 0);
125 bgp_address_hash_cmp (const void *p1
, const void *p2
)
127 const struct bgp_addr
*addr1
= p1
;
128 const struct bgp_addr
*addr2
= p2
;
130 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
134 bgp_address_init (struct bgp
*bgp
)
136 bgp
->address_hash
= hash_create (bgp_address_hash_key_make
,
137 bgp_address_hash_cmp
);
141 bgp_address_destroy (struct bgp
*bgp
)
143 if (bgp
->address_hash
== NULL
)
145 hash_clean(bgp
->address_hash
, NULL
);
146 hash_free(bgp
->address_hash
);
147 bgp
->address_hash
= NULL
;
151 bgp_address_add (struct bgp
*bgp
, struct prefix
*p
)
154 struct bgp_addr
*addr
;
156 tmp
.addr
= p
->u
.prefix4
;
158 addr
= hash_get (bgp
->address_hash
, &tmp
, bgp_address_hash_alloc
);
166 bgp_address_del (struct bgp
*bgp
, struct prefix
*p
)
169 struct bgp_addr
*addr
;
171 tmp
.addr
= p
->u
.prefix4
;
173 addr
= hash_lookup (bgp
->address_hash
, &tmp
);
174 /* may have been deleted earlier by bgp_interface_down() */
180 if (addr
->refcnt
== 0)
182 hash_release (bgp
->address_hash
, addr
);
183 XFREE (MTYPE_BGP_ADDR
, addr
);
188 struct bgp_connected_ref
194 bgp_connected_add (struct bgp
*bgp
, struct connected
*ifc
)
199 struct bgp_connected_ref
*bc
;
200 struct listnode
*node
, *nnode
;
205 p
= *(CONNECTED_PREFIX(ifc
));
206 if (addr
->family
== AF_INET
)
208 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
210 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
213 bgp_address_add (bgp
, addr
);
215 rn
= bgp_node_get (bgp
->connected_table
[AFI_IP
], (struct prefix
*) &p
);
223 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
228 for (ALL_LIST_ELEMENTS (bgp
->peer
, node
, nnode
, peer
))
230 if (peer
->conf_if
&& (strcmp (peer
->conf_if
, ifc
->ifp
->name
) == 0) &&
231 peer
->status
!= Established
&&
232 !CHECK_FLAG(peer
->flags
, PEER_FLAG_IFPEER_V6ONLY
))
234 if (peer_active(peer
))
235 BGP_EVENT_ADD (peer
, BGP_Stop
);
236 BGP_EVENT_ADD (peer
, BGP_Start
);
241 else if (addr
->family
== AF_INET6
)
243 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
245 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
248 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
251 rn
= bgp_node_get (bgp
->connected_table
[AFI_IP6
], (struct prefix
*) &p
);
259 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
264 #endif /* HAVE_IPV6 */
268 bgp_connected_delete (struct bgp
*bgp
, struct connected
*ifc
)
273 struct bgp_connected_ref
*bc
;
277 p
= *(CONNECTED_PREFIX(ifc
));
278 if (addr
->family
== AF_INET
)
280 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
282 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
285 bgp_address_del (bgp
, addr
);
287 rn
= bgp_node_lookup (bgp
->connected_table
[AFI_IP
], &p
);
295 XFREE (MTYPE_BGP_CONN
, bc
);
298 bgp_unlock_node (rn
);
299 bgp_unlock_node (rn
);
302 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_lookup (bgp
->connected_table
[AFI_IP6
], (struct prefix
*) &p
);
320 XFREE (MTYPE_BGP_CONN
, bc
);
323 bgp_unlock_node (rn
);
324 bgp_unlock_node (rn
);
326 #endif /* HAVE_IPV6 */
330 bgp_nexthop_self (struct bgp
*bgp
, struct attr
*attr
)
332 struct bgp_addr tmp
, *addr
;
334 tmp
.addr
= attr
->nexthop
;
336 addr
= hash_lookup (bgp
->address_hash
, &tmp
);
344 bgp_multiaccess_check_v4 (struct in_addr nexthop
, struct peer
*peer
)
346 struct bgp_node
*rn1
;
347 struct bgp_node
*rn2
;
352 p
.prefixlen
= IPV4_MAX_BITLEN
;
353 p
.u
.prefix4
= nexthop
;
355 rn1
= bgp_node_match (peer
->bgp
->connected_table
[AFI_IP
], &p
);
360 p
.prefixlen
= IPV4_MAX_BITLEN
;
361 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
363 rn2
= bgp_node_match (peer
->bgp
->connected_table
[AFI_IP
], &p
);
366 bgp_unlock_node(rn1
);
370 ret
= (rn1
== rn2
) ? 1 : 0;
372 bgp_unlock_node(rn1
);
373 bgp_unlock_node(rn2
);
379 bgp_show_nexthops (struct vty
*vty
, struct bgp
*bgp
, int detail
)
382 struct bgp_nexthop_cache
*bnc
;
383 char buf
[PREFIX2STR_BUFFER
];
384 struct nexthop
*nexthop
;
388 vty_out (vty
, "Current BGP nexthop cache:%s", VTY_NEWLINE
);
389 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
391 if (!bgp
->nexthop_cache_table
[afi
])
394 for (rn
= bgp_table_top (bgp
->nexthop_cache_table
[afi
]); rn
; rn
= bgp_route_next (rn
))
396 if ((bnc
= rn
->info
) != NULL
)
398 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
400 vty_out (vty
, " %s valid [IGP metric %d], #paths %d%s",
401 inet_ntop (rn
->p
.family
, &rn
->p
.u
.prefix
, buf
, sizeof (buf
)),
402 bnc
->metric
, bnc
->path_count
, VTY_NEWLINE
);
404 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
405 switch (nexthop
->type
)
407 case NEXTHOP_TYPE_IPV6
:
408 vty_out (vty
, " gate %s%s",
409 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
,
410 buf
, sizeof (buf
)), VTY_NEWLINE
);
412 case NEXTHOP_TYPE_IPV6_IFINDEX
:
413 vty_out(vty
, " gate %s, if %s%s",
414 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
416 ifindex2ifname(nexthop
->ifindex
),
419 case NEXTHOP_TYPE_IPV4
:
420 vty_out (vty
, " gate %s%s",
421 inet_ntop (AF_INET
, &nexthop
->gate
.ipv4
, buf
,
422 sizeof (buf
)), VTY_NEWLINE
);
424 case NEXTHOP_TYPE_IFINDEX
:
425 vty_out (vty
, " if %s%s",
426 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
428 case NEXTHOP_TYPE_IPV4_IFINDEX
:
429 vty_out (vty
, " gate %s, if %s%s",
430 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
432 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
435 vty_out (vty
, " invalid nexthop type %u%s",
436 nexthop
->type
, VTY_NEWLINE
);
441 vty_out (vty
, " %s invalid%s",
442 inet_ntop (rn
->p
.family
, &rn
->p
.u
.prefix
,
443 buf
, sizeof (buf
)), VTY_NEWLINE
);
444 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
445 vty_out (vty
, " Must be Connected%s", VTY_NEWLINE
);
447 #ifdef HAVE_CLOCK_MONOTONIC
448 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
449 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
451 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
452 #endif /* HAVE_CLOCK_MONOTONIC */
453 vty_out(vty
, "%s", VTY_NEWLINE
);
460 show_ip_bgp_nexthop_table (struct vty
*vty
, const char *name
, int detail
)
465 bgp
= bgp_lookup_by_name (name
);
467 bgp
= bgp_get_default ();
470 vty_out (vty
, "%% No such BGP instance exist%s", VTY_NEWLINE
);
474 bgp_show_nexthops (vty
, bgp
, detail
);
480 bgp_show_all_instances_nexthops_vty (struct vty
*vty
)
482 struct listnode
*node
, *nnode
;
485 for (ALL_LIST_ELEMENTS (bm
->bgp
, node
, nnode
, bgp
))
487 vty_out (vty
, "%sInstance %s:%s",
489 (bgp
->inst_type
== BGP_INSTANCE_TYPE_DEFAULT
) ? "Default" : bgp
->name
,
491 bgp_show_nexthops (vty
, bgp
, 0);
495 DEFUN (show_ip_bgp_nexthop
,
496 show_ip_bgp_nexthop_cmd
,
497 "show [ip] bgp [<view|vrf> VRFNAME] nexthop [detail]",
501 BGP_INSTANCE_HELP_STR
502 "BGP nexthop table\n")
505 char *vrf
= argv_find (argv
, argc
, "VRFNAME", &idx
) ? argv
[idx
]->arg
: NULL
;
506 int detail
= argv_find (argv
, argc
, "detail", &idx
) ? 1 : 0;
507 return show_ip_bgp_nexthop_table (vty
, vrf
, detail
);
510 DEFUN (show_ip_bgp_instance_all_nexthop
,
511 show_ip_bgp_instance_all_nexthop_cmd
,
512 "show [ip] bgp <view|vrf> all nexthop",
516 BGP_INSTANCE_ALL_HELP_STR
517 "BGP nexthop table\n")
519 bgp_show_all_instances_nexthops_vty (vty
);
524 bgp_scan_init (struct bgp
*bgp
)
526 bgp
->nexthop_cache_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
527 bgp
->connected_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
528 bgp
->import_check_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
530 bgp
->nexthop_cache_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
531 bgp
->connected_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
532 bgp
->import_check_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
534 bgp
->nexthop_cache_table
[AFI_ETHER
] = bgp_table_init (AFI_ETHER
, SAFI_UNICAST
);
535 bgp
->connected_table
[AFI_ETHER
] = bgp_table_init (AFI_ETHER
, SAFI_UNICAST
);
536 bgp
->import_check_table
[AFI_ETHER
] = bgp_table_init (AFI_ETHER
, SAFI_UNICAST
);
540 bgp_scan_vty_init (void)
542 install_element (VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
543 install_element (VIEW_NODE
, &show_ip_bgp_instance_all_nexthop_cmd
);
547 bgp_scan_finish (struct bgp
*bgp
)
549 /* Only the current one needs to be reset. */
550 bgp_nexthop_cache_reset (bgp
->nexthop_cache_table
[AFI_IP
]);
552 bgp_table_unlock (bgp
->nexthop_cache_table
[AFI_IP
]);
553 bgp
->nexthop_cache_table
[AFI_IP
] = NULL
;
555 bgp_table_unlock (bgp
->connected_table
[AFI_IP
]);
556 bgp
->connected_table
[AFI_IP
] = NULL
;
558 bgp_table_unlock (bgp
->import_check_table
[AFI_IP
]);
559 bgp
->import_check_table
[AFI_IP
] = NULL
;
562 /* Only the current one needs to be reset. */
563 bgp_nexthop_cache_reset (bgp
->nexthop_cache_table
[AFI_IP6
]);
565 bgp_table_unlock (bgp
->nexthop_cache_table
[AFI_IP6
]);
566 bgp
->nexthop_cache_table
[AFI_IP6
] = NULL
;
568 bgp_table_unlock (bgp
->connected_table
[AFI_IP6
]);
569 bgp
->connected_table
[AFI_IP6
] = NULL
;
571 bgp_table_unlock (bgp
->import_check_table
[AFI_IP6
]);
572 bgp
->import_check_table
[AFI_IP6
] = NULL
;
573 #endif /* HAVE_IPV6 */