Annotation of embedaddon/quagga/bgpd/bgp_nexthop.c, revision 1.1.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>