]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* BGP nexthop scan |
2 | Copyright (C) 2000 Kunihiro Ishiguro | |
3 | ||
4 | This file is part of GNU Zebra. | |
5 | ||
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 | |
9 | later version. | |
10 | ||
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. | |
15 | ||
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 | |
19 | 02111-1307, USA. */ | |
20 | ||
21 | #include <zebra.h> | |
22 | ||
23 | #include "command.h" | |
24 | #include "thread.h" | |
25 | #include "prefix.h" | |
26 | #include "zclient.h" | |
27 | #include "stream.h" | |
28 | #include "network.h" | |
29 | #include "log.h" | |
30 | #include "memory.h" | |
10f9bf3f JBD |
31 | #include "hash.h" |
32 | #include "jhash.h" | |
fb018d25 | 33 | #include "nexthop.h" |
3f9c7369 | 34 | #include "queue.h" |
718e3744 | 35 | |
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" | |
fb018d25 | 41 | #include "bgpd/bgp_nht.h" |
718e3744 | 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. */ | |
46 | ||
fb018d25 | 47 | |
718e3744 | 48 | |
49 | /* Route table for next-hop lookup cache. */ | |
fb018d25 | 50 | struct bgp_table *bgp_nexthop_cache_table[AFI_MAX]; |
00d252cb | 51 | static struct bgp_table *cache1_table[AFI_MAX]; |
718e3744 | 52 | |
53 | /* Route table for connected route. */ | |
00d252cb | 54 | static struct bgp_table *bgp_connected_table[AFI_MAX]; |
718e3744 | 55 | |
6b0655a2 | 56 | |
fb018d25 DS |
57 | char * |
58 | bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size) | |
59 | { | |
60 | prefix2str(&(bnc->node->p), buf, size); | |
61 | return buf; | |
62 | } | |
63 | ||
fb018d25 | 64 | void |
718e3744 | 65 | bnc_nexthop_free (struct bgp_nexthop_cache *bnc) |
66 | { | |
67 | struct nexthop *nexthop; | |
68 | struct nexthop *next = NULL; | |
69 | ||
70 | for (nexthop = bnc->nexthop; nexthop; nexthop = next) | |
71 | { | |
72 | next = nexthop->next; | |
73 | XFREE (MTYPE_NEXTHOP, nexthop); | |
74 | } | |
75 | } | |
76 | ||
fb018d25 DS |
77 | struct bgp_nexthop_cache * |
78 | bnc_new () | |
718e3744 | 79 | { |
fb018d25 DS |
80 | struct bgp_nexthop_cache *bnc; |
81 | ||
82 | bnc = XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache)); | |
83 | LIST_INIT(&(bnc->paths)); | |
84 | return bnc; | |
718e3744 | 85 | } |
86 | ||
fb018d25 | 87 | void |
718e3744 | 88 | bnc_free (struct bgp_nexthop_cache *bnc) |
89 | { | |
90 | bnc_nexthop_free (bnc); | |
91 | XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc); | |
92 | } | |
6b0655a2 | 93 | |
718e3744 | 94 | /* If nexthop exists on connected network return 1. */ |
95 | int | |
8e80bdf2 | 96 | bgp_nexthop_onlink (afi_t afi, struct attr *attr) |
718e3744 | 97 | { |
98 | struct bgp_node *rn; | |
fc98d16e | 99 | |
718e3744 | 100 | /* Lookup the address is onlink or not. */ |
101 | if (afi == AFI_IP) | |
102 | { | |
5932020b | 103 | rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop); |
718e3744 | 104 | if (rn) |
105 | { | |
106 | bgp_unlock_node (rn); | |
107 | return 1; | |
108 | } | |
109 | } | |
110 | #ifdef HAVE_IPV6 | |
111 | else if (afi == AFI_IP6) | |
112 | { | |
fb982c25 | 113 | if (attr->extra->mp_nexthop_len == 32) |
718e3744 | 114 | return 1; |
fb982c25 | 115 | else if (attr->extra->mp_nexthop_len == 16) |
718e3744 | 116 | { |
fb982c25 | 117 | if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global)) |
718e3744 | 118 | return 1; |
119 | ||
5932020b | 120 | rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6], |
fb982c25 | 121 | &attr->extra->mp_nexthop_global); |
718e3744 | 122 | if (rn) |
123 | { | |
124 | bgp_unlock_node (rn); | |
125 | return 1; | |
126 | } | |
127 | } | |
128 | } | |
129 | #endif /* HAVE_IPV6 */ | |
130 | return 0; | |
131 | } | |
132 | ||
718e3744 | 133 | /* Reset and free all BGP nexthop cache. */ |
94f2b392 | 134 | static void |
718e3744 | 135 | bgp_nexthop_cache_reset (struct bgp_table *table) |
136 | { | |
137 | struct bgp_node *rn; | |
138 | struct bgp_nexthop_cache *bnc; | |
139 | ||
140 | for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) | |
141 | if ((bnc = rn->info) != NULL) | |
142 | { | |
143 | bnc_free (bnc); | |
144 | rn->info = NULL; | |
145 | bgp_unlock_node (rn); | |
146 | } | |
147 | } | |
148 | ||
10f9bf3f JBD |
149 | /* BGP own address structure */ |
150 | struct bgp_addr | |
151 | { | |
152 | struct in_addr addr; | |
153 | int refcnt; | |
154 | }; | |
155 | ||
156 | static struct hash *bgp_address_hash; | |
157 | ||
158 | static void * | |
159 | bgp_address_hash_alloc (void *p) | |
160 | { | |
161 | struct in_addr *val = p; | |
162 | struct bgp_addr *addr; | |
163 | ||
164 | addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr)); | |
165 | addr->refcnt = 0; | |
166 | addr->addr.s_addr = val->s_addr; | |
167 | ||
168 | return addr; | |
169 | } | |
170 | ||
171 | static unsigned int | |
172 | bgp_address_hash_key_make (void *p) | |
173 | { | |
174 | const struct bgp_addr *addr = p; | |
175 | ||
176 | return jhash_1word(addr->addr.s_addr, 0); | |
177 | } | |
178 | ||
179 | static int | |
180 | bgp_address_hash_cmp (const void *p1, const void *p2) | |
181 | { | |
182 | const struct bgp_addr *addr1 = p1; | |
183 | const struct bgp_addr *addr2 = p2; | |
184 | ||
185 | return addr1->addr.s_addr == addr2->addr.s_addr; | |
186 | } | |
187 | ||
188 | void | |
189 | bgp_address_init (void) | |
190 | { | |
191 | bgp_address_hash = hash_create (bgp_address_hash_key_make, | |
192 | bgp_address_hash_cmp); | |
193 | } | |
194 | ||
195 | static void | |
196 | bgp_address_add (struct prefix *p) | |
197 | { | |
198 | struct bgp_addr tmp; | |
199 | struct bgp_addr *addr; | |
200 | ||
201 | tmp.addr = p->u.prefix4; | |
202 | ||
203 | addr = hash_get (bgp_address_hash, &tmp, bgp_address_hash_alloc); | |
5ce10e92 DS |
204 | if (!addr) |
205 | return; | |
206 | ||
10f9bf3f JBD |
207 | addr->refcnt++; |
208 | } | |
209 | ||
210 | static void | |
211 | bgp_address_del (struct prefix *p) | |
212 | { | |
213 | struct bgp_addr tmp; | |
214 | struct bgp_addr *addr; | |
215 | ||
216 | tmp.addr = p->u.prefix4; | |
217 | ||
218 | addr = hash_lookup (bgp_address_hash, &tmp); | |
9e47abd8 RG |
219 | /* may have been deleted earlier by bgp_interface_down() */ |
220 | if (addr == NULL) | |
221 | return; | |
222 | ||
10f9bf3f JBD |
223 | addr->refcnt--; |
224 | ||
225 | if (addr->refcnt == 0) | |
226 | { | |
227 | hash_release (bgp_address_hash, addr); | |
228 | XFREE (MTYPE_BGP_ADDR, addr); | |
229 | } | |
230 | } | |
231 | ||
6b0655a2 | 232 | |
5932020b | 233 | struct bgp_connected_ref |
718e3744 | 234 | { |
235 | unsigned int refcnt; | |
236 | }; | |
237 | ||
238 | void | |
239 | bgp_connected_add (struct connected *ifc) | |
240 | { | |
241 | struct prefix p; | |
242 | struct prefix *addr; | |
718e3744 | 243 | struct interface *ifp; |
244 | struct bgp_node *rn; | |
5932020b | 245 | struct bgp_connected_ref *bc; |
718e3744 | 246 | |
247 | ifp = ifc->ifp; | |
248 | ||
249 | if (! ifp) | |
250 | return; | |
251 | ||
252 | if (if_is_loopback (ifp)) | |
253 | return; | |
254 | ||
255 | addr = ifc->address; | |
718e3744 | 256 | |
257 | if (addr->family == AF_INET) | |
258 | { | |
e4529636 | 259 | PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); |
718e3744 | 260 | apply_mask_ipv4 ((struct prefix_ipv4 *) &p); |
261 | ||
262 | if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) | |
263 | return; | |
264 | ||
10f9bf3f JBD |
265 | bgp_address_add (addr); |
266 | ||
5932020b | 267 | rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p); |
718e3744 | 268 | if (rn->info) |
269 | { | |
270 | bc = rn->info; | |
271 | bc->refcnt++; | |
272 | } | |
273 | else | |
274 | { | |
6c88b44d | 275 | bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); |
718e3744 | 276 | bc->refcnt = 1; |
277 | rn->info = bc; | |
278 | } | |
279 | } | |
280 | #ifdef HAVE_IPV6 | |
e4529636 | 281 | else if (addr->family == AF_INET6) |
718e3744 | 282 | { |
e4529636 | 283 | PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); |
718e3744 | 284 | apply_mask_ipv6 ((struct prefix_ipv6 *) &p); |
285 | ||
286 | if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) | |
287 | return; | |
288 | ||
289 | if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) | |
290 | return; | |
291 | ||
5932020b | 292 | rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p); |
718e3744 | 293 | if (rn->info) |
294 | { | |
295 | bc = rn->info; | |
296 | bc->refcnt++; | |
297 | } | |
298 | else | |
299 | { | |
6c88b44d | 300 | bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref)); |
718e3744 | 301 | bc->refcnt = 1; |
302 | rn->info = bc; | |
303 | } | |
304 | } | |
305 | #endif /* HAVE_IPV6 */ | |
306 | } | |
307 | ||
308 | void | |
309 | bgp_connected_delete (struct connected *ifc) | |
310 | { | |
311 | struct prefix p; | |
312 | struct prefix *addr; | |
718e3744 | 313 | struct interface *ifp; |
314 | struct bgp_node *rn; | |
5932020b | 315 | struct bgp_connected_ref *bc; |
718e3744 | 316 | |
317 | ifp = ifc->ifp; | |
318 | ||
319 | if (if_is_loopback (ifp)) | |
320 | return; | |
321 | ||
322 | addr = ifc->address; | |
718e3744 | 323 | |
324 | if (addr->family == AF_INET) | |
325 | { | |
e4529636 | 326 | PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); |
718e3744 | 327 | apply_mask_ipv4 ((struct prefix_ipv4 *) &p); |
328 | ||
329 | if (prefix_ipv4_any ((struct prefix_ipv4 *) &p)) | |
330 | return; | |
331 | ||
10f9bf3f JBD |
332 | bgp_address_del (addr); |
333 | ||
5932020b | 334 | rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p); |
718e3744 | 335 | if (! rn) |
336 | return; | |
337 | ||
338 | bc = rn->info; | |
339 | bc->refcnt--; | |
340 | if (bc->refcnt == 0) | |
341 | { | |
6c88b44d | 342 | XFREE (MTYPE_BGP_CONN, bc); |
718e3744 | 343 | rn->info = NULL; |
344 | } | |
345 | bgp_unlock_node (rn); | |
346 | bgp_unlock_node (rn); | |
347 | } | |
348 | #ifdef HAVE_IPV6 | |
349 | else if (addr->family == AF_INET6) | |
350 | { | |
e4529636 | 351 | PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc)); |
718e3744 | 352 | apply_mask_ipv6 ((struct prefix_ipv6 *) &p); |
353 | ||
354 | if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) | |
355 | return; | |
356 | ||
357 | if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6)) | |
358 | return; | |
359 | ||
5932020b | 360 | rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p); |
718e3744 | 361 | if (! rn) |
362 | return; | |
363 | ||
364 | bc = rn->info; | |
365 | bc->refcnt--; | |
366 | if (bc->refcnt == 0) | |
367 | { | |
6c88b44d | 368 | XFREE (MTYPE_BGP_CONN, bc); |
718e3744 | 369 | rn->info = NULL; |
370 | } | |
371 | bgp_unlock_node (rn); | |
372 | bgp_unlock_node (rn); | |
373 | } | |
374 | #endif /* HAVE_IPV6 */ | |
375 | } | |
376 | ||
377 | int | |
10f9bf3f | 378 | bgp_nexthop_self (struct attr *attr) |
718e3744 | 379 | { |
10f9bf3f | 380 | struct bgp_addr tmp, *addr; |
718e3744 | 381 | |
10f9bf3f JBD |
382 | tmp.addr = attr->nexthop; |
383 | ||
384 | addr = hash_lookup (bgp_address_hash, &tmp); | |
385 | if (addr) | |
386 | return 1; | |
718e3744 | 387 | |
718e3744 | 388 | return 0; |
389 | } | |
6b0655a2 | 390 | |
718e3744 | 391 | |
718e3744 | 392 | int |
fc9a856f | 393 | bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer) |
718e3744 | 394 | { |
395 | struct bgp_node *rn1; | |
396 | struct bgp_node *rn2; | |
fc9a856f | 397 | struct prefix p; |
718e3744 | 398 | int ret; |
399 | ||
fc9a856f DS |
400 | p.family = AF_INET; |
401 | p.prefixlen = IPV4_MAX_BITLEN; | |
402 | p.u.prefix4 = nexthop; | |
718e3744 | 403 | |
fc9a856f DS |
404 | rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p); |
405 | if (!rn1) | |
718e3744 | 406 | return 0; |
718e3744 | 407 | |
fc9a856f DS |
408 | p.family = AF_INET; |
409 | p.prefixlen = IPV4_MAX_BITLEN; | |
410 | p.u.prefix4 = peer->su.sin.sin_addr; | |
718e3744 | 411 | |
fc9a856f DS |
412 | rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p); |
413 | if (!rn2) | |
718e3744 | 414 | { |
fc9a856f DS |
415 | bgp_unlock_node(rn1); |
416 | return 0; | |
718e3744 | 417 | } |
418 | ||
fc9a856f | 419 | ret = (rn1 == rn2) ? 1 : 0; |
718e3744 | 420 | |
fc9a856f DS |
421 | bgp_unlock_node(rn1); |
422 | bgp_unlock_node(rn2); | |
718e3744 | 423 | |
fc9a856f | 424 | return (ret); |
718e3744 | 425 | } |
426 | ||
fb018d25 DS |
427 | static int |
428 | show_ip_bgp_nexthop_table (struct vty *vty, int detail) | |
429 | { | |
430 | struct bgp_node *rn; | |
431 | struct bgp_nexthop_cache *bnc; | |
432 | char buf[INET6_ADDRSTRLEN]; | |
77217fd4 | 433 | struct nexthop *nexthop; |
fb018d25 DS |
434 | time_t tbuf; |
435 | u_char i; | |
436 | ||
437 | vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE); | |
438 | for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn)) | |
439 | if ((bnc = rn->info) != NULL) | |
440 | { | |
441 | if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) | |
442 | { | |
443 | vty_out (vty, " %s valid [IGP metric %d], #paths %d%s", | |
444 | inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), | |
445 | bnc->metric, bnc->path_count, VTY_NEWLINE); | |
446 | if (detail) | |
77217fd4 DS |
447 | for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) |
448 | switch (nexthop->type) | |
449 | { | |
450 | case NEXTHOP_TYPE_IPV4: | |
451 | vty_out (vty, " gate %s%s", | |
452 | inet_ntop (AF_INET, &nexthop->gate.ipv4, buf, | |
453 | INET6_ADDRSTRLEN), VTY_NEWLINE); | |
454 | break; | |
455 | case NEXTHOP_TYPE_IFINDEX: | |
456 | vty_out (vty, " if %s%s", | |
457 | ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); | |
458 | break; | |
459 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
460 | vty_out (vty, " gate %s, if %s%s", | |
461 | inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, | |
462 | INET6_ADDRSTRLEN), | |
463 | ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); | |
464 | break; | |
465 | default: | |
466 | vty_out (vty, " invalid nexthop type %u%s", | |
467 | nexthop->type, VTY_NEWLINE); | |
468 | } | |
fb018d25 DS |
469 | } |
470 | else | |
471 | vty_out (vty, " %s invalid%s", | |
472 | inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE); | |
473 | #ifdef HAVE_CLOCK_MONOTONIC | |
474 | tbuf = time(NULL) - (bgp_clock() - bnc->last_update); | |
475 | vty_out (vty, " Last update: %s", ctime(&tbuf)); | |
476 | #else | |
477 | vty_out (vty, " Last update: %s", ctime(&bnc->uptime)); | |
478 | #endif /* HAVE_CLOCK_MONOTONIC */ | |
479 | ||
480 | vty_out(vty, "%s", VTY_NEWLINE); | |
481 | } | |
482 | ||
483 | #ifdef HAVE_IPV6 | |
484 | { | |
485 | for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]); | |
486 | rn; | |
487 | rn = bgp_route_next (rn)) | |
488 | if ((bnc = rn->info) != NULL) | |
489 | { | |
490 | if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) | |
491 | { | |
492 | vty_out (vty, " %s valid [IGP metric %d]%s", | |
493 | inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, | |
494 | INET6_ADDRSTRLEN), | |
495 | bnc->metric, VTY_NEWLINE); | |
496 | if (detail) | |
77217fd4 DS |
497 | for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) |
498 | switch (nexthop->type) | |
499 | { | |
500 | case NEXTHOP_TYPE_IPV6: | |
501 | vty_out (vty, " gate %s%s", | |
502 | inet_ntop (AF_INET6, &nexthop->gate.ipv6, | |
503 | buf, INET6_ADDRSTRLEN), VTY_NEWLINE); | |
504 | break; | |
505 | case NEXTHOP_TYPE_IPV6_IFINDEX: | |
506 | vty_out(vty, " gate %s, if %s%s", | |
507 | inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, | |
508 | INET6_ADDRSTRLEN), | |
509 | ifindex2ifname(nexthop->ifindex), | |
510 | VTY_NEWLINE); | |
511 | break; | |
512 | case NEXTHOP_TYPE_IFINDEX: | |
513 | vty_out (vty, " ifidx %u%s", nexthop->ifindex, | |
514 | VTY_NEWLINE); | |
515 | break; | |
516 | default: | |
517 | vty_out (vty, " invalid nexthop type %u%s", | |
518 | nexthop->type, VTY_NEWLINE); | |
519 | } | |
fb018d25 DS |
520 | } |
521 | else | |
522 | vty_out (vty, " %s invalid%s", | |
523 | inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN), | |
524 | VTY_NEWLINE); | |
525 | #ifdef HAVE_CLOCK_MONOTONIC | |
526 | tbuf = time(NULL) - (bgp_clock() - bnc->last_update); | |
527 | vty_out (vty, " Last update: %s", ctime(&tbuf)); | |
528 | #else | |
529 | vty_out (vty, " Last update: %s", ctime(&bnc->uptime)); | |
530 | #endif /* HAVE_CLOCK_MONOTONIC */ | |
531 | ||
532 | vty_out(vty, "%s", VTY_NEWLINE); | |
533 | } | |
534 | } | |
535 | #endif /* HAVE_IPV6 */ | |
536 | return CMD_SUCCESS; | |
537 | } | |
538 | ||
fb018d25 DS |
539 | DEFUN (show_ip_bgp_nexthop, |
540 | show_ip_bgp_nexthop_cmd, | |
541 | "show ip bgp nexthop", | |
542 | SHOW_STR | |
543 | IP_STR | |
544 | BGP_STR | |
545 | "BGP nexthop table\n") | |
546 | { | |
547 | return show_ip_bgp_nexthop_table (vty, 0); | |
548 | } | |
549 | ||
550 | DEFUN (show_ip_bgp_nexthop_detail, | |
551 | show_ip_bgp_nexthop_detail_cmd, | |
552 | "show ip bgp nexthop detail", | |
553 | SHOW_STR | |
554 | IP_STR | |
555 | BGP_STR | |
556 | "BGP nexthop table\n") | |
557 | { | |
558 | return show_ip_bgp_nexthop_table (vty, 1); | |
559 | } | |
560 | ||
718e3744 | 561 | void |
66e5cd87 | 562 | bgp_scan_init (void) |
718e3744 | 563 | { |
64e580a7 | 564 | cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); |
5932020b | 565 | bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP]; |
718e3744 | 566 | |
64e580a7 | 567 | bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST); |
718e3744 | 568 | |
569 | #ifdef HAVE_IPV6 | |
64e580a7 | 570 | cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); |
5932020b | 571 | bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6]; |
64e580a7 | 572 | bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST); |
718e3744 | 573 | #endif /* HAVE_IPV6 */ |
574 | ||
fc9a856f DS |
575 | } |
576 | ||
577 | void | |
578 | bgp_scan_vty_init() | |
579 | { | |
580 | install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd); | |
fb018d25 DS |
581 | install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd); |
582 | install_element (VIEW_NODE, &show_ip_bgp_nexthop_detail_cmd); | |
fb018d25 | 583 | install_element (ENABLE_NODE, &show_ip_bgp_nexthop_detail_cmd); |
718e3744 | 584 | } |
228da428 CC |
585 | |
586 | void | |
587 | bgp_scan_finish (void) | |
588 | { | |
6c88b44d CC |
589 | /* Only the current one needs to be reset. */ |
590 | bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]); | |
591 | ||
228da428 CC |
592 | bgp_table_unlock (cache1_table[AFI_IP]); |
593 | cache1_table[AFI_IP] = NULL; | |
594 | ||
228da428 CC |
595 | bgp_table_unlock (bgp_connected_table[AFI_IP]); |
596 | bgp_connected_table[AFI_IP] = NULL; | |
597 | ||
598 | #ifdef HAVE_IPV6 | |
6c88b44d CC |
599 | /* Only the current one needs to be reset. */ |
600 | bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]); | |
601 | ||
228da428 CC |
602 | bgp_table_unlock (cache1_table[AFI_IP6]); |
603 | cache1_table[AFI_IP6] = NULL; | |
604 | ||
228da428 CC |
605 | bgp_table_unlock (bgp_connected_table[AFI_IP6]); |
606 | bgp_connected_table[AFI_IP6] = NULL; | |
607 | #endif /* HAVE_IPV6 */ | |
608 | } |