2 * BIRD -- The Babel protocol
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.
8 * Can be freely distributed and used under the terms of the GNU GPL.
10 * This file contains the main routines for handling and sending TLVs, as
11 * well as timers and interaction with the nest.
15 * DOC: The Babel protocol
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
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.
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.
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.
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.
47 static inline int ge_mod64k(uint a
, uint b
)
48 { return (u16
)(a
- b
) < 0x8000; }
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
);
59 static inline void babel_lock_neighbor(struct babel_neighbor
*nbr
)
60 { if (nbr
) nbr
->uc
++; }
62 static inline void babel_unlock_neighbor(struct babel_neighbor
*nbr
)
63 { if (nbr
&& !--nbr
->uc
) mb_free(nbr
); }
67 * Functions to maintain data structures
71 babel_init_entry(void *E
)
73 struct babel_entry
*e
= E
;
75 e
->updated
= current_time();
76 init_list(&e
->requests
);
77 init_list(&e
->sources
);
78 init_list(&e
->routes
);
81 static inline struct babel_entry
*
82 babel_find_entry(struct babel_proto
*p
, const net_addr
*n
)
84 struct fib
*rtable
= (n
->type
== NET_IP4
) ? &p
->ip4_rtable
: &p
->ip6_rtable
;
85 return fib_find(rtable
, n
);
88 static struct babel_entry
*
89 babel_get_entry(struct babel_proto
*p
, const net_addr
*n
)
91 struct fib
*rtable
= (n
->type
== NET_IP4
) ? &p
->ip4_rtable
: &p
->ip6_rtable
;
92 struct babel_entry
*e
= fib_get(rtable
, n
);
96 static struct babel_source
*
97 babel_find_source(struct babel_entry
*e
, u64 router_id
)
99 struct babel_source
*s
;
101 WALK_LIST(s
, e
->sources
)
102 if (s
->router_id
== router_id
)
108 static struct babel_source
*
109 babel_get_source(struct babel_proto
*p
, struct babel_entry
*e
, u64 router_id
)
111 struct babel_source
*s
= babel_find_source(e
, router_id
);
116 s
= sl_alloc(p
->source_slab
);
117 s
->router_id
= router_id
;
118 s
->expires
= current_time() + BABEL_GARBAGE_INTERVAL
;
120 s
->metric
= BABEL_INFINITY
;
121 add_tail(&e
->sources
, NODE s
);
127 babel_expire_sources(struct babel_proto
*p
, struct babel_entry
*e
)
129 struct babel_source
*n
, *nx
;
130 btime now_
= current_time();
132 WALK_LIST_DELSAFE(n
, nx
, e
->sources
)
134 if (n
->expires
&& n
->expires
<= now_
)
137 sl_free(p
->source_slab
, n
);
142 static struct babel_route
*
143 babel_find_route(struct babel_entry
*e
, struct babel_neighbor
*n
)
145 struct babel_route
*r
;
147 WALK_LIST(r
, e
->routes
)
154 static struct babel_route
*
155 babel_get_route(struct babel_proto
*p
, struct babel_entry
*e
, struct babel_neighbor
*nbr
)
157 struct babel_route
*r
= babel_find_route(e
, nbr
);
162 r
= sl_alloc(p
->route_slab
);
163 memset(r
, 0, sizeof(*r
));
167 add_tail(&e
->routes
, NODE r
);
168 add_tail(&nbr
->routes
, NODE
&r
->neigh_route
);
174 babel_retract_route(struct babel_proto
*p
, struct babel_route
*r
)
176 r
->metric
= r
->advert_metric
= BABEL_INFINITY
;
178 if (r
== r
->e
->selected
)
179 babel_select_route(p
, r
->e
, r
);
183 babel_flush_route(struct babel_proto
*p
, struct babel_route
*r
)
185 DBG("Babel: Flush route %N router_id %lR neigh %I\n",
186 r
->e
->n
.addr
, r
->router_id
, r
->neigh
->addr
);
189 rem_node(&r
->neigh_route
);
191 if (r
->e
->selected
== r
)
192 r
->e
->selected
= NULL
;
194 sl_free(p
->route_slab
, r
);
198 babel_expire_route(struct babel_proto
*p
, struct babel_route
*r
)
200 struct babel_config
*cf
= (void *) p
->p
.cf
;
202 TRACE(D_EVENTS
, "Route expiry timer for %N router-id %lR fired",
203 r
->e
->n
.addr
, r
->router_id
);
205 if (r
->metric
< BABEL_INFINITY
)
207 r
->metric
= r
->advert_metric
= BABEL_INFINITY
;
208 r
->expires
= current_time() + cf
->hold_time
;
212 babel_flush_route(p
, r
);
217 babel_refresh_route(struct babel_proto
*p
, struct babel_route
*r
)
219 if (r
== r
->e
->selected
)
220 babel_send_route_request(p
, r
->e
, r
->neigh
);
226 babel_expire_routes_(struct babel_proto
*p
, struct fib
*rtable
)
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();
233 FIB_ITERATE_INIT(&fit
, rtable
);
236 FIB_ITERATE_START(rtable
, &fit
, struct babel_entry
, e
)
240 WALK_LIST_DELSAFE(r
, rx
, e
->routes
)
242 if (r
->refresh_time
&& r
->refresh_time
<= now_
)
243 babel_refresh_route(p
, r
);
245 if (r
->expires
&& r
->expires
<= now_
)
247 changed
= changed
|| (r
== e
->selected
);
248 babel_expire_route(p
, r
);
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.
259 FIB_ITERATE_PUT(&fit
);
260 babel_select_route(p
, e
, NULL
);
264 /* Clean up stale entries */
265 if ((e
->valid
== BABEL_ENTRY_STALE
) && ((e
->updated
+ cf
->hold_time
) <= now_
))
266 e
->valid
= BABEL_ENTRY_DUMMY
;
268 /* Clean up unreachable route */
269 if (e
->unreachable
&& (!e
->valid
|| (e
->router_id
== p
->router_id
)))
271 FIB_ITERATE_PUT(&fit
);
272 babel_announce_retraction(p
, e
);
276 babel_expire_sources(p
, e
);
277 babel_expire_requests(p
, e
);
279 /* Remove empty entries */
280 if (!e
->valid
&& EMPTY_LIST(e
->routes
) && EMPTY_LIST(e
->sources
) && EMPTY_LIST(e
->requests
))
282 FIB_ITERATE_PUT(&fit
);
283 fib_delete(rtable
, e
);
291 babel_expire_routes(struct babel_proto
*p
)
293 babel_expire_routes_(p
, &p
->ip4_rtable
);
294 babel_expire_routes_(p
, &p
->ip6_rtable
);
297 static inline int seqno_request_valid(struct babel_seqno_request
*sr
)
298 { return !sr
->nbr
|| sr
->nbr
->ifa
; }
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.
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
)
310 struct babel_seqno_request
*sr
;
312 WALK_LIST(sr
, e
->requests
)
313 if (sr
->router_id
== router_id
)
315 /* Found matching or newer */
316 if (ge_mod64k(sr
->seqno
, seqno
) && seqno_request_valid(sr
))
320 babel_unlock_neighbor(sr
->nbr
);
325 /* No entries found */
326 sr
= sl_alloc(p
->seqno_slab
);
329 sr
->router_id
= router_id
;
331 sr
->hop_count
= hop_count
;
333 sr
->expires
= current_time() + BABEL_SEQNO_REQUEST_EXPIRY
;
334 babel_lock_neighbor(sr
->nbr
= nbr
);
335 add_tail(&e
->requests
, NODE sr
);
337 babel_send_seqno_request(p
, e
, sr
);
341 babel_remove_seqno_request(struct babel_proto
*p
, struct babel_seqno_request
*sr
)
343 babel_unlock_neighbor(sr
->nbr
);
345 sl_free(p
->seqno_slab
, sr
);
349 babel_satisfy_seqno_request(struct babel_proto
*p
, struct babel_entry
*e
,
350 u64 router_id
, u16 seqno
)
352 struct babel_seqno_request
*sr
;
354 WALK_LIST(sr
, e
->requests
)
355 if ((sr
->router_id
== router_id
) && ge_mod64k(seqno
, sr
->seqno
))
357 /* Found the request, remove it */
358 babel_remove_seqno_request(p
, sr
);
366 babel_expire_requests(struct babel_proto
*p
, struct babel_entry
*e
)
368 struct babel_seqno_request
*sr
, *srx
;
369 btime now_
= current_time();
371 WALK_LIST_DELSAFE(sr
, srx
, e
->requests
)
373 /* Remove seqno requests sent to dead neighbors */
374 if (!seqno_request_valid(sr
))
376 babel_remove_seqno_request(p
, sr
);
380 /* Handle expired requests - resend or remove */
381 if (sr
->expires
&& sr
->expires
<= now_
)
383 if (sr
->count
< BABEL_SEQNO_REQUEST_RETRY
)
386 sr
->expires
+= (BABEL_SEQNO_REQUEST_EXPIRY
<< sr
->count
);
387 babel_send_seqno_request(p
, e
, sr
);
391 TRACE(D_EVENTS
, "Seqno request for %N router-id %lR expired",
392 e
->n
.addr
, sr
->router_id
);
394 babel_remove_seqno_request(p
, sr
);
401 static struct babel_neighbor
*
402 babel_find_neighbor(struct babel_iface
*ifa
, ip_addr addr
)
404 struct babel_neighbor
*nbr
;
406 WALK_LIST(nbr
, ifa
->neigh_list
)
407 if (ipa_equal(nbr
->addr
, addr
))
413 static struct babel_neighbor
*
414 babel_get_neighbor(struct babel_iface
*ifa
, ip_addr addr
)
416 struct babel_proto
*p
= ifa
->proto
;
417 struct babel_neighbor
*nbr
= babel_find_neighbor(ifa
, addr
);
422 TRACE(D_EVENTS
, "New neighbor %I on %s", addr
, ifa
->iface
->name
);
424 nbr
= mb_allocz(ifa
->pool
, sizeof(struct babel_neighbor
));
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
);
438 babel_flush_neighbor(struct babel_proto
*p
, struct babel_neighbor
*nbr
)
440 struct babel_route
*r
;
443 TRACE(D_EVENTS
, "Removing neighbor %I on %s", nbr
->addr
, nbr
->ifa
->iface
->name
);
445 WALK_LIST_FIRST(n
, nbr
->routes
)
447 r
= SKIP_BACK(struct babel_route
, neigh_route
, n
);
448 babel_retract_route(p
, r
);
449 babel_flush_route(p
, r
);
454 babel_unlock_neighbor(nbr
);
458 babel_expire_ihu(struct babel_proto
*p
, struct babel_neighbor
*nbr
)
460 TRACE(D_EVENTS
, "IHU from nbr %I on %s expired", nbr
->addr
, nbr
->ifa
->iface
->name
);
462 nbr
->txcost
= BABEL_INFINITY
;
464 babel_update_cost(nbr
);
468 babel_expire_hello(struct babel_proto
*p
, struct babel_neighbor
*nbr
, btime now_
)
471 nbr
->hello_map
<<= 1;
473 if (nbr
->hello_cnt
< 16)
476 nbr
->hello_expiry
+= nbr
->last_hello_int
;
478 /* We may expire multiple hellos if last_hello_int is too short */
479 if (nbr
->hello_map
&& nbr
->hello_expiry
<= now_
)
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
));
486 babel_update_cost(nbr
);
488 babel_flush_neighbor(p
, nbr
);
492 babel_expire_neighbors(struct babel_proto
*p
)
494 struct babel_iface
*ifa
;
495 struct babel_neighbor
*nbr
, *nbx
;
496 btime now_
= current_time();
498 WALK_LIST(ifa
, p
->interfaces
)
500 WALK_LIST_DELSAFE(nbr
, nbx
, ifa
->neigh_list
)
502 if (nbr
->ihu_expiry
&& nbr
->ihu_expiry
<= now_
)
503 babel_expire_ihu(p
, nbr
);
505 if (nbr
->hello_expiry
&& nbr
->hello_expiry
<= now_
)
506 babel_expire_hello(p
, nbr
, now_
);
513 * Best route selection
517 * From the RFC (section 3.5.1):
519 * a route advertisement carrying the quintuple (prefix, plen, router-id, seqno,
520 * metric) is feasible if one of the following conditions holds:
522 * - metric is infinite; or
524 * - no entry exists in the source table indexed by (id, prefix, plen); or
526 * - an entry (prefix, plen, router-id, seqno', metric') exists in the source
528 * - seqno' < seqno or
529 * - seqno = seqno' and metric < metric'.
532 babel_is_feasible(struct babel_source
*s
, u16 seqno
, u16 metric
)
535 (metric
== BABEL_INFINITY
) ||
536 (seqno
> s
->seqno
) ||
537 ((seqno
== s
->seqno
) && (metric
< s
->metric
));
540 /* Simple additive metric - Appendix 3.1 in the RFC */
542 babel_compute_metric(struct babel_neighbor
*n
, uint metric
)
544 return MIN(metric
+ n
->cost
, BABEL_INFINITY
);
548 babel_update_cost(struct babel_neighbor
*nbr
)
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 */
557 if (!rcv
|| !nbr
->ifa
->up
)
562 case BABEL_IFACE_TYPE_WIRED
:
563 /* k-out-of-j selection - Appendix 2.1 in the RFC. */
565 /* Link is bad if less than cf->limit/16 of expected hellos were received */
566 if (rcv
* 16 < cf
->limit
* max
)
570 txcost
= nbr
->txcost
;
573 case BABEL_IFACE_TYPE_WIRELESS
:
575 * ETX - Appendix 2.2 in the RFC.
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
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.
586 rxcost
= MIN( cf
->rxcost
* max
/ rcv
, BABEL_INFINITY
);
587 txcost
= MIN(nbr
->txcost
* max
/ rcv
, BABEL_INFINITY
);
592 /* If RX cost changed, send IHU with next Hello */
593 if (rxcost
!= nbr
->rxcost
)
595 nbr
->rxcost
= rxcost
;
599 /* If link cost changed, run route selection */
600 if (txcost
!= nbr
->cost
)
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
);
607 struct babel_route
*r
; node
*n
;
608 WALK_LIST2(r
, n
, nbr
->routes
, neigh_route
)
610 r
->metric
= babel_compute_metric(nbr
, r
->advert_metric
);
611 babel_select_route(p
, r
->e
, r
);
617 * babel_announce_rte - announce selected route to the core
618 * @p: Babel protocol instance
619 * @e: Babel route entry to announce
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.
626 babel_announce_rte(struct babel_proto
*p
, struct babel_entry
*e
)
628 struct babel_route
*r
= e
->selected
;
629 struct channel
*c
= (e
->n
.addr
->type
== NET_IP4
) ? p
->ip4_channel
: p
->ip6_channel
;
634 .src
= p
->p
.main_source
,
636 .scope
= SCOPE_UNIVERSE
,
638 .from
= r
->neigh
->addr
,
639 .nh
.gw
= r
->next_hop
,
640 .nh
.iface
= r
->neigh
->ifa
->iface
,
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
648 if (!neigh_find(&p
->p
, r
->next_hop
, r
->neigh
->ifa
->iface
, 0))
649 a0
.nh
.flags
= RNF_ONLINK
;
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
);
659 rte_update2(c
, e
->n
.addr
, rte
, p
->p
.main_source
);
661 else if (e
->valid
&& (e
->router_id
!= p
->router_id
))
665 .src
= p
->p
.main_source
,
667 .scope
= SCOPE_UNIVERSE
,
668 .dest
= RTD_UNREACHABLE
,
671 rta
*a
= rta_lookup(&a0
);
672 rte
*rte
= rte_get_temp(a
);
673 memset(&rte
->u
.babel
, 0, sizeof(rte
->u
.babel
));
678 rte_update2(c
, e
->n
.addr
, rte
, p
->p
.main_source
);
684 rte_update2(c
, e
->n
.addr
, NULL
, p
->p
.main_source
);
688 /* Special case of babel_announce_rte() just for retraction */
690 babel_announce_retraction(struct babel_proto
*p
, struct babel_entry
*e
)
692 struct channel
*c
= (e
->n
.addr
->type
== NET_IP4
) ? p
->ip4_channel
: p
->ip6_channel
;
694 rte_update2(c
, e
->n
.addr
, NULL
, p
->p
.main_source
);
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
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.
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.
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.
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.
727 babel_select_route(struct babel_proto
*p
, struct babel_entry
*e
, struct babel_route
*mod
)
729 struct babel_route
*r
, *best
= e
->selected
;
731 /* Shortcut if only non-best was modified */
732 if (mod
&& (mod
!= best
))
734 /* Either select modified route, or keep old best route */
735 if ((mod
->metric
< (best
? best
->metric
: BABEL_INFINITY
)) && mod
->feasible
)
742 /* Selected route may be modified and no longer admissible */
743 if (!best
|| (best
->metric
== BABEL_INFINITY
) || !best
->feasible
)
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
)
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
);
758 else if (e
->selected
)
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().
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
);
774 babel_announce_rte(p
, e
);
778 * Functions to send replies
782 babel_send_ack(struct babel_iface
*ifa
, ip_addr dest
, u16 nonce
)
784 struct babel_proto
*p
= ifa
->proto
;
785 union babel_msg msg
= {};
787 TRACE(D_PACKETS
, "Sending ACK to %I with nonce %d", dest
, nonce
);
789 msg
.type
= BABEL_TLV_ACK
;
790 msg
.ack
.nonce
= nonce
;
792 babel_send_unicast(&msg
, ifa
, dest
);
796 babel_build_ihu(union babel_msg
*msg
, struct babel_iface
*ifa
, struct babel_neighbor
*n
)
798 struct babel_proto
*p
= ifa
->proto
;
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
;
805 TRACE(D_PACKETS
, "Sending IHU for %I with rxcost %d interval %t",
806 msg
->ihu
.addr
, msg
->ihu
.rxcost
, (btime
) msg
->ihu
.interval
);
810 babel_send_ihu(struct babel_iface
*ifa
, struct babel_neighbor
*n
)
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
;
819 babel_send_ihus(struct babel_iface
*ifa
)
821 struct babel_neighbor
*n
;
822 WALK_LIST(n
, ifa
->neigh_list
)
824 if (n
->hello_cnt
&& (--n
->ihu_cnt
<= 0))
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
;
835 babel_send_hello(struct babel_iface
*ifa
)
837 struct babel_proto
*p
= ifa
->proto
;
838 union babel_msg msg
= {};
840 msg
.type
= BABEL_TLV_HELLO
;
841 msg
.hello
.seqno
= ifa
->hello_seqno
++;
842 msg
.hello
.interval
= ifa
->cf
->hello_interval
;
844 TRACE(D_PACKETS
, "Sending hello on %s with seqno %d interval %t",
845 ifa
->ifname
, msg
.hello
.seqno
, (btime
) msg
.hello
.interval
);
847 babel_enqueue(&msg
, ifa
);
849 babel_send_ihus(ifa
);
853 babel_send_route_request(struct babel_proto
*p
, struct babel_entry
*e
, struct babel_neighbor
*n
)
855 union babel_msg msg
= {};
857 TRACE(D_PACKETS
, "Sending route request for %N to %I", e
->n
.addr
, n
->addr
);
859 msg
.type
= BABEL_TLV_ROUTE_REQUEST
;
860 net_copy(&msg
.route_request
.net
, e
->n
.addr
);
862 babel_send_unicast(&msg
, n
->ifa
, n
->addr
);
866 babel_send_wildcard_request(struct babel_iface
*ifa
)
868 struct babel_proto
*p
= ifa
->proto
;
869 union babel_msg msg
= {};
871 TRACE(D_PACKETS
, "Sending wildcard route request on %s", ifa
->ifname
);
873 msg
.type
= BABEL_TLV_ROUTE_REQUEST
;
874 msg
.route_request
.full
= 1;
876 babel_enqueue(&msg
, ifa
);
880 babel_send_seqno_request(struct babel_proto
*p
, struct babel_entry
*e
, struct babel_seqno_request
*sr
)
882 union babel_msg msg
= {};
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
);
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
);
895 babel_send_unicast(&msg
, sr
->nbr
->ifa
, sr
->nbr
->addr
);
899 TRACE(D_PACKETS
, "Sending broadcast seqno request for %N router-id %lR seqno %d",
900 e
->n
.addr
, sr
->router_id
, sr
->seqno
);
902 struct babel_iface
*ifa
;
903 WALK_LIST(ifa
, p
->interfaces
)
904 babel_enqueue(&msg
, ifa
);
909 * babel_send_update - send route table updates
910 * @ifa: Interface to transmit on
911 * @changed: Only send entries changed since this time
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.
919 babel_send_update_(struct babel_iface
*ifa
, btime changed
, struct fib
*rtable
)
921 struct babel_proto
*p
= ifa
->proto
;
923 /* Update increase was requested */
924 if (p
->update_seqno_inc
)
927 p
->update_seqno_inc
= 0;
930 FIB_WALK(rtable
, struct babel_entry
, e
)
935 /* Our own seqno might have changed, in which case we update the routes we
937 if ((e
->router_id
== p
->router_id
) && (e
->seqno
< p
->update_seqno
))
939 e
->seqno
= p
->update_seqno
;
940 e
->updated
= current_time();
943 /* Skip routes that weren't updated since 'changed' time */
944 if (e
->updated
< changed
)
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
);
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
);
958 msg
.update
.next_hop
= ((e
->n
.addr
->type
== NET_IP4
) ?
959 ifa
->next_hop_ip4
: ifa
->next_hop_ip6
);
961 /* Do not send route if next hop is unknown, e.g. no configured IPv4 address */
962 if (ipa_zero(msg
.update
.next_hop
))
965 babel_enqueue(&msg
, ifa
);
967 /* Update feasibility distance for redistributed routes */
968 if (e
->router_id
!= p
->router_id
)
970 struct babel_source
*s
= babel_get_source(p
, e
, e
->router_id
);
971 s
->expires
= current_time() + BABEL_GARBAGE_INTERVAL
;
973 if ((msg
.update
.seqno
> s
->seqno
) ||
974 ((msg
.update
.seqno
== s
->seqno
) && (msg
.update
.metric
< s
->metric
)))
976 s
->seqno
= msg
.update
.seqno
;
977 s
->metric
= msg
.update
.metric
;
985 babel_send_update(struct babel_iface
*ifa
, btime changed
)
987 struct babel_proto
*p
= ifa
->proto
;
989 babel_send_update_(ifa
, changed
, &p
->ip4_rtable
);
990 babel_send_update_(ifa
, changed
, &p
->ip6_rtable
);
994 babel_trigger_iface_update(struct babel_iface
*ifa
)
996 struct babel_proto
*p
= ifa
->proto
;
998 /* Interface not active or already scheduled */
999 if (!ifa
->up
|| ifa
->want_triggered
)
1002 TRACE(D_EVENTS
, "Scheduling triggered updates for %s seqno %d",
1003 ifa
->iface
->name
, p
->update_seqno
);
1005 ifa
->want_triggered
= current_time();
1006 babel_iface_kick_timer(ifa
);
1009 /* Sends and update on all interfaces. */
1011 babel_trigger_update(struct babel_proto
*p
)
1016 struct babel_iface
*ifa
;
1017 WALK_LIST(ifa
, p
->interfaces
)
1018 babel_trigger_iface_update(ifa
);
1023 /* A retraction is an update with an infinite metric */
1025 babel_send_retraction(struct babel_iface
*ifa
, net_addr
*n
)
1027 struct babel_proto
*p
= ifa
->proto
;
1028 union babel_msg msg
= {};
1030 TRACE(D_PACKETS
, "Sending retraction for %N seqno %d", n
, p
->update_seqno
);
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
;
1038 babel_enqueue(&msg
, ifa
);
1042 babel_send_wildcard_retraction(struct babel_iface
*ifa
)
1044 struct babel_proto
*p
= ifa
->proto
;
1045 union babel_msg msg
= {};
1047 TRACE(D_PACKETS
, "Sending wildcard retraction on %s", ifa
->ifname
);
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
;
1055 babel_enqueue(&msg
, ifa
);
1060 * TLV handler helpers
1063 /* Update hello history according to Appendix A1 of the RFC */
1065 babel_update_hello_history(struct babel_neighbor
*n
, u16 seqno
, uint interval
)
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.
1074 u16 delta
= ((uint
) seqno
- (uint
) n
->next_hello_seqno
);
1076 if ((delta
== 0) || (n
->hello_cnt
== 0))
1080 else if (delta
<= 16)
1082 /* Sending node decreased interval; fast-forward */
1083 n
->hello_map
<<= delta
;
1084 n
->hello_cnt
= MIN(n
->hello_cnt
+ delta
, 16);
1086 else if (delta
>= 0xfff0)
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;
1095 /* Note state reset - flush entries */
1096 n
->hello_map
= n
->hello_cnt
= 0;
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
++;
1104 /* Update expiration */
1105 n
->hello_expiry
= current_time() + BABEL_HELLO_EXPIRY_FACTOR(interval
);
1106 n
->last_hello_int
= interval
;
1115 babel_handle_ack_req(union babel_msg
*m
, struct babel_iface
*ifa
)
1117 struct babel_proto
*p
= ifa
->proto
;
1118 struct babel_msg_ack_req
*msg
= &m
->ack_req
;
1120 TRACE(D_PACKETS
, "Handling ACK request nonce %d interval %t",
1121 msg
->nonce
, (btime
) msg
->interval
);
1123 babel_send_ack(ifa
, msg
->sender
, msg
->nonce
);
1127 babel_handle_hello(union babel_msg
*m
, struct babel_iface
*ifa
)
1129 struct babel_proto
*p
= ifa
->proto
;
1130 struct babel_msg_hello
*msg
= &m
->hello
;
1132 TRACE(D_PACKETS
, "Handling hello seqno %d interval %t",
1133 msg
->seqno
, (btime
) msg
->interval
);
1135 struct babel_neighbor
*n
= babel_get_neighbor(ifa
, msg
->sender
);
1136 int first_hello
= !n
->hello_cnt
;
1138 babel_update_hello_history(n
, msg
->seqno
, msg
->interval
);
1139 babel_update_cost(n
);
1141 /* Speed up session establishment by sending IHU immediately */
1143 babel_send_ihu(ifa
, n
);
1147 babel_handle_ihu(union babel_msg
*m
, struct babel_iface
*ifa
)
1149 struct babel_proto
*p
= ifa
->proto
;
1150 struct babel_msg_ihu
*msg
= &m
->ihu
;
1152 /* Ignore IHUs that are not about us */
1153 if ((msg
->ae
!= BABEL_AE_WILDCARD
) && !ipa_equal(msg
->addr
, ifa
->addr
))
1156 TRACE(D_PACKETS
, "Handling IHU rxcost %d interval %t",
1157 msg
->rxcost
, (btime
) msg
->interval
);
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
);
1166 * babel_handle_update - handle incoming route updates
1167 * @m: Incoming update TLV
1168 * @ifa: Interface the update was received on
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.
1177 babel_handle_update(union babel_msg
*m
, struct babel_iface
*ifa
)
1179 struct babel_proto
*p
= ifa
->proto
;
1180 struct babel_msg_update
*msg
= &m
->update
;
1182 struct babel_neighbor
*nbr
;
1183 struct babel_entry
*e
;
1184 struct babel_source
*s
;
1185 struct babel_route
*r
, *best
;
1187 int feasible
, metric
;
1190 TRACE(D_PACKETS
, "Handling wildcard retraction", msg
->seqno
);
1192 TRACE(D_PACKETS
, "Handling update for %N with seqno %d metric %d",
1193 &msg
->net
, msg
->seqno
, msg
->metric
);
1195 nbr
= babel_find_neighbor(ifa
, msg
->sender
);
1198 DBG("Babel: Haven't heard from neighbor %I; ignoring update.\n", msg
->sender
);
1202 if (msg
->router_id
== p
->router_id
)
1204 DBG("Babel: Ignoring update for our own router ID.\n");
1208 struct channel
*c
= (msg
->net
.type
== NET_IP4
) ? p
->ip4_channel
: p
->ip6_channel
;
1209 if (!c
|| (c
->channel_state
!= CS_UP
))
1211 DBG("Babel: Ignoring update for inactive address family.\n");
1216 if (msg
->metric
== BABEL_INFINITY
)
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).
1224 WALK_LIST(n
, nbr
->routes
)
1226 r
= SKIP_BACK(struct babel_route
, neigh_route
, n
);
1227 babel_retract_route(p
, r
);
1232 e
= babel_find_entry(p
, &msg
->net
);
1237 /* The route entry indexed by neighbour */
1238 r
= babel_find_route(e
, nbr
);
1243 /* Router-id, next-hop and seqno are ignored for retractions */
1244 babel_retract_route(p
, r
);
1247 /* Done with retractions */
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
);
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
);
1264 /* Special case - ignore unfeasible update to best route */
1265 if (r
== best
&& !feasible
&& (msg
->router_id
== r
->router_id
))
1268 r
->expires
= current_time() + BABEL_ROUTE_EXPIRY_FACTOR(msg
->interval
);
1269 r
->refresh_time
= current_time() + BABEL_ROUTE_REFRESH_FACTOR(msg
->interval
);
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
))
1277 /* Last paragraph above - update the entry */
1278 r
->feasible
= feasible
;
1279 r
->seqno
= msg
->seqno
;
1281 r
->advert_metric
= msg
->metric
;
1282 r
->router_id
= msg
->router_id
;
1283 r
->next_hop
= msg
->next_hop
;
1285 /* If received update satisfies seqno request, we send triggered updates */
1286 if (babel_satisfy_seqno_request(p
, e
, msg
->router_id
, msg
->seqno
))
1288 babel_trigger_update(p
);
1289 e
->updated
= current_time();
1292 babel_select_route(p
, e
, r
);
1296 babel_handle_route_request(union babel_msg
*m
, struct babel_iface
*ifa
)
1298 struct babel_proto
*p
= ifa
->proto
;
1299 struct babel_msg_route_request
*msg
= &m
->route_request
;
1301 /* RFC 6126 3.8.1.1 */
1303 /* Wildcard request - full update on the interface */
1306 TRACE(D_PACKETS
, "Handling wildcard route request");
1307 ifa
->want_triggered
= 1;
1311 TRACE(D_PACKETS
, "Handling route request for %N", &msg
->net
);
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
);
1318 babel_send_retraction(ifa
, &msg
->net
);
1322 babel_trigger_iface_update(ifa
);
1323 e
->updated
= current_time();
1328 babel_handle_seqno_request(union babel_msg
*m
, struct babel_iface
*ifa
)
1330 struct babel_proto
*p
= ifa
->proto
;
1331 struct babel_msg_seqno_request
*msg
= &m
->seqno_request
;
1333 /* RFC 6126 3.8.1.2 */
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
);
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
))
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
))
1347 babel_trigger_iface_update(ifa
);
1348 e
->updated
= current_time();
1352 /* Seqno is larger; check if we own the router id */
1353 if (msg
->router_id
== p
->router_id
)
1355 /* Ours; seqno increase and trigger global update */
1356 p
->update_seqno_inc
= 1;
1357 babel_trigger_update(p
);
1359 else if (msg
->hop_count
> 1)
1361 /* Not ours; forward if TTL allows it */
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
))
1368 /* Find best feasible route */
1369 if ((!best1
|| r
->metric
< best1
->metric
) && r
->feasible
)
1372 /* Find best not necessary feasible route */
1373 if (!best2
|| r
->metric
< best2
->metric
)
1377 /* If no route is found, do nothing */
1382 babel_add_seqno_request(p
, e
, msg
->router_id
, msg
->seqno
, msg
->hop_count
-1, r
->neigh
);
1392 * babel_iface_timer - Babel interface timer handler
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.
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.
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.
1413 babel_iface_timer(timer
*t
)
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();
1421 if (now_
>= ifa
->next_hello
)
1423 babel_send_hello(ifa
);
1424 ifa
->next_hello
+= hello_period
* (1 + (now_
- ifa
->next_hello
) / hello_period
);
1427 if (now_
>= ifa
->next_regular
)
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;
1435 else if (ifa
->want_triggered
&& (now_
>= ifa
->next_triggered
))
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;
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
);
1450 babel_iface_kick_timer(struct babel_iface
*ifa
)
1452 if (ifa
->timer
->expires
> (current_time() + 100 MS
))
1453 tm_start(ifa
->timer
, 100 MS
);
1457 babel_iface_start(struct babel_iface
*ifa
)
1459 struct babel_proto
*p
= ifa
->proto
;
1461 TRACE(D_EVENTS
, "Starting interface %s", ifa
->ifname
);
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
);
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 */
1477 babel_iface_stop(struct babel_iface
*ifa
)
1479 struct babel_proto
*p
= ifa
->proto
;
1480 struct babel_neighbor
*nbr
;
1481 struct babel_route
*r
;
1484 TRACE(D_EVENTS
, "Stopping interface %s", ifa
->ifname
);
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.
1491 WALK_LIST(nbr
, ifa
->neigh_list
)
1493 WALK_LIST(n
, nbr
->routes
)
1495 r
= SKIP_BACK(struct babel_route
, neigh_route
, n
);
1496 babel_retract_route(p
, r
);
1500 tm_stop(ifa
->timer
);
1505 babel_iface_link_up(struct babel_iface
*ifa
)
1507 return !ifa
->cf
->check_link
|| (ifa
->iface
->flags
& IF_LINK_UP
);
1511 babel_iface_update_state(struct babel_iface
*ifa
)
1513 int up
= ifa
->sk
&& babel_iface_link_up(ifa
);
1519 babel_iface_start(ifa
);
1521 babel_iface_stop(ifa
);
1525 babel_iface_update_addr4(struct babel_iface
*ifa
)
1527 struct babel_proto
*p
= ifa
->proto
;
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
;
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
);
1536 babel_iface_kick_timer(ifa
);
1540 babel_iface_update_buffers(struct babel_iface
*ifa
)
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
);
1550 sk_set_rbsize(ifa
->sk
, rbsize
);
1551 sk_set_tbsize(ifa
->sk
, tbsize
);
1553 ifa
->tx_length
= tbsize
- BABEL_OVERHEAD
;
1556 static struct babel_iface
*
1557 babel_find_iface(struct babel_proto
*p
, struct iface
*what
)
1559 struct babel_iface
*ifa
;
1561 WALK_LIST (ifa
, p
->interfaces
)
1562 if (ifa
->iface
== what
)
1569 babel_iface_locked(struct object_lock
*lock
)
1571 struct babel_iface
*ifa
= lock
->data
;
1572 struct babel_proto
*p
= ifa
->proto
;
1574 if (!babel_open_socket(ifa
))
1576 log(L_ERR
"%s: Cannot open socket for %s", p
->p
.name
, ifa
->iface
->name
);
1580 babel_iface_update_buffers(ifa
);
1581 babel_iface_update_state(ifa
);
1585 babel_add_iface(struct babel_proto
*p
, struct iface
*new, struct babel_iface_config
*ic
)
1587 struct babel_iface
*ifa
;
1589 TRACE(D_EVENTS
, "Adding interface %s", new->name
);
1591 pool
*pool
= rp_new(p
->p
.pool
, new->name
);
1593 ifa
= mb_allocz(pool
, sizeof(struct babel_iface
));
1598 ifa
->ifname
= new->name
;
1599 ifa
->addr
= new->llv6
->ip
;
1601 add_tail(&p
->interfaces
, NODE ifa
);
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
;
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
);
1610 init_list(&ifa
->neigh_list
);
1611 ifa
->hello_seqno
= 1;
1613 ifa
->timer
= tm_new_init(ifa
->pool
, babel_iface_timer
, ifa
, 0, 0);
1615 init_list(&ifa
->msg_queue
);
1616 ifa
->send_event
= ev_new_init(ifa
->pool
, babel_send_queue
, ifa
);
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
;
1626 olock_acquire(lock
);
1630 babel_remove_iface(struct babel_proto
*p
, struct babel_iface
*ifa
)
1632 TRACE(D_EVENTS
, "Removing interface %s", ifa
->iface
->name
);
1634 struct babel_neighbor
*n
;
1635 WALK_LIST_FIRST(n
, ifa
->neigh_list
)
1636 babel_flush_neighbor(p
, n
);
1640 rfree(ifa
->pool
); /* contains ifa itself, locks, socket, etc */
1644 babel_if_notify(struct proto
*P
, unsigned flags
, struct iface
*iface
)
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
);
1650 if (iface
->flags
& IF_IGNORE
)
1653 /* Add, remove or restart interface */
1654 if (flags
& (IF_CHANGE_UPDOWN
| IF_CHANGE_LLV6
))
1657 babel_remove_iface(p
, ifa
);
1659 if (!(iface
->flags
& IF_UP
))
1662 /* We only speak multicast */
1663 if (!(iface
->flags
& IF_MULTICAST
))
1666 /* Ignore ifaces without link-local address */
1670 struct babel_iface_config
*ic
= (void *) iface_patt_find(&cf
->iface_list
, iface
, NULL
);
1672 babel_add_iface(p
, iface
, ic
);
1680 if (flags
& IF_CHANGE_ADDR4
)
1681 babel_iface_update_addr4(ifa
);
1683 if (flags
& IF_CHANGE_MTU
)
1684 babel_iface_update_buffers(ifa
);
1686 if (flags
& IF_CHANGE_LINK
)
1687 babel_iface_update_state(ifa
);
1691 babel_reconfigure_iface(struct babel_proto
*p
, struct babel_iface
*ifa
, struct babel_iface_config
*new)
1693 struct babel_iface_config
*old
= ifa
->cf
;
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
))
1701 TRACE(D_EVENTS
, "Reconfiguring interface %s", ifa
->iface
->name
);
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
;
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
);
1712 if (ifa
->next_hello
> (current_time() + new->hello_interval
))
1713 ifa
->next_hello
= current_time() + (random() % new->hello_interval
);
1715 if (ifa
->next_regular
> (current_time() + new->update_interval
))
1716 ifa
->next_regular
= current_time() + (random() % new->update_interval
);
1718 if ((new->tx_length
!= old
->tx_length
) || (new->rx_buffer
!= old
->rx_buffer
))
1719 babel_iface_update_buffers(ifa
);
1721 if (new->check_link
!= old
->check_link
)
1722 babel_iface_update_state(ifa
);
1725 babel_iface_kick_timer(ifa
);
1731 babel_reconfigure_ifaces(struct babel_proto
*p
, struct babel_config
*cf
)
1733 struct iface
*iface
;
1735 WALK_LIST(iface
, iface_list
)
1737 if (!(iface
->flags
& IF_UP
))
1740 /* Ignore non-multicast ifaces */
1741 if (!(iface
->flags
& IF_MULTICAST
))
1744 /* Ignore ifaces without link-local address */
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
);
1753 if (babel_reconfigure_iface(p
, ifa
, ic
))
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
);
1763 babel_remove_iface(p
, ifa
);
1766 babel_add_iface(p
, iface
, ic
);
1772 * Debugging and info output functions
1776 babel_dump_source(struct babel_source
*s
)
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);
1784 babel_dump_route(struct babel_route
*r
)
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);
1792 babel_dump_entry(struct babel_entry
*e
)
1794 struct babel_source
*s
;
1795 struct babel_route
*r
;
1797 debug("Babel: Entry %N:\n", e
->n
.addr
);
1799 WALK_LIST(s
,e
->sources
)
1800 { debug(" "); babel_dump_source(s
); }
1802 WALK_LIST(r
,e
->routes
)
1805 if (r
== e
->selected
) debug("*");
1806 babel_dump_route(r
);
1811 babel_dump_neighbor(struct babel_neighbor
*n
)
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);
1820 babel_dump_iface(struct babel_iface
*ifa
)
1822 struct babel_neighbor
*n
;
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
);
1829 WALK_LIST(n
, ifa
->neigh_list
)
1830 { debug(" "); babel_dump_neighbor(n
); }
1834 babel_dump(struct proto
*P
)
1836 struct babel_proto
*p
= (struct babel_proto
*) P
;
1837 struct babel_iface
*ifa
;
1839 debug("Babel: router id %lR update seqno %d\n", p
->router_id
, p
->update_seqno
);
1841 WALK_LIST(ifa
, p
->interfaces
)
1842 babel_dump_iface(ifa
);
1844 FIB_WALK(&p
->ip4_rtable
, struct babel_entry
, e
)
1846 babel_dump_entry(e
);
1849 FIB_WALK(&p
->ip6_rtable
, struct babel_entry
, e
)
1851 babel_dump_entry(e
);
1857 babel_get_route_info(rte
*rte
, byte
*buf
)
1859 buf
+= bsprintf(buf
, " (%d/%d) [%lR]", rte
->pref
, rte
->u
.babel
.metric
, rte
->u
.babel
.router_id
);
1863 babel_get_attr(const eattr
*a
, byte
*buf
, int buflen UNUSED
)
1867 case EA_BABEL_METRIC
:
1868 bsprintf(buf
, "metric: %d", a
->u
.data
);
1871 case EA_BABEL_ROUTER_ID
:
1874 memcpy(&rid
, a
->u
.ptr
->data
, sizeof(u64
));
1875 bsprintf(buf
, "router_id: %lR", rid
);
1885 babel_show_interfaces(struct proto
*P
, const char *iff
)
1887 struct babel_proto
*p
= (void *) P
;
1888 struct babel_iface
*ifa
= NULL
;
1889 struct babel_neighbor
*nbr
= NULL
;
1891 if (p
->p
.proto_state
!= PS_UP
)
1893 cli_msg(-1023, "%s: is not up", p
->p
.name
);
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)");
1903 WALK_LIST(ifa
, p
->interfaces
)
1905 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1909 WALK_LIST(nbr
, ifa
->neigh_list
)
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
);
1923 babel_show_neighbors(struct proto
*P
, const char *iff
)
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
;
1930 if (p
->p
.proto_state
!= PS_UP
)
1932 cli_msg(-1024, "%s: is not up", p
->p
.name
);
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");
1941 WALK_LIST(ifa
, p
->interfaces
)
1943 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1946 WALK_LIST(n
, ifa
->neigh_list
)
1949 WALK_LIST(r
, n
->routes
)
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));
1963 babel_show_entries_(struct babel_proto
*p
, struct fib
*rtable
)
1965 int width
= babel_sadr_enabled(p
) ? -54 : -24;
1967 FIB_WALK(rtable
, struct babel_entry
, e
)
1969 struct babel_route
*r
= NULL
;
1970 uint rts
= 0, srcs
= 0;
1973 WALK_LIST(n
, e
->routes
)
1976 WALK_LIST(n
, e
->sources
)
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
);
1986 cli_msg(-1025, "%-*N %-23s %6s %5s %7u %7u", width
,
1987 e
->n
.addr
, "<none>", "-", "-", rts
, srcs
);
1993 babel_show_entries(struct proto
*P
)
1995 struct babel_proto
*p
= (void *) P
;
1996 int width
= babel_sadr_enabled(p
) ? -54 : -24;
1998 if (p
->p
.proto_state
!= PS_UP
)
2000 cli_msg(-1025, "%s: is not up", p
->p
.name
);
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");
2009 babel_show_entries_(p
, &p
->ip4_rtable
);
2010 babel_show_entries_(p
, &p
->ip6_rtable
);
2016 babel_show_routes_(struct babel_proto
*p
, struct fib
*rtable
)
2018 int width
= babel_sadr_enabled(p
) ? -54 : -24;
2020 FIB_WALK(rtable
, struct babel_entry
, e
)
2022 struct babel_route
*r
;
2023 WALK_LIST(r
, e
->routes
)
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));
2036 babel_show_routes(struct proto
*P
)
2038 struct babel_proto
*p
= (void *) P
;
2039 int width
= babel_sadr_enabled(p
) ? -54 : -24;
2041 if (p
->p
.proto_state
!= PS_UP
)
2043 cli_msg(-1025, "%s: is not up", p
->p
.name
);
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");
2052 babel_show_routes_(p
, &p
->ip4_rtable
);
2053 babel_show_routes_(p
, &p
->ip6_rtable
);
2060 * Babel protocol glue
2064 * babel_timer - global timer hook
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
2072 babel_timer(timer
*t
)
2074 struct babel_proto
*p
= t
->data
;
2076 babel_expire_routes(p
);
2077 babel_expire_neighbors(p
);
2081 babel_kick_timer(struct babel_proto
*p
)
2083 if (p
->timer
->expires
> (current_time() + 100 MS
))
2084 tm_start(p
->timer
, 100 MS
);
2089 babel_preexport(struct proto
*P
, struct rte
**new, struct linpool
*pool UNUSED
)
2091 struct rta
*a
= (*new)->attrs
;
2093 /* Reject our own unreachable routes */
2094 if ((a
->dest
== RTD_UNREACHABLE
) && (a
->src
->proto
== P
))
2101 babel_make_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
2103 struct adata
*id
= lp_alloc_adata(pool
, sizeof(u64
));
2104 memcpy(id
->data
, &rt
->u
.babel
.router_id
, sizeof(u64
));
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
);
2112 babel_store_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
2114 rte_init_tmp_attrs(rt
, pool
, 2);
2115 rt
->u
.babel
.metric
= rte_store_tmp_attr(rt
, EA_BABEL_METRIC
);
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
);
2122 * babel_rt_notify - core tells us about new route (possibly our own),
2123 * so store it into our data structures.
2126 babel_rt_notify(struct proto
*P
, struct channel
*c UNUSED
, struct network
*net
,
2127 struct rte
*new, struct rte
*old UNUSED
)
2129 struct babel_proto
*p
= (void *) P
;
2130 struct babel_entry
*e
;
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
;
2140 if (rt_metric
> BABEL_INFINITY
)
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
;
2147 e
= babel_get_entry(p
, net
->n
.addr
);
2149 /* Activate triggered updates */
2150 if ((e
->valid
!= BABEL_ENTRY_VALID
) ||
2151 (e
->router_id
!= rt_router_id
))
2153 babel_trigger_update(p
);
2154 e
->updated
= current_time();
2157 e
->valid
= BABEL_ENTRY_VALID
;
2158 e
->seqno
= rt_seqno
;
2159 e
->metric
= rt_metric
;
2160 e
->router_id
= rt_router_id
;
2165 e
= babel_find_entry(p
, net
->n
.addr
);
2167 if (!e
|| e
->valid
!= BABEL_ENTRY_VALID
)
2170 e
->valid
= BABEL_ENTRY_STALE
;
2171 e
->metric
= BABEL_INFINITY
;
2173 babel_trigger_update(p
);
2174 e
->updated
= current_time();
2179 babel_rte_better(struct rte
*new, struct rte
*old
)
2181 return new->u
.babel
.metric
< old
->u
.babel
.metric
;
2185 babel_rte_same(struct rte
*new, struct rte
*old
)
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
));
2194 babel_postconfig(struct proto_config
*CF
)
2196 struct babel_config
*cf
= (void *) CF
;
2197 struct channel_config
*ip4
, *ip6
, *ip6_sadr
;
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
);
2203 if (ip6
&& ip6_sadr
)
2204 cf_error("Both ipv6 and ipv6-sadr channels");
2206 cf
->ip4_channel
= ip4
;
2207 cf
->ip6_channel
= ip6
?: ip6_sadr
;
2210 static struct proto
*
2211 babel_init(struct proto_config
*CF
)
2213 struct proto
*P
= proto_new(CF
);
2214 struct babel_proto
*p
= (void *) P
;
2215 struct babel_config
*cf
= (void *) CF
;
2217 proto_configure_channel(P
, &p
->ip4_channel
, cf
->ip4_channel
);
2218 proto_configure_channel(P
, &p
->ip6_channel
, cf
->ip6_channel
);
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
;
2232 babel_randomize_router_id(struct babel_proto
*p
)
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
);
2240 babel_start(struct proto
*P
)
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
;
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
);
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
);
2257 if (cf
->randomize_router_id
)
2258 babel_randomize_router_id(p
);
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
));
2265 p
->log_pkt_tbf
= (struct tbf
){ .rate
= 1, .burst
= 5 };
2271 babel_iface_shutdown(struct babel_iface
*ifa
)
2275 babel_send_wildcard_retraction(ifa
);
2276 babel_send_queue(ifa
);
2281 babel_shutdown(struct proto
*P
)
2283 struct babel_proto
*p
= (void *) P
;
2284 struct babel_iface
*ifa
;
2286 TRACE(D_EVENTS
, "Shutdown requested");
2288 WALK_LIST(ifa
, p
->interfaces
)
2289 babel_iface_shutdown(ifa
);
2295 babel_reconfigure(struct proto
*P
, struct proto_config
*CF
)
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
;
2301 TRACE(D_EVENTS
, "Reconfiguring");
2303 if (p
->ip6_rtable
.addr_type
!= ip6_type
)
2306 if (!proto_configure_channel(P
, &p
->ip4_channel
, new->ip4_channel
) ||
2307 !proto_configure_channel(P
, &p
->ip6_channel
, new->ip6_channel
))
2311 babel_reconfigure_ifaces(p
, new);
2313 babel_trigger_update(p
);
2314 babel_kick_timer(p
);
2320 struct protocol proto_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
,
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