Skip to content

Commit

Permalink
AdvRASolicitedUnicast: unicast RA response to RS.
Browse files Browse the repository at this point in the history
RFC 7772 section 2.1 describes a network flooded with multicast RA at
the maximum 3 second interval due a high client turnover.

The mitigation described in RFC 7772 section 5.1.1 states that a unicast
RA response can be sent, but SHOULD be a configurable option
(AdvRASolicitedUnicast), and that networks containing tens or hundreds
of battery-powered devices SHOULD enable the option.

The new option is defaulted to on, as it has very few downsides, and
represents significent battery life improvements for many clients.

See TODO for further possible improvements to AdvRASolicitedUnicast.

Fixes: radvd-project#63
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
  • Loading branch information
robbat2 committed Mar 16, 2017
1 parent c779509 commit 7006816
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
2017/03/05 Implement RFC 7772 Section 5.1.1, 5.1.2, defaulted to on. <Robin H. Johnson>

2017/02/04 clang-format the code

2017/02/01 Release v2.16
Expand Down
17 changes: 17 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,20 @@ Known problems (probably can't do anything about these):
Ethernet frames with the old MAC until interface is flapped.
More: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=508466

AdvRASolicitedUnicast: Further improvement is possible.
- If we get a RS and are about to send a multicast RA, then we can further save
battery on the client device by NOT sending a unicast response, and just
letting the client wait for the multicast response. This should be
implemented as a new time value, specifying the maximum amount of time
remaining to as a deciding factor between send-solicited-RA-now vs
wait-for-next-multicast.
- The above can also form part of rate-limiting of unicast RA responses when
network topology has recently changed.

The following parts of RFC7222 are not yet implemented:
- Section 5.1.3: Networks that serve battery-powered devices SHOULD NOT send
multicast RAs too frequently (see Section 4) unless the information in the RA
packet has substantially changed. If there is a desire to ensure that hosts
pick up configuration changes quickly, those networks MAY send frequent
Router Advertisements for a limited period of time (e.g., not more than one
minute) immediately after a configuration change.
2 changes: 2 additions & 0 deletions defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
#define DFLT_MinDelayBetweenRAs MIN_DELAY_BETWEEN_RAS
#define DFLT_AdvDefaultPreference 0
#define DFLT_AdvRAMTU RFC2460_MIN_MTU
#define DFLT_UnicastOnly 0
#define DFLT_AdvRASolicitedUnicast 1

/* Options sent with RA */

Expand Down
5 changes: 5 additions & 0 deletions gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
%token T_Base6Interface
%token T_Base6to4Interface
%token T_UnicastOnly
%token T_AdvRASolicitedUnicast

%token T_HomeAgentPreference
%token T_HomeAgentLifetime
Expand Down Expand Up @@ -332,6 +333,10 @@ ifaceval : T_MinRtrAdvInterval NUMBER ';'
{
iface->UnicastOnly = $2;
}
| T_AdvRASolicitedUnicast SWITCH ';'
{
iface->AdvRASolicitedUnicast = $2;
}
| T_AdvMobRtrSupportFlag SWITCH ';'
{
iface->mipv6.AdvMobRtrSupportFlag = $2;
Expand Down
2 changes: 2 additions & 0 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void iface_init_defaults(struct Interface *iface)
iface->AdvSourceLLAddress = DFLT_AdvSourceLLAddress;
iface->MinDelayBetweenRAs = DFLT_MinDelayBetweenRAs;
iface->MinRtrAdvInterval = -1;
iface->UnicastOnly = DFLT_UnicastOnly;
iface->AdvRASolicitedUnicast = DFLT_AdvRASolicitedUnicast;

iface->ra_header_info.AdvDefaultPreference = DFLT_AdvDefaultPreference;
iface->ra_header_info.AdvDefaultLifetime = -1;
Expand Down
30 changes: 25 additions & 5 deletions process.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ void process(int sock, struct Interface *interfaces, unsigned char *msg, int len

static void process_rs(int sock, struct Interface *iface, unsigned char *msg, int len, struct sockaddr_in6 *addr)
{
/* RFC 7772, section 5.1:
* 5.1. Network-Side Recommendations
* 1. Router manufacturers SHOULD allow network administrators to
* configure the routers to respond to Router Solicitations with
* unicast Router Advertisements if:
* * The Router Solicitation's source address is not the
* unspecified address, and:
* * The solicitation contains a valid Source Link-Layer Address
* option.
*/
int rfc7772_unicast_response = 0;

/* validation */
len -= sizeof(struct nd_router_solicit);

Expand All @@ -143,10 +155,14 @@ static void process_rs(int sock, struct Interface *iface, unsigned char *msg, in
return;
}

if (*opt_str == ND_OPT_SOURCE_LINKADDR && IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
flog(LOG_WARNING,
"received icmpv6 RS packet with unspecified source address and there is a lladdr option");
return;
if (*opt_str == ND_OPT_SOURCE_LINKADDR) {
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
rfc7772_unicast_response = iface->AdvRASolicitedUnicast;
} else {
flog(LOG_WARNING,
"received icmpv6 RS packet with unspecified source address and there is a lladdr option");
return;
}
}

len -= optlen;
Expand All @@ -158,7 +174,11 @@ static void process_rs(int sock, struct Interface *iface, unsigned char *msg, in

double const delay = (MAX_RA_DELAY_SECONDS * rand() / (RAND_MAX + 1.0));

if (iface->UnicastOnly) {
// rfc7772_unicast_response will only be true at this point if
// - The config option AdvRASolicitedUnicast was set.
// - The RS contained a LLaddr option
// - The RS was not from the unspecified address.
if (iface->UnicastOnly || rfc7772_unicast_response) {
send_ra_forall(sock, iface, &addr->sin6_addr);
} else if (timespecdiff(&ts, &iface->times.last_multicast) / 1000.0 < iface->MinDelayBetweenRAs) {
/* last RA was sent only a few moments ago, don't send another immediately. */
Expand Down
15 changes: 14 additions & 1 deletion radvd.conf.5.man
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ DNSSL (DNS Search List) definitions are of the form:
.B };
.fi

By default radvd will send route advertisements so that every node on the link can use them.
By default radvd will send multicast route advertisements so that every node on the link can use them.
The list of clients (IPv6 address) to advertise to, and accept route solicitations from can be configured.
If done, radvd does not send send messages to the multicast addresses but
to the configured unicast addresses only. Solicitations from other addresses are refused.
Expand Down Expand Up @@ -172,6 +172,19 @@ multiple-access links, such as ISATAP.

Default: off

.TP
.BR AdvRASolicitedUnicast " " on | off

Indicates that router solicitations will be responded to with unicast
router advertisements, as recommended by RFC7772. Large networks with a
high concentration of mobile devices might experience like battery
depletion, when solicited Router Advertisement messages are multicast.

This corresponds to the Cisco IOS option
.B ipv6 nd ra solicited unicast

Default: on

.TP
.BR "MaxRtrAdvInterval " seconds

Expand Down
1 change: 1 addition & 0 deletions radvd.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct Interface {
double MinDelayBetweenRAs;
int AdvSourceLLAddress;
int UnicastOnly;
int AdvRASolicitedUnicast;
struct Clients *ClientList;

struct state_info {
Expand Down
1 change: 1 addition & 0 deletions scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ AdvHomeAgentFlag { return T_AdvHomeAgentFlag; }
AdvIntervalOpt { return T_AdvIntervalOpt; }
AdvHomeAgentInfo { return T_AdvHomeAgentInfo; }
UnicastOnly { return T_UnicastOnly; }
AdvRASolicitedUnicast { return T_AdvRASolicitedUnicast; }

Base6Interface { return T_Base6Interface; }
Base6to4Interface { return T_Base6to4Interface; }
Expand Down

0 comments on commit 7006816

Please sign in to comment.