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