Annotation of embedaddon/bird2/proto/babel/babel.c, revision 1.1.1.1
1.1 misho 1: /*
2: * BIRD -- The Babel protocol
3: *
4: * Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
5: * (c) 2016--2017 Ondrej Zajicek <santiago@crfreenet.org>
6: * (c) 2016--2017 CZ.NIC z.s.p.o.
7: *
8: * Can be freely distributed and used under the terms of the GNU GPL.
9: *
10: * This file contains the main routines for handling and sending TLVs, as
11: * well as timers and interaction with the nest.
12: */
13:
14: /**
15: * DOC: The Babel protocol
16: *
17: * Babel (RFC6126) is a loop-avoiding distance-vector routing protocol that is
18: * robust and efficient both in ordinary wired networks and in wireless mesh
19: * networks.
20: *
21: * The Babel protocol keeps state for each neighbour in a &babel_neighbor
22: * struct, tracking received Hello and I Heard You (IHU) messages. A
23: * &babel_interface struct keeps hello and update times for each interface, and
24: * a separate hello seqno is maintained for each interface.
25: *
26: * For each prefix, Babel keeps track of both the possible routes (with next hop
27: * and router IDs), as well as the feasibility distance for each prefix and
28: * router id. The prefix itself is tracked in a &babel_entry struct, while the
29: * possible routes for the prefix are tracked as &babel_route entries and the
30: * feasibility distance is maintained through &babel_source structures.
31: *
32: * The main route selection is done in babel_select_route(). This is called when
33: * an entry is updated by receiving updates from the network or when modified by
34: * internal timers. The function selects from feasible and reachable routes the
35: * one with the lowest metric to be announced to the core.
36: */
37:
38: #include <stdlib.h>
39: #include "babel.h"
40:
41:
42: /*
43: * Is one number greater or equal than another mod 2^16? This is based on the
44: * definition of serial number space in RFC 1982. Note that arguments are of
45: * uint type to avoid integer promotion to signed integer.
46: */
47: static inline int ge_mod64k(uint a, uint b)
48: { return (u16)(a - b) < 0x8000; }
49:
50: static void babel_expire_requests(struct babel_proto *p, struct babel_entry *e);
51: static void babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod);
52: static inline void babel_announce_retraction(struct babel_proto *p, struct babel_entry *e);
53: static void babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n);
54: static void babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr);
55: static void babel_update_cost(struct babel_neighbor *n);
56: static inline void babel_kick_timer(struct babel_proto *p);
57: static inline void babel_iface_kick_timer(struct babel_iface *ifa);
58:
59: static inline void babel_lock_neighbor(struct babel_neighbor *nbr)
60: { if (nbr) nbr->uc++; }
61:
62: static inline void babel_unlock_neighbor(struct babel_neighbor *nbr)
63: { if (nbr && !--nbr->uc) mb_free(nbr); }
64:
65:
66: /*
67: * Functions to maintain data structures
68: */
69:
70: static void
71: babel_init_entry(void *E)
72: {
73: struct babel_entry *e = E;
74:
75: e->updated = current_time();
76: init_list(&e->requests);
77: init_list(&e->sources);
78: init_list(&e->routes);
79: }
80:
81: static inline struct babel_entry *
82: babel_find_entry(struct babel_proto *p, const net_addr *n)
83: {
84: struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable;
85: return fib_find(rtable, n);
86: }
87:
88: static struct babel_entry *
89: babel_get_entry(struct babel_proto *p, const net_addr *n)
90: {
91: struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable;
92: struct babel_entry *e = fib_get(rtable, n);
93: return e;
94: }
95:
96: static struct babel_source *
97: babel_find_source(struct babel_entry *e, u64 router_id)
98: {
99: struct babel_source *s;
100:
101: WALK_LIST(s, e->sources)
102: if (s->router_id == router_id)
103: return s;
104:
105: return NULL;
106: }
107:
108: static struct babel_source *
109: babel_get_source(struct babel_proto *p, struct babel_entry *e, u64 router_id)
110: {
111: struct babel_source *s = babel_find_source(e, router_id);
112:
113: if (s)
114: return s;
115:
116: s = sl_alloc(p->source_slab);
117: s->router_id = router_id;
118: s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
119: s->seqno = 0;
120: s->metric = BABEL_INFINITY;
121: add_tail(&e->sources, NODE s);
122:
123: return s;
124: }
125:
126: static void
127: babel_expire_sources(struct babel_proto *p, struct babel_entry *e)
128: {
129: struct babel_source *n, *nx;
130: btime now_ = current_time();
131:
132: WALK_LIST_DELSAFE(n, nx, e->sources)
133: {
134: if (n->expires && n->expires <= now_)
135: {
136: rem_node(NODE n);
137: sl_free(p->source_slab, n);
138: }
139: }
140: }
141:
142: static struct babel_route *
143: babel_find_route(struct babel_entry *e, struct babel_neighbor *n)
144: {
145: struct babel_route *r;
146:
147: WALK_LIST(r, e->routes)
148: if (r->neigh == n)
149: return r;
150:
151: return NULL;
152: }
153:
154: static struct babel_route *
155: babel_get_route(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *nbr)
156: {
157: struct babel_route *r = babel_find_route(e, nbr);
158:
159: if (r)
160: return r;
161:
162: r = sl_alloc(p->route_slab);
163: memset(r, 0, sizeof(*r));
164:
165: r->e = e;
166: r->neigh = nbr;
167: add_tail(&e->routes, NODE r);
168: add_tail(&nbr->routes, NODE &r->neigh_route);
169:
170: return r;
171: }
172:
173: static inline void
174: babel_retract_route(struct babel_proto *p, struct babel_route *r)
175: {
176: r->metric = r->advert_metric = BABEL_INFINITY;
177:
178: if (r == r->e->selected)
179: babel_select_route(p, r->e, r);
180: }
181:
182: static void
183: babel_flush_route(struct babel_proto *p, struct babel_route *r)
184: {
185: DBG("Babel: Flush route %N router_id %lR neigh %I\n",
186: r->e->n.addr, r->router_id, r->neigh->addr);
187:
188: rem_node(NODE r);
189: rem_node(&r->neigh_route);
190:
191: if (r->e->selected == r)
192: r->e->selected = NULL;
193:
194: sl_free(p->route_slab, r);
195: }
196:
197: static void
198: babel_expire_route(struct babel_proto *p, struct babel_route *r)
199: {
200: struct babel_config *cf = (void *) p->p.cf;
201:
202: TRACE(D_EVENTS, "Route expiry timer for %N router-id %lR fired",
203: r->e->n.addr, r->router_id);
204:
205: if (r->metric < BABEL_INFINITY)
206: {
207: r->metric = r->advert_metric = BABEL_INFINITY;
208: r->expires = current_time() + cf->hold_time;
209: }
210: else
211: {
212: babel_flush_route(p, r);
213: }
214: }
215:
216: static void
217: babel_refresh_route(struct babel_proto *p, struct babel_route *r)
218: {
219: if (r == r->e->selected)
220: babel_send_route_request(p, r->e, r->neigh);
221:
222: r->refresh_time = 0;
223: }
224:
225: static void
226: babel_expire_routes_(struct babel_proto *p, struct fib *rtable)
227: {
228: struct babel_config *cf = (void *) p->p.cf;
229: struct babel_route *r, *rx;
230: struct fib_iterator fit;
231: btime now_ = current_time();
232:
233: FIB_ITERATE_INIT(&fit, rtable);
234:
235: loop:
236: FIB_ITERATE_START(rtable, &fit, struct babel_entry, e)
237: {
238: int changed = 0;
239:
240: WALK_LIST_DELSAFE(r, rx, e->routes)
241: {
242: if (r->refresh_time && r->refresh_time <= now_)
243: babel_refresh_route(p, r);
244:
245: if (r->expires && r->expires <= now_)
246: {
247: changed = changed || (r == e->selected);
248: babel_expire_route(p, r);
249: }
250: }
251:
252: if (changed)
253: {
254: /*
255: * We have to restart the iteration because there may be a cascade of
256: * synchronous events babel_select_route() -> nest table change ->
257: * babel_rt_notify() -> rtable change, invalidating hidden variables.
258: */
259: FIB_ITERATE_PUT(&fit);
260: babel_select_route(p, e, NULL);
261: goto loop;
262: }
263:
264: /* Clean up stale entries */
265: if ((e->valid == BABEL_ENTRY_STALE) && ((e->updated + cf->hold_time) <= now_))
266: e->valid = BABEL_ENTRY_DUMMY;
267:
268: /* Clean up unreachable route */
269: if (e->unreachable && (!e->valid || (e->router_id == p->router_id)))
270: {
271: FIB_ITERATE_PUT(&fit);
272: babel_announce_retraction(p, e);
273: goto loop;
274: }
275:
276: babel_expire_sources(p, e);
277: babel_expire_requests(p, e);
278:
279: /* Remove empty entries */
280: if (!e->valid && EMPTY_LIST(e->routes) && EMPTY_LIST(e->sources) && EMPTY_LIST(e->requests))
281: {
282: FIB_ITERATE_PUT(&fit);
283: fib_delete(rtable, e);
284: goto loop;
285: }
286: }
287: FIB_ITERATE_END;
288: }
289:
290: static void
291: babel_expire_routes(struct babel_proto *p)
292: {
293: babel_expire_routes_(p, &p->ip4_rtable);
294: babel_expire_routes_(p, &p->ip6_rtable);
295: }
296:
297: static inline int seqno_request_valid(struct babel_seqno_request *sr)
298: { return !sr->nbr || sr->nbr->ifa; }
299:
300: /*
301: * Add seqno request to the table of pending requests (RFC 6216 3.2.6) and send
302: * it to network. Do nothing if it is already in the table.
303: */
304:
305: static void
306: babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
307: u64 router_id, u16 seqno, u8 hop_count,
308: struct babel_neighbor *nbr)
309: {
310: struct babel_seqno_request *sr;
311:
312: WALK_LIST(sr, e->requests)
313: if (sr->router_id == router_id)
314: {
315: /* Found matching or newer */
316: if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
317: return;
318:
319: /* Found older */
320: babel_unlock_neighbor(sr->nbr);
321: rem_node(NODE sr);
322: goto found;
323: }
324:
325: /* No entries found */
326: sr = sl_alloc(p->seqno_slab);
327:
328: found:
329: sr->router_id = router_id;
330: sr->seqno = seqno;
331: sr->hop_count = hop_count;
332: sr->count = 0;
333: sr->expires = current_time() + BABEL_SEQNO_REQUEST_EXPIRY;
334: babel_lock_neighbor(sr->nbr = nbr);
335: add_tail(&e->requests, NODE sr);
336:
337: babel_send_seqno_request(p, e, sr);
338: }
339:
340: static void
341: babel_remove_seqno_request(struct babel_proto *p, struct babel_seqno_request *sr)
342: {
343: babel_unlock_neighbor(sr->nbr);
344: rem_node(NODE sr);
345: sl_free(p->seqno_slab, sr);
346: }
347:
348: static int
349: babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
350: u64 router_id, u16 seqno)
351: {
352: struct babel_seqno_request *sr;
353:
354: WALK_LIST(sr, e->requests)
355: if ((sr->router_id == router_id) && ge_mod64k(seqno, sr->seqno))
356: {
357: /* Found the request, remove it */
358: babel_remove_seqno_request(p, sr);
359: return 1;
360: }
361:
362: return 0;
363: }
364:
365: static void
366: babel_expire_requests(struct babel_proto *p, struct babel_entry *e)
367: {
368: struct babel_seqno_request *sr, *srx;
369: btime now_ = current_time();
370:
371: WALK_LIST_DELSAFE(sr, srx, e->requests)
372: {
373: /* Remove seqno requests sent to dead neighbors */
374: if (!seqno_request_valid(sr))
375: {
376: babel_remove_seqno_request(p, sr);
377: continue;
378: }
379:
380: /* Handle expired requests - resend or remove */
381: if (sr->expires && sr->expires <= now_)
382: {
383: if (sr->count < BABEL_SEQNO_REQUEST_RETRY)
384: {
385: sr->count++;
386: sr->expires += (BABEL_SEQNO_REQUEST_EXPIRY << sr->count);
387: babel_send_seqno_request(p, e, sr);
388: }
389: else
390: {
391: TRACE(D_EVENTS, "Seqno request for %N router-id %lR expired",
392: e->n.addr, sr->router_id);
393:
394: babel_remove_seqno_request(p, sr);
395: continue;
396: }
397: }
398: }
399: }
400:
401: static struct babel_neighbor *
402: babel_find_neighbor(struct babel_iface *ifa, ip_addr addr)
403: {
404: struct babel_neighbor *nbr;
405:
406: WALK_LIST(nbr, ifa->neigh_list)
407: if (ipa_equal(nbr->addr, addr))
408: return nbr;
409:
410: return NULL;
411: }
412:
413: static struct babel_neighbor *
414: babel_get_neighbor(struct babel_iface *ifa, ip_addr addr)
415: {
416: struct babel_proto *p = ifa->proto;
417: struct babel_neighbor *nbr = babel_find_neighbor(ifa, addr);
418:
419: if (nbr)
420: return nbr;
421:
422: TRACE(D_EVENTS, "New neighbor %I on %s", addr, ifa->iface->name);
423:
424: nbr = mb_allocz(ifa->pool, sizeof(struct babel_neighbor));
425: nbr->ifa = ifa;
426: nbr->addr = addr;
427: nbr->rxcost = BABEL_INFINITY;
428: nbr->txcost = BABEL_INFINITY;
429: nbr->cost = BABEL_INFINITY;
430: init_list(&nbr->routes);
431: babel_lock_neighbor(nbr);
432: add_tail(&ifa->neigh_list, NODE nbr);
433:
434: return nbr;
435: }
436:
437: static void
438: babel_flush_neighbor(struct babel_proto *p, struct babel_neighbor *nbr)
439: {
440: struct babel_route *r;
441: node *n;
442:
443: TRACE(D_EVENTS, "Removing neighbor %I on %s", nbr->addr, nbr->ifa->iface->name);
444:
445: WALK_LIST_FIRST(n, nbr->routes)
446: {
447: r = SKIP_BACK(struct babel_route, neigh_route, n);
448: babel_retract_route(p, r);
449: babel_flush_route(p, r);
450: }
451:
452: nbr->ifa = NULL;
453: rem_node(NODE nbr);
454: babel_unlock_neighbor(nbr);
455: }
456:
457: static void
458: babel_expire_ihu(struct babel_proto *p, struct babel_neighbor *nbr)
459: {
460: TRACE(D_EVENTS, "IHU from nbr %I on %s expired", nbr->addr, nbr->ifa->iface->name);
461:
462: nbr->txcost = BABEL_INFINITY;
463: nbr->ihu_expiry = 0;
464: babel_update_cost(nbr);
465: }
466:
467: static void
468: babel_expire_hello(struct babel_proto *p, struct babel_neighbor *nbr, btime now_)
469: {
470: again:
471: nbr->hello_map <<= 1;
472:
473: if (nbr->hello_cnt < 16)
474: nbr->hello_cnt++;
475:
476: nbr->hello_expiry += nbr->last_hello_int;
477:
478: /* We may expire multiple hellos if last_hello_int is too short */
479: if (nbr->hello_map && nbr->hello_expiry <= now_)
480: goto again;
481:
482: TRACE(D_EVENTS, "Hello from nbr %I on %s expired, %d left",
483: nbr->addr, nbr->ifa->iface->name, u32_popcount(nbr->hello_map));
484:
485: if (nbr->hello_map)
486: babel_update_cost(nbr);
487: else
488: babel_flush_neighbor(p, nbr);
489: }
490:
491: static void
492: babel_expire_neighbors(struct babel_proto *p)
493: {
494: struct babel_iface *ifa;
495: struct babel_neighbor *nbr, *nbx;
496: btime now_ = current_time();
497:
498: WALK_LIST(ifa, p->interfaces)
499: {
500: WALK_LIST_DELSAFE(nbr, nbx, ifa->neigh_list)
501: {
502: if (nbr->ihu_expiry && nbr->ihu_expiry <= now_)
503: babel_expire_ihu(p, nbr);
504:
505: if (nbr->hello_expiry && nbr->hello_expiry <= now_)
506: babel_expire_hello(p, nbr, now_);
507: }
508: }
509: }
510:
511:
512: /*
513: * Best route selection
514: */
515:
516: /*
517: * From the RFC (section 3.5.1):
518: *
519: * a route advertisement carrying the quintuple (prefix, plen, router-id, seqno,
520: * metric) is feasible if one of the following conditions holds:
521: *
522: * - metric is infinite; or
523: *
524: * - no entry exists in the source table indexed by (id, prefix, plen); or
525: *
526: * - an entry (prefix, plen, router-id, seqno', metric') exists in the source
527: * table, and either
528: * - seqno' < seqno or
529: * - seqno = seqno' and metric < metric'.
530: */
531: static inline int
532: babel_is_feasible(struct babel_source *s, u16 seqno, u16 metric)
533: {
534: return !s ||
535: (metric == BABEL_INFINITY) ||
536: (seqno > s->seqno) ||
537: ((seqno == s->seqno) && (metric < s->metric));
538: }
539:
540: /* Simple additive metric - Appendix 3.1 in the RFC */
541: static inline u16
542: babel_compute_metric(struct babel_neighbor *n, uint metric)
543: {
544: return MIN(metric + n->cost, BABEL_INFINITY);
545: }
546:
547: static void
548: babel_update_cost(struct babel_neighbor *nbr)
549: {
550: struct babel_proto *p = nbr->ifa->proto;
551: struct babel_iface_config *cf = nbr->ifa->cf;
552: uint rcv = u32_popcount(nbr->hello_map); // number of bits set
553: uint max = nbr->hello_cnt;
554: uint rxcost = BABEL_INFINITY; /* Cost to announce in IHU */
555: uint txcost = BABEL_INFINITY; /* Effective cost for route selection */
556:
557: if (!rcv || !nbr->ifa->up)
558: goto done;
559:
560: switch (cf->type)
561: {
562: case BABEL_IFACE_TYPE_WIRED:
563: /* k-out-of-j selection - Appendix 2.1 in the RFC. */
564:
565: /* Link is bad if less than cf->limit/16 of expected hellos were received */
566: if (rcv * 16 < cf->limit * max)
567: break;
568:
569: rxcost = cf->rxcost;
570: txcost = nbr->txcost;
571: break;
572:
573: case BABEL_IFACE_TYPE_WIRELESS:
574: /*
575: * ETX - Appendix 2.2 in the RFC.
576: *
577: * alpha = prob. of successful transmission estimated by the neighbor
578: * beta = prob. of successful transmission estimated by the router
579: * rxcost = nominal rxcost of the router / beta
580: * txcost = nominal rxcost of the neighbor / (alpha * beta)
581: * = received txcost / beta
582: *
583: * Note that received txcost is just neighbor's rxcost. Beta is rcv/max,
584: * we use inverse values of beta (i.e. max/rcv) to stay in integers.
585: */
586: rxcost = MIN( cf->rxcost * max / rcv, BABEL_INFINITY);
587: txcost = MIN(nbr->txcost * max / rcv, BABEL_INFINITY);
588: break;
589: }
590:
591: done:
592: /* If RX cost changed, send IHU with next Hello */
593: if (rxcost != nbr->rxcost)
594: {
595: nbr->rxcost = rxcost;
596: nbr->ihu_cnt = 0;
597: }
598:
599: /* If link cost changed, run route selection */
600: if (txcost != nbr->cost)
601: {
602: TRACE(D_EVENTS, "Cost of nbr %I on %s changed from %u to %u",
603: nbr->addr, nbr->ifa->iface->name, nbr->cost, txcost);
604:
605: nbr->cost = txcost;
606:
607: struct babel_route *r; node *n;
608: WALK_LIST2(r, n, nbr->routes, neigh_route)
609: {
610: r->metric = babel_compute_metric(nbr, r->advert_metric);
611: babel_select_route(p, r->e, r);
612: }
613: }
614: }
615:
616: /**
617: * babel_announce_rte - announce selected route to the core
618: * @p: Babel protocol instance
619: * @e: Babel route entry to announce
620: *
621: * This function announces a Babel entry to the core if it has a selected
622: * incoming path, and retracts it otherwise. If there is no selected route but
623: * the entry is valid and ours, the unreachable route is announced instead.
624: */
625: static void
626: babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
627: {
628: struct babel_route *r = e->selected;
629: struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
630:
631: if (r)
632: {
633: rta a0 = {
634: .src = p->p.main_source,
635: .source = RTS_BABEL,
636: .scope = SCOPE_UNIVERSE,
637: .dest = RTD_UNICAST,
638: .from = r->neigh->addr,
639: .nh.gw = r->next_hop,
640: .nh.iface = r->neigh->ifa->iface,
641: };
642:
643: rta *a = rta_lookup(&a0);
644: rte *rte = rte_get_temp(a);
645: rte->u.babel.seqno = r->seqno;
646: rte->u.babel.metric = r->metric;
647: rte->u.babel.router_id = r->router_id;
648: rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
649:
650: e->unreachable = 0;
651: rte_update2(c, e->n.addr, rte, p->p.main_source);
652: }
653: else if (e->valid && (e->router_id != p->router_id))
654: {
655: /* Unreachable */
656: rta a0 = {
657: .src = p->p.main_source,
658: .source = RTS_BABEL,
659: .scope = SCOPE_UNIVERSE,
660: .dest = RTD_UNREACHABLE,
661: };
662:
663: rta *a = rta_lookup(&a0);
664: rte *rte = rte_get_temp(a);
665: memset(&rte->u.babel, 0, sizeof(rte->u.babel));
666: rte->pflags = 0;
667: rte->pref = 1;
668:
669: e->unreachable = 1;
670: rte_update2(c, e->n.addr, rte, p->p.main_source);
671: }
672: else
673: {
674: /* Retraction */
675: e->unreachable = 0;
676: rte_update2(c, e->n.addr, NULL, p->p.main_source);
677: }
678: }
679:
680: /* Special case of babel_announce_rte() just for retraction */
681: static inline void
682: babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
683: {
684: struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
685: e->unreachable = 0;
686: rte_update2(c, e->n.addr, NULL, p->p.main_source);
687: }
688:
689:
690: /**
691: * babel_select_route - select best route for given route entry
692: * @p: Babel protocol instance
693: * @e: Babel entry to select the best route for
694: * @mod: Babel route that was modified or NULL if unspecified
695: *
696: * Select the best reachable and feasible route for a given prefix among the
697: * routes received from peers, and propagate it to the nest. This just selects
698: * the reachable and feasible route with the lowest metric, but keeps selected
699: * the old one in case of tie.
700: *
701: * If no feasible route is available for a prefix that previously had a route
702: * selected, a seqno request is sent to try to get a valid route. If the entry
703: * is valid and not owned by us, the unreachable route is announced to the nest
704: * (to blackhole packets going to it, as per section 2.8). It is later removed
705: * by babel_expire_routes(). Otherwise, the route is just removed from the nest.
706: *
707: * Argument @mod is used to optimize best route calculation. When specified, the
708: * function can assume that only the @mod route was modified to avoid full best
709: * route selection and announcement when non-best route was modified in minor
710: * way. The caller is advised to not call babel_select_route() when no change is
711: * done (e.g. periodic route updates) to avoid unnecessary announcements of the
712: * same best route. The caller is not required to call the function in case of a
713: * retraction of a non-best route.
714: *
715: * Note that the function does not active triggered updates. That is done by
716: * babel_rt_notify() when the change is propagated back to Babel.
717: */
718: static void
719: babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod)
720: {
721: struct babel_route *r, *best = e->selected;
722:
723: /* Shortcut if only non-best was modified */
724: if (mod && (mod != best))
725: {
726: /* Either select modified route, or keep old best route */
727: if ((mod->metric < (best ? best->metric : BABEL_INFINITY)) && mod->feasible)
728: best = mod;
729: else
730: return;
731: }
732: else
733: {
734: /* Selected route may be modified and no longer admissible */
735: if (!best || (best->metric == BABEL_INFINITY) || !best->feasible)
736: best = NULL;
737:
738: /* Find the best feasible route from all routes */
739: WALK_LIST(r, e->routes)
740: if ((r->metric < (best ? best->metric : BABEL_INFINITY)) && r->feasible)
741: best = r;
742: }
743:
744: if (best)
745: {
746: if (best != e->selected)
747: TRACE(D_EVENTS, "Picked new route for prefix %N: router-id %lR metric %d",
748: e->n.addr, best->router_id, best->metric);
749: }
750: else if (e->selected)
751: {
752: /*
753: * We have lost all feasible routes. We have to broadcast seqno request
754: * (Section 3.8.2.1) and keep unreachable route for a while (section 2.8).
755: * The later is done automatically by babel_announce_rte().
756: */
757:
758: TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr);
759: if (e->valid && (e->selected->router_id == e->router_id))
760: babel_add_seqno_request(p, e, e->selected->router_id, e->selected->seqno + 1, 0, NULL);
761: }
762: else
763: return;
764:
765: e->selected = best;
766: babel_announce_rte(p, e);
767: }
768:
769: /*
770: * Functions to send replies
771: */
772:
773: static void
774: babel_send_ack(struct babel_iface *ifa, ip_addr dest, u16 nonce)
775: {
776: struct babel_proto *p = ifa->proto;
777: union babel_msg msg = {};
778:
779: TRACE(D_PACKETS, "Sending ACK to %I with nonce %d", dest, nonce);
780:
781: msg.type = BABEL_TLV_ACK;
782: msg.ack.nonce = nonce;
783:
784: babel_send_unicast(&msg, ifa, dest);
785: }
786:
787: static void
788: babel_build_ihu(union babel_msg *msg, struct babel_iface *ifa, struct babel_neighbor *n)
789: {
790: struct babel_proto *p = ifa->proto;
791:
792: msg->type = BABEL_TLV_IHU;
793: msg->ihu.addr = n->addr;
794: msg->ihu.rxcost = n->rxcost;
795: msg->ihu.interval = ifa->cf->ihu_interval;
796:
797: TRACE(D_PACKETS, "Sending IHU for %I with rxcost %d interval %t",
798: msg->ihu.addr, msg->ihu.rxcost, (btime) msg->ihu.interval);
799: }
800:
801: static void
802: babel_send_ihu(struct babel_iface *ifa, struct babel_neighbor *n)
803: {
804: union babel_msg msg = {};
805: babel_build_ihu(&msg, ifa, n);
806: babel_send_unicast(&msg, ifa, n->addr);
807: n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
808: }
809:
810: static void
811: babel_send_ihus(struct babel_iface *ifa)
812: {
813: struct babel_neighbor *n;
814: WALK_LIST(n, ifa->neigh_list)
815: {
816: if (n->hello_cnt && (--n->ihu_cnt <= 0))
817: {
818: union babel_msg msg = {};
819: babel_build_ihu(&msg, ifa, n);
820: babel_enqueue(&msg, ifa);
821: n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
822: }
823: }
824: }
825:
826: static void
827: babel_send_hello(struct babel_iface *ifa)
828: {
829: struct babel_proto *p = ifa->proto;
830: union babel_msg msg = {};
831:
832: msg.type = BABEL_TLV_HELLO;
833: msg.hello.seqno = ifa->hello_seqno++;
834: msg.hello.interval = ifa->cf->hello_interval;
835:
836: TRACE(D_PACKETS, "Sending hello on %s with seqno %d interval %t",
837: ifa->ifname, msg.hello.seqno, (btime) msg.hello.interval);
838:
839: babel_enqueue(&msg, ifa);
840:
841: babel_send_ihus(ifa);
842: }
843:
844: static void
845: babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n)
846: {
847: union babel_msg msg = {};
848:
849: TRACE(D_PACKETS, "Sending route request for %N to %I", e->n.addr, n->addr);
850:
851: msg.type = BABEL_TLV_ROUTE_REQUEST;
852: net_copy(&msg.route_request.net, e->n.addr);
853:
854: babel_send_unicast(&msg, n->ifa, n->addr);
855: }
856:
857: static void
858: babel_send_wildcard_request(struct babel_iface *ifa)
859: {
860: struct babel_proto *p = ifa->proto;
861: union babel_msg msg = {};
862:
863: TRACE(D_PACKETS, "Sending wildcard route request on %s", ifa->ifname);
864:
865: msg.type = BABEL_TLV_ROUTE_REQUEST;
866: msg.route_request.full = 1;
867:
868: babel_enqueue(&msg, ifa);
869: }
870:
871: static void
872: babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr)
873: {
874: union babel_msg msg = {};
875:
876: msg.type = BABEL_TLV_SEQNO_REQUEST;
877: msg.seqno_request.hop_count = sr->hop_count ?: BABEL_INITIAL_HOP_COUNT;
878: msg.seqno_request.seqno = sr->seqno;
879: msg.seqno_request.router_id = sr->router_id;
880: net_copy(&msg.seqno_request.net, e->n.addr);
881:
882: if (sr->nbr)
883: {
884: TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d to %I on %s",
885: e->n.addr, sr->router_id, sr->seqno, sr->nbr->addr, sr->nbr->ifa->ifname);
886:
887: babel_send_unicast(&msg, sr->nbr->ifa, sr->nbr->addr);
888: }
889: else
890: {
891: TRACE(D_PACKETS, "Sending broadcast seqno request for %N router-id %lR seqno %d",
892: e->n.addr, sr->router_id, sr->seqno);
893:
894: struct babel_iface *ifa;
895: WALK_LIST(ifa, p->interfaces)
896: babel_enqueue(&msg, ifa);
897: }
898: }
899:
900: /**
901: * babel_send_update - send route table updates
902: * @ifa: Interface to transmit on
903: * @changed: Only send entries changed since this time
904: *
905: * This function produces update TLVs for all entries changed since the time
906: * indicated by the &changed parameter and queues them for transmission on the
907: * selected interface. During the process, the feasibility distance for each
908: * transmitted entry is updated.
909: */
910: static void
911: babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable)
912: {
913: struct babel_proto *p = ifa->proto;
914:
915: /* Update increase was requested */
916: if (p->update_seqno_inc)
917: {
918: p->update_seqno++;
919: p->update_seqno_inc = 0;
920: }
921:
922: FIB_WALK(rtable, struct babel_entry, e)
923: {
924: if (!e->valid)
925: continue;
926:
927: /* Our own seqno might have changed, in which case we update the routes we
928: originate. */
929: if ((e->router_id == p->router_id) && (e->seqno < p->update_seqno))
930: {
931: e->seqno = p->update_seqno;
932: e->updated = current_time();
933: }
934:
935: /* Skip routes that weren't updated since 'changed' time */
936: if (e->updated < changed)
937: continue;
938:
939: TRACE(D_PACKETS, "Sending update for %N router-id %lR seqno %d metric %d",
940: e->n.addr, e->router_id, e->seqno, e->metric);
941:
942: union babel_msg msg = {};
943: msg.type = BABEL_TLV_UPDATE;
944: msg.update.interval = ifa->cf->update_interval;
945: msg.update.seqno = e->seqno;
946: msg.update.metric = e->metric;
947: msg.update.router_id = e->router_id;
948: net_copy(&msg.update.net, e->n.addr);
949:
950: msg.update.next_hop = ((e->n.addr->type == NET_IP4) ?
951: ifa->next_hop_ip4 : ifa->next_hop_ip6);
952:
953: /* Do not send route if next hop is unknown, e.g. no configured IPv4 address */
954: if (ipa_zero(msg.update.next_hop))
955: continue;
956:
957: babel_enqueue(&msg, ifa);
958:
959: /* Update feasibility distance for redistributed routes */
960: if (e->router_id != p->router_id)
961: {
962: struct babel_source *s = babel_get_source(p, e, e->router_id);
963: s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
964:
965: if ((msg.update.seqno > s->seqno) ||
966: ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric)))
967: {
968: s->seqno = msg.update.seqno;
969: s->metric = msg.update.metric;
970: }
971: }
972: }
973: FIB_WALK_END;
974: }
975:
976: static void
977: babel_send_update(struct babel_iface *ifa, btime changed)
978: {
979: struct babel_proto *p = ifa->proto;
980:
981: babel_send_update_(ifa, changed, &p->ip4_rtable);
982: babel_send_update_(ifa, changed, &p->ip6_rtable);
983: }
984:
985: static void
986: babel_trigger_iface_update(struct babel_iface *ifa)
987: {
988: struct babel_proto *p = ifa->proto;
989:
990: /* Interface not active or already scheduled */
991: if (!ifa->up || ifa->want_triggered)
992: return;
993:
994: TRACE(D_EVENTS, "Scheduling triggered updates for %s seqno %d",
995: ifa->iface->name, p->update_seqno);
996:
997: ifa->want_triggered = current_time();
998: babel_iface_kick_timer(ifa);
999: }
1000:
1001: /* Sends and update on all interfaces. */
1002: static void
1003: babel_trigger_update(struct babel_proto *p)
1004: {
1005: if (p->triggered)
1006: return;
1007:
1008: struct babel_iface *ifa;
1009: WALK_LIST(ifa, p->interfaces)
1010: babel_trigger_iface_update(ifa);
1011:
1012: p->triggered = 1;
1013: }
1014:
1015: /* A retraction is an update with an infinite metric */
1016: static void
1017: babel_send_retraction(struct babel_iface *ifa, net_addr *n)
1018: {
1019: struct babel_proto *p = ifa->proto;
1020: union babel_msg msg = {};
1021:
1022: TRACE(D_PACKETS, "Sending retraction for %N seqno %d", n, p->update_seqno);
1023:
1024: msg.type = BABEL_TLV_UPDATE;
1025: msg.update.interval = ifa->cf->update_interval;
1026: msg.update.seqno = p->update_seqno;
1027: msg.update.metric = BABEL_INFINITY;
1028: msg.update.net = *n;
1029:
1030: babel_enqueue(&msg, ifa);
1031: }
1032:
1033: static void
1034: babel_send_wildcard_retraction(struct babel_iface *ifa)
1035: {
1036: struct babel_proto *p = ifa->proto;
1037: union babel_msg msg = {};
1038:
1039: TRACE(D_PACKETS, "Sending wildcard retraction on %s", ifa->ifname);
1040:
1041: msg.type = BABEL_TLV_UPDATE;
1042: msg.update.wildcard = 1;
1043: msg.update.interval = ifa->cf->update_interval;
1044: msg.update.seqno = p->update_seqno;
1045: msg.update.metric = BABEL_INFINITY;
1046:
1047: babel_enqueue(&msg, ifa);
1048: }
1049:
1050:
1051: /*
1052: * TLV handler helpers
1053: */
1054:
1055: /* Update hello history according to Appendix A1 of the RFC */
1056: static void
1057: babel_update_hello_history(struct babel_neighbor *n, u16 seqno, uint interval)
1058: {
1059: /*
1060: * Compute the difference between expected and received seqno (modulo 2^16).
1061: * If the expected and received seqnos are within 16 of each other, the modular
1062: * difference is going to be less than 16 for one of the directions. Otherwise,
1063: * the values differ too much, so just reset the state.
1064: */
1065:
1066: u16 delta = ((uint) seqno - (uint) n->next_hello_seqno);
1067:
1068: if ((delta == 0) || (n->hello_cnt == 0))
1069: {
1070: /* Do nothing */
1071: }
1072: else if (delta <= 16)
1073: {
1074: /* Sending node decreased interval; fast-forward */
1075: n->hello_map <<= delta;
1076: n->hello_cnt = MIN(n->hello_cnt + delta, 16);
1077: }
1078: else if (delta >= 0xfff0)
1079: {
1080: u8 diff = (0xffff - delta);
1081: /* Sending node increased interval; undo history */
1082: n->hello_map >>= diff;
1083: n->hello_cnt = (diff < n->hello_cnt) ? n->hello_cnt - diff : 0;
1084: }
1085: else
1086: {
1087: /* Note state reset - flush entries */
1088: n->hello_map = n->hello_cnt = 0;
1089: }
1090:
1091: /* Current entry */
1092: n->hello_map = (n->hello_map << 1) | 1;
1093: n->next_hello_seqno = seqno+1;
1094: if (n->hello_cnt < 16) n->hello_cnt++;
1095:
1096: /* Update expiration */
1097: n->hello_expiry = current_time() + BABEL_HELLO_EXPIRY_FACTOR(interval);
1098: n->last_hello_int = interval;
1099: }
1100:
1101:
1102: /*
1103: * TLV handlers
1104: */
1105:
1106: void
1107: babel_handle_ack_req(union babel_msg *m, struct babel_iface *ifa)
1108: {
1109: struct babel_proto *p = ifa->proto;
1110: struct babel_msg_ack_req *msg = &m->ack_req;
1111:
1112: TRACE(D_PACKETS, "Handling ACK request nonce %d interval %t",
1113: msg->nonce, (btime) msg->interval);
1114:
1115: babel_send_ack(ifa, msg->sender, msg->nonce);
1116: }
1117:
1118: void
1119: babel_handle_hello(union babel_msg *m, struct babel_iface *ifa)
1120: {
1121: struct babel_proto *p = ifa->proto;
1122: struct babel_msg_hello *msg = &m->hello;
1123:
1124: TRACE(D_PACKETS, "Handling hello seqno %d interval %t",
1125: msg->seqno, (btime) msg->interval);
1126:
1127: struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
1128: int first_hello = !n->hello_cnt;
1129:
1130: babel_update_hello_history(n, msg->seqno, msg->interval);
1131: babel_update_cost(n);
1132:
1133: /* Speed up session establishment by sending IHU immediately */
1134: if (first_hello)
1135: babel_send_ihu(ifa, n);
1136: }
1137:
1138: void
1139: babel_handle_ihu(union babel_msg *m, struct babel_iface *ifa)
1140: {
1141: struct babel_proto *p = ifa->proto;
1142: struct babel_msg_ihu *msg = &m->ihu;
1143:
1144: /* Ignore IHUs that are not about us */
1145: if ((msg->ae != BABEL_AE_WILDCARD) && !ipa_equal(msg->addr, ifa->addr))
1146: return;
1147:
1148: TRACE(D_PACKETS, "Handling IHU rxcost %d interval %t",
1149: msg->rxcost, (btime) msg->interval);
1150:
1151: struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
1152: n->txcost = msg->rxcost;
1153: n->ihu_expiry = current_time() + BABEL_IHU_EXPIRY_FACTOR(msg->interval);
1154: babel_update_cost(n);
1155: }
1156:
1157: /**
1158: * babel_handle_update - handle incoming route updates
1159: * @m: Incoming update TLV
1160: * @ifa: Interface the update was received on
1161: *
1162: * This function is called as a handler for update TLVs and handles the updating
1163: * and maintenance of route entries in Babel's internal routing cache. The
1164: * handling follows the actions described in the Babel RFC, and at the end of
1165: * each update handling, babel_select_route() is called on the affected entry to
1166: * optionally update the selected routes and propagate them to the core.
1167: */
1168: void
1169: babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
1170: {
1171: struct babel_proto *p = ifa->proto;
1172: struct babel_msg_update *msg = &m->update;
1173:
1174: struct babel_neighbor *nbr;
1175: struct babel_entry *e;
1176: struct babel_source *s;
1177: struct babel_route *r, *best;
1178: node *n;
1179: int feasible, metric;
1180:
1181: if (msg->wildcard)
1182: TRACE(D_PACKETS, "Handling wildcard retraction", msg->seqno);
1183: else
1184: TRACE(D_PACKETS, "Handling update for %N with seqno %d metric %d",
1185: &msg->net, msg->seqno, msg->metric);
1186:
1187: nbr = babel_find_neighbor(ifa, msg->sender);
1188: if (!nbr)
1189: {
1190: DBG("Babel: Haven't heard from neighbor %I; ignoring update.\n", msg->sender);
1191: return;
1192: }
1193:
1194: if (msg->router_id == p->router_id)
1195: {
1196: DBG("Babel: Ignoring update for our own router ID.\n");
1197: return;
1198: }
1199:
1200: struct channel *c = (msg->net.type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
1201: if (!c || (c->channel_state != CS_UP))
1202: {
1203: DBG("Babel: Ignoring update for inactive address family.\n");
1204: return;
1205: }
1206:
1207: /* Retraction */
1208: if (msg->metric == BABEL_INFINITY)
1209: {
1210: if (msg->wildcard)
1211: {
1212: /*
1213: * Special case: This is a retraction of all prefixes announced by this
1214: * neighbour (see second-to-last paragraph of section 4.4.9 in the RFC).
1215: */
1216: WALK_LIST(n, nbr->routes)
1217: {
1218: r = SKIP_BACK(struct babel_route, neigh_route, n);
1219: babel_retract_route(p, r);
1220: }
1221: }
1222: else
1223: {
1224: e = babel_find_entry(p, &msg->net);
1225:
1226: if (!e)
1227: return;
1228:
1229: /* The route entry indexed by neighbour */
1230: r = babel_find_route(e, nbr);
1231:
1232: if (!r)
1233: return;
1234:
1235: /* Router-id, next-hop and seqno are ignored for retractions */
1236: babel_retract_route(p, r);
1237: }
1238:
1239: /* Done with retractions */
1240: return;
1241: }
1242:
1243: /* Regular update */
1244: e = babel_get_entry(p, &msg->net);
1245: r = babel_get_route(p, e, nbr); /* the route entry indexed by neighbour */
1246: s = babel_find_source(e, msg->router_id); /* for feasibility */
1247: feasible = babel_is_feasible(s, msg->seqno, msg->metric);
1248: metric = babel_compute_metric(nbr, msg->metric);
1249: best = e->selected;
1250:
1251: /* RFC section 3.8.2.2 - Dealing with unfeasible updates */
1252: if (!feasible && (metric != BABEL_INFINITY) &&
1253: (!best || (r == best) || (metric < best->metric)))
1254: babel_add_seqno_request(p, e, s->router_id, s->seqno + 1, 0, nbr);
1255:
1256: /* Special case - ignore unfeasible update to best route */
1257: if (r == best && !feasible && (msg->router_id == r->router_id))
1258: return;
1259:
1260: r->expires = current_time() + BABEL_ROUTE_EXPIRY_FACTOR(msg->interval);
1261: r->refresh_time = current_time() + BABEL_ROUTE_REFRESH_FACTOR(msg->interval);
1262:
1263: /* No further processing if there is no change */
1264: if ((r->feasible == feasible) && (r->seqno == msg->seqno) &&
1265: (r->metric == metric) && (r->advert_metric == msg->metric) &&
1266: (r->router_id == msg->router_id) && ipa_equal(r->next_hop, msg->next_hop))
1267: return;
1268:
1269: /* Last paragraph above - update the entry */
1270: r->feasible = feasible;
1271: r->seqno = msg->seqno;
1272: r->metric = metric;
1273: r->advert_metric = msg->metric;
1274: r->router_id = msg->router_id;
1275: r->next_hop = msg->next_hop;
1276:
1277: /* If received update satisfies seqno request, we send triggered updates */
1278: if (babel_satisfy_seqno_request(p, e, msg->router_id, msg->seqno))
1279: {
1280: babel_trigger_update(p);
1281: e->updated = current_time();
1282: }
1283:
1284: babel_select_route(p, e, r);
1285: }
1286:
1287: void
1288: babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa)
1289: {
1290: struct babel_proto *p = ifa->proto;
1291: struct babel_msg_route_request *msg = &m->route_request;
1292:
1293: /* RFC 6126 3.8.1.1 */
1294:
1295: /* Wildcard request - full update on the interface */
1296: if (msg->full)
1297: {
1298: TRACE(D_PACKETS, "Handling wildcard route request");
1299: ifa->want_triggered = 1;
1300: return;
1301: }
1302:
1303: TRACE(D_PACKETS, "Handling route request for %N", &msg->net);
1304:
1305: /* Non-wildcard request - see if we have an entry for the route.
1306: If not, send a retraction, otherwise send an update. */
1307: struct babel_entry *e = babel_find_entry(p, &msg->net);
1308: if (!e)
1309: {
1310: babel_send_retraction(ifa, &msg->net);
1311: }
1312: else
1313: {
1314: babel_trigger_iface_update(ifa);
1315: e->updated = current_time();
1316: }
1317: }
1318:
1319: void
1320: babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
1321: {
1322: struct babel_proto *p = ifa->proto;
1323: struct babel_msg_seqno_request *msg = &m->seqno_request;
1324:
1325: /* RFC 6126 3.8.1.2 */
1326:
1327: TRACE(D_PACKETS, "Handling seqno request for %N router-id %lR seqno %d hop count %d",
1328: &msg->net, msg->router_id, msg->seqno, msg->hop_count);
1329:
1330: /* Ignore if we have no such entry or entry has infinite metric */
1331: struct babel_entry *e = babel_find_entry(p, &msg->net);
1332: if (!e || !e->valid || (e->metric == BABEL_INFINITY))
1333: return;
1334:
1335: /* Trigger update on incoming interface if we have a selected route with
1336: different router id or seqno no smaller than requested */
1337: if ((e->router_id != msg->router_id) || ge_mod64k(e->seqno, msg->seqno))
1338: {
1339: babel_trigger_iface_update(ifa);
1340: e->updated = current_time();
1341: return;
1342: }
1343:
1344: /* Seqno is larger; check if we own the router id */
1345: if (msg->router_id == p->router_id)
1346: {
1347: /* Ours; seqno increase and trigger global update */
1348: p->update_seqno_inc = 1;
1349: babel_trigger_update(p);
1350: }
1351: else if (msg->hop_count > 1)
1352: {
1353: /* Not ours; forward if TTL allows it */
1354:
1355: /* Find best admissible route */
1356: struct babel_route *r, *best1 = NULL, *best2 = NULL;
1357: WALK_LIST(r, e->routes)
1358: if ((r->router_id == msg->router_id) && !ipa_equal(r->neigh->addr, msg->sender))
1359: {
1360: /* Find best feasible route */
1361: if ((!best1 || r->metric < best1->metric) && r->feasible)
1362: best1 = r;
1363:
1364: /* Find best not necessary feasible route */
1365: if (!best2 || r->metric < best2->metric)
1366: best2 = r;
1367: }
1368:
1369: /* If no route is found, do nothing */
1370: r = best1 ?: best2;
1371: if (!r)
1372: return;
1373:
1374: babel_add_seqno_request(p, e, msg->router_id, msg->seqno, msg->hop_count-1, r->neigh);
1375: }
1376: }
1377:
1378:
1379: /*
1380: * Babel interfaces
1381: */
1382:
1383: /**
1384: * babel_iface_timer - Babel interface timer handler
1385: * @t: Timer
1386: *
1387: * This function is called by the per-interface timer and triggers sending of
1388: * periodic Hello's and both triggered and periodic updates. Periodic Hello's
1389: * and updates are simply handled by setting the next_{hello,regular} variables
1390: * on the interface, and triggering an update (and resetting the variable)
1391: * whenever 'now' exceeds that value.
1392: *
1393: * For triggered updates, babel_trigger_iface_update() will set the
1394: * want_triggered field on the interface to a timestamp value. If this is set
1395: * (and the next_triggered time has passed; this is a rate limiting mechanism),
1396: * babel_send_update() will be called with this timestamp as the second
1397: * parameter. This causes updates to be send consisting of only the routes that
1398: * have changed since the time saved in want_triggered.
1399: *
1400: * Mostly when an update is triggered, the route being modified will be set to
1401: * the value of 'now' at the time of the trigger; the >= comparison for
1402: * selecting which routes to send in the update will make sure this is included.
1403: */
1404: static void
1405: babel_iface_timer(timer *t)
1406: {
1407: struct babel_iface *ifa = t->data;
1408: struct babel_proto *p = ifa->proto;
1409: btime hello_period = ifa->cf->hello_interval;
1410: btime update_period = ifa->cf->update_interval;
1411: btime now_ = current_time();
1412:
1413: if (now_ >= ifa->next_hello)
1414: {
1415: babel_send_hello(ifa);
1416: ifa->next_hello += hello_period * (1 + (now_ - ifa->next_hello) / hello_period);
1417: }
1418:
1419: if (now_ >= ifa->next_regular)
1420: {
1421: TRACE(D_EVENTS, "Sending regular updates on %s", ifa->ifname);
1422: babel_send_update(ifa, 0);
1423: ifa->next_regular += update_period * (1 + (now_ - ifa->next_regular) / update_period);
1424: ifa->want_triggered = 0;
1425: p->triggered = 0;
1426: }
1427: else if (ifa->want_triggered && (now_ >= ifa->next_triggered))
1428: {
1429: TRACE(D_EVENTS, "Sending triggered updates on %s", ifa->ifname);
1430: babel_send_update(ifa, ifa->want_triggered);
1431: ifa->next_triggered = now_ + MIN(1 S, update_period / 2);
1432: ifa->want_triggered = 0;
1433: p->triggered = 0;
1434: }
1435:
1436: btime next_event = MIN(ifa->next_hello, ifa->next_regular);
1437: if (ifa->want_triggered) next_event = MIN(next_event, ifa->next_triggered);
1438: tm_set(ifa->timer, next_event);
1439: }
1440:
1441: static inline void
1442: babel_iface_kick_timer(struct babel_iface *ifa)
1443: {
1444: if (ifa->timer->expires > (current_time() + 100 MS))
1445: tm_start(ifa->timer, 100 MS);
1446: }
1447:
1448: static void
1449: babel_iface_start(struct babel_iface *ifa)
1450: {
1451: struct babel_proto *p = ifa->proto;
1452:
1453: TRACE(D_EVENTS, "Starting interface %s", ifa->ifname);
1454:
1455: ifa->next_hello = current_time() + (random() % ifa->cf->hello_interval);
1456: ifa->next_regular = current_time() + (random() % ifa->cf->update_interval);
1457: ifa->next_triggered = current_time() + MIN(1 S, ifa->cf->update_interval / 2);
1458: ifa->want_triggered = 0; /* We send an immediate update (below) */
1459: tm_start(ifa->timer, 100 MS);
1460: ifa->up = 1;
1461:
1462: babel_send_hello(ifa);
1463: babel_send_wildcard_retraction(ifa);
1464: babel_send_wildcard_request(ifa);
1465: babel_send_update(ifa, 0); /* Full update */
1466: }
1467:
1468: static void
1469: babel_iface_stop(struct babel_iface *ifa)
1470: {
1471: struct babel_proto *p = ifa->proto;
1472: struct babel_neighbor *nbr;
1473: struct babel_route *r;
1474: node *n;
1475:
1476: TRACE(D_EVENTS, "Stopping interface %s", ifa->ifname);
1477:
1478: /*
1479: * Rather than just flushing the neighbours, we set the metric of their routes
1480: * to infinity. This allows us to keep the neighbour hello state for when the
1481: * interface comes back up. The routes will also be kept until they expire.
1482: */
1483: WALK_LIST(nbr, ifa->neigh_list)
1484: {
1485: WALK_LIST(n, nbr->routes)
1486: {
1487: r = SKIP_BACK(struct babel_route, neigh_route, n);
1488: babel_retract_route(p, r);
1489: }
1490: }
1491:
1492: tm_stop(ifa->timer);
1493: ifa->up = 0;
1494: }
1495:
1496: static inline int
1497: babel_iface_link_up(struct babel_iface *ifa)
1498: {
1499: return !ifa->cf->check_link || (ifa->iface->flags & IF_LINK_UP);
1500: }
1501:
1502: static void
1503: babel_iface_update_state(struct babel_iface *ifa)
1504: {
1505: int up = ifa->sk && babel_iface_link_up(ifa);
1506:
1507: if (up == ifa->up)
1508: return;
1509:
1510: if (up)
1511: babel_iface_start(ifa);
1512: else
1513: babel_iface_stop(ifa);
1514: }
1515:
1516: static void
1517: babel_iface_update_addr4(struct babel_iface *ifa)
1518: {
1519: struct babel_proto *p = ifa->proto;
1520:
1521: ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
1522: ifa->next_hop_ip4 = ipa_nonzero(ifa->cf->next_hop_ip4) ? ifa->cf->next_hop_ip4 : addr4;
1523:
1524: if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1525: log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
1526:
1527: if (ifa->up)
1528: babel_iface_kick_timer(ifa);
1529: }
1530:
1531: static void
1532: babel_iface_update_buffers(struct babel_iface *ifa)
1533: {
1534: if (!ifa->sk)
1535: return;
1536:
1537: uint mtu = MAX(BABEL_MIN_MTU, ifa->iface->mtu);
1538: uint rbsize = ifa->cf->rx_buffer ?: mtu;
1539: uint tbsize = ifa->cf->tx_length ?: mtu;
1540: rbsize = MAX(rbsize, tbsize);
1541:
1542: sk_set_rbsize(ifa->sk, rbsize);
1543: sk_set_tbsize(ifa->sk, tbsize);
1544:
1545: ifa->tx_length = tbsize - BABEL_OVERHEAD;
1546: }
1547:
1548: static struct babel_iface*
1549: babel_find_iface(struct babel_proto *p, struct iface *what)
1550: {
1551: struct babel_iface *ifa;
1552:
1553: WALK_LIST (ifa, p->interfaces)
1554: if (ifa->iface == what)
1555: return ifa;
1556:
1557: return NULL;
1558: }
1559:
1560: static void
1561: babel_iface_locked(struct object_lock *lock)
1562: {
1563: struct babel_iface *ifa = lock->data;
1564: struct babel_proto *p = ifa->proto;
1565:
1566: if (!babel_open_socket(ifa))
1567: {
1568: log(L_ERR "%s: Cannot open socket for %s", p->p.name, ifa->iface->name);
1569: return;
1570: }
1571:
1572: babel_iface_update_buffers(ifa);
1573: babel_iface_update_state(ifa);
1574: }
1575:
1576: static void
1577: babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_config *ic)
1578: {
1579: struct babel_iface *ifa;
1580:
1581: TRACE(D_EVENTS, "Adding interface %s", new->name);
1582:
1583: pool *pool = rp_new(p->p.pool, new->name);
1584:
1585: ifa = mb_allocz(pool, sizeof(struct babel_iface));
1586: ifa->proto = p;
1587: ifa->iface = new;
1588: ifa->cf = ic;
1589: ifa->pool = pool;
1590: ifa->ifname = new->name;
1591: ifa->addr = new->llv6->ip;
1592:
1593: add_tail(&p->interfaces, NODE ifa);
1594:
1595: ip_addr addr4 = new->addr4 ? new->addr4->ip : IPA_NONE;
1596: ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4;
1597: ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr;
1598:
1599: if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1600: log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, new->name);
1601:
1602: init_list(&ifa->neigh_list);
1603: ifa->hello_seqno = 1;
1604:
1605: ifa->timer = tm_new_init(ifa->pool, babel_iface_timer, ifa, 0, 0);
1606:
1607: init_list(&ifa->msg_queue);
1608: ifa->send_event = ev_new_init(ifa->pool, babel_send_queue, ifa);
1609:
1610: struct object_lock *lock = olock_new(ifa->pool);
1611: lock->type = OBJLOCK_UDP;
1612: lock->addr = IP6_BABEL_ROUTERS;
1613: lock->port = ifa->cf->port;
1614: lock->iface = ifa->iface;
1615: lock->hook = babel_iface_locked;
1616: lock->data = ifa;
1617:
1618: olock_acquire(lock);
1619: }
1620:
1621: static void
1622: babel_remove_iface(struct babel_proto *p, struct babel_iface *ifa)
1623: {
1624: TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
1625:
1626: struct babel_neighbor *n;
1627: WALK_LIST_FIRST(n, ifa->neigh_list)
1628: babel_flush_neighbor(p, n);
1629:
1630: rem_node(NODE ifa);
1631:
1632: rfree(ifa->pool); /* contains ifa itself, locks, socket, etc */
1633: }
1634:
1635: static void
1636: babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
1637: {
1638: struct babel_proto *p = (void *) P;
1639: struct babel_config *cf = (void *) P->cf;
1640: struct babel_iface *ifa = babel_find_iface(p, iface);
1641:
1642: if (iface->flags & IF_IGNORE)
1643: return;
1644:
1645: /* Add, remove or restart interface */
1646: if (flags & (IF_CHANGE_UPDOWN | IF_CHANGE_LLV6))
1647: {
1648: if (ifa)
1649: babel_remove_iface(p, ifa);
1650:
1651: if (!(iface->flags & IF_UP))
1652: return;
1653:
1654: /* We only speak multicast */
1655: if (!(iface->flags & IF_MULTICAST))
1656: return;
1657:
1658: /* Ignore ifaces without link-local address */
1659: if (!iface->llv6)
1660: return;
1661:
1662: struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
1663: if (ic)
1664: babel_add_iface(p, iface, ic);
1665:
1666: return;
1667: }
1668:
1669: if (!ifa)
1670: return;
1671:
1672: if (flags & IF_CHANGE_ADDR4)
1673: babel_iface_update_addr4(ifa);
1674:
1675: if (flags & IF_CHANGE_MTU)
1676: babel_iface_update_buffers(ifa);
1677:
1678: if (flags & IF_CHANGE_LINK)
1679: babel_iface_update_state(ifa);
1680: }
1681:
1682: static int
1683: babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct babel_iface_config *new)
1684: {
1685: struct babel_iface_config *old = ifa->cf;
1686:
1687: /* Change of these options would require to reset the iface socket */
1688: if ((new->port != old->port) ||
1689: (new->tx_tos != old->tx_tos) ||
1690: (new->tx_priority != old->tx_priority))
1691: return 0;
1692:
1693: TRACE(D_EVENTS, "Reconfiguring interface %s", ifa->iface->name);
1694:
1695: ifa->cf = new;
1696:
1697: ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
1698: ifa->next_hop_ip4 = ipa_nonzero(new->next_hop_ip4) ? new->next_hop_ip4 : addr4;
1699: ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr;
1700:
1701: if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1702: log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
1703:
1704: if (ifa->next_hello > (current_time() + new->hello_interval))
1705: ifa->next_hello = current_time() + (random() % new->hello_interval);
1706:
1707: if (ifa->next_regular > (current_time() + new->update_interval))
1708: ifa->next_regular = current_time() + (random() % new->update_interval);
1709:
1710: if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
1711: babel_iface_update_buffers(ifa);
1712:
1713: if (new->check_link != old->check_link)
1714: babel_iface_update_state(ifa);
1715:
1716: if (ifa->up)
1717: babel_iface_kick_timer(ifa);
1718:
1719: return 1;
1720: }
1721:
1722: static void
1723: babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
1724: {
1725: struct iface *iface;
1726:
1727: WALK_LIST(iface, iface_list)
1728: {
1729: if (!(iface->flags & IF_UP))
1730: continue;
1731:
1732: /* Ignore non-multicast ifaces */
1733: if (!(iface->flags & IF_MULTICAST))
1734: continue;
1735:
1736: /* Ignore ifaces without link-local address */
1737: if (!iface->llv6)
1738: continue;
1739:
1740: struct babel_iface *ifa = babel_find_iface(p, iface);
1741: struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
1742:
1743: if (ifa && ic)
1744: {
1745: if (babel_reconfigure_iface(p, ifa, ic))
1746: continue;
1747:
1748: /* Hard restart */
1749: log(L_INFO "%s: Restarting interface %s", p->p.name, ifa->iface->name);
1750: babel_remove_iface(p, ifa);
1751: babel_add_iface(p, iface, ic);
1752: }
1753:
1754: if (ifa && !ic)
1755: babel_remove_iface(p, ifa);
1756:
1757: if (!ifa && ic)
1758: babel_add_iface(p, iface, ic);
1759: }
1760: }
1761:
1762:
1763: /*
1764: * Debugging and info output functions
1765: */
1766:
1767: static void
1768: babel_dump_source(struct babel_source *s)
1769: {
1770: debug("Source router_id %lR seqno %d metric %d expires %t\n",
1771: s->router_id, s->seqno, s->metric,
1772: s->expires ? s->expires - current_time() : 0);
1773: }
1774:
1775: static void
1776: babel_dump_route(struct babel_route *r)
1777: {
1778: debug("Route neigh %I if %s seqno %d metric %d/%d router_id %lR expires %t\n",
1779: r->neigh->addr, r->neigh->ifa->ifname, r->seqno, r->advert_metric, r->metric,
1780: r->router_id, r->expires ? r->expires - current_time() : 0);
1781: }
1782:
1783: static void
1784: babel_dump_entry(struct babel_entry *e)
1785: {
1786: struct babel_source *s;
1787: struct babel_route *r;
1788:
1789: debug("Babel: Entry %N:\n", e->n.addr);
1790:
1791: WALK_LIST(s,e->sources)
1792: { debug(" "); babel_dump_source(s); }
1793:
1794: WALK_LIST(r,e->routes)
1795: {
1796: debug(" ");
1797: if (r == e->selected) debug("*");
1798: babel_dump_route(r);
1799: }
1800: }
1801:
1802: static void
1803: babel_dump_neighbor(struct babel_neighbor *n)
1804: {
1805: debug("Neighbor %I txcost %d hello_map %x next seqno %d expires %t/%t\n",
1806: n->addr, n->txcost, n->hello_map, n->next_hello_seqno,
1807: n->hello_expiry ? n->hello_expiry - current_time() : 0,
1808: n->ihu_expiry ? n->ihu_expiry - current_time() : 0);
1809: }
1810:
1811: static void
1812: babel_dump_iface(struct babel_iface *ifa)
1813: {
1814: struct babel_neighbor *n;
1815:
1816: debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %t %t",
1817: ifa->ifname, ifa->addr, ifa->cf->rxcost, ifa->cf->type, ifa->hello_seqno,
1818: ifa->cf->hello_interval, ifa->cf->update_interval);
1819: debug(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6);
1820:
1821: WALK_LIST(n, ifa->neigh_list)
1822: { debug(" "); babel_dump_neighbor(n); }
1823: }
1824:
1825: static void
1826: babel_dump(struct proto *P)
1827: {
1828: struct babel_proto *p = (struct babel_proto *) P;
1829: struct babel_iface *ifa;
1830:
1831: debug("Babel: router id %lR update seqno %d\n", p->router_id, p->update_seqno);
1832:
1833: WALK_LIST(ifa, p->interfaces)
1834: babel_dump_iface(ifa);
1835:
1836: FIB_WALK(&p->ip4_rtable, struct babel_entry, e)
1837: {
1838: babel_dump_entry(e);
1839: }
1840: FIB_WALK_END;
1841: FIB_WALK(&p->ip6_rtable, struct babel_entry, e)
1842: {
1843: babel_dump_entry(e);
1844: }
1845: FIB_WALK_END;
1846: }
1847:
1848: static void
1849: babel_get_route_info(rte *rte, byte *buf)
1850: {
1851: buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
1852: }
1853:
1854: static int
1855: babel_get_attr(eattr *a, byte *buf, int buflen UNUSED)
1856: {
1857: switch (a->id)
1858: {
1859: case EA_BABEL_METRIC:
1860: bsprintf(buf, "metric: %d", a->u.data);
1861: return GA_FULL;
1862:
1863: case EA_BABEL_ROUTER_ID:
1864: {
1865: u64 rid = 0;
1866: memcpy(&rid, a->u.ptr->data, sizeof(u64));
1867: bsprintf(buf, "router_id: %lR", rid);
1868: return GA_FULL;
1869: }
1870:
1871: default:
1872: return GA_UNKNOWN;
1873: }
1874: }
1875:
1876: void
1877: babel_show_interfaces(struct proto *P, char *iff)
1878: {
1879: struct babel_proto *p = (void *) P;
1880: struct babel_iface *ifa = NULL;
1881: struct babel_neighbor *nbr = NULL;
1882:
1883: if (p->p.proto_state != PS_UP)
1884: {
1885: cli_msg(-1023, "%s: is not up", p->p.name);
1886: cli_msg(0, "");
1887: return;
1888: }
1889:
1890: cli_msg(-1023, "%s:", p->p.name);
1891: cli_msg(-1023, "%-10s %-6s %7s %6s %7s %-15s %s",
1892: "Interface", "State", "RX cost", "Nbrs", "Timer",
1893: "Next hop (v4)", "Next hop (v6)");
1894:
1895: WALK_LIST(ifa, p->interfaces)
1896: {
1897: if (iff && !patmatch(iff, ifa->iface->name))
1898: continue;
1899:
1900: int nbrs = 0;
1901: WALK_LIST(nbr, ifa->neigh_list)
1902: nbrs++;
1903:
1904: btime timer = MIN(ifa->next_regular, ifa->next_hello) - current_time();
1905: cli_msg(-1023, "%-10s %-6s %7u %6u %7t %-15I %I",
1906: ifa->iface->name, (ifa->up ? "Up" : "Down"),
1907: ifa->cf->rxcost, nbrs, MAX(timer, 0),
1908: ifa->next_hop_ip4, ifa->next_hop_ip6);
1909: }
1910:
1911: cli_msg(0, "");
1912: }
1913:
1914: void
1915: babel_show_neighbors(struct proto *P, char *iff)
1916: {
1917: struct babel_proto *p = (void *) P;
1918: struct babel_iface *ifa = NULL;
1919: struct babel_neighbor *n = NULL;
1920: struct babel_route *r = NULL;
1921:
1922: if (p->p.proto_state != PS_UP)
1923: {
1924: cli_msg(-1024, "%s: is not up", p->p.name);
1925: cli_msg(0, "");
1926: return;
1927: }
1928:
1929: cli_msg(-1024, "%s:", p->p.name);
1930: cli_msg(-1024, "%-25s %-10s %6s %6s %6s %7s",
1931: "IP address", "Interface", "Metric", "Routes", "Hellos", "Expires");
1932:
1933: WALK_LIST(ifa, p->interfaces)
1934: {
1935: if (iff && !patmatch(iff, ifa->iface->name))
1936: continue;
1937:
1938: WALK_LIST(n, ifa->neigh_list)
1939: {
1940: int rts = 0;
1941: WALK_LIST(r, n->routes)
1942: rts++;
1943:
1944: uint hellos = u32_popcount(n->hello_map);
1945: btime timer = n->hello_expiry - current_time();
1946: cli_msg(-1024, "%-25I %-10s %6u %6u %6u %7t",
1947: n->addr, ifa->iface->name, n->cost, rts, hellos, MAX(timer, 0));
1948: }
1949: }
1950:
1951: cli_msg(0, "");
1952: }
1953:
1954: static void
1955: babel_show_entries_(struct babel_proto *p, struct fib *rtable)
1956: {
1957: int width = babel_sadr_enabled(p) ? -54 : -24;
1958:
1959: FIB_WALK(rtable, struct babel_entry, e)
1960: {
1961: struct babel_route *r = NULL;
1962: uint rts = 0, srcs = 0;
1963: node *n;
1964:
1965: WALK_LIST(n, e->routes)
1966: rts++;
1967:
1968: WALK_LIST(n, e->sources)
1969: srcs++;
1970:
1971: if (e->valid)
1972: cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
1973: e->n.addr, e->router_id, e->metric, e->seqno, rts, srcs);
1974: else if (r = e->selected)
1975: cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
1976: e->n.addr, r->router_id, r->metric, r->seqno, rts, srcs);
1977: else
1978: cli_msg(-1025, "%-*N %-23s %6s %5s %7u %7u", width,
1979: e->n.addr, "<none>", "-", "-", rts, srcs);
1980: }
1981: FIB_WALK_END;
1982: }
1983:
1984: void
1985: babel_show_entries(struct proto *P)
1986: {
1987: struct babel_proto *p = (void *) P;
1988: int width = babel_sadr_enabled(p) ? -54 : -24;
1989:
1990: if (p->p.proto_state != PS_UP)
1991: {
1992: cli_msg(-1025, "%s: is not up", p->p.name);
1993: cli_msg(0, "");
1994: return;
1995: }
1996:
1997: cli_msg(-1025, "%s:", p->p.name);
1998: cli_msg(-1025, "%-*s %-23s %6s %5s %7s %7s", width,
1999: "Prefix", "Router ID", "Metric", "Seqno", "Routes", "Sources");
2000:
2001: babel_show_entries_(p, &p->ip4_rtable);
2002: babel_show_entries_(p, &p->ip6_rtable);
2003:
2004: cli_msg(0, "");
2005: }
2006:
2007: static void
2008: babel_show_routes_(struct babel_proto *p, struct fib *rtable)
2009: {
2010: int width = babel_sadr_enabled(p) ? -54 : -24;
2011:
2012: FIB_WALK(rtable, struct babel_entry, e)
2013: {
2014: struct babel_route *r;
2015: WALK_LIST(r, e->routes)
2016: {
2017: char c = (r == e->selected) ? '*' : (r->feasible ? '+' : ' ');
2018: btime time = r->expires ? r->expires - current_time() : 0;
2019: cli_msg(-1025, "%-*N %-25I %-10s %5u %c %5u %7t", width,
2020: e->n.addr, r->next_hop, r->neigh->ifa->ifname,
2021: r->metric, c, r->seqno, MAX(time, 0));
2022: }
2023: }
2024: FIB_WALK_END;
2025: }
2026:
2027: void
2028: babel_show_routes(struct proto *P)
2029: {
2030: struct babel_proto *p = (void *) P;
2031: int width = babel_sadr_enabled(p) ? -54 : -24;
2032:
2033: if (p->p.proto_state != PS_UP)
2034: {
2035: cli_msg(-1025, "%s: is not up", p->p.name);
2036: cli_msg(0, "");
2037: return;
2038: }
2039:
2040: cli_msg(-1025, "%s:", p->p.name);
2041: cli_msg(-1025, "%-*s %-25s %-9s %6s F %5s %7s", width,
2042: "Prefix", "Nexthop", "Interface", "Metric", "Seqno", "Expires");
2043:
2044: babel_show_routes_(p, &p->ip4_rtable);
2045: babel_show_routes_(p, &p->ip6_rtable);
2046:
2047: cli_msg(0, "");
2048: }
2049:
2050:
2051: /*
2052: * Babel protocol glue
2053: */
2054:
2055: /**
2056: * babel_timer - global timer hook
2057: * @t: Timer
2058: *
2059: * This function is called by the global protocol instance timer and handles
2060: * expiration of routes and neighbours as well as pruning of the seqno request
2061: * cache.
2062: */
2063: static void
2064: babel_timer(timer *t)
2065: {
2066: struct babel_proto *p = t->data;
2067:
2068: babel_expire_routes(p);
2069: babel_expire_neighbors(p);
2070: }
2071:
2072: static inline void
2073: babel_kick_timer(struct babel_proto *p)
2074: {
2075: if (p->timer->expires > (current_time() + 100 MS))
2076: tm_start(p->timer, 100 MS);
2077: }
2078:
2079:
2080: static int
2081: babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
2082: {
2083: struct rta *a = (*new)->attrs;
2084:
2085: /* Reject our own unreachable routes */
2086: if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
2087: return -1;
2088:
2089: return 0;
2090: }
2091:
2092: static void
2093: babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
2094: {
2095: struct adata *id = lp_alloc_adata(pool, sizeof(u64));
2096: memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
2097:
2098: rte_init_tmp_attrs(rt, pool, 2);
2099: rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
2100: rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
2101: }
2102:
2103: static void
2104: babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
2105: {
2106: rte_init_tmp_attrs(rt, pool, 2);
2107: rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
2108:
2109: /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
2110: rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
2111: }
2112:
2113: /*
2114: * babel_rt_notify - core tells us about new route (possibly our own),
2115: * so store it into our data structures.
2116: */
2117: static void
2118: babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
2119: struct rte *new, struct rte *old UNUSED)
2120: {
2121: struct babel_proto *p = (void *) P;
2122: struct babel_entry *e;
2123:
2124: if (new)
2125: {
2126: /* Update */
2127: uint internal = (new->attrs->src->proto == P);
2128: uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
2129: uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
2130: u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
2131:
2132: if (rt_metric > BABEL_INFINITY)
2133: {
2134: log(L_WARN "%s: Invalid babel_metric value %u for route %N",
2135: p->p.name, rt_metric, net->n.addr);
2136: rt_metric = BABEL_INFINITY;
2137: }
2138:
2139: e = babel_get_entry(p, net->n.addr);
2140:
2141: /* Activate triggered updates */
2142: if ((e->valid != BABEL_ENTRY_VALID) ||
2143: (e->router_id != rt_router_id))
2144: {
2145: babel_trigger_update(p);
2146: e->updated = current_time();
2147: }
2148:
2149: e->valid = BABEL_ENTRY_VALID;
2150: e->seqno = rt_seqno;
2151: e->metric = rt_metric;
2152: e->router_id = rt_router_id;
2153: }
2154: else
2155: {
2156: /* Withdraw */
2157: e = babel_find_entry(p, net->n.addr);
2158:
2159: if (!e || e->valid != BABEL_ENTRY_VALID)
2160: return;
2161:
2162: e->valid = BABEL_ENTRY_STALE;
2163: e->metric = BABEL_INFINITY;
2164:
2165: babel_trigger_update(p);
2166: e->updated = current_time();
2167: }
2168: }
2169:
2170: static int
2171: babel_rte_better(struct rte *new, struct rte *old)
2172: {
2173: return new->u.babel.metric < old->u.babel.metric;
2174: }
2175:
2176: static int
2177: babel_rte_same(struct rte *new, struct rte *old)
2178: {
2179: return ((new->u.babel.seqno == old->u.babel.seqno) &&
2180: (new->u.babel.metric == old->u.babel.metric) &&
2181: (new->u.babel.router_id == old->u.babel.router_id));
2182: }
2183:
2184:
2185: static void
2186: babel_postconfig(struct proto_config *CF)
2187: {
2188: struct babel_config *cf = (void *) CF;
2189: struct channel_config *ip4, *ip6, *ip6_sadr;
2190:
2191: ip4 = proto_cf_find_channel(CF, NET_IP4);
2192: ip6 = proto_cf_find_channel(CF, NET_IP6);
2193: ip6_sadr = proto_cf_find_channel(CF, NET_IP6_SADR);
2194:
2195: if (ip6 && ip6_sadr)
2196: cf_error("Both ipv6 and ipv6-sadr channels");
2197:
2198: cf->ip4_channel = ip4;
2199: cf->ip6_channel = ip6 ?: ip6_sadr;
2200: }
2201:
2202: static struct proto *
2203: babel_init(struct proto_config *CF)
2204: {
2205: struct proto *P = proto_new(CF);
2206: struct babel_proto *p = (void *) P;
2207: struct babel_config *cf = (void *) CF;
2208:
2209: proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
2210: proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
2211:
2212: P->if_notify = babel_if_notify;
2213: P->rt_notify = babel_rt_notify;
2214: P->preexport = babel_preexport;
2215: P->make_tmp_attrs = babel_make_tmp_attrs;
2216: P->store_tmp_attrs = babel_store_tmp_attrs;
2217: P->rte_better = babel_rte_better;
2218: P->rte_same = babel_rte_same;
2219:
2220: return P;
2221: }
2222:
2223: static inline void
2224: babel_randomize_router_id(struct babel_proto *p)
2225: {
2226: p->router_id &= (u64) 0xffffffff;
2227: p->router_id |= ((u64) random()) << 32;
2228: TRACE(D_EVENTS, "Randomized router ID to %lR", p->router_id);
2229: }
2230:
2231: static int
2232: babel_start(struct proto *P)
2233: {
2234: struct babel_proto *p = (void *) P;
2235: struct babel_config *cf = (void *) P->cf;
2236: u8 ip6_type = cf->ip6_channel ? cf->ip6_channel->net_type : NET_IP6;
2237:
2238: fib_init(&p->ip4_rtable, P->pool, NET_IP4, sizeof(struct babel_entry),
2239: OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
2240: fib_init(&p->ip6_rtable, P->pool, ip6_type, sizeof(struct babel_entry),
2241: OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
2242:
2243: init_list(&p->interfaces);
2244: p->timer = tm_new_init(P->pool, babel_timer, p, 1 S, 0);
2245: tm_start(p->timer, 1 S);
2246: p->update_seqno = 1;
2247: p->router_id = proto_get_router_id(&cf->c);
2248:
2249: if (cf->randomize_router_id)
2250: babel_randomize_router_id(p);
2251:
2252: p->route_slab = sl_new(P->pool, sizeof(struct babel_route));
2253: p->source_slab = sl_new(P->pool, sizeof(struct babel_source));
2254: p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node));
2255: p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request));
2256:
2257: p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
2258:
2259: return PS_UP;
2260: }
2261:
2262: static inline void
2263: babel_iface_shutdown(struct babel_iface *ifa)
2264: {
2265: if (ifa->sk)
2266: {
2267: babel_send_wildcard_retraction(ifa);
2268: babel_send_queue(ifa);
2269: }
2270: }
2271:
2272: static int
2273: babel_shutdown(struct proto *P)
2274: {
2275: struct babel_proto *p = (void *) P;
2276: struct babel_iface *ifa;
2277:
2278: TRACE(D_EVENTS, "Shutdown requested");
2279:
2280: WALK_LIST(ifa, p->interfaces)
2281: babel_iface_shutdown(ifa);
2282:
2283: return PS_DOWN;
2284: }
2285:
2286: static int
2287: babel_reconfigure(struct proto *P, struct proto_config *CF)
2288: {
2289: struct babel_proto *p = (void *) P;
2290: struct babel_config *new = (void *) CF;
2291: u8 ip6_type = new->ip6_channel ? new->ip6_channel->net_type : NET_IP6;
2292:
2293: TRACE(D_EVENTS, "Reconfiguring");
2294:
2295: if (p->ip6_rtable.addr_type != ip6_type)
2296: return 0;
2297:
2298: if (!proto_configure_channel(P, &p->ip4_channel, new->ip4_channel) ||
2299: !proto_configure_channel(P, &p->ip6_channel, new->ip6_channel))
2300: return 0;
2301:
2302: p->p.cf = CF;
2303: babel_reconfigure_ifaces(p, new);
2304:
2305: babel_trigger_update(p);
2306: babel_kick_timer(p);
2307:
2308: return 1;
2309: }
2310:
2311:
2312: struct protocol proto_babel = {
2313: .name = "Babel",
2314: .template = "babel%d",
2315: .class = PROTOCOL_BABEL,
2316: .preference = DEF_PREF_BABEL,
2317: .channel_mask = NB_IP | NB_IP6_SADR,
2318: .proto_size = sizeof(struct babel_proto),
2319: .config_size = sizeof(struct babel_config),
2320: .postconfig = babel_postconfig,
2321: .init = babel_init,
2322: .dump = babel_dump,
2323: .start = babel_start,
2324: .shutdown = babel_shutdown,
2325: .reconfigure = babel_reconfigure,
2326: .get_route_info = babel_get_route_info,
2327: .get_attr = babel_get_attr
2328: };
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>