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