]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_nexthop.c
bgpd: optimize aspath string representation and assegments handling
[mirror_frr.git] / bgpd / bgp_nexthop.c
CommitLineData
718e3744 1/* BGP nexthop scan
2 Copyright (C) 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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"
31
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_table.h"
34#include "bgpd/bgp_route.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_nexthop.h"
37#include "bgpd/bgp_debug.h"
38#include "bgpd/bgp_damp.h"
39#include "zebra/rib.h"
40#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
41
42struct bgp_nexthop_cache *zlookup_query (struct in_addr);
43#ifdef HAVE_IPV6
44struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
45#endif /* HAVE_IPV6 */
46\f
47/* Only one BGP scan thread are activated at the same time. */
00d252cb 48static struct thread *bgp_scan_thread = NULL;
718e3744 49
50/* BGP import thread */
00d252cb 51static struct thread *bgp_import_thread = NULL;
718e3744 52
53/* BGP scan interval. */
00d252cb 54static int bgp_scan_interval;
718e3744 55
56/* BGP import interval. */
00d252cb 57static int bgp_import_interval;
718e3744 58
59/* Route table for next-hop lookup cache. */
00d252cb 60static struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
61static struct bgp_table *cache1_table[AFI_MAX];
62static struct bgp_table *cache2_table[AFI_MAX];
718e3744 63
64/* Route table for connected route. */
00d252cb 65static struct bgp_table *bgp_connected_table[AFI_MAX];
718e3744 66
67/* BGP nexthop lookup query client. */
228da428 68struct zclient *zlookup = NULL;
718e3744 69\f
70/* Add nexthop to the end of the list. */
94f2b392 71static void
718e3744 72bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
73{
74 struct nexthop *last;
75
76 for (last = bnc->nexthop; last && last->next; last = last->next)
77 ;
78 if (last)
79 last->next = nexthop;
80 else
81 bnc->nexthop = nexthop;
82 nexthop->prev = last;
83}
84
94f2b392 85static void
718e3744 86bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
87{
88 struct nexthop *nexthop;
89 struct nexthop *next = NULL;
90
91 for (nexthop = bnc->nexthop; nexthop; nexthop = next)
92 {
93 next = nexthop->next;
94 XFREE (MTYPE_NEXTHOP, nexthop);
95 }
96}
97
94f2b392 98static struct bgp_nexthop_cache *
66e5cd87 99bnc_new (void)
718e3744 100{
393deb9b 101 return XCALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
718e3744 102}
103
94f2b392 104static void
718e3744 105bnc_free (struct bgp_nexthop_cache *bnc)
106{
107 bnc_nexthop_free (bnc);
108 XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
109}
110\f
94f2b392 111static int
718e3744 112bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
113{
114 if (next1->type != next2->type)
115 return 0;
116
117 switch (next1->type)
118 {
119 case ZEBRA_NEXTHOP_IPV4:
120 if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
121 return 0;
122 break;
123 case ZEBRA_NEXTHOP_IFINDEX:
124 case ZEBRA_NEXTHOP_IFNAME:
125 if (next1->ifindex != next2->ifindex)
126 return 0;
127 break;
128#ifdef HAVE_IPV6
129 case ZEBRA_NEXTHOP_IPV6:
130 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
131 return 0;
132 break;
133 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
134 case ZEBRA_NEXTHOP_IPV6_IFNAME:
135 if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
136 return 0;
137 if (next1->ifindex != next2->ifindex)
138 return 0;
139 break;
140#endif /* HAVE_IPV6 */
fa2b17e3 141 default:
142 /* do nothing */
143 break;
718e3744 144 }
145 return 1;
146}
147
94f2b392 148static int
8e80bdf2 149bgp_nexthop_cache_different (struct bgp_nexthop_cache *bnc1,
718e3744 150 struct bgp_nexthop_cache *bnc2)
151{
152 int i;
153 struct nexthop *next1, *next2;
154
155 if (bnc1->nexthop_num != bnc2->nexthop_num)
156 return 1;
157
158 next1 = bnc1->nexthop;
159 next2 = bnc2->nexthop;
160
161 for (i = 0; i < bnc1->nexthop_num; i++)
162 {
163 if (! bgp_nexthop_same (next1, next2))
164 return 1;
165
166 next1 = next1->next;
167 next2 = next2->next;
168 }
169 return 0;
170}
171
172/* If nexthop exists on connected network return 1. */
173int
8e80bdf2 174bgp_nexthop_onlink (afi_t afi, struct attr *attr)
718e3744 175{
176 struct bgp_node *rn;
fc98d16e
PJ
177
178 /* If zebra is not enabled return */
179 if (zlookup->sock < 0)
180 return 1;
181
718e3744 182 /* Lookup the address is onlink or not. */
183 if (afi == AFI_IP)
184 {
5932020b 185 rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
718e3744 186 if (rn)
187 {
188 bgp_unlock_node (rn);
189 return 1;
190 }
191 }
192#ifdef HAVE_IPV6
193 else if (afi == AFI_IP6)
194 {
fb982c25 195 if (attr->extra->mp_nexthop_len == 32)
718e3744 196 return 1;
fb982c25 197 else if (attr->extra->mp_nexthop_len == 16)
718e3744 198 {
fb982c25 199 if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
718e3744 200 return 1;
201
5932020b 202 rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
fb982c25 203 &attr->extra->mp_nexthop_global);
718e3744 204 if (rn)
205 {
206 bgp_unlock_node (rn);
207 return 1;
208 }
209 }
210 }
211#endif /* HAVE_IPV6 */
212 return 0;
213}
214
215#ifdef HAVE_IPV6
216/* Check specified next-hop is reachable or not. */
94f2b392 217static int
718e3744 218bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
219 int *metricchanged)
220{
221 struct bgp_node *rn;
222 struct prefix p;
223 struct bgp_nexthop_cache *bnc;
224 struct attr *attr;
fc98d16e
PJ
225
226 /* If lookup is not enabled, return valid. */
227 if (zlookup->sock < 0)
228 {
229 if (ri->extra)
230 ri->extra->igpmetric = 0;
231 return 1;
232 }
233
718e3744 234 /* Only check IPv6 global address only nexthop. */
235 attr = ri->attr;
236
fb982c25
PJ
237 if (attr->extra->mp_nexthop_len != 16
238 || IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
718e3744 239 return 1;
240
241 memset (&p, 0, sizeof (struct prefix));
242 p.family = AF_INET6;
243 p.prefixlen = IPV6_MAX_BITLEN;
fb982c25 244 p.u.prefix6 = attr->extra->mp_nexthop_global;
718e3744 245
246 /* IBGP or ebgp-multihop */
5932020b 247 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP6], &p);
718e3744 248
249 if (rn->info)
250 {
251 bnc = rn->info;
252 bgp_unlock_node (rn);
253 }
254 else
255 {
b64bfc1c
DO
256 if (NULL == (bnc = zlookup_query_ipv6 (&attr->extra->mp_nexthop_global)))
257 bnc = bnc_new ();
258 else
718e3744 259 {
718e3744 260 if (changed)
261 {
8e80bdf2
DO
262 struct bgp_table *old;
263 struct bgp_node *oldrn;
264
5932020b 265 if (bgp_nexthop_cache_table[AFI_IP6] == cache1_table[AFI_IP6])
266 old = cache2_table[AFI_IP6];
718e3744 267 else
5932020b 268 old = cache1_table[AFI_IP6];
718e3744 269
270 oldrn = bgp_node_lookup (old, &p);
271 if (oldrn)
272 {
8e80bdf2 273 struct bgp_nexthop_cache *oldbnc = oldrn->info;
718e3744 274
8e80bdf2 275 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
718e3744 276
277 if (bnc->metric != oldbnc->metric)
278 bnc->metricchanged = 1;
6c88b44d
CC
279
280 bgp_unlock_node (oldrn);
718e3744 281 }
282 }
283 }
718e3744 284 rn->info = bnc;
285 }
286
287 if (changed)
288 *changed = bnc->changed;
289
290 if (metricchanged)
291 *metricchanged = bnc->metricchanged;
292
fb982c25
PJ
293 if (bnc->valid && bnc->metric)
294 (bgp_info_extra_get (ri))->igpmetric = bnc->metric;
295 else if (ri->extra)
296 ri->extra->igpmetric = 0;
718e3744 297
298 return bnc->valid;
299}
300#endif /* HAVE_IPV6 */
301
302/* Check specified next-hop is reachable or not. */
303int
304bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
305 int *changed, int *metricchanged)
306{
307 struct bgp_node *rn;
308 struct prefix p;
309 struct bgp_nexthop_cache *bnc;
310 struct in_addr addr;
fc98d16e
PJ
311
312 /* If lookup is not enabled, return valid. */
313 if (zlookup->sock < 0)
314 {
315 if (ri->extra)
316 ri->extra->igpmetric = 0;
317 return 1;
318 }
319
718e3744 320#ifdef HAVE_IPV6
321 if (afi == AFI_IP6)
322 return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
323#endif /* HAVE_IPV6 */
324
325 addr = ri->attr->nexthop;
326
327 memset (&p, 0, sizeof (struct prefix));
328 p.family = AF_INET;
329 p.prefixlen = IPV4_MAX_BITLEN;
330 p.u.prefix4 = addr;
331
332 /* IBGP or ebgp-multihop */
5932020b 333 rn = bgp_node_get (bgp_nexthop_cache_table[AFI_IP], &p);
718e3744 334
335 if (rn->info)
336 {
337 bnc = rn->info;
338 bgp_unlock_node (rn);
339 }
340 else
341 {
b64bfc1c
DO
342 if (NULL == (bnc = zlookup_query (addr)))
343 bnc = bnc_new ();
344 else
718e3744 345 {
718e3744 346 if (changed)
347 {
8e80bdf2
DO
348 struct bgp_table *old;
349 struct bgp_node *oldrn;
350
5932020b 351 if (bgp_nexthop_cache_table[AFI_IP] == cache1_table[AFI_IP])
352 old = cache2_table[AFI_IP];
718e3744 353 else
5932020b 354 old = cache1_table[AFI_IP];
718e3744 355
356 oldrn = bgp_node_lookup (old, &p);
357 if (oldrn)
358 {
8e80bdf2 359 struct bgp_nexthop_cache *oldbnc = oldrn->info;
718e3744 360
8e80bdf2 361 bnc->changed = bgp_nexthop_cache_different (bnc, oldbnc);
718e3744 362
363 if (bnc->metric != oldbnc->metric)
364 bnc->metricchanged = 1;
6c88b44d
CC
365
366 bgp_unlock_node (oldrn);
718e3744 367 }
368 }
369 }
718e3744 370 rn->info = bnc;
371 }
372
373 if (changed)
374 *changed = bnc->changed;
375
376 if (metricchanged)
377 *metricchanged = bnc->metricchanged;
378
fb982c25
PJ
379 if (bnc->valid && bnc->metric)
380 (bgp_info_extra_get(ri))->igpmetric = bnc->metric;
381 else if (ri->extra)
382 ri->extra->igpmetric = 0;
718e3744 383
384 return bnc->valid;
385}
386
387/* Reset and free all BGP nexthop cache. */
94f2b392 388static void
718e3744 389bgp_nexthop_cache_reset (struct bgp_table *table)
390{
391 struct bgp_node *rn;
392 struct bgp_nexthop_cache *bnc;
393
394 for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
395 if ((bnc = rn->info) != NULL)
396 {
397 bnc_free (bnc);
398 rn->info = NULL;
399 bgp_unlock_node (rn);
400 }
401}
402
94f2b392 403static void
5932020b 404bgp_scan (afi_t afi, safi_t safi)
718e3744 405{
406 struct bgp_node *rn;
407 struct bgp *bgp;
408 struct bgp_info *bi;
409 struct bgp_info *next;
410 struct peer *peer;
1eb8ef25 411 struct listnode *node, *nnode;
718e3744 412 int valid;
413 int current;
414 int changed;
415 int metricchanged;
416
417 /* Change cache. */
5932020b 418 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
419 bgp_nexthop_cache_table[afi] = cache2_table[afi];
718e3744 420 else
5932020b 421 bgp_nexthop_cache_table[afi] = cache1_table[afi];
718e3744 422
423 /* Get default bgp. */
424 bgp = bgp_get_default ();
425 if (bgp == NULL)
426 return;
427
428 /* Maximum prefix check */
1eb8ef25 429 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 430 {
431 if (peer->status != Established)
432 continue;
433
5932020b 434 if (peer->afc[afi][SAFI_UNICAST])
435 bgp_maximum_prefix_overflow (peer, afi, SAFI_UNICAST, 1);
436 if (peer->afc[afi][SAFI_MULTICAST])
437 bgp_maximum_prefix_overflow (peer, afi, SAFI_MULTICAST, 1);
438 if (peer->afc[afi][SAFI_MPLS_VPN])
439 bgp_maximum_prefix_overflow (peer, afi, SAFI_MPLS_VPN, 1);
718e3744 440 }
441
5932020b 442 for (rn = bgp_table_top (bgp->rib[afi][SAFI_UNICAST]); rn;
718e3744 443 rn = bgp_route_next (rn))
444 {
445 for (bi = rn->info; bi; bi = next)
446 {
447 next = bi->next;
448
449 if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
450 {
451 changed = 0;
452 metricchanged = 0;
453
454 if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
8e80bdf2 455 valid = bgp_nexthop_onlink (afi, bi->attr);
718e3744 456 else
5932020b 457 valid = bgp_nexthop_lookup (afi, bi->peer, bi,
718e3744 458 &changed, &metricchanged);
459
460 current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
461
462 if (changed)
463 SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
464 else
465 UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
466
467 if (valid != current)
468 {
469 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
470 {
471 bgp_aggregate_decrement (bgp, &rn->p, bi,
5932020b 472 afi, SAFI_UNICAST);
1a392d46 473 bgp_info_unset_flag (rn, bi, BGP_INFO_VALID);
718e3744 474 }
475 else
476 {
1a392d46 477 bgp_info_set_flag (rn, bi, BGP_INFO_VALID);
718e3744 478 bgp_aggregate_increment (bgp, &rn->p, bi,
5932020b 479 afi, SAFI_UNICAST);
718e3744 480 }
481 }
482
5932020b 483 if (CHECK_FLAG (bgp->af_flags[afi][SAFI_UNICAST],
718e3744 484 BGP_CONFIG_DAMPENING)
fb982c25 485 && bi->extra && bi->extra->damp_info )
5932020b 486 if (bgp_damp_scan (bi, afi, SAFI_UNICAST))
718e3744 487 bgp_aggregate_increment (bgp, &rn->p, bi,
5932020b 488 afi, SAFI_UNICAST);
718e3744 489 }
490 }
5932020b 491 bgp_process (bgp, rn, afi, SAFI_UNICAST);
718e3744 492 }
493
494 /* Flash old cache. */
5932020b 495 if (bgp_nexthop_cache_table[afi] == cache1_table[afi])
496 bgp_nexthop_cache_reset (cache2_table[afi]);
718e3744 497 else
5932020b 498 bgp_nexthop_cache_reset (cache1_table[afi]);
f418446b 499
500 if (BGP_DEBUG (events, EVENTS))
501 {
502 if (afi == AFI_IP)
503 zlog_debug ("scanning IPv4 Unicast routing tables");
504 else if (afi == AFI_IP6)
505 zlog_debug ("scanning IPv6 Unicast routing tables");
506 }
718e3744 507}
718e3744 508
509/* BGP scan thread. This thread check nexthop reachability. */
94f2b392 510static int
5932020b 511bgp_scan_timer (struct thread *t)
718e3744 512{
513 bgp_scan_thread =
5932020b 514 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 515
f418446b 516 if (BGP_DEBUG (events, EVENTS))
478ba054 517 zlog_debug ("Performing BGP general scanning");
718e3744 518
5932020b 519 bgp_scan (AFI_IP, SAFI_UNICAST);
718e3744 520
521#ifdef HAVE_IPV6
5932020b 522 bgp_scan (AFI_IP6, SAFI_UNICAST);
718e3744 523#endif /* HAVE_IPV6 */
524
525 return 0;
526}
527\f
5932020b 528struct bgp_connected_ref
718e3744 529{
530 unsigned int refcnt;
531};
532
533void
534bgp_connected_add (struct connected *ifc)
535{
536 struct prefix p;
537 struct prefix *addr;
718e3744 538 struct interface *ifp;
539 struct bgp_node *rn;
5932020b 540 struct bgp_connected_ref *bc;
718e3744 541
542 ifp = ifc->ifp;
543
544 if (! ifp)
545 return;
546
547 if (if_is_loopback (ifp))
548 return;
549
550 addr = ifc->address;
718e3744 551
552 if (addr->family == AF_INET)
553 {
e4529636 554 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 555 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
556
557 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
558 return;
559
5932020b 560 rn = bgp_node_get (bgp_connected_table[AFI_IP], (struct prefix *) &p);
718e3744 561 if (rn->info)
562 {
563 bc = rn->info;
564 bc->refcnt++;
565 }
566 else
567 {
6c88b44d 568 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 569 bc->refcnt = 1;
570 rn->info = bc;
571 }
572 }
573#ifdef HAVE_IPV6
e4529636 574 else if (addr->family == AF_INET6)
718e3744 575 {
e4529636 576 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 577 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
578
579 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
580 return;
581
582 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
583 return;
584
5932020b 585 rn = bgp_node_get (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 586 if (rn->info)
587 {
588 bc = rn->info;
589 bc->refcnt++;
590 }
591 else
592 {
6c88b44d 593 bc = XCALLOC (MTYPE_BGP_CONN, sizeof (struct bgp_connected_ref));
718e3744 594 bc->refcnt = 1;
595 rn->info = bc;
596 }
597 }
598#endif /* HAVE_IPV6 */
599}
600
601void
602bgp_connected_delete (struct connected *ifc)
603{
604 struct prefix p;
605 struct prefix *addr;
718e3744 606 struct interface *ifp;
607 struct bgp_node *rn;
5932020b 608 struct bgp_connected_ref *bc;
718e3744 609
610 ifp = ifc->ifp;
611
612 if (if_is_loopback (ifp))
613 return;
614
615 addr = ifc->address;
718e3744 616
617 if (addr->family == AF_INET)
618 {
e4529636 619 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 620 apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
621
622 if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
623 return;
624
5932020b 625 rn = bgp_node_lookup (bgp_connected_table[AFI_IP], &p);
718e3744 626 if (! rn)
627 return;
628
629 bc = rn->info;
630 bc->refcnt--;
631 if (bc->refcnt == 0)
632 {
6c88b44d 633 XFREE (MTYPE_BGP_CONN, bc);
718e3744 634 rn->info = NULL;
635 }
636 bgp_unlock_node (rn);
637 bgp_unlock_node (rn);
638 }
639#ifdef HAVE_IPV6
640 else if (addr->family == AF_INET6)
641 {
e4529636 642 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 643 apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
644
645 if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
646 return;
647
648 if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
649 return;
650
5932020b 651 rn = bgp_node_lookup (bgp_connected_table[AFI_IP6], (struct prefix *) &p);
718e3744 652 if (! rn)
653 return;
654
655 bc = rn->info;
656 bc->refcnt--;
657 if (bc->refcnt == 0)
658 {
6c88b44d 659 XFREE (MTYPE_BGP_CONN, bc);
718e3744 660 rn->info = NULL;
661 }
662 bgp_unlock_node (rn);
663 bgp_unlock_node (rn);
664 }
665#endif /* HAVE_IPV6 */
666}
667
668int
669bgp_nexthop_self (afi_t afi, struct attr *attr)
670{
52dc7ee6 671 struct listnode *node;
672 struct listnode *node2;
718e3744 673 struct interface *ifp;
674 struct connected *ifc;
675 struct prefix *p;
676
1eb8ef25 677 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
718e3744 678 {
1eb8ef25 679 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
718e3744 680 {
718e3744 681 p = ifc->address;
682
683 if (p && p->family == AF_INET
684 && IPV4_ADDR_SAME (&p->u.prefix4, &attr->nexthop))
685 return 1;
686 }
687 }
688 return 0;
689}
690\f
94f2b392 691static struct bgp_nexthop_cache *
66e5cd87 692zlookup_read (void)
718e3744 693{
694 struct stream *s;
d3092e7f 695 uint16_t length;
696 u_char marker;
697 u_char version;
698 uint16_t command;
718e3744 699 int nbytes;
700 struct in_addr raddr;
d3092e7f 701 uint32_t metric;
718e3744 702 int i;
703 u_char nexthop_num;
704 struct nexthop *nexthop;
705 struct bgp_nexthop_cache *bnc;
706
707 s = zlookup->ibuf;
708 stream_reset (s);
709
710 nbytes = stream_read (s, zlookup->sock, 2);
711 length = stream_getw (s);
712
713 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 714 marker = stream_getc (s);
715 version = stream_getc (s);
716
717 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
718 {
719 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
720 __func__, zlookup->sock, marker, version);
721 return NULL;
722 }
723
724 command = stream_getw (s);
725
718e3744 726 raddr.s_addr = stream_get_ipv4 (s);
727 metric = stream_getl (s);
728 nexthop_num = stream_getc (s);
729
730 if (nexthop_num)
731 {
732 bnc = bnc_new ();
733 bnc->valid = 1;
734 bnc->metric = metric;
735 bnc->nexthop_num = nexthop_num;
736
737 for (i = 0; i < nexthop_num; i++)
738 {
393deb9b 739 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
718e3744 740 nexthop->type = stream_getc (s);
741 switch (nexthop->type)
742 {
743 case ZEBRA_NEXTHOP_IPV4:
744 nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
745 break;
746 case ZEBRA_NEXTHOP_IFINDEX:
747 case ZEBRA_NEXTHOP_IFNAME:
748 nexthop->ifindex = stream_getl (s);
749 break;
fa2b17e3 750 default:
751 /* do nothing */
752 break;
718e3744 753 }
754 bnc_nexthop_add (bnc, nexthop);
755 }
756 }
757 else
758 return NULL;
759
760 return bnc;
761}
762
763struct bgp_nexthop_cache *
764zlookup_query (struct in_addr addr)
765{
766 int ret;
767 struct stream *s;
768
769 /* Check socket. */
770 if (zlookup->sock < 0)
771 return NULL;
772
773 s = zlookup->obuf;
774 stream_reset (s);
d3092e7f 775 zclient_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
718e3744 776 stream_put_in_addr (s, &addr);
d3092e7f 777
778 stream_putw_at (s, 0, stream_get_endp (s));
779
780 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 781 if (ret < 0)
782 {
783 zlog_err ("can't write to zlookup->sock");
784 close (zlookup->sock);
785 zlookup->sock = -1;
786 return NULL;
787 }
788 if (ret == 0)
789 {
790 zlog_err ("zlookup->sock connection closed");
791 close (zlookup->sock);
792 zlookup->sock = -1;
793 return NULL;
794 }
795
796 return zlookup_read ();
797}
798
799#ifdef HAVE_IPV6
94f2b392 800static struct bgp_nexthop_cache *
66e5cd87 801zlookup_read_ipv6 (void)
718e3744 802{
803 struct stream *s;
d3092e7f 804 uint16_t length;
805 u_char version, marker;
806 uint16_t command;
718e3744 807 int nbytes;
808 struct in6_addr raddr;
d3092e7f 809 uint32_t metric;
718e3744 810 int i;
811 u_char nexthop_num;
812 struct nexthop *nexthop;
813 struct bgp_nexthop_cache *bnc;
814
815 s = zlookup->ibuf;
816 stream_reset (s);
817
818 nbytes = stream_read (s, zlookup->sock, 2);
819 length = stream_getw (s);
820
821 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 822 marker = stream_getc (s);
823 version = stream_getc (s);
824
825 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
826 {
827 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
828 __func__, zlookup->sock, marker, version);
829 return NULL;
830 }
831
832 command = stream_getw (s);
833
718e3744 834 stream_get (&raddr, s, 16);
835
836 metric = stream_getl (s);
837 nexthop_num = stream_getc (s);
838
839 if (nexthop_num)
840 {
841 bnc = bnc_new ();
842 bnc->valid = 1;
843 bnc->metric = metric;
844 bnc->nexthop_num = nexthop_num;
845
846 for (i = 0; i < nexthop_num; i++)
847 {
393deb9b 848 nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
718e3744 849 nexthop->type = stream_getc (s);
850 switch (nexthop->type)
851 {
852 case ZEBRA_NEXTHOP_IPV6:
853 stream_get (&nexthop->gate.ipv6, s, 16);
854 break;
855 case ZEBRA_NEXTHOP_IPV6_IFINDEX:
856 case ZEBRA_NEXTHOP_IPV6_IFNAME:
857 stream_get (&nexthop->gate.ipv6, s, 16);
858 nexthop->ifindex = stream_getl (s);
859 break;
860 case ZEBRA_NEXTHOP_IFINDEX:
861 case ZEBRA_NEXTHOP_IFNAME:
862 nexthop->ifindex = stream_getl (s);
863 break;
fa2b17e3 864 default:
865 /* do nothing */
866 break;
718e3744 867 }
868 bnc_nexthop_add (bnc, nexthop);
869 }
870 }
871 else
872 return NULL;
873
874 return bnc;
875}
876
877struct bgp_nexthop_cache *
878zlookup_query_ipv6 (struct in6_addr *addr)
879{
880 int ret;
881 struct stream *s;
882
883 /* Check socket. */
884 if (zlookup->sock < 0)
885 return NULL;
886
887 s = zlookup->obuf;
888 stream_reset (s);
d3092e7f 889 zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
718e3744 890 stream_put (s, addr, 16);
d3092e7f 891 stream_putw_at (s, 0, stream_get_endp (s));
892
893 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 894 if (ret < 0)
895 {
896 zlog_err ("can't write to zlookup->sock");
897 close (zlookup->sock);
898 zlookup->sock = -1;
899 return NULL;
900 }
901 if (ret == 0)
902 {
903 zlog_err ("zlookup->sock connection closed");
904 close (zlookup->sock);
905 zlookup->sock = -1;
906 return NULL;
907 }
908
909 return zlookup_read_ipv6 ();
910}
911#endif /* HAVE_IPV6 */
912
94f2b392 913static int
914bgp_import_check (struct prefix *p, u_int32_t *igpmetric,
915 struct in_addr *igpnexthop)
718e3744 916{
917 struct stream *s;
918 int ret;
d3092e7f 919 u_int16_t length, command;
920 u_char version, marker;
718e3744 921 int nbytes;
922 struct in_addr addr;
923 struct in_addr nexthop;
924 u_int32_t metric = 0;
925 u_char nexthop_num;
926 u_char nexthop_type;
927
928 /* If lookup connection is not available return valid. */
929 if (zlookup->sock < 0)
930 {
931 if (igpmetric)
932 *igpmetric = 0;
933 return 1;
934 }
935
936 /* Send query to the lookup connection */
937 s = zlookup->obuf;
938 stream_reset (s);
d3092e7f 939 zclient_create_header (s, ZEBRA_IPV4_IMPORT_LOOKUP);
940
718e3744 941 stream_putc (s, p->prefixlen);
942 stream_put_in_addr (s, &p->u.prefix4);
d3092e7f 943
944 stream_putw_at (s, 0, stream_get_endp (s));
945
718e3744 946 /* Write the packet. */
d3092e7f 947 ret = writen (zlookup->sock, s->data, stream_get_endp (s));
718e3744 948
949 if (ret < 0)
950 {
951 zlog_err ("can't write to zlookup->sock");
952 close (zlookup->sock);
953 zlookup->sock = -1;
954 return 1;
955 }
956 if (ret == 0)
957 {
958 zlog_err ("zlookup->sock connection closed");
959 close (zlookup->sock);
960 zlookup->sock = -1;
961 return 1;
962 }
963
964 /* Get result. */
965 stream_reset (s);
966
967 /* Fetch length. */
968 nbytes = stream_read (s, zlookup->sock, 2);
969 length = stream_getw (s);
970
971 /* Fetch whole data. */
972 nbytes = stream_read (s, zlookup->sock, length - 2);
d3092e7f 973 marker = stream_getc (s);
974 version = stream_getc (s);
975
976 if (version != ZSERV_VERSION || marker != ZEBRA_HEADER_MARKER)
977 {
978 zlog_err("%s: socket %d version mismatch, marker %d, version %d",
979 __func__, zlookup->sock, marker, version);
980 return 0;
981 }
982
983 command = stream_getw (s);
984
718e3744 985 addr.s_addr = stream_get_ipv4 (s);
986 metric = stream_getl (s);
987 nexthop_num = stream_getc (s);
988
989 /* Set IGP metric value. */
990 if (igpmetric)
991 *igpmetric = metric;
992
993 /* If there is nexthop then this is active route. */
994 if (nexthop_num)
995 {
996 nexthop.s_addr = 0;
997 nexthop_type = stream_getc (s);
998 if (nexthop_type == ZEBRA_NEXTHOP_IPV4)
999 {
1000 nexthop.s_addr = stream_get_ipv4 (s);
1001 if (igpnexthop)
1002 *igpnexthop = nexthop;
1003 }
1004 else
1005 *igpnexthop = nexthop;
1006
1007 return 1;
1008 }
1009 else
1010 return 0;
1011}
1012
1013/* Scan all configured BGP route then check the route exists in IGP or
1014 not. */
94f2b392 1015static int
718e3744 1016bgp_import (struct thread *t)
1017{
1018 struct bgp *bgp;
1019 struct bgp_node *rn;
1020 struct bgp_static *bgp_static;
1eb8ef25 1021 struct listnode *node, *nnode;
718e3744 1022 int valid;
1023 u_int32_t metric;
1024 struct in_addr nexthop;
1025 afi_t afi;
1026 safi_t safi;
1027
1028 bgp_import_thread =
1029 thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
1030
f418446b 1031 if (BGP_DEBUG (events, EVENTS))
1032 zlog_debug ("Import timer expired.");
718e3744 1033
1eb8ef25 1034 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
6cbbc3cc 1035 {
1036 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1037 for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
1038 for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
1039 rn = bgp_route_next (rn))
1040 if ((bgp_static = rn->info) != NULL)
718e3744 1041 {
6cbbc3cc 1042 if (bgp_static->backdoor)
1043 continue;
718e3744 1044
6cbbc3cc 1045 valid = bgp_static->valid;
1046 metric = bgp_static->igpmetric;
1047 nexthop = bgp_static->igpnexthop;
1048
1049 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
1050 && afi == AFI_IP && safi == SAFI_UNICAST)
1051 bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
1052 &bgp_static->igpnexthop);
718e3744 1053 else
6cbbc3cc 1054 {
1055 bgp_static->valid = 1;
1056 bgp_static->igpmetric = 0;
1057 bgp_static->igpnexthop.s_addr = 0;
1058 }
1059
1060 if (bgp_static->valid != valid)
1061 {
1062 if (bgp_static->valid)
1063 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1064 else
1065 bgp_static_withdraw (bgp, &rn->p, afi, safi);
1066 }
1067 else if (bgp_static->valid)
1068 {
1069 if (bgp_static->igpmetric != metric
1070 || bgp_static->igpnexthop.s_addr != nexthop.s_addr
1071 || bgp_static->rmap.name)
1072 bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
1073 }
718e3744 1074 }
6cbbc3cc 1075 }
718e3744 1076 return 0;
1077}
1078
1079/* Connect to zebra for nexthop lookup. */
94f2b392 1080static int
718e3744 1081zlookup_connect (struct thread *t)
1082{
1083 struct zclient *zlookup;
1084
1085 zlookup = THREAD_ARG (t);
1086 zlookup->t_connect = NULL;
1087
1088 if (zlookup->sock != -1)
1089 return 0;
1090
b5114685 1091 if (zclient_socket_connect (zlookup) < 0)
718e3744 1092 return -1;
1093
718e3744 1094 return 0;
1095}
1096
1097/* Check specified multiaccess next-hop. */
1098int
1099bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
1100{
1101 struct bgp_node *rn1;
1102 struct bgp_node *rn2;
1103 struct prefix p1;
1104 struct prefix p2;
1105 struct in_addr addr;
1106 int ret;
1107
1108 ret = inet_aton (peer, &addr);
1109 if (! ret)
1110 return 0;
1111
1112 memset (&p1, 0, sizeof (struct prefix));
1113 p1.family = AF_INET;
1114 p1.prefixlen = IPV4_MAX_BITLEN;
1115 p1.u.prefix4 = nexthop;
1116 memset (&p2, 0, sizeof (struct prefix));
1117 p2.family = AF_INET;
1118 p2.prefixlen = IPV4_MAX_BITLEN;
1119 p2.u.prefix4 = addr;
1120
1121 /* If bgp scan is not enabled, return invalid. */
1122 if (zlookup->sock < 0)
1123 return 0;
1124
5932020b 1125 rn1 = bgp_node_match (bgp_connected_table[AFI_IP], &p1);
718e3744 1126 if (! rn1)
1127 return 0;
6c88b44d 1128 bgp_unlock_node (rn1);
718e3744 1129
5932020b 1130 rn2 = bgp_node_match (bgp_connected_table[AFI_IP], &p2);
718e3744 1131 if (! rn2)
1132 return 0;
6c88b44d 1133 bgp_unlock_node (rn2);
718e3744 1134
6c88b44d
CC
1135 /* This is safe, even with above unlocks, since we are just
1136 comparing pointers to the objects, not the objects themselves. */
718e3744 1137 if (rn1 == rn2)
1138 return 1;
1139
1140 return 0;
1141}
1142\f
1143DEFUN (bgp_scan_time,
1144 bgp_scan_time_cmd,
1145 "bgp scan-time <5-60>",
1146 "BGP specific commands\n"
1147 "Configure background scanner interval\n"
1148 "Scanner interval (seconds)\n")
1149{
1150 bgp_scan_interval = atoi (argv[0]);
1151
1152 if (bgp_scan_thread)
1153 {
1154 thread_cancel (bgp_scan_thread);
1155 bgp_scan_thread =
5932020b 1156 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 1157 }
1158
1159 return CMD_SUCCESS;
1160}
1161
1162DEFUN (no_bgp_scan_time,
1163 no_bgp_scan_time_cmd,
1164 "no bgp scan-time",
1165 NO_STR
1166 "BGP specific commands\n"
1167 "Configure background scanner interval\n")
1168{
1169 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1170
1171 if (bgp_scan_thread)
1172 {
1173 thread_cancel (bgp_scan_thread);
1174 bgp_scan_thread =
5932020b 1175 thread_add_timer (master, bgp_scan_timer, NULL, bgp_scan_interval);
718e3744 1176 }
1177
1178 return CMD_SUCCESS;
1179}
1180
1181ALIAS (no_bgp_scan_time,
1182 no_bgp_scan_time_val_cmd,
1183 "no bgp scan-time <5-60>",
1184 NO_STR
1185 "BGP specific commands\n"
1186 "Configure background scanner interval\n"
1187 "Scanner interval (seconds)\n")
1188
318f0d8a
DO
1189static int
1190show_ip_bgp_scan_tables (struct vty *vty, const char detail)
718e3744 1191{
1192 struct bgp_node *rn;
1193 struct bgp_nexthop_cache *bnc;
318f0d8a
DO
1194 char buf[INET6_ADDRSTRLEN];
1195 u_char i;
718e3744 1196
1197 if (bgp_scan_thread)
1198 vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
1199 else
1200 vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
1201 vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
1202
1203 vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
5932020b 1204 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
718e3744 1205 if ((bnc = rn->info) != NULL)
1206 {
1207 if (bnc->valid)
318f0d8a 1208 {
718e3744 1209 vty_out (vty, " %s valid [IGP metric %d]%s",
318f0d8a
DO
1210 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), bnc->metric, VTY_NEWLINE);
1211 if (detail)
1212 for (i = 0; i < bnc->nexthop_num; i++)
0e8032d6
DO
1213 switch (bnc->nexthop[i].type)
1214 {
1215 case NEXTHOP_TYPE_IPV4:
1216 vty_out (vty, " gate %s%s", inet_ntop (AF_INET, &bnc->nexthop[i].gate.ipv4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1217 break;
1218 case NEXTHOP_TYPE_IFINDEX:
1219 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1220 break;
1221 default:
1222 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1223 }
318f0d8a 1224 }
718e3744 1225 else
1226 vty_out (vty, " %s invalid%s",
318f0d8a 1227 inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
718e3744 1228 }
1229
1230#ifdef HAVE_IPV6
1231 {
5932020b 1232 for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
1233 rn;
1234 rn = bgp_route_next (rn))
718e3744 1235 if ((bnc = rn->info) != NULL)
1236 {
1237 if (bnc->valid)
318f0d8a 1238 {
718e3744 1239 vty_out (vty, " %s valid [IGP metric %d]%s",
318f0d8a 1240 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1241 bnc->metric, VTY_NEWLINE);
318f0d8a
DO
1242 if (detail)
1243 for (i = 0; i < bnc->nexthop_num; i++)
0e8032d6
DO
1244 switch (bnc->nexthop[i].type)
1245 {
1246 case NEXTHOP_TYPE_IPV6:
1247 vty_out (vty, " gate %s%s", inet_ntop (AF_INET6, &bnc->nexthop[i].gate.ipv6, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
1248 break;
1249 case NEXTHOP_TYPE_IFINDEX:
1250 vty_out (vty, " ifidx %u%s", bnc->nexthop[i].ifindex, VTY_NEWLINE);
1251 break;
1252 default:
1253 vty_out (vty, " invalid nexthop type %u%s", bnc->nexthop[i].type, VTY_NEWLINE);
1254 }
318f0d8a 1255 }
718e3744 1256 else
1257 vty_out (vty, " %s invalid%s",
318f0d8a 1258 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1259 VTY_NEWLINE);
1260 }
1261 }
1262#endif /* HAVE_IPV6 */
1263
1264 vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
5932020b 1265 for (rn = bgp_table_top (bgp_connected_table[AFI_IP]);
1266 rn;
1267 rn = bgp_route_next (rn))
718e3744 1268 if (rn->info != NULL)
1269 vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
1270 VTY_NEWLINE);
1271
1272#ifdef HAVE_IPV6
1273 {
5932020b 1274 for (rn = bgp_table_top (bgp_connected_table[AFI_IP6]);
1275 rn;
1276 rn = bgp_route_next (rn))
718e3744 1277 if (rn->info != NULL)
1278 vty_out (vty, " %s/%d%s",
318f0d8a 1279 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
718e3744 1280 rn->p.prefixlen,
1281 VTY_NEWLINE);
1282 }
1283#endif /* HAVE_IPV6 */
1284
1285 return CMD_SUCCESS;
1286}
1287
318f0d8a
DO
1288DEFUN (show_ip_bgp_scan,
1289 show_ip_bgp_scan_cmd,
1290 "show ip bgp scan",
1291 SHOW_STR
1292 IP_STR
1293 BGP_STR
1294 "BGP scan status\n")
1295{
1296 return show_ip_bgp_scan_tables (vty, 0);
1297}
1298
1299DEFUN (show_ip_bgp_scan_detail,
1300 show_ip_bgp_scan_detail_cmd,
1301 "show ip bgp scan detail",
1302 SHOW_STR
1303 IP_STR
1304 BGP_STR
1305 "BGP scan status\n"
1306 "More detailed output\n")
1307{
1308 return show_ip_bgp_scan_tables (vty, 1);
1309}
1310
718e3744 1311int
1312bgp_config_write_scan_time (struct vty *vty)
1313{
1314 if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
1315 vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
1316 return CMD_SUCCESS;
1317}
1318
1319void
66e5cd87 1320bgp_scan_init (void)
718e3744 1321{
1322 zlookup = zclient_new ();
1323 zlookup->sock = -1;
718e3744 1324 zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
1325
1326 bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
1327 bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
1328
64e580a7
PJ
1329 cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
1330 cache2_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
5932020b 1331 bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
718e3744 1332
64e580a7 1333 bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
718e3744 1334
1335#ifdef HAVE_IPV6
64e580a7
PJ
1336 cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
1337 cache2_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
5932020b 1338 bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
64e580a7 1339 bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
718e3744 1340#endif /* HAVE_IPV6 */
1341
1342 /* Make BGP scan thread. */
5932020b 1343 bgp_scan_thread = thread_add_timer (master, bgp_scan_timer,
1344 NULL, bgp_scan_interval);
6cbbc3cc 1345 /* Make BGP import there. */
1346 bgp_import_thread = thread_add_timer (master, bgp_import, NULL, 0);
718e3744 1347
1348 install_element (BGP_NODE, &bgp_scan_time_cmd);
1349 install_element (BGP_NODE, &no_bgp_scan_time_cmd);
1350 install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
1351 install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
318f0d8a 1352 install_element (VIEW_NODE, &show_ip_bgp_scan_detail_cmd);
62687ff1 1353 install_element (RESTRICTED_NODE, &show_ip_bgp_scan_cmd);
718e3744 1354 install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
318f0d8a 1355 install_element (ENABLE_NODE, &show_ip_bgp_scan_detail_cmd);
718e3744 1356}
228da428
CC
1357
1358void
1359bgp_scan_finish (void)
1360{
6c88b44d
CC
1361 /* Only the current one needs to be reset. */
1362 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
1363
228da428
CC
1364 bgp_table_unlock (cache1_table[AFI_IP]);
1365 cache1_table[AFI_IP] = NULL;
1366
1367 bgp_table_unlock (cache2_table[AFI_IP]);
1368 cache2_table[AFI_IP] = NULL;
1369
1370 bgp_table_unlock (bgp_connected_table[AFI_IP]);
1371 bgp_connected_table[AFI_IP] = NULL;
1372
1373#ifdef HAVE_IPV6
6c88b44d
CC
1374 /* Only the current one needs to be reset. */
1375 bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
1376
228da428
CC
1377 bgp_table_unlock (cache1_table[AFI_IP6]);
1378 cache1_table[AFI_IP6] = NULL;
1379
1380 bgp_table_unlock (cache2_table[AFI_IP6]);
1381 cache2_table[AFI_IP6] = NULL;
1382
1383 bgp_table_unlock (bgp_connected_table[AFI_IP6]);
1384 bgp_connected_table[AFI_IP6] = NULL;
1385#endif /* HAVE_IPV6 */
1386}