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