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