]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
bgpd: Abstract bgp_connected_ref retrieving/setting from info pointer
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
896014f4
DL
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 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
19 */
718e3744 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"
039f3a34 35#include "filter.h"
718e3744 36
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"
fb018d25 42#include "bgpd/bgp_nht.h"
718e3744 43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_damp.h"
8ffedcea 45#include "bgpd/bgp_fsm.h"
8386ac43 46#include "bgpd/bgp_vty.h"
718e3744 47#include "zebra/rib.h"
d62a17ae 48#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
718e3744 49
d62a17ae 50char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
fb018d25 51{
d62a17ae 52 prefix2str(&(bnc->node->p), buf, size);
53 return buf;
fb018d25
DS
54}
55
d62a17ae 56void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
718e3744 57{
d62a17ae 58 nexthops_free(bnc->nexthop);
718e3744 59}
60
d62a17ae 61struct bgp_nexthop_cache *bnc_new(void)
718e3744 62{
d62a17ae 63 struct bgp_nexthop_cache *bnc;
fb018d25 64
d62a17ae 65 bnc = XCALLOC(MTYPE_BGP_NEXTHOP_CACHE,
66 sizeof(struct bgp_nexthop_cache));
67 LIST_INIT(&(bnc->paths));
68 return bnc;
718e3744 69}
70
d62a17ae 71void bnc_free(struct bgp_nexthop_cache *bnc)
718e3744 72{
d62a17ae 73 bnc_nexthop_free(bnc);
74 XFREE(MTYPE_BGP_NEXTHOP_CACHE, bnc);
718e3744 75}
6b0655a2 76
718e3744 77/* Reset and free all BGP nexthop cache. */
d62a17ae 78static void bgp_nexthop_cache_reset(struct bgp_table *table)
718e3744 79{
d62a17ae 80 struct bgp_node *rn;
81 struct bgp_nexthop_cache *bnc;
82
83 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
84 if ((bnc = rn->info) != NULL) {
85 bnc_free(bnc);
86 rn->info = NULL;
87 bgp_unlock_node(rn);
88 }
718e3744 89}
90
db0e1937
MK
91static void *bgp_tip_hash_alloc(void *p)
92{
0291c246
MK
93 const struct in_addr *val = (const struct in_addr *)p;
94 struct tip_addr *addr;
db0e1937
MK
95
96 addr = XMALLOC(MTYPE_TIP_ADDR, sizeof(struct tip_addr));
97 addr->refcnt = 0;
98 addr->addr.s_addr = val->s_addr;
99
100 return addr;
101}
102
103static void bgp_tip_hash_free(void *addr)
104{
105 XFREE(MTYPE_TIP_ADDR, addr);
106}
107
108static unsigned int bgp_tip_hash_key_make(void *p)
109{
0291c246 110 const struct tip_addr *addr = p;
db0e1937
MK
111
112 return jhash_1word(addr->addr.s_addr, 0);
113}
114
115static int bgp_tip_hash_cmp(const void *p1, const void *p2)
116{
0291c246
MK
117 const struct tip_addr *addr1 = p1;
118 const struct tip_addr *addr2 = p2;
db0e1937
MK
119
120 return addr1->addr.s_addr == addr2->addr.s_addr;
121}
122
123void bgp_tip_hash_init(struct bgp *bgp)
124{
996c9314 125 bgp->tip_hash = hash_create(bgp_tip_hash_key_make, bgp_tip_hash_cmp,
3f65c5b1 126 "BGP TIP hash");
db0e1937
MK
127}
128
129void bgp_tip_hash_destroy(struct bgp *bgp)
130{
131 if (bgp->tip_hash == NULL)
132 return;
133 hash_clean(bgp->tip_hash, bgp_tip_hash_free);
134 hash_free(bgp->tip_hash);
135 bgp->tip_hash = NULL;
136}
137
138void bgp_tip_add(struct bgp *bgp, struct in_addr *tip)
139{
0291c246
MK
140 struct tip_addr tmp;
141 struct tip_addr *addr;
db0e1937
MK
142
143 tmp.addr = *tip;
144
145 addr = hash_get(bgp->tip_hash, &tmp, bgp_tip_hash_alloc);
146 if (!addr)
147 return;
148
149 addr->refcnt++;
150}
151
152void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
153{
0291c246
MK
154 struct tip_addr tmp;
155 struct tip_addr *addr;
db0e1937
MK
156
157 tmp.addr = *tip;
158
159 addr = hash_lookup(bgp->tip_hash, &tmp);
160 /* may have been deleted earlier by bgp_interface_down() */
161 if (addr == NULL)
162 return;
163
164 addr->refcnt--;
165
166 if (addr->refcnt == 0) {
167 hash_release(bgp->tip_hash, addr);
168 XFREE(MTYPE_TIP_ADDR, addr);
169 }
170}
10f9bf3f 171
d62a17ae 172static void *bgp_address_hash_alloc(void *p)
10f9bf3f 173{
d62a17ae 174 const struct in_addr *val = (const struct in_addr *)p;
175 struct bgp_addr *addr;
10f9bf3f 176
d62a17ae 177 addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
178 addr->refcnt = 0;
179 addr->addr.s_addr = val->s_addr;
10f9bf3f 180
d62a17ae 181 return addr;
10f9bf3f
JBD
182}
183
d62a17ae 184static void bgp_address_hash_free(void *addr)
37d361e7 185{
d62a17ae 186 XFREE(MTYPE_BGP_ADDR, addr);
37d361e7
RW
187}
188
d62a17ae 189static unsigned int bgp_address_hash_key_make(void *p)
10f9bf3f 190{
d62a17ae 191 const struct bgp_addr *addr = p;
10f9bf3f 192
d62a17ae 193 return jhash_1word(addr->addr.s_addr, 0);
10f9bf3f
JBD
194}
195
d62a17ae 196static int bgp_address_hash_cmp(const void *p1, const void *p2)
10f9bf3f 197{
d62a17ae 198 const struct bgp_addr *addr1 = p1;
199 const struct bgp_addr *addr2 = p2;
10f9bf3f 200
d62a17ae 201 return addr1->addr.s_addr == addr2->addr.s_addr;
10f9bf3f
JBD
202}
203
d62a17ae 204void bgp_address_init(struct bgp *bgp)
10f9bf3f 205{
996c9314
LB
206 bgp->address_hash =
207 hash_create(bgp_address_hash_key_make, bgp_address_hash_cmp,
208 "BGP Address Hash");
10f9bf3f
JBD
209}
210
d62a17ae 211void bgp_address_destroy(struct bgp *bgp)
bb86c601 212{
d62a17ae 213 if (bgp->address_hash == NULL)
214 return;
215 hash_clean(bgp->address_hash, bgp_address_hash_free);
216 hash_free(bgp->address_hash);
217 bgp->address_hash = NULL;
bb86c601
LB
218}
219
d62a17ae 220static void bgp_address_add(struct bgp *bgp, struct prefix *p)
10f9bf3f 221{
d62a17ae 222 struct bgp_addr tmp;
223 struct bgp_addr *addr;
10f9bf3f 224
d62a17ae 225 tmp.addr = p->u.prefix4;
10f9bf3f 226
d62a17ae 227 addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
228 if (!addr)
229 return;
5ce10e92 230
d62a17ae 231 addr->refcnt++;
10f9bf3f
JBD
232}
233
d62a17ae 234static void bgp_address_del(struct bgp *bgp, struct prefix *p)
10f9bf3f 235{
d62a17ae 236 struct bgp_addr tmp;
237 struct bgp_addr *addr;
10f9bf3f 238
d62a17ae 239 tmp.addr = p->u.prefix4;
10f9bf3f 240
d62a17ae 241 addr = hash_lookup(bgp->address_hash, &tmp);
242 /* may have been deleted earlier by bgp_interface_down() */
243 if (addr == NULL)
244 return;
9e47abd8 245
d62a17ae 246 addr->refcnt--;
10f9bf3f 247
d62a17ae 248 if (addr->refcnt == 0) {
249 hash_release(bgp->address_hash, addr);
250 XFREE(MTYPE_BGP_ADDR, addr);
251 }
10f9bf3f
JBD
252}
253
6b0655a2 254
d62a17ae 255struct bgp_connected_ref {
256 unsigned int refcnt;
718e3744 257};
258
d62a17ae 259void bgp_connected_add(struct bgp *bgp, struct connected *ifc)
718e3744 260{
d62a17ae 261 struct prefix p;
262 struct prefix *addr;
263 struct bgp_node *rn;
264 struct bgp_connected_ref *bc;
265 struct listnode *node, *nnode;
266 struct peer *peer;
267
268 addr = ifc->address;
269
270 p = *(CONNECTED_PREFIX(ifc));
271 if (addr->family == AF_INET) {
272 apply_mask_ipv4((struct prefix_ipv4 *)&p);
273
274 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
275 return;
276
277 bgp_address_add(bgp, addr);
278
279 rn = bgp_node_get(bgp->connected_table[AFI_IP],
280 (struct prefix *)&p);
3d9dbdbe
DS
281 bc = bgp_connected_get_node_info(rn);
282 if (bc)
d62a17ae 283 bc->refcnt++;
3d9dbdbe 284 else {
d62a17ae 285 bc = XCALLOC(MTYPE_BGP_CONN,
286 sizeof(struct bgp_connected_ref));
287 bc->refcnt = 1;
3d9dbdbe 288 bgp_connected_set_node_info(rn, bc);
d62a17ae 289 }
8ffedcea 290
d62a17ae 291 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
292 if (peer->conf_if
293 && (strcmp(peer->conf_if, ifc->ifp->name) == 0)
294 && peer->status != Established
295 && !CHECK_FLAG(peer->flags,
296 PEER_FLAG_IFPEER_V6ONLY)) {
297 if (peer_active(peer))
298 BGP_EVENT_ADD(peer, BGP_Stop);
299 BGP_EVENT_ADD(peer, BGP_Start);
300 }
301 }
302 } else if (addr->family == AF_INET6) {
303 apply_mask_ipv6((struct prefix_ipv6 *)&p);
304
305 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
306 return;
307
308 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
309 return;
310
311 rn = bgp_node_get(bgp->connected_table[AFI_IP6],
312 (struct prefix *)&p);
3d9dbdbe
DS
313
314 bc = bgp_connected_get_node_info(rn);
315 if (bc)
d62a17ae 316 bc->refcnt++;
3d9dbdbe 317 else {
d62a17ae 318 bc = XCALLOC(MTYPE_BGP_CONN,
319 sizeof(struct bgp_connected_ref));
320 bc->refcnt = 1;
3d9dbdbe 321 bgp_connected_set_node_info(rn, bc);
d62a17ae 322 }
718e3744 323 }
718e3744 324}
325
d62a17ae 326void bgp_connected_delete(struct bgp *bgp, struct connected *ifc)
718e3744 327{
d62a17ae 328 struct prefix p;
329 struct prefix *addr;
f6bdc080 330 struct bgp_node *rn = NULL;
d62a17ae 331 struct bgp_connected_ref *bc;
718e3744 332
d62a17ae 333 addr = ifc->address;
718e3744 334
d62a17ae 335 p = *(CONNECTED_PREFIX(ifc));
f6bdc080 336 apply_mask(&p);
d62a17ae 337 if (addr->family == AF_INET) {
d62a17ae 338 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
339 return;
718e3744 340
d62a17ae 341 bgp_address_del(bgp, addr);
10f9bf3f 342
d62a17ae 343 rn = bgp_node_lookup(bgp->connected_table[AFI_IP], &p);
d62a17ae 344 } else if (addr->family == AF_INET6) {
d62a17ae 345 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
346 return;
347
348 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
349 return;
350
351 rn = bgp_node_lookup(bgp->connected_table[AFI_IP6],
352 (struct prefix *)&p);
f6bdc080 353 }
d62a17ae 354
f6bdc080
DS
355 if (!rn)
356 return;
357
3d9dbdbe 358 bc = bgp_connected_get_node_info(rn);
f6bdc080
DS
359 bc->refcnt--;
360 if (bc->refcnt == 0) {
361 XFREE(MTYPE_BGP_CONN, bc);
3d9dbdbe 362 bgp_connected_set_node_info(rn, NULL);
718e3744 363 }
f6bdc080
DS
364 bgp_unlock_node(rn);
365 bgp_unlock_node(rn);
718e3744 366}
367
3292693b
DS
368static void bgp_connected_cleanup(struct route_table *table,
369 struct route_node *rn)
370{
371 struct bgp_connected_ref *bc;
3d9dbdbe 372 struct bgp_node *bn = bgp_node_from_rnode(rn);
3292693b 373
3d9dbdbe 374 bc = bgp_connected_get_node_info(bn);
3292693b
DS
375 if (!bc)
376 return;
377
378 bc->refcnt--;
379 if (bc->refcnt == 0) {
380 XFREE(MTYPE_BGP_CONN, bc);
3d9dbdbe 381 bgp_connected_set_node_info(bn, NULL);
3292693b
DS
382 }
383}
384
d62a17ae 385int bgp_nexthop_self(struct bgp *bgp, struct in_addr nh_addr)
718e3744 386{
d62a17ae 387 struct bgp_addr tmp, *addr;
db0e1937 388 struct tip_addr tmp_tip, *tip;
718e3744 389
d62a17ae 390 tmp.addr = nh_addr;
10f9bf3f 391
d62a17ae 392 addr = hash_lookup(bgp->address_hash, &tmp);
393 if (addr)
394 return 1;
718e3744 395
db0e1937
MK
396 tmp_tip.addr = nh_addr;
397 tip = hash_lookup(bgp->tip_hash, &tmp_tip);
398 if (tip)
399 return 1;
400
d62a17ae 401 return 0;
718e3744 402}
6b0655a2 403
d62a17ae 404int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)
718e3744 405{
d62a17ae 406 struct bgp_node *rn1;
407 struct bgp_node *rn2;
408 struct prefix p;
409 int ret;
410
411 p.family = AF_INET;
412 p.prefixlen = IPV4_MAX_BITLEN;
413 p.u.prefix4 = nexthop;
414
415 rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
416 if (!rn1)
417 return 0;
418
419 p.family = AF_INET;
420 p.prefixlen = IPV4_MAX_BITLEN;
421 p.u.prefix4 = peer->su.sin.sin_addr;
422
423 rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p);
424 if (!rn2) {
425 bgp_unlock_node(rn1);
426 return 0;
427 }
718e3744 428
d62a17ae 429 ret = (rn1 == rn2) ? 1 : 0;
718e3744 430
d62a17ae 431 bgp_unlock_node(rn1);
432 bgp_unlock_node(rn2);
718e3744 433
d62a17ae 434 return (ret);
718e3744 435}
436
65d4e0c6
DS
437int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
438 struct update_subgroup *subgrp)
439{
440 struct bgp_node *rn1, *rn2;
441 struct peer_af *paf;
442 struct prefix p, np;
a2b6e694 443 struct bgp *bgp;
65d4e0c6
DS
444
445 np.family = AF_INET;
446 np.prefixlen = IPV4_MAX_BITLEN;
447 np.u.prefix4 = nexthop;
448
449 p.family = AF_INET;
450 p.prefixlen = IPV4_MAX_BITLEN;
451
65d4e0c6 452 bgp = SUBGRP_INST(subgrp);
996c9314 453 rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np);
65d4e0c6
DS
454 if (!rn1)
455 return 0;
456
996c9314 457 SUBGRP_FOREACH_PEER (subgrp, paf) {
65d4e0c6
DS
458 p.u.prefix4 = paf->peer->su.sin.sin_addr;
459
996c9314 460 rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
65d4e0c6
DS
461 if (rn1 == rn2) {
462 bgp_unlock_node(rn1);
463 bgp_unlock_node(rn2);
464 return 1;
465 }
466
467 if (rn2)
468 bgp_unlock_node(rn2);
469 }
470
471 bgp_unlock_node(rn1);
472 return 0;
473}
474
996c9314 475static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
e22ac3ee
DS
476 struct bgp_nexthop_cache *bnc)
477{
478 char buf[PREFIX2STR_BUFFER];
479 struct nexthop *nexthop;
480
481 for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
482 switch (nexthop->type) {
483 case NEXTHOP_TYPE_IPV6:
484 vty_out(vty, " gate %s\n",
996c9314
LB
485 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
486 sizeof(buf)));
e22ac3ee
DS
487 break;
488 case NEXTHOP_TYPE_IPV6_IFINDEX:
489 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
490 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
491 sizeof(buf)),
492 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
493 break;
494 case NEXTHOP_TYPE_IPV4:
495 vty_out(vty, " gate %s\n",
996c9314
LB
496 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
497 sizeof(buf)));
e22ac3ee
DS
498 break;
499 case NEXTHOP_TYPE_IFINDEX:
500 vty_out(vty, " if %s\n",
996c9314 501 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
502 break;
503 case NEXTHOP_TYPE_IPV4_IFINDEX:
504 vty_out(vty, " gate %s, if %s\n",
996c9314
LB
505 inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
506 sizeof(buf)),
507 ifindex2ifname(nexthop->ifindex, bgp->vrf_id));
e22ac3ee
DS
508 break;
509 case NEXTHOP_TYPE_BLACKHOLE:
510 vty_out(vty, " blackhole\n");
511 break;
512 default:
996c9314 513 vty_out(vty, " invalid nexthop type %u\n",
e22ac3ee
DS
514 nexthop->type);
515 }
516}
517
d62a17ae 518static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail)
fb018d25 519{
d62a17ae 520 struct bgp_node *rn;
521 struct bgp_nexthop_cache *bnc;
522 char buf[PREFIX2STR_BUFFER];
d62a17ae 523 time_t tbuf;
524 afi_t afi;
525
526 vty_out(vty, "Current BGP nexthop cache:\n");
527 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
528 if (!bgp->nexthop_cache_table[afi])
529 continue;
530
531 for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn;
532 rn = bgp_route_next(rn)) {
533 if ((bnc = rn->info) != NULL) {
534 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
535 vty_out(vty,
536 " %s valid [IGP metric %d], #paths %d\n",
537 inet_ntop(rn->p.family,
538 &rn->p.u.prefix, buf,
539 sizeof(buf)),
540 bnc->metric, bnc->path_count);
e22ac3ee
DS
541
542 if (!detail)
543 continue;
544
545 bgp_show_nexthops_detail(vty, bgp, bnc);
546
996c9314 547 } else {
d62a17ae 548 vty_out(vty, " %s invalid\n",
549 inet_ntop(rn->p.family,
550 &rn->p.u.prefix, buf,
551 sizeof(buf)));
552 if (CHECK_FLAG(bnc->flags,
553 BGP_NEXTHOP_CONNECTED))
554 vty_out(vty,
555 " Must be Connected\n");
556 }
557 tbuf = time(NULL)
558 - (bgp_clock() - bnc->last_update);
559 vty_out(vty, " Last update: %s", ctime(&tbuf));
560 vty_out(vty, "\n");
da11a696
DS
561 }
562 }
fb018d25 563 }
f186de26 564}
565
d62a17ae 566static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
567 int detail)
f186de26 568{
d62a17ae 569 struct bgp *bgp;
570
571 if (name)
572 bgp = bgp_lookup_by_name(name);
573 else
574 bgp = bgp_get_default();
575 if (!bgp) {
576 vty_out(vty, "%% No such BGP instance exist\n");
577 return CMD_WARNING;
578 }
f186de26 579
d62a17ae 580 bgp_show_nexthops(vty, bgp, detail);
f186de26 581
d62a17ae 582 return CMD_SUCCESS;
fb018d25
DS
583}
584
d62a17ae 585static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
f186de26 586{
d62a17ae 587 struct listnode *node, *nnode;
588 struct bgp *bgp;
589
590 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
591 vty_out(vty, "\nInstance %s:\n",
592 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
593 ? "Default"
594 : bgp->name);
595 bgp_show_nexthops(vty, bgp, 0);
596 }
f186de26 597}
598
fb018d25
DS
599DEFUN (show_ip_bgp_nexthop,
600 show_ip_bgp_nexthop_cmd,
18c57037 601 "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
50ef26d4 602 SHOW_STR
603 IP_STR
604 BGP_STR
8386ac43 605 BGP_INSTANCE_HELP_STR
3a2d747c
QY
606 "BGP nexthop table\n"
607 "Show detailed information\n")
50ef26d4 608{
d62a17ae 609 int idx = 0;
b7ada628
DS
610 char *vrf = NULL;
611
612 if (argv_find(argv, argc, "view", &idx)
613 || argv_find(argv, argc, "vrf", &idx))
614 vrf = argv[++idx]->arg;
d62a17ae 615 int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
616 return show_ip_bgp_nexthop_table(vty, vrf, detail);
50ef26d4 617}
618
f186de26 619DEFUN (show_ip_bgp_instance_all_nexthop,
620 show_ip_bgp_instance_all_nexthop_cmd,
bec37ba5 621 "show [ip] bgp <view|vrf> all nexthop",
f186de26 622 SHOW_STR
623 IP_STR
624 BGP_STR
625 BGP_INSTANCE_ALL_HELP_STR
626 "BGP nexthop table\n")
627{
d62a17ae 628 bgp_show_all_instances_nexthops_vty(vty);
629 return CMD_SUCCESS;
f186de26 630}
631
d62a17ae 632void bgp_scan_init(struct bgp *bgp)
718e3744 633{
d62a17ae 634 afi_t afi;
635
636 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
637 bgp->nexthop_cache_table[afi] =
960035b2
PZ
638 bgp_table_init(bgp, afi, SAFI_UNICAST);
639 bgp->connected_table[afi] = bgp_table_init(bgp, afi,
640 SAFI_UNICAST);
d62a17ae 641 bgp->import_check_table[afi] =
960035b2 642 bgp_table_init(bgp, afi, SAFI_UNICAST);
d62a17ae 643 }
fc9a856f
DS
644}
645
d62a17ae 646void bgp_scan_vty_init(void)
fc9a856f 647{
d62a17ae 648 install_element(VIEW_NODE, &show_ip_bgp_nexthop_cmd);
649 install_element(VIEW_NODE, &show_ip_bgp_instance_all_nexthop_cmd);
718e3744 650}
228da428 651
d62a17ae 652void bgp_scan_finish(struct bgp *bgp)
228da428 653{
d62a17ae 654 afi_t afi;
6c88b44d 655
d62a17ae 656 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
657 /* Only the current one needs to be reset. */
658 bgp_nexthop_cache_reset(bgp->nexthop_cache_table[afi]);
659 bgp_table_unlock(bgp->nexthop_cache_table[afi]);
660 bgp->nexthop_cache_table[afi] = NULL;
228da428 661
3292693b
DS
662 bgp->connected_table[afi]->route_table->cleanup =
663 bgp_connected_cleanup;
d62a17ae 664 bgp_table_unlock(bgp->connected_table[afi]);
665 bgp->connected_table[afi] = NULL;
078430f6 666
d62a17ae 667 bgp_table_unlock(bgp->import_check_table[afi]);
668 bgp->import_check_table[afi] = NULL;
669 }
228da428 670}