[PATCH 1/3] babel: Fix type of route entry router ID
The router ID being assigned to routes was a uint, which discards the upper 32 bits. This also has the nice side effect of echoing the wrong router ID back to other routers. Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> --- proto/babel/babel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 4fd88042..a8eb5ea8 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2140,7 +2140,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, uint internal = (new->attrs->src->proto == P); uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno; uint rt_metric = ea_get_int(attrs, EA_BABEL_METRIC, 0); - uint rt_router_id = internal ? new->u.babel.router_id : p->router_id; + u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id; if (rt_metric > BABEL_INFINITY) { -- 2.17.0
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes). There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time. This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network. Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk> --- doc/bird.sgml | 10 ++++++++++ proto/babel/babel.c | 14 ++++++++++++++ proto/babel/babel.h | 1 + proto/babel/config.Y | 3 ++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index 1191fa03..47a6a60a 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1691,6 +1691,7 @@ supports the following per-interface configuration options: protocol babel [<name>] { ipv4 { <channel config> }; ipv6 [sadr] { <channel config> }; + random router id <switch>; interface <interface pattern> { type <wired|wireless>; rxcost <number>; @@ -1713,6 +1714,15 @@ protocol babel [<name>] { <tag><label id="babel-channel">ipv4 | ipv6 [sadr] <m/channel config/</tag> The supported channels are IPv4, IPv6, and IPv6 SADR. + <tag><label id="babel-random-router-id">check link <m/switch/</tag> + If enabled, Bird will randomise the top 32 bits of its router ID whenever + the protocol instance starts up. If a Babel node restarts, it loses its sequence + number, which can cause its routes to be rejected by peers until the state + is cleared out by other nodes in the network (which can take on the order + of minutes). Enabling this option causes Bird to pick a random router ID + every time it starts up, which avoids this problem at the cost of not + having stable router IDs in the network. + <tag><label id="babel-type">type wired|wireless </tag> This option specifies the interface type: Wired or wireless. On wired interfaces a neighbor is considered unreachable after a small number of diff --git a/proto/babel/babel.c b/proto/babel/babel.c index f7981333..5f1adca3 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2236,6 +2236,13 @@ babel_init(struct proto_config *CF) return P; } +static inline void +babel_randomise_router_id(struct babel_proto *p) +{ + p->router_id |= ((u64) random()) << 32; + TRACE(D_EVENTS, "Randomised router ID to %lR", p->router_id); +} + static int babel_start(struct proto *P) { @@ -2254,6 +2261,9 @@ babel_start(struct proto *P) p->update_seqno = 1; p->router_id = proto_get_router_id(&cf->c); + if (cf->random_router_id) + babel_randomise_router_id(p); + p->route_slab = sl_new(P->pool, sizeof(struct babel_route)); p->source_slab = sl_new(P->pool, sizeof(struct babel_source)); p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node)); @@ -2293,6 +2303,7 @@ babel_reconfigure(struct proto *P, struct proto_config *CF) { struct babel_proto *p = (void *) P; struct babel_config *new = (void *) CF; + struct babel_config *old = (void *) p->p.cf; u8 ip6_type = new->ip6_channel ? new->ip6_channel->net_type : NET_IP6; TRACE(D_EVENTS, "Reconfiguring"); @@ -2304,6 +2315,9 @@ babel_reconfigure(struct proto *P, struct proto_config *CF) !proto_configure_channel(P, &p->ip6_channel, new->ip6_channel)) return 0; + if (new->random_router_id && !old->random_router_id) + babel_randomise_router_id(p); + p->p.cf = CF; babel_reconfigure_ifaces(p, new); diff --git a/proto/babel/babel.h b/proto/babel/babel.h index b194ce30..830c18ee 100644 --- a/proto/babel/babel.h +++ b/proto/babel/babel.h @@ -112,6 +112,7 @@ struct babel_config { struct proto_config c; list iface_list; /* List of iface configs (struct babel_iface_config) */ uint hold_time; /* Time to hold stale entries and unreachable routes */ + u8 random_router_id; struct channel_config *ip4_channel; struct channel_config *ip6_channel; diff --git a/proto/babel/config.Y b/proto/babel/config.Y index 7adfb4bb..25a0c2f0 100644 --- a/proto/babel/config.Y +++ b/proto/babel/config.Y @@ -25,7 +25,7 @@ CF_DECLS CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT, TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK, NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS, - ENTRIES) + ENTRIES, RANDOM, ROUTER, ID) CF_GRAMMAR @@ -42,6 +42,7 @@ babel_proto_item: proto_item | proto_channel | INTERFACE babel_iface + | RANDOM ROUTER ID bool { BABEL_CFG->random_router_id = $4; } ; babel_proto_opts: -- 2.17.0
Toke Høiland-Jørgensen <toke@toke.dk> writes:
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes).
There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time.
This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network.
BTW, I would also like to implement the EUI-64-based router ID assignment that babeld does, since it can significantly improve protocol efficiency in some v6 deployments. But that would require ignoring the global setting for router ID; is that acceptable, if it's made a configuration option? -Toke
On Tue, May 01, 2018 at 12:41:01PM +0200, Toke Høiland-Jørgensen wrote:
Toke Høiland-Jørgensen <toke@toke.dk> writes:
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes).
There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time.
This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network.
BTW, I would also like to implement the EUI-64-based router ID assignment that babeld does, since it can significantly improve protocol efficiency in some v6 deployments. But that would require ignoring the global setting for router ID; is that acceptable, if it's made a configuration option?
Hi, how exactly 'EUI-64-based router ID assignment' works? Based on MAC addresses, IPv6 LL addresses, /etc/machine-id, random assignment or some other source? Ignoring global setting is OK, i just wonder whether some global EUI-64-based unique ID should not be provided directly by the nest -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Ondrej Zajicek <santiago@crfreenet.org> writes:
On Tue, May 01, 2018 at 12:41:01PM +0200, Toke Høiland-Jørgensen wrote:
Toke Høiland-Jørgensen <toke@toke.dk> writes:
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes).
There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time.
This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network.
BTW, I would also like to implement the EUI-64-based router ID assignment that babeld does, since it can significantly improve protocol efficiency in some v6 deployments. But that would require ignoring the global setting for router ID; is that acceptable, if it's made a configuration option?
Hi, how exactly 'EUI-64-based router ID assignment' works? Based on MAC addresses, IPv6 LL addresses, /etc/machine-id, random assignment or some other source?
It is basically using the lower 64 bits of the LL address as router ID. There's a flag in the protocol encoding that makes it possible to elide the router ID TLV in this case; if there are only a few routes this can save quite a bit of space, percentage-wise :) Of course this only works for one interface, but in pure wireless meshes, everything is usually on the same interface anyway, so that is fine (and otherwise you could configure the same LL-addr on all interfaces of course).
Ignoring global setting is OK, i just wonder whether some global EUI-64-based unique ID should not be provided directly by the nest
That might be convenient, yeah. There's the issue of picking the right interface, though; some kind of logic that says "first interface with a configured protocol"? Or should it be a per-protocol type thing? -Toke
On Thu, May 03, 2018 at 03:14:58PM +0200, Toke Høiland-Jørgensen wrote:
Ondrej Zajicek <santiago@crfreenet.org> writes:
Ignoring global setting is OK, i just wonder whether some global EUI-64-based unique ID should not be provided directly by the nest
That might be convenient, yeah. There's the issue of picking the right interface, though; some kind of logic that says "first interface with a configured protocol"? Or should it be a per-protocol type thing?
It would make sense to use an analogous mechanism to 32bit router id, just use IPv6-LL address instead of IPv4 address. See 'router id' / 'router id from' options and function if_choose_router_id(). One issue is that if BIRD is started during boot then IPv6-LL addresses may not be available immediately after start due to waiting for duplicate address detection. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Ondrej Zajicek <santiago@crfreenet.org> writes:
On Thu, May 03, 2018 at 03:14:58PM +0200, Toke Høiland-Jørgensen wrote:
Ondrej Zajicek <santiago@crfreenet.org> writes:
Ignoring global setting is OK, i just wonder whether some global EUI-64-based unique ID should not be provided directly by the nest
That might be convenient, yeah. There's the issue of picking the right interface, though; some kind of logic that says "first interface with a configured protocol"? Or should it be a per-protocol type thing?
It would make sense to use an analogous mechanism to 32bit router id, just use IPv6-LL address instead of IPv4 address. See 'router id' / 'router id from' options and function if_choose_router_id().
Right, that makes sense. A 'v6-ll/64bit router id [from]' config option? The nest could provide proto_get_router_id64() which would return an LL-based ID if configured/available and the 32-bit version if it isn't?
One issue is that if BIRD is started during boot then IPv6-LL addresses may not be available immediately after start due to waiting for duplicate address detection.
Hmm, true. Should we deal with this (by deferring startup of protocols that need them, I guess?), or leave it up to administrators to fix their init scripts? With the fallback option mentioned above it would not be strictly necessary, we could just fall back to 32-bit... :) -Toke
On Wed, May 09, 2018 at 04:29:54PM +0200, Toke Høiland-Jørgensen wrote:
Ondrej Zajicek <santiago@crfreenet.org> writes:
On Thu, May 03, 2018 at 03:14:58PM +0200, Toke Høiland-Jørgensen wrote:
Ondrej Zajicek <santiago@crfreenet.org> writes:
Ignoring global setting is OK, i just wonder whether some global EUI-64-based unique ID should not be provided directly by the nest
That might be convenient, yeah. There's the issue of picking the right interface, though; some kind of logic that says "first interface with a configured protocol"? Or should it be a per-protocol type thing?
It would make sense to use an analogous mechanism to 32bit router id, just use IPv6-LL address instead of IPv4 address. See 'router id' / 'router id from' options and function if_choose_router_id().
Right, that makes sense. A 'v6-ll/64bit router id [from]' config option?
Something like that. I would prefer '64bit', but unfortunately keywords in BIRD have to use {alpha}{alnum}* format. It should also check if the address is really EUI-64 and skip configured ones like fe80::1.
The nest could provide proto_get_router_id64() which would return an LL-based ID if configured/available and the 32-bit version if it isn't?
Yes. Or just 64-bit ID could be set based on 32-bit value as a last resort.
One issue is that if BIRD is started during boot then IPv6-LL addresses may not be available immediately after start due to waiting for duplicate address detection.
Hmm, true. Should we deal with this (by deferring startup of protocols that need them, I guess?), or leave it up to administrators to fix their init scripts? With the fallback option mentioned above it would not be strictly necessary, we could just fall back to 32-bit... :)
Well, ignoring it is ugly and leads to nondeterministic behavior. Deferring protocol startup could be hacked, but it is still problematic (e.g., you have to rerun router id election when DUD finished for initial addresses). Another option would be be to process even tentative addresses but mark them in such way, so protocols could ignore them while router-id selection could still use them. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
On Mon, Apr 30, 2018 at 05:15:19PM +0200, Toke Høiland-Jørgensen wrote:
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes).
There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time.
This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network.
Merged with some minor changes (option renamed to 'randomize router id', no router ID change when changed during reconfiguration). Also note that when tested on my VM test setup, all router IDs were generated with the same value due to way how random() is initialized in BIRD. Fixed that with a further commit. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Ondrej Zajicek <santiago@crfreenet.org> writes:
On Mon, Apr 30, 2018 at 05:15:19PM +0200, Toke Høiland-Jørgensen wrote:
When a Babel node restarts, it loses its sequence number, which can cause its routes to be rejected by peers until the state is cleared out by other nodes in the network (which can take on the order of minutes).
There are two ways to fix this: Having stable storage to keep the sequence number across restarts, or picking a different router ID each time.
This implements the latter, by introducing a new option that will cause Bird to pick a random router ID every time it starts up. This avoids the problem at the cost of not having stable router IDs in the network.
Merged with some minor changes (option renamed to 'randomize router id', no router ID change when changed during reconfiguration).
Also note that when tested on my VM test setup, all router IDs were generated with the same value due to way how random() is initialized in BIRD. Fixed that with a further commit.
Great, thanks! :) -Toke
On Mon, Apr 30, 2018 at 05:15:17PM +0200, Toke Høiland-Jørgensen wrote:
The router ID being assigned to routes was a uint, which discards the upper 32 bits. This also has the nice side effect of echoing the wrong router ID back to other routers.
Thanks for bugfix. -- Elen sila lumenn' omentielvo Ondrej 'Santiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
participants (2)
-
Ondrej Zajicek -
Toke Høiland-Jørgensen