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
36 #include "bgpd/bgpd.h"
37 #include "bgpd/bgp_table.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_nexthop.h"
41 #include "bgpd/bgp_nht.h"
42 #include "bgpd/bgp_debug.h"
43 #include "bgpd/bgp_damp.h"
44 #include "zebra/rib.h"
45 #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
49 /* Route table for next-hop lookup cache. */
50 struct bgp_table
*bgp_nexthop_cache_table
[AFI_MAX
];
52 /* Route table for connected route. */
53 static struct bgp_table
*bgp_connected_table
[AFI_MAX
];
55 /* Route table for import-check */
56 struct bgp_table
*bgp_import_check_table
[AFI_MAX
];
59 bnc_str (struct bgp_nexthop_cache
*bnc
, char *buf
, int size
)
61 prefix2str(&(bnc
->node
->p
), buf
, size
);
66 bnc_nexthop_free (struct bgp_nexthop_cache
*bnc
)
68 struct nexthop
*nexthop
;
69 struct nexthop
*next
= NULL
;
71 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= next
)
74 XFREE (MTYPE_NEXTHOP
, nexthop
);
78 struct bgp_nexthop_cache
*
81 struct bgp_nexthop_cache
*bnc
;
83 bnc
= XCALLOC (MTYPE_BGP_NEXTHOP_CACHE
, sizeof (struct bgp_nexthop_cache
));
84 LIST_INIT(&(bnc
->paths
));
89 bnc_free (struct bgp_nexthop_cache
*bnc
)
91 bnc_nexthop_free (bnc
);
92 XFREE (MTYPE_BGP_NEXTHOP_CACHE
, bnc
);
95 /* Reset and free all BGP nexthop cache. */
97 bgp_nexthop_cache_reset (struct bgp_table
*table
)
100 struct bgp_nexthop_cache
*bnc
;
102 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
103 if ((bnc
= rn
->info
) != NULL
)
107 bgp_unlock_node (rn
);
111 /* BGP own address structure */
118 static struct hash
*bgp_address_hash
;
121 bgp_address_hash_alloc (void *p
)
123 const struct in_addr
*val
= (const struct in_addr
*)p
;
124 struct bgp_addr
*addr
;
126 addr
= XMALLOC (MTYPE_BGP_ADDR
, sizeof (struct bgp_addr
));
128 addr
->addr
.s_addr
= val
->s_addr
;
134 bgp_address_hash_key_make (void *p
)
136 const struct bgp_addr
*addr
= p
;
138 return jhash_1word(addr
->addr
.s_addr
, 0);
142 bgp_address_hash_cmp (const void *p1
, const void *p2
)
144 const struct bgp_addr
*addr1
= p1
;
145 const struct bgp_addr
*addr2
= p2
;
147 return addr1
->addr
.s_addr
== addr2
->addr
.s_addr
;
151 bgp_address_init (void)
153 bgp_address_hash
= hash_create (bgp_address_hash_key_make
,
154 bgp_address_hash_cmp
);
158 bgp_address_add (struct prefix
*p
)
161 struct bgp_addr
*addr
;
163 tmp
.addr
= p
->u
.prefix4
;
165 addr
= hash_get (bgp_address_hash
, &tmp
, bgp_address_hash_alloc
);
173 bgp_address_del (struct prefix
*p
)
176 struct bgp_addr
*addr
;
178 tmp
.addr
= p
->u
.prefix4
;
180 addr
= hash_lookup (bgp_address_hash
, &tmp
);
181 /* may have been deleted earlier by bgp_interface_down() */
187 if (addr
->refcnt
== 0)
189 hash_release (bgp_address_hash
, addr
);
190 XFREE (MTYPE_BGP_ADDR
, addr
);
195 struct bgp_connected_ref
201 bgp_connected_add (struct connected
*ifc
)
206 struct bgp_connected_ref
*bc
;
210 if (addr
->family
== AF_INET
)
212 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
213 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
215 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
218 bgp_address_add (addr
);
220 rn
= bgp_node_get (bgp_connected_table
[AFI_IP
], (struct prefix
*) &p
);
228 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
234 else if (addr
->family
== AF_INET6
)
236 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
237 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
239 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
242 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
245 rn
= bgp_node_get (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
253 bc
= XCALLOC (MTYPE_BGP_CONN
, sizeof (struct bgp_connected_ref
));
258 #endif /* HAVE_IPV6 */
262 bgp_connected_delete (struct connected
*ifc
)
267 struct bgp_connected_ref
*bc
;
271 if (addr
->family
== AF_INET
)
273 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
274 apply_mask_ipv4 ((struct prefix_ipv4
*) &p
);
276 if (prefix_ipv4_any ((struct prefix_ipv4
*) &p
))
279 bgp_address_del (addr
);
281 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP
], &p
);
289 XFREE (MTYPE_BGP_CONN
, bc
);
292 bgp_unlock_node (rn
);
293 bgp_unlock_node (rn
);
296 else if (addr
->family
== AF_INET6
)
298 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
299 apply_mask_ipv6 ((struct prefix_ipv6
*) &p
);
301 if (IN6_IS_ADDR_UNSPECIFIED (&p
.u
.prefix6
))
304 if (IN6_IS_ADDR_LINKLOCAL (&p
.u
.prefix6
))
307 rn
= bgp_node_lookup (bgp_connected_table
[AFI_IP6
], (struct prefix
*) &p
);
315 XFREE (MTYPE_BGP_CONN
, bc
);
318 bgp_unlock_node (rn
);
319 bgp_unlock_node (rn
);
321 #endif /* HAVE_IPV6 */
325 bgp_nexthop_self (struct attr
*attr
)
327 struct bgp_addr tmp
, *addr
;
329 tmp
.addr
= attr
->nexthop
;
331 addr
= hash_lookup (bgp_address_hash
, &tmp
);
340 bgp_multiaccess_check_v4 (struct in_addr nexthop
, struct peer
*peer
)
342 struct bgp_node
*rn1
;
343 struct bgp_node
*rn2
;
348 p
.prefixlen
= IPV4_MAX_BITLEN
;
349 p
.u
.prefix4
= nexthop
;
351 rn1
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
356 p
.prefixlen
= IPV4_MAX_BITLEN
;
357 p
.u
.prefix4
= peer
->su
.sin
.sin_addr
;
359 rn2
= bgp_node_match (bgp_connected_table
[AFI_IP
], &p
);
362 bgp_unlock_node(rn1
);
366 ret
= (rn1
== rn2
) ? 1 : 0;
368 bgp_unlock_node(rn1
);
369 bgp_unlock_node(rn2
);
375 show_ip_bgp_nexthop_table (struct vty
*vty
, int detail
)
378 struct bgp_nexthop_cache
*bnc
;
379 char buf
[INET6_ADDRSTRLEN
];
380 struct nexthop
*nexthop
;
383 vty_out (vty
, "Current BGP nexthop cache:%s", VTY_NEWLINE
);
384 for (rn
= bgp_table_top (bgp_nexthop_cache_table
[AFI_IP
]); rn
; rn
= bgp_route_next (rn
))
385 if ((bnc
= rn
->info
) != NULL
)
387 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
389 vty_out (vty
, " %s valid [IGP metric %d], #paths %d%s",
390 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf
, INET6_ADDRSTRLEN
),
391 bnc
->metric
, bnc
->path_count
, VTY_NEWLINE
);
393 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
394 switch (nexthop
->type
)
396 case NEXTHOP_TYPE_IPV4
:
397 vty_out (vty
, " gate %s%s",
398 inet_ntop (AF_INET
, &nexthop
->gate
.ipv4
, buf
,
399 INET6_ADDRSTRLEN
), VTY_NEWLINE
);
401 case NEXTHOP_TYPE_IFINDEX
:
402 vty_out (vty
, " if %s%s",
403 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
405 case NEXTHOP_TYPE_IPV4_IFINDEX
:
406 vty_out (vty
, " gate %s, if %s%s",
407 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
409 ifindex2ifname(nexthop
->ifindex
), VTY_NEWLINE
);
412 vty_out (vty
, " invalid nexthop type %u%s",
413 nexthop
->type
, VTY_NEWLINE
);
418 vty_out (vty
, " %s invalid%s",
419 inet_ntop (AF_INET
, &rn
->p
.u
.prefix4
, buf
, INET6_ADDRSTRLEN
), VTY_NEWLINE
);
421 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
422 vty_out (vty
, " Must be Connected%s", VTY_NEWLINE
);
424 #ifdef HAVE_CLOCK_MONOTONIC
425 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
426 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
428 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
429 #endif /* HAVE_CLOCK_MONOTONIC */
431 vty_out(vty
, "%s", VTY_NEWLINE
);
436 for (rn
= bgp_table_top (bgp_nexthop_cache_table
[AFI_IP6
]);
438 rn
= bgp_route_next (rn
))
439 if ((bnc
= rn
->info
) != NULL
)
441 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_VALID
))
443 vty_out (vty
, " %s valid [IGP metric %d]%s",
444 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
,
446 bnc
->metric
, VTY_NEWLINE
);
448 for (nexthop
= bnc
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
449 switch (nexthop
->type
)
451 case NEXTHOP_TYPE_IPV6
:
452 vty_out (vty
, " gate %s%s",
453 inet_ntop (AF_INET6
, &nexthop
->gate
.ipv6
,
454 buf
, INET6_ADDRSTRLEN
), VTY_NEWLINE
);
456 case NEXTHOP_TYPE_IPV6_IFINDEX
:
457 vty_out(vty
, " gate %s, if %s%s",
458 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
460 ifindex2ifname(nexthop
->ifindex
),
463 case NEXTHOP_TYPE_IFINDEX
:
464 vty_out (vty
, " ifidx %u%s", nexthop
->ifindex
,
468 vty_out (vty
, " invalid nexthop type %u%s",
469 nexthop
->type
, VTY_NEWLINE
);
474 vty_out (vty
, " %s invalid%s",
475 inet_ntop (AF_INET6
, &rn
->p
.u
.prefix6
, buf
, INET6_ADDRSTRLEN
),
478 if (CHECK_FLAG(bnc
->flags
, BGP_NEXTHOP_CONNECTED
))
479 vty_out (vty
, " Must be Connected%s", VTY_NEWLINE
);
481 #ifdef HAVE_CLOCK_MONOTONIC
482 tbuf
= time(NULL
) - (bgp_clock() - bnc
->last_update
);
483 vty_out (vty
, " Last update: %s", ctime(&tbuf
));
485 vty_out (vty
, " Last update: %s", ctime(&bnc
->uptime
));
486 #endif /* HAVE_CLOCK_MONOTONIC */
488 vty_out(vty
, "%s", VTY_NEWLINE
);
491 #endif /* HAVE_IPV6 */
495 DEFUN (show_ip_bgp_nexthop
,
496 show_ip_bgp_nexthop_cmd
,
497 "show ip bgp nexthop",
501 "BGP nexthop table\n")
503 return show_ip_bgp_nexthop_table (vty
, 0);
506 DEFUN (show_ip_bgp_nexthop_detail
,
507 show_ip_bgp_nexthop_detail_cmd
,
508 "show ip bgp nexthop detail",
512 "BGP nexthop table\n")
514 return show_ip_bgp_nexthop_table (vty
, 1);
520 bgp_nexthop_cache_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
521 bgp_connected_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
522 bgp_import_check_table
[AFI_IP
] = bgp_table_init (AFI_IP
, SAFI_UNICAST
);
525 bgp_nexthop_cache_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
526 bgp_connected_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
527 bgp_import_check_table
[AFI_IP6
] = bgp_table_init (AFI_IP6
, SAFI_UNICAST
);
528 #endif /* HAVE_IPV6 */
533 bgp_scan_vty_init (void)
535 install_element (ENABLE_NODE
, &show_ip_bgp_nexthop_cmd
);
536 install_element (VIEW_NODE
, &show_ip_bgp_nexthop_cmd
);
537 install_element (VIEW_NODE
, &show_ip_bgp_nexthop_detail_cmd
);
538 install_element (ENABLE_NODE
, &show_ip_bgp_nexthop_detail_cmd
);
542 bgp_scan_finish (void)
544 /* Only the current one needs to be reset. */
545 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP
]);
547 bgp_table_unlock (bgp_nexthop_cache_table
[AFI_IP
]);
548 bgp_nexthop_cache_table
[AFI_IP
] = NULL
;
550 bgp_table_unlock (bgp_connected_table
[AFI_IP
]);
551 bgp_connected_table
[AFI_IP
] = NULL
;
553 bgp_table_unlock (bgp_import_check_table
[AFI_IP
]);
554 bgp_import_check_table
[AFI_IP
] = NULL
;
557 /* Only the current one needs to be reset. */
558 bgp_nexthop_cache_reset (bgp_nexthop_cache_table
[AFI_IP6
]);
560 bgp_table_unlock (bgp_nexthop_cache_table
[AFI_IP6
]);
561 bgp_nexthop_cache_table
[AFI_IP6
] = NULL
;
563 bgp_table_unlock (bgp_connected_table
[AFI_IP6
]);
564 bgp_connected_table
[AFI_IP6
] = NULL
;
566 bgp_table_unlock (bgp_import_check_table
[AFI_IP6
]);
567 bgp_import_check_table
[AFI_IP6
] = NULL
;
568 #endif /* HAVE_IPV6 */