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