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