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