]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/babel/babel.c
Babel: Set onlink flag for IPv4 routes with unreachable next hop
[thirdparty/bird.git] / proto / babel / babel.c
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 /*
644 * If we cannot find a reachable neighbour, set the entry to be onlink. This
645 * makes it possible to, e.g., assign /32 addresses on a mesh interface and
646 * have routing work.
647 */
648 if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0))
649 a0.nh.flags = RNF_ONLINK;
650
651 rta *a = rta_lookup(&a0);
652 rte *rte = rte_get_temp(a);
653 rte->u.babel.seqno = r->seqno;
654 rte->u.babel.metric = r->metric;
655 rte->u.babel.router_id = r->router_id;
656 rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
657
658 e->unreachable = 0;
659 rte_update2(c, e->n.addr, rte, p->p.main_source);
660 }
661 else if (e->valid && (e->router_id != p->router_id))
662 {
663 /* Unreachable */
664 rta a0 = {
665 .src = p->p.main_source,
666 .source = RTS_BABEL,
667 .scope = SCOPE_UNIVERSE,
668 .dest = RTD_UNREACHABLE,
669 };
670
671 rta *a = rta_lookup(&a0);
672 rte *rte = rte_get_temp(a);
673 memset(&rte->u.babel, 0, sizeof(rte->u.babel));
674 rte->pflags = 0;
675 rte->pref = 1;
676
677 e->unreachable = 1;
678 rte_update2(c, e->n.addr, rte, p->p.main_source);
679 }
680 else
681 {
682 /* Retraction */
683 e->unreachable = 0;
684 rte_update2(c, e->n.addr, NULL, p->p.main_source);
685 }
686 }
687
688 /* Special case of babel_announce_rte() just for retraction */
689 static inline void
690 babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
691 {
692 struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
693 e->unreachable = 0;
694 rte_update2(c, e->n.addr, NULL, p->p.main_source);
695 }
696
697
698 /**
699 * babel_select_route - select best route for given route entry
700 * @p: Babel protocol instance
701 * @e: Babel entry to select the best route for
702 * @mod: Babel route that was modified or NULL if unspecified
703 *
704 * Select the best reachable and feasible route for a given prefix among the
705 * routes received from peers, and propagate it to the nest. This just selects
706 * the reachable and feasible route with the lowest metric, but keeps selected
707 * the old one in case of tie.
708 *
709 * If no feasible route is available for a prefix that previously had a route
710 * selected, a seqno request is sent to try to get a valid route. If the entry
711 * is valid and not owned by us, the unreachable route is announced to the nest
712 * (to blackhole packets going to it, as per section 2.8). It is later removed
713 * by babel_expire_routes(). Otherwise, the route is just removed from the nest.
714 *
715 * Argument @mod is used to optimize best route calculation. When specified, the
716 * function can assume that only the @mod route was modified to avoid full best
717 * route selection and announcement when non-best route was modified in minor
718 * way. The caller is advised to not call babel_select_route() when no change is
719 * done (e.g. periodic route updates) to avoid unnecessary announcements of the
720 * same best route. The caller is not required to call the function in case of a
721 * retraction of a non-best route.
722 *
723 * Note that the function does not active triggered updates. That is done by
724 * babel_rt_notify() when the change is propagated back to Babel.
725 */
726 static void
727 babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod)
728 {
729 struct babel_route *r, *best = e->selected;
730
731 /* Shortcut if only non-best was modified */
732 if (mod && (mod != best))
733 {
734 /* Either select modified route, or keep old best route */
735 if ((mod->metric < (best ? best->metric : BABEL_INFINITY)) && mod->feasible)
736 best = mod;
737 else
738 return;
739 }
740 else
741 {
742 /* Selected route may be modified and no longer admissible */
743 if (!best || (best->metric == BABEL_INFINITY) || !best->feasible)
744 best = NULL;
745
746 /* Find the best feasible route from all routes */
747 WALK_LIST(r, e->routes)
748 if ((r->metric < (best ? best->metric : BABEL_INFINITY)) && r->feasible)
749 best = r;
750 }
751
752 if (best)
753 {
754 if (best != e->selected)
755 TRACE(D_EVENTS, "Picked new route for prefix %N: router-id %lR metric %d",
756 e->n.addr, best->router_id, best->metric);
757 }
758 else if (e->selected)
759 {
760 /*
761 * We have lost all feasible routes. We have to broadcast seqno request
762 * (Section 3.8.2.1) and keep unreachable route for a while (section 2.8).
763 * The later is done automatically by babel_announce_rte().
764 */
765
766 TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr);
767 if (e->valid && (e->selected->router_id == e->router_id))
768 babel_add_seqno_request(p, e, e->selected->router_id, e->selected->seqno + 1, 0, NULL);
769 }
770 else
771 return;
772
773 e->selected = best;
774 babel_announce_rte(p, e);
775 }
776
777 /*
778 * Functions to send replies
779 */
780
781 static void
782 babel_send_ack(struct babel_iface *ifa, ip_addr dest, u16 nonce)
783 {
784 struct babel_proto *p = ifa->proto;
785 union babel_msg msg = {};
786
787 TRACE(D_PACKETS, "Sending ACK to %I with nonce %d", dest, nonce);
788
789 msg.type = BABEL_TLV_ACK;
790 msg.ack.nonce = nonce;
791
792 babel_send_unicast(&msg, ifa, dest);
793 }
794
795 static void
796 babel_build_ihu(union babel_msg *msg, struct babel_iface *ifa, struct babel_neighbor *n)
797 {
798 struct babel_proto *p = ifa->proto;
799
800 msg->type = BABEL_TLV_IHU;
801 msg->ihu.addr = n->addr;
802 msg->ihu.rxcost = n->rxcost;
803 msg->ihu.interval = ifa->cf->ihu_interval;
804
805 TRACE(D_PACKETS, "Sending IHU for %I with rxcost %d interval %t",
806 msg->ihu.addr, msg->ihu.rxcost, (btime) msg->ihu.interval);
807 }
808
809 static void
810 babel_send_ihu(struct babel_iface *ifa, struct babel_neighbor *n)
811 {
812 union babel_msg msg = {};
813 babel_build_ihu(&msg, ifa, n);
814 babel_send_unicast(&msg, ifa, n->addr);
815 n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
816 }
817
818 static void
819 babel_send_ihus(struct babel_iface *ifa)
820 {
821 struct babel_neighbor *n;
822 WALK_LIST(n, ifa->neigh_list)
823 {
824 if (n->hello_cnt && (--n->ihu_cnt <= 0))
825 {
826 union babel_msg msg = {};
827 babel_build_ihu(&msg, ifa, n);
828 babel_enqueue(&msg, ifa);
829 n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
830 }
831 }
832 }
833
834 static void
835 babel_send_hello(struct babel_iface *ifa)
836 {
837 struct babel_proto *p = ifa->proto;
838 union babel_msg msg = {};
839
840 msg.type = BABEL_TLV_HELLO;
841 msg.hello.seqno = ifa->hello_seqno++;
842 msg.hello.interval = ifa->cf->hello_interval;
843
844 TRACE(D_PACKETS, "Sending hello on %s with seqno %d interval %t",
845 ifa->ifname, msg.hello.seqno, (btime) msg.hello.interval);
846
847 babel_enqueue(&msg, ifa);
848
849 babel_send_ihus(ifa);
850 }
851
852 static void
853 babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n)
854 {
855 union babel_msg msg = {};
856
857 TRACE(D_PACKETS, "Sending route request for %N to %I", e->n.addr, n->addr);
858
859 msg.type = BABEL_TLV_ROUTE_REQUEST;
860 net_copy(&msg.route_request.net, e->n.addr);
861
862 babel_send_unicast(&msg, n->ifa, n->addr);
863 }
864
865 static void
866 babel_send_wildcard_request(struct babel_iface *ifa)
867 {
868 struct babel_proto *p = ifa->proto;
869 union babel_msg msg = {};
870
871 TRACE(D_PACKETS, "Sending wildcard route request on %s", ifa->ifname);
872
873 msg.type = BABEL_TLV_ROUTE_REQUEST;
874 msg.route_request.full = 1;
875
876 babel_enqueue(&msg, ifa);
877 }
878
879 static void
880 babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr)
881 {
882 union babel_msg msg = {};
883
884 msg.type = BABEL_TLV_SEQNO_REQUEST;
885 msg.seqno_request.hop_count = sr->hop_count ?: BABEL_INITIAL_HOP_COUNT;
886 msg.seqno_request.seqno = sr->seqno;
887 msg.seqno_request.router_id = sr->router_id;
888 net_copy(&msg.seqno_request.net, e->n.addr);
889
890 if (sr->nbr)
891 {
892 TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d to %I on %s",
893 e->n.addr, sr->router_id, sr->seqno, sr->nbr->addr, sr->nbr->ifa->ifname);
894
895 babel_send_unicast(&msg, sr->nbr->ifa, sr->nbr->addr);
896 }
897 else
898 {
899 TRACE(D_PACKETS, "Sending broadcast seqno request for %N router-id %lR seqno %d",
900 e->n.addr, sr->router_id, sr->seqno);
901
902 struct babel_iface *ifa;
903 WALK_LIST(ifa, p->interfaces)
904 babel_enqueue(&msg, ifa);
905 }
906 }
907
908 /**
909 * babel_send_update - send route table updates
910 * @ifa: Interface to transmit on
911 * @changed: Only send entries changed since this time
912 *
913 * This function produces update TLVs for all entries changed since the time
914 * indicated by the &changed parameter and queues them for transmission on the
915 * selected interface. During the process, the feasibility distance for each
916 * transmitted entry is updated.
917 */
918 static void
919 babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable)
920 {
921 struct babel_proto *p = ifa->proto;
922
923 /* Update increase was requested */
924 if (p->update_seqno_inc)
925 {
926 p->update_seqno++;
927 p->update_seqno_inc = 0;
928 }
929
930 FIB_WALK(rtable, struct babel_entry, e)
931 {
932 if (!e->valid)
933 continue;
934
935 /* Our own seqno might have changed, in which case we update the routes we
936 originate. */
937 if ((e->router_id == p->router_id) && (e->seqno < p->update_seqno))
938 {
939 e->seqno = p->update_seqno;
940 e->updated = current_time();
941 }
942
943 /* Skip routes that weren't updated since 'changed' time */
944 if (e->updated < changed)
945 continue;
946
947 TRACE(D_PACKETS, "Sending update for %N router-id %lR seqno %d metric %d",
948 e->n.addr, e->router_id, e->seqno, e->metric);
949
950 union babel_msg msg = {};
951 msg.type = BABEL_TLV_UPDATE;
952 msg.update.interval = ifa->cf->update_interval;
953 msg.update.seqno = e->seqno;
954 msg.update.metric = e->metric;
955 msg.update.router_id = e->router_id;
956 net_copy(&msg.update.net, e->n.addr);
957
958 msg.update.next_hop = ((e->n.addr->type == NET_IP4) ?
959 ifa->next_hop_ip4 : ifa->next_hop_ip6);
960
961 /* Do not send route if next hop is unknown, e.g. no configured IPv4 address */
962 if (ipa_zero(msg.update.next_hop))
963 continue;
964
965 babel_enqueue(&msg, ifa);
966
967 /* Update feasibility distance for redistributed routes */
968 if (e->router_id != p->router_id)
969 {
970 struct babel_source *s = babel_get_source(p, e, e->router_id);
971 s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
972
973 if ((msg.update.seqno > s->seqno) ||
974 ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric)))
975 {
976 s->seqno = msg.update.seqno;
977 s->metric = msg.update.metric;
978 }
979 }
980 }
981 FIB_WALK_END;
982 }
983
984 static void
985 babel_send_update(struct babel_iface *ifa, btime changed)
986 {
987 struct babel_proto *p = ifa->proto;
988
989 babel_send_update_(ifa, changed, &p->ip4_rtable);
990 babel_send_update_(ifa, changed, &p->ip6_rtable);
991 }
992
993 static void
994 babel_trigger_iface_update(struct babel_iface *ifa)
995 {
996 struct babel_proto *p = ifa->proto;
997
998 /* Interface not active or already scheduled */
999 if (!ifa->up || ifa->want_triggered)
1000 return;
1001
1002 TRACE(D_EVENTS, "Scheduling triggered updates for %s seqno %d",
1003 ifa->iface->name, p->update_seqno);
1004
1005 ifa->want_triggered = current_time();
1006 babel_iface_kick_timer(ifa);
1007 }
1008
1009 /* Sends and update on all interfaces. */
1010 static void
1011 babel_trigger_update(struct babel_proto *p)
1012 {
1013 if (p->triggered)
1014 return;
1015
1016 struct babel_iface *ifa;
1017 WALK_LIST(ifa, p->interfaces)
1018 babel_trigger_iface_update(ifa);
1019
1020 p->triggered = 1;
1021 }
1022
1023 /* A retraction is an update with an infinite metric */
1024 static void
1025 babel_send_retraction(struct babel_iface *ifa, net_addr *n)
1026 {
1027 struct babel_proto *p = ifa->proto;
1028 union babel_msg msg = {};
1029
1030 TRACE(D_PACKETS, "Sending retraction for %N seqno %d", n, p->update_seqno);
1031
1032 msg.type = BABEL_TLV_UPDATE;
1033 msg.update.interval = ifa->cf->update_interval;
1034 msg.update.seqno = p->update_seqno;
1035 msg.update.metric = BABEL_INFINITY;
1036 msg.update.net = *n;
1037
1038 babel_enqueue(&msg, ifa);
1039 }
1040
1041 static void
1042 babel_send_wildcard_retraction(struct babel_iface *ifa)
1043 {
1044 struct babel_proto *p = ifa->proto;
1045 union babel_msg msg = {};
1046
1047 TRACE(D_PACKETS, "Sending wildcard retraction on %s", ifa->ifname);
1048
1049 msg.type = BABEL_TLV_UPDATE;
1050 msg.update.wildcard = 1;
1051 msg.update.interval = ifa->cf->update_interval;
1052 msg.update.seqno = p->update_seqno;
1053 msg.update.metric = BABEL_INFINITY;
1054
1055 babel_enqueue(&msg, ifa);
1056 }
1057
1058
1059 /*
1060 * TLV handler helpers
1061 */
1062
1063 /* Update hello history according to Appendix A1 of the RFC */
1064 static void
1065 babel_update_hello_history(struct babel_neighbor *n, u16 seqno, uint interval)
1066 {
1067 /*
1068 * Compute the difference between expected and received seqno (modulo 2^16).
1069 * If the expected and received seqnos are within 16 of each other, the modular
1070 * difference is going to be less than 16 for one of the directions. Otherwise,
1071 * the values differ too much, so just reset the state.
1072 */
1073
1074 u16 delta = ((uint) seqno - (uint) n->next_hello_seqno);
1075
1076 if ((delta == 0) || (n->hello_cnt == 0))
1077 {
1078 /* Do nothing */
1079 }
1080 else if (delta <= 16)
1081 {
1082 /* Sending node decreased interval; fast-forward */
1083 n->hello_map <<= delta;
1084 n->hello_cnt = MIN(n->hello_cnt + delta, 16);
1085 }
1086 else if (delta >= 0xfff0)
1087 {
1088 u8 diff = (0xffff - delta);
1089 /* Sending node increased interval; undo history */
1090 n->hello_map >>= diff;
1091 n->hello_cnt = (diff < n->hello_cnt) ? n->hello_cnt - diff : 0;
1092 }
1093 else
1094 {
1095 /* Note state reset - flush entries */
1096 n->hello_map = n->hello_cnt = 0;
1097 }
1098
1099 /* Current entry */
1100 n->hello_map = (n->hello_map << 1) | 1;
1101 n->next_hello_seqno = seqno+1;
1102 if (n->hello_cnt < 16) n->hello_cnt++;
1103
1104 /* Update expiration */
1105 n->hello_expiry = current_time() + BABEL_HELLO_EXPIRY_FACTOR(interval);
1106 n->last_hello_int = interval;
1107 }
1108
1109
1110 /*
1111 * TLV handlers
1112 */
1113
1114 void
1115 babel_handle_ack_req(union babel_msg *m, struct babel_iface *ifa)
1116 {
1117 struct babel_proto *p = ifa->proto;
1118 struct babel_msg_ack_req *msg = &m->ack_req;
1119
1120 TRACE(D_PACKETS, "Handling ACK request nonce %d interval %t",
1121 msg->nonce, (btime) msg->interval);
1122
1123 babel_send_ack(ifa, msg->sender, msg->nonce);
1124 }
1125
1126 void
1127 babel_handle_hello(union babel_msg *m, struct babel_iface *ifa)
1128 {
1129 struct babel_proto *p = ifa->proto;
1130 struct babel_msg_hello *msg = &m->hello;
1131
1132 TRACE(D_PACKETS, "Handling hello seqno %d interval %t",
1133 msg->seqno, (btime) msg->interval);
1134
1135 struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
1136 int first_hello = !n->hello_cnt;
1137
1138 babel_update_hello_history(n, msg->seqno, msg->interval);
1139 babel_update_cost(n);
1140
1141 /* Speed up session establishment by sending IHU immediately */
1142 if (first_hello)
1143 babel_send_ihu(ifa, n);
1144 }
1145
1146 void
1147 babel_handle_ihu(union babel_msg *m, struct babel_iface *ifa)
1148 {
1149 struct babel_proto *p = ifa->proto;
1150 struct babel_msg_ihu *msg = &m->ihu;
1151
1152 /* Ignore IHUs that are not about us */
1153 if ((msg->ae != BABEL_AE_WILDCARD) && !ipa_equal(msg->addr, ifa->addr))
1154 return;
1155
1156 TRACE(D_PACKETS, "Handling IHU rxcost %d interval %t",
1157 msg->rxcost, (btime) msg->interval);
1158
1159 struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
1160 n->txcost = msg->rxcost;
1161 n->ihu_expiry = current_time() + BABEL_IHU_EXPIRY_FACTOR(msg->interval);
1162 babel_update_cost(n);
1163 }
1164
1165 /**
1166 * babel_handle_update - handle incoming route updates
1167 * @m: Incoming update TLV
1168 * @ifa: Interface the update was received on
1169 *
1170 * This function is called as a handler for update TLVs and handles the updating
1171 * and maintenance of route entries in Babel's internal routing cache. The
1172 * handling follows the actions described in the Babel RFC, and at the end of
1173 * each update handling, babel_select_route() is called on the affected entry to
1174 * optionally update the selected routes and propagate them to the core.
1175 */
1176 void
1177 babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
1178 {
1179 struct babel_proto *p = ifa->proto;
1180 struct babel_msg_update *msg = &m->update;
1181
1182 struct babel_neighbor *nbr;
1183 struct babel_entry *e;
1184 struct babel_source *s;
1185 struct babel_route *r, *best;
1186 node *n;
1187 int feasible, metric;
1188
1189 if (msg->wildcard)
1190 TRACE(D_PACKETS, "Handling wildcard retraction", msg->seqno);
1191 else
1192 TRACE(D_PACKETS, "Handling update for %N with seqno %d metric %d",
1193 &msg->net, msg->seqno, msg->metric);
1194
1195 nbr = babel_find_neighbor(ifa, msg->sender);
1196 if (!nbr)
1197 {
1198 DBG("Babel: Haven't heard from neighbor %I; ignoring update.\n", msg->sender);
1199 return;
1200 }
1201
1202 if (msg->router_id == p->router_id)
1203 {
1204 DBG("Babel: Ignoring update for our own router ID.\n");
1205 return;
1206 }
1207
1208 struct channel *c = (msg->net.type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
1209 if (!c || (c->channel_state != CS_UP))
1210 {
1211 DBG("Babel: Ignoring update for inactive address family.\n");
1212 return;
1213 }
1214
1215 /* Retraction */
1216 if (msg->metric == BABEL_INFINITY)
1217 {
1218 if (msg->wildcard)
1219 {
1220 /*
1221 * Special case: This is a retraction of all prefixes announced by this
1222 * neighbour (see second-to-last paragraph of section 4.4.9 in the RFC).
1223 */
1224 WALK_LIST(n, nbr->routes)
1225 {
1226 r = SKIP_BACK(struct babel_route, neigh_route, n);
1227 babel_retract_route(p, r);
1228 }
1229 }
1230 else
1231 {
1232 e = babel_find_entry(p, &msg->net);
1233
1234 if (!e)
1235 return;
1236
1237 /* The route entry indexed by neighbour */
1238 r = babel_find_route(e, nbr);
1239
1240 if (!r)
1241 return;
1242
1243 /* Router-id, next-hop and seqno are ignored for retractions */
1244 babel_retract_route(p, r);
1245 }
1246
1247 /* Done with retractions */
1248 return;
1249 }
1250
1251 /* Regular update */
1252 e = babel_get_entry(p, &msg->net);
1253 r = babel_get_route(p, e, nbr); /* the route entry indexed by neighbour */
1254 s = babel_find_source(e, msg->router_id); /* for feasibility */
1255 feasible = babel_is_feasible(s, msg->seqno, msg->metric);
1256 metric = babel_compute_metric(nbr, msg->metric);
1257 best = e->selected;
1258
1259 /* RFC section 3.8.2.2 - Dealing with unfeasible updates */
1260 if (!feasible && (metric != BABEL_INFINITY) &&
1261 (!best || (r == best) || (metric < best->metric)))
1262 babel_add_seqno_request(p, e, s->router_id, s->seqno + 1, 0, nbr);
1263
1264 /* Special case - ignore unfeasible update to best route */
1265 if (r == best && !feasible && (msg->router_id == r->router_id))
1266 return;
1267
1268 r->expires = current_time() + BABEL_ROUTE_EXPIRY_FACTOR(msg->interval);
1269 r->refresh_time = current_time() + BABEL_ROUTE_REFRESH_FACTOR(msg->interval);
1270
1271 /* No further processing if there is no change */
1272 if ((r->feasible == feasible) && (r->seqno == msg->seqno) &&
1273 (r->metric == metric) && (r->advert_metric == msg->metric) &&
1274 (r->router_id == msg->router_id) && ipa_equal(r->next_hop, msg->next_hop))
1275 return;
1276
1277 /* Last paragraph above - update the entry */
1278 r->feasible = feasible;
1279 r->seqno = msg->seqno;
1280 r->metric = metric;
1281 r->advert_metric = msg->metric;
1282 r->router_id = msg->router_id;
1283 r->next_hop = msg->next_hop;
1284
1285 /* If received update satisfies seqno request, we send triggered updates */
1286 if (babel_satisfy_seqno_request(p, e, msg->router_id, msg->seqno))
1287 {
1288 babel_trigger_update(p);
1289 e->updated = current_time();
1290 }
1291
1292 babel_select_route(p, e, r);
1293 }
1294
1295 void
1296 babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa)
1297 {
1298 struct babel_proto *p = ifa->proto;
1299 struct babel_msg_route_request *msg = &m->route_request;
1300
1301 /* RFC 6126 3.8.1.1 */
1302
1303 /* Wildcard request - full update on the interface */
1304 if (msg->full)
1305 {
1306 TRACE(D_PACKETS, "Handling wildcard route request");
1307 ifa->want_triggered = 1;
1308 return;
1309 }
1310
1311 TRACE(D_PACKETS, "Handling route request for %N", &msg->net);
1312
1313 /* Non-wildcard request - see if we have an entry for the route.
1314 If not, send a retraction, otherwise send an update. */
1315 struct babel_entry *e = babel_find_entry(p, &msg->net);
1316 if (!e)
1317 {
1318 babel_send_retraction(ifa, &msg->net);
1319 }
1320 else
1321 {
1322 babel_trigger_iface_update(ifa);
1323 e->updated = current_time();
1324 }
1325 }
1326
1327 void
1328 babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
1329 {
1330 struct babel_proto *p = ifa->proto;
1331 struct babel_msg_seqno_request *msg = &m->seqno_request;
1332
1333 /* RFC 6126 3.8.1.2 */
1334
1335 TRACE(D_PACKETS, "Handling seqno request for %N router-id %lR seqno %d hop count %d",
1336 &msg->net, msg->router_id, msg->seqno, msg->hop_count);
1337
1338 /* Ignore if we have no such entry or entry has infinite metric */
1339 struct babel_entry *e = babel_find_entry(p, &msg->net);
1340 if (!e || !e->valid || (e->metric == BABEL_INFINITY))
1341 return;
1342
1343 /* Trigger update on incoming interface if we have a selected route with
1344 different router id or seqno no smaller than requested */
1345 if ((e->router_id != msg->router_id) || ge_mod64k(e->seqno, msg->seqno))
1346 {
1347 babel_trigger_iface_update(ifa);
1348 e->updated = current_time();
1349 return;
1350 }
1351
1352 /* Seqno is larger; check if we own the router id */
1353 if (msg->router_id == p->router_id)
1354 {
1355 /* Ours; seqno increase and trigger global update */
1356 p->update_seqno_inc = 1;
1357 babel_trigger_update(p);
1358 }
1359 else if (msg->hop_count > 1)
1360 {
1361 /* Not ours; forward if TTL allows it */
1362
1363 /* Find best admissible route */
1364 struct babel_route *r, *best1 = NULL, *best2 = NULL;
1365 WALK_LIST(r, e->routes)
1366 if ((r->router_id == msg->router_id) && !ipa_equal(r->neigh->addr, msg->sender))
1367 {
1368 /* Find best feasible route */
1369 if ((!best1 || r->metric < best1->metric) && r->feasible)
1370 best1 = r;
1371
1372 /* Find best not necessary feasible route */
1373 if (!best2 || r->metric < best2->metric)
1374 best2 = r;
1375 }
1376
1377 /* If no route is found, do nothing */
1378 r = best1 ?: best2;
1379 if (!r)
1380 return;
1381
1382 babel_add_seqno_request(p, e, msg->router_id, msg->seqno, msg->hop_count-1, r->neigh);
1383 }
1384 }
1385
1386
1387 /*
1388 * Babel interfaces
1389 */
1390
1391 /**
1392 * babel_iface_timer - Babel interface timer handler
1393 * @t: Timer
1394 *
1395 * This function is called by the per-interface timer and triggers sending of
1396 * periodic Hello's and both triggered and periodic updates. Periodic Hello's
1397 * and updates are simply handled by setting the next_{hello,regular} variables
1398 * on the interface, and triggering an update (and resetting the variable)
1399 * whenever 'now' exceeds that value.
1400 *
1401 * For triggered updates, babel_trigger_iface_update() will set the
1402 * want_triggered field on the interface to a timestamp value. If this is set
1403 * (and the next_triggered time has passed; this is a rate limiting mechanism),
1404 * babel_send_update() will be called with this timestamp as the second
1405 * parameter. This causes updates to be send consisting of only the routes that
1406 * have changed since the time saved in want_triggered.
1407 *
1408 * Mostly when an update is triggered, the route being modified will be set to
1409 * the value of 'now' at the time of the trigger; the >= comparison for
1410 * selecting which routes to send in the update will make sure this is included.
1411 */
1412 static void
1413 babel_iface_timer(timer *t)
1414 {
1415 struct babel_iface *ifa = t->data;
1416 struct babel_proto *p = ifa->proto;
1417 btime hello_period = ifa->cf->hello_interval;
1418 btime update_period = ifa->cf->update_interval;
1419 btime now_ = current_time();
1420
1421 if (now_ >= ifa->next_hello)
1422 {
1423 babel_send_hello(ifa);
1424 ifa->next_hello += hello_period * (1 + (now_ - ifa->next_hello) / hello_period);
1425 }
1426
1427 if (now_ >= ifa->next_regular)
1428 {
1429 TRACE(D_EVENTS, "Sending regular updates on %s", ifa->ifname);
1430 babel_send_update(ifa, 0);
1431 ifa->next_regular += update_period * (1 + (now_ - ifa->next_regular) / update_period);
1432 ifa->want_triggered = 0;
1433 p->triggered = 0;
1434 }
1435 else if (ifa->want_triggered && (now_ >= ifa->next_triggered))
1436 {
1437 TRACE(D_EVENTS, "Sending triggered updates on %s", ifa->ifname);
1438 babel_send_update(ifa, ifa->want_triggered);
1439 ifa->next_triggered = now_ + MIN(1 S, update_period / 2);
1440 ifa->want_triggered = 0;
1441 p->triggered = 0;
1442 }
1443
1444 btime next_event = MIN(ifa->next_hello, ifa->next_regular);
1445 if (ifa->want_triggered) next_event = MIN(next_event, ifa->next_triggered);
1446 tm_set(ifa->timer, next_event);
1447 }
1448
1449 static inline void
1450 babel_iface_kick_timer(struct babel_iface *ifa)
1451 {
1452 if (ifa->timer->expires > (current_time() + 100 MS))
1453 tm_start(ifa->timer, 100 MS);
1454 }
1455
1456 static void
1457 babel_iface_start(struct babel_iface *ifa)
1458 {
1459 struct babel_proto *p = ifa->proto;
1460
1461 TRACE(D_EVENTS, "Starting interface %s", ifa->ifname);
1462
1463 ifa->next_hello = current_time() + (random() % ifa->cf->hello_interval);
1464 ifa->next_regular = current_time() + (random() % ifa->cf->update_interval);
1465 ifa->next_triggered = current_time() + MIN(1 S, ifa->cf->update_interval / 2);
1466 ifa->want_triggered = 0; /* We send an immediate update (below) */
1467 tm_start(ifa->timer, 100 MS);
1468 ifa->up = 1;
1469
1470 babel_send_hello(ifa);
1471 babel_send_wildcard_retraction(ifa);
1472 babel_send_wildcard_request(ifa);
1473 babel_send_update(ifa, 0); /* Full update */
1474 }
1475
1476 static void
1477 babel_iface_stop(struct babel_iface *ifa)
1478 {
1479 struct babel_proto *p = ifa->proto;
1480 struct babel_neighbor *nbr;
1481 struct babel_route *r;
1482 node *n;
1483
1484 TRACE(D_EVENTS, "Stopping interface %s", ifa->ifname);
1485
1486 /*
1487 * Rather than just flushing the neighbours, we set the metric of their routes
1488 * to infinity. This allows us to keep the neighbour hello state for when the
1489 * interface comes back up. The routes will also be kept until they expire.
1490 */
1491 WALK_LIST(nbr, ifa->neigh_list)
1492 {
1493 WALK_LIST(n, nbr->routes)
1494 {
1495 r = SKIP_BACK(struct babel_route, neigh_route, n);
1496 babel_retract_route(p, r);
1497 }
1498 }
1499
1500 tm_stop(ifa->timer);
1501 ifa->up = 0;
1502 }
1503
1504 static inline int
1505 babel_iface_link_up(struct babel_iface *ifa)
1506 {
1507 return !ifa->cf->check_link || (ifa->iface->flags & IF_LINK_UP);
1508 }
1509
1510 static void
1511 babel_iface_update_state(struct babel_iface *ifa)
1512 {
1513 int up = ifa->sk && babel_iface_link_up(ifa);
1514
1515 if (up == ifa->up)
1516 return;
1517
1518 if (up)
1519 babel_iface_start(ifa);
1520 else
1521 babel_iface_stop(ifa);
1522 }
1523
1524 static void
1525 babel_iface_update_addr4(struct babel_iface *ifa)
1526 {
1527 struct babel_proto *p = ifa->proto;
1528
1529 ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
1530 ifa->next_hop_ip4 = ipa_nonzero(ifa->cf->next_hop_ip4) ? ifa->cf->next_hop_ip4 : addr4;
1531
1532 if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1533 log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
1534
1535 if (ifa->up)
1536 babel_iface_kick_timer(ifa);
1537 }
1538
1539 static void
1540 babel_iface_update_buffers(struct babel_iface *ifa)
1541 {
1542 if (!ifa->sk)
1543 return;
1544
1545 uint mtu = MAX(BABEL_MIN_MTU, ifa->iface->mtu);
1546 uint rbsize = ifa->cf->rx_buffer ?: mtu;
1547 uint tbsize = ifa->cf->tx_length ?: mtu;
1548 rbsize = MAX(rbsize, tbsize);
1549
1550 sk_set_rbsize(ifa->sk, rbsize);
1551 sk_set_tbsize(ifa->sk, tbsize);
1552
1553 ifa->tx_length = tbsize - BABEL_OVERHEAD;
1554 }
1555
1556 static struct babel_iface*
1557 babel_find_iface(struct babel_proto *p, struct iface *what)
1558 {
1559 struct babel_iface *ifa;
1560
1561 WALK_LIST (ifa, p->interfaces)
1562 if (ifa->iface == what)
1563 return ifa;
1564
1565 return NULL;
1566 }
1567
1568 static void
1569 babel_iface_locked(struct object_lock *lock)
1570 {
1571 struct babel_iface *ifa = lock->data;
1572 struct babel_proto *p = ifa->proto;
1573
1574 if (!babel_open_socket(ifa))
1575 {
1576 log(L_ERR "%s: Cannot open socket for %s", p->p.name, ifa->iface->name);
1577 return;
1578 }
1579
1580 babel_iface_update_buffers(ifa);
1581 babel_iface_update_state(ifa);
1582 }
1583
1584 static void
1585 babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_config *ic)
1586 {
1587 struct babel_iface *ifa;
1588
1589 TRACE(D_EVENTS, "Adding interface %s", new->name);
1590
1591 pool *pool = rp_new(p->p.pool, new->name);
1592
1593 ifa = mb_allocz(pool, sizeof(struct babel_iface));
1594 ifa->proto = p;
1595 ifa->iface = new;
1596 ifa->cf = ic;
1597 ifa->pool = pool;
1598 ifa->ifname = new->name;
1599 ifa->addr = new->llv6->ip;
1600
1601 add_tail(&p->interfaces, NODE ifa);
1602
1603 ip_addr addr4 = new->addr4 ? new->addr4->ip : IPA_NONE;
1604 ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4;
1605 ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr;
1606
1607 if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1608 log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, new->name);
1609
1610 init_list(&ifa->neigh_list);
1611 ifa->hello_seqno = 1;
1612
1613 ifa->timer = tm_new_init(ifa->pool, babel_iface_timer, ifa, 0, 0);
1614
1615 init_list(&ifa->msg_queue);
1616 ifa->send_event = ev_new_init(ifa->pool, babel_send_queue, ifa);
1617
1618 struct object_lock *lock = olock_new(ifa->pool);
1619 lock->type = OBJLOCK_UDP;
1620 lock->addr = IP6_BABEL_ROUTERS;
1621 lock->port = ifa->cf->port;
1622 lock->iface = ifa->iface;
1623 lock->hook = babel_iface_locked;
1624 lock->data = ifa;
1625
1626 olock_acquire(lock);
1627 }
1628
1629 static void
1630 babel_remove_iface(struct babel_proto *p, struct babel_iface *ifa)
1631 {
1632 TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
1633
1634 struct babel_neighbor *n;
1635 WALK_LIST_FIRST(n, ifa->neigh_list)
1636 babel_flush_neighbor(p, n);
1637
1638 rem_node(NODE ifa);
1639
1640 rfree(ifa->pool); /* contains ifa itself, locks, socket, etc */
1641 }
1642
1643 static void
1644 babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
1645 {
1646 struct babel_proto *p = (void *) P;
1647 struct babel_config *cf = (void *) P->cf;
1648 struct babel_iface *ifa = babel_find_iface(p, iface);
1649
1650 if (iface->flags & IF_IGNORE)
1651 return;
1652
1653 /* Add, remove or restart interface */
1654 if (flags & (IF_CHANGE_UPDOWN | IF_CHANGE_LLV6))
1655 {
1656 if (ifa)
1657 babel_remove_iface(p, ifa);
1658
1659 if (!(iface->flags & IF_UP))
1660 return;
1661
1662 /* We only speak multicast */
1663 if (!(iface->flags & IF_MULTICAST))
1664 return;
1665
1666 /* Ignore ifaces without link-local address */
1667 if (!iface->llv6)
1668 return;
1669
1670 struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
1671 if (ic)
1672 babel_add_iface(p, iface, ic);
1673
1674 return;
1675 }
1676
1677 if (!ifa)
1678 return;
1679
1680 if (flags & IF_CHANGE_ADDR4)
1681 babel_iface_update_addr4(ifa);
1682
1683 if (flags & IF_CHANGE_MTU)
1684 babel_iface_update_buffers(ifa);
1685
1686 if (flags & IF_CHANGE_LINK)
1687 babel_iface_update_state(ifa);
1688 }
1689
1690 static int
1691 babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct babel_iface_config *new)
1692 {
1693 struct babel_iface_config *old = ifa->cf;
1694
1695 /* Change of these options would require to reset the iface socket */
1696 if ((new->port != old->port) ||
1697 (new->tx_tos != old->tx_tos) ||
1698 (new->tx_priority != old->tx_priority))
1699 return 0;
1700
1701 TRACE(D_EVENTS, "Reconfiguring interface %s", ifa->iface->name);
1702
1703 ifa->cf = new;
1704
1705 ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
1706 ifa->next_hop_ip4 = ipa_nonzero(new->next_hop_ip4) ? new->next_hop_ip4 : addr4;
1707 ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr;
1708
1709 if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
1710 log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
1711
1712 if (ifa->next_hello > (current_time() + new->hello_interval))
1713 ifa->next_hello = current_time() + (random() % new->hello_interval);
1714
1715 if (ifa->next_regular > (current_time() + new->update_interval))
1716 ifa->next_regular = current_time() + (random() % new->update_interval);
1717
1718 if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
1719 babel_iface_update_buffers(ifa);
1720
1721 if (new->check_link != old->check_link)
1722 babel_iface_update_state(ifa);
1723
1724 if (ifa->up)
1725 babel_iface_kick_timer(ifa);
1726
1727 return 1;
1728 }
1729
1730 static void
1731 babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
1732 {
1733 struct iface *iface;
1734
1735 WALK_LIST(iface, iface_list)
1736 {
1737 if (!(iface->flags & IF_UP))
1738 continue;
1739
1740 /* Ignore non-multicast ifaces */
1741 if (!(iface->flags & IF_MULTICAST))
1742 continue;
1743
1744 /* Ignore ifaces without link-local address */
1745 if (!iface->llv6)
1746 continue;
1747
1748 struct babel_iface *ifa = babel_find_iface(p, iface);
1749 struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
1750
1751 if (ifa && ic)
1752 {
1753 if (babel_reconfigure_iface(p, ifa, ic))
1754 continue;
1755
1756 /* Hard restart */
1757 log(L_INFO "%s: Restarting interface %s", p->p.name, ifa->iface->name);
1758 babel_remove_iface(p, ifa);
1759 babel_add_iface(p, iface, ic);
1760 }
1761
1762 if (ifa && !ic)
1763 babel_remove_iface(p, ifa);
1764
1765 if (!ifa && ic)
1766 babel_add_iface(p, iface, ic);
1767 }
1768 }
1769
1770
1771 /*
1772 * Debugging and info output functions
1773 */
1774
1775 static void
1776 babel_dump_source(struct babel_source *s)
1777 {
1778 debug("Source router_id %lR seqno %d metric %d expires %t\n",
1779 s->router_id, s->seqno, s->metric,
1780 s->expires ? s->expires - current_time() : 0);
1781 }
1782
1783 static void
1784 babel_dump_route(struct babel_route *r)
1785 {
1786 debug("Route neigh %I if %s seqno %d metric %d/%d router_id %lR expires %t\n",
1787 r->neigh->addr, r->neigh->ifa->ifname, r->seqno, r->advert_metric, r->metric,
1788 r->router_id, r->expires ? r->expires - current_time() : 0);
1789 }
1790
1791 static void
1792 babel_dump_entry(struct babel_entry *e)
1793 {
1794 struct babel_source *s;
1795 struct babel_route *r;
1796
1797 debug("Babel: Entry %N:\n", e->n.addr);
1798
1799 WALK_LIST(s,e->sources)
1800 { debug(" "); babel_dump_source(s); }
1801
1802 WALK_LIST(r,e->routes)
1803 {
1804 debug(" ");
1805 if (r == e->selected) debug("*");
1806 babel_dump_route(r);
1807 }
1808 }
1809
1810 static void
1811 babel_dump_neighbor(struct babel_neighbor *n)
1812 {
1813 debug("Neighbor %I txcost %d hello_map %x next seqno %d expires %t/%t\n",
1814 n->addr, n->txcost, n->hello_map, n->next_hello_seqno,
1815 n->hello_expiry ? n->hello_expiry - current_time() : 0,
1816 n->ihu_expiry ? n->ihu_expiry - current_time() : 0);
1817 }
1818
1819 static void
1820 babel_dump_iface(struct babel_iface *ifa)
1821 {
1822 struct babel_neighbor *n;
1823
1824 debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %t %t",
1825 ifa->ifname, ifa->addr, ifa->cf->rxcost, ifa->cf->type, ifa->hello_seqno,
1826 ifa->cf->hello_interval, ifa->cf->update_interval);
1827 debug(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6);
1828
1829 WALK_LIST(n, ifa->neigh_list)
1830 { debug(" "); babel_dump_neighbor(n); }
1831 }
1832
1833 static void
1834 babel_dump(struct proto *P)
1835 {
1836 struct babel_proto *p = (struct babel_proto *) P;
1837 struct babel_iface *ifa;
1838
1839 debug("Babel: router id %lR update seqno %d\n", p->router_id, p->update_seqno);
1840
1841 WALK_LIST(ifa, p->interfaces)
1842 babel_dump_iface(ifa);
1843
1844 FIB_WALK(&p->ip4_rtable, struct babel_entry, e)
1845 {
1846 babel_dump_entry(e);
1847 }
1848 FIB_WALK_END;
1849 FIB_WALK(&p->ip6_rtable, struct babel_entry, e)
1850 {
1851 babel_dump_entry(e);
1852 }
1853 FIB_WALK_END;
1854 }
1855
1856 static void
1857 babel_get_route_info(rte *rte, byte *buf)
1858 {
1859 buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
1860 }
1861
1862 static int
1863 babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
1864 {
1865 switch (a->id)
1866 {
1867 case EA_BABEL_METRIC:
1868 bsprintf(buf, "metric: %d", a->u.data);
1869 return GA_FULL;
1870
1871 case EA_BABEL_ROUTER_ID:
1872 {
1873 u64 rid = 0;
1874 memcpy(&rid, a->u.ptr->data, sizeof(u64));
1875 bsprintf(buf, "router_id: %lR", rid);
1876 return GA_FULL;
1877 }
1878
1879 default:
1880 return GA_UNKNOWN;
1881 }
1882 }
1883
1884 void
1885 babel_show_interfaces(struct proto *P, const char *iff)
1886 {
1887 struct babel_proto *p = (void *) P;
1888 struct babel_iface *ifa = NULL;
1889 struct babel_neighbor *nbr = NULL;
1890
1891 if (p->p.proto_state != PS_UP)
1892 {
1893 cli_msg(-1023, "%s: is not up", p->p.name);
1894 cli_msg(0, "");
1895 return;
1896 }
1897
1898 cli_msg(-1023, "%s:", p->p.name);
1899 cli_msg(-1023, "%-10s %-6s %7s %6s %7s %-15s %s",
1900 "Interface", "State", "RX cost", "Nbrs", "Timer",
1901 "Next hop (v4)", "Next hop (v6)");
1902
1903 WALK_LIST(ifa, p->interfaces)
1904 {
1905 if (iff && !patmatch(iff, ifa->iface->name))
1906 continue;
1907
1908 int nbrs = 0;
1909 WALK_LIST(nbr, ifa->neigh_list)
1910 nbrs++;
1911
1912 btime timer = MIN(ifa->next_regular, ifa->next_hello) - current_time();
1913 cli_msg(-1023, "%-10s %-6s %7u %6u %7t %-15I %I",
1914 ifa->iface->name, (ifa->up ? "Up" : "Down"),
1915 ifa->cf->rxcost, nbrs, MAX(timer, 0),
1916 ifa->next_hop_ip4, ifa->next_hop_ip6);
1917 }
1918
1919 cli_msg(0, "");
1920 }
1921
1922 void
1923 babel_show_neighbors(struct proto *P, const char *iff)
1924 {
1925 struct babel_proto *p = (void *) P;
1926 struct babel_iface *ifa = NULL;
1927 struct babel_neighbor *n = NULL;
1928 struct babel_route *r = NULL;
1929
1930 if (p->p.proto_state != PS_UP)
1931 {
1932 cli_msg(-1024, "%s: is not up", p->p.name);
1933 cli_msg(0, "");
1934 return;
1935 }
1936
1937 cli_msg(-1024, "%s:", p->p.name);
1938 cli_msg(-1024, "%-25s %-10s %6s %6s %6s %7s",
1939 "IP address", "Interface", "Metric", "Routes", "Hellos", "Expires");
1940
1941 WALK_LIST(ifa, p->interfaces)
1942 {
1943 if (iff && !patmatch(iff, ifa->iface->name))
1944 continue;
1945
1946 WALK_LIST(n, ifa->neigh_list)
1947 {
1948 int rts = 0;
1949 WALK_LIST(r, n->routes)
1950 rts++;
1951
1952 uint hellos = u32_popcount(n->hello_map);
1953 btime timer = n->hello_expiry - current_time();
1954 cli_msg(-1024, "%-25I %-10s %6u %6u %6u %7t",
1955 n->addr, ifa->iface->name, n->cost, rts, hellos, MAX(timer, 0));
1956 }
1957 }
1958
1959 cli_msg(0, "");
1960 }
1961
1962 static void
1963 babel_show_entries_(struct babel_proto *p, struct fib *rtable)
1964 {
1965 int width = babel_sadr_enabled(p) ? -54 : -24;
1966
1967 FIB_WALK(rtable, struct babel_entry, e)
1968 {
1969 struct babel_route *r = NULL;
1970 uint rts = 0, srcs = 0;
1971 node *n;
1972
1973 WALK_LIST(n, e->routes)
1974 rts++;
1975
1976 WALK_LIST(n, e->sources)
1977 srcs++;
1978
1979 if (e->valid)
1980 cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
1981 e->n.addr, e->router_id, e->metric, e->seqno, rts, srcs);
1982 else if (r = e->selected)
1983 cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
1984 e->n.addr, r->router_id, r->metric, r->seqno, rts, srcs);
1985 else
1986 cli_msg(-1025, "%-*N %-23s %6s %5s %7u %7u", width,
1987 e->n.addr, "<none>", "-", "-", rts, srcs);
1988 }
1989 FIB_WALK_END;
1990 }
1991
1992 void
1993 babel_show_entries(struct proto *P)
1994 {
1995 struct babel_proto *p = (void *) P;
1996 int width = babel_sadr_enabled(p) ? -54 : -24;
1997
1998 if (p->p.proto_state != PS_UP)
1999 {
2000 cli_msg(-1025, "%s: is not up", p->p.name);
2001 cli_msg(0, "");
2002 return;
2003 }
2004
2005 cli_msg(-1025, "%s:", p->p.name);
2006 cli_msg(-1025, "%-*s %-23s %6s %5s %7s %7s", width,
2007 "Prefix", "Router ID", "Metric", "Seqno", "Routes", "Sources");
2008
2009 babel_show_entries_(p, &p->ip4_rtable);
2010 babel_show_entries_(p, &p->ip6_rtable);
2011
2012 cli_msg(0, "");
2013 }
2014
2015 static void
2016 babel_show_routes_(struct babel_proto *p, struct fib *rtable)
2017 {
2018 int width = babel_sadr_enabled(p) ? -54 : -24;
2019
2020 FIB_WALK(rtable, struct babel_entry, e)
2021 {
2022 struct babel_route *r;
2023 WALK_LIST(r, e->routes)
2024 {
2025 char c = (r == e->selected) ? '*' : (r->feasible ? '+' : ' ');
2026 btime time = r->expires ? r->expires - current_time() : 0;
2027 cli_msg(-1025, "%-*N %-25I %-10s %5u %c %5u %7t", width,
2028 e->n.addr, r->next_hop, r->neigh->ifa->ifname,
2029 r->metric, c, r->seqno, MAX(time, 0));
2030 }
2031 }
2032 FIB_WALK_END;
2033 }
2034
2035 void
2036 babel_show_routes(struct proto *P)
2037 {
2038 struct babel_proto *p = (void *) P;
2039 int width = babel_sadr_enabled(p) ? -54 : -24;
2040
2041 if (p->p.proto_state != PS_UP)
2042 {
2043 cli_msg(-1025, "%s: is not up", p->p.name);
2044 cli_msg(0, "");
2045 return;
2046 }
2047
2048 cli_msg(-1025, "%s:", p->p.name);
2049 cli_msg(-1025, "%-*s %-25s %-9s %6s F %5s %7s", width,
2050 "Prefix", "Nexthop", "Interface", "Metric", "Seqno", "Expires");
2051
2052 babel_show_routes_(p, &p->ip4_rtable);
2053 babel_show_routes_(p, &p->ip6_rtable);
2054
2055 cli_msg(0, "");
2056 }
2057
2058
2059 /*
2060 * Babel protocol glue
2061 */
2062
2063 /**
2064 * babel_timer - global timer hook
2065 * @t: Timer
2066 *
2067 * This function is called by the global protocol instance timer and handles
2068 * expiration of routes and neighbours as well as pruning of the seqno request
2069 * cache.
2070 */
2071 static void
2072 babel_timer(timer *t)
2073 {
2074 struct babel_proto *p = t->data;
2075
2076 babel_expire_routes(p);
2077 babel_expire_neighbors(p);
2078 }
2079
2080 static inline void
2081 babel_kick_timer(struct babel_proto *p)
2082 {
2083 if (p->timer->expires > (current_time() + 100 MS))
2084 tm_start(p->timer, 100 MS);
2085 }
2086
2087
2088 static int
2089 babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
2090 {
2091 struct rta *a = (*new)->attrs;
2092
2093 /* Reject our own unreachable routes */
2094 if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
2095 return -1;
2096
2097 return 0;
2098 }
2099
2100 static void
2101 babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
2102 {
2103 struct adata *id = lp_alloc_adata(pool, sizeof(u64));
2104 memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
2105
2106 rte_init_tmp_attrs(rt, pool, 2);
2107 rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
2108 rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
2109 }
2110
2111 static void
2112 babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
2113 {
2114 rte_init_tmp_attrs(rt, pool, 2);
2115 rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
2116
2117 /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
2118 rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
2119 }
2120
2121 /*
2122 * babel_rt_notify - core tells us about new route (possibly our own),
2123 * so store it into our data structures.
2124 */
2125 static void
2126 babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
2127 struct rte *new, struct rte *old UNUSED)
2128 {
2129 struct babel_proto *p = (void *) P;
2130 struct babel_entry *e;
2131
2132 if (new)
2133 {
2134 /* Update */
2135 uint internal = (new->attrs->src->proto == P);
2136 uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
2137 uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
2138 u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
2139
2140 if (rt_metric > BABEL_INFINITY)
2141 {
2142 log(L_WARN "%s: Invalid babel_metric value %u for route %N",
2143 p->p.name, rt_metric, net->n.addr);
2144 rt_metric = BABEL_INFINITY;
2145 }
2146
2147 e = babel_get_entry(p, net->n.addr);
2148
2149 /* Activate triggered updates */
2150 if ((e->valid != BABEL_ENTRY_VALID) ||
2151 (e->router_id != rt_router_id))
2152 {
2153 babel_trigger_update(p);
2154 e->updated = current_time();
2155 }
2156
2157 e->valid = BABEL_ENTRY_VALID;
2158 e->seqno = rt_seqno;
2159 e->metric = rt_metric;
2160 e->router_id = rt_router_id;
2161 }
2162 else
2163 {
2164 /* Withdraw */
2165 e = babel_find_entry(p, net->n.addr);
2166
2167 if (!e || e->valid != BABEL_ENTRY_VALID)
2168 return;
2169
2170 e->valid = BABEL_ENTRY_STALE;
2171 e->metric = BABEL_INFINITY;
2172
2173 babel_trigger_update(p);
2174 e->updated = current_time();
2175 }
2176 }
2177
2178 static int
2179 babel_rte_better(struct rte *new, struct rte *old)
2180 {
2181 return new->u.babel.metric < old->u.babel.metric;
2182 }
2183
2184 static int
2185 babel_rte_same(struct rte *new, struct rte *old)
2186 {
2187 return ((new->u.babel.seqno == old->u.babel.seqno) &&
2188 (new->u.babel.metric == old->u.babel.metric) &&
2189 (new->u.babel.router_id == old->u.babel.router_id));
2190 }
2191
2192
2193 static void
2194 babel_postconfig(struct proto_config *CF)
2195 {
2196 struct babel_config *cf = (void *) CF;
2197 struct channel_config *ip4, *ip6, *ip6_sadr;
2198
2199 ip4 = proto_cf_find_channel(CF, NET_IP4);
2200 ip6 = proto_cf_find_channel(CF, NET_IP6);
2201 ip6_sadr = proto_cf_find_channel(CF, NET_IP6_SADR);
2202
2203 if (ip6 && ip6_sadr)
2204 cf_error("Both ipv6 and ipv6-sadr channels");
2205
2206 cf->ip4_channel = ip4;
2207 cf->ip6_channel = ip6 ?: ip6_sadr;
2208 }
2209
2210 static struct proto *
2211 babel_init(struct proto_config *CF)
2212 {
2213 struct proto *P = proto_new(CF);
2214 struct babel_proto *p = (void *) P;
2215 struct babel_config *cf = (void *) CF;
2216
2217 proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
2218 proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
2219
2220 P->if_notify = babel_if_notify;
2221 P->rt_notify = babel_rt_notify;
2222 P->preexport = babel_preexport;
2223 P->make_tmp_attrs = babel_make_tmp_attrs;
2224 P->store_tmp_attrs = babel_store_tmp_attrs;
2225 P->rte_better = babel_rte_better;
2226 P->rte_same = babel_rte_same;
2227
2228 return P;
2229 }
2230
2231 static inline void
2232 babel_randomize_router_id(struct babel_proto *p)
2233 {
2234 p->router_id &= (u64) 0xffffffff;
2235 p->router_id |= ((u64) random()) << 32;
2236 TRACE(D_EVENTS, "Randomized router ID to %lR", p->router_id);
2237 }
2238
2239 static int
2240 babel_start(struct proto *P)
2241 {
2242 struct babel_proto *p = (void *) P;
2243 struct babel_config *cf = (void *) P->cf;
2244 u8 ip6_type = cf->ip6_channel ? cf->ip6_channel->net_type : NET_IP6;
2245
2246 fib_init(&p->ip4_rtable, P->pool, NET_IP4, sizeof(struct babel_entry),
2247 OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
2248 fib_init(&p->ip6_rtable, P->pool, ip6_type, sizeof(struct babel_entry),
2249 OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
2250
2251 init_list(&p->interfaces);
2252 p->timer = tm_new_init(P->pool, babel_timer, p, 1 S, 0);
2253 tm_start(p->timer, 1 S);
2254 p->update_seqno = 1;
2255 p->router_id = proto_get_router_id(&cf->c);
2256
2257 if (cf->randomize_router_id)
2258 babel_randomize_router_id(p);
2259
2260 p->route_slab = sl_new(P->pool, sizeof(struct babel_route));
2261 p->source_slab = sl_new(P->pool, sizeof(struct babel_source));
2262 p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node));
2263 p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request));
2264
2265 p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
2266
2267 return PS_UP;
2268 }
2269
2270 static inline void
2271 babel_iface_shutdown(struct babel_iface *ifa)
2272 {
2273 if (ifa->sk)
2274 {
2275 babel_send_wildcard_retraction(ifa);
2276 babel_send_queue(ifa);
2277 }
2278 }
2279
2280 static int
2281 babel_shutdown(struct proto *P)
2282 {
2283 struct babel_proto *p = (void *) P;
2284 struct babel_iface *ifa;
2285
2286 TRACE(D_EVENTS, "Shutdown requested");
2287
2288 WALK_LIST(ifa, p->interfaces)
2289 babel_iface_shutdown(ifa);
2290
2291 return PS_DOWN;
2292 }
2293
2294 static int
2295 babel_reconfigure(struct proto *P, struct proto_config *CF)
2296 {
2297 struct babel_proto *p = (void *) P;
2298 struct babel_config *new = (void *) CF;
2299 u8 ip6_type = new->ip6_channel ? new->ip6_channel->net_type : NET_IP6;
2300
2301 TRACE(D_EVENTS, "Reconfiguring");
2302
2303 if (p->ip6_rtable.addr_type != ip6_type)
2304 return 0;
2305
2306 if (!proto_configure_channel(P, &p->ip4_channel, new->ip4_channel) ||
2307 !proto_configure_channel(P, &p->ip6_channel, new->ip6_channel))
2308 return 0;
2309
2310 p->p.cf = CF;
2311 babel_reconfigure_ifaces(p, new);
2312
2313 babel_trigger_update(p);
2314 babel_kick_timer(p);
2315
2316 return 1;
2317 }
2318
2319
2320 struct protocol proto_babel = {
2321 .name = "Babel",
2322 .template = "babel%d",
2323 .class = PROTOCOL_BABEL,
2324 .preference = DEF_PREF_BABEL,
2325 .channel_mask = NB_IP | NB_IP6_SADR,
2326 .proto_size = sizeof(struct babel_proto),
2327 .config_size = sizeof(struct babel_config),
2328 .postconfig = babel_postconfig,
2329 .init = babel_init,
2330 .dump = babel_dump,
2331 .start = babel_start,
2332 .shutdown = babel_shutdown,
2333 .reconfigure = babel_reconfigure,
2334 .get_route_info = babel_get_route_info,
2335 .get_attr = babel_get_attr
2336 };