From 46fd632e9185d51f89e98996d9c35eae27146680 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Wed, 9 Oct 2019 18:23:29 +0200 Subject: [PATCH 1/3] gnrc_netif: highest source address scope wins selection Rule 2 of the source address algorithm outlined in [RFC6724] states the possible source addresses must also be compared among each other: > Rule 2: Prefer appropriate scope. > If Scope(SA) < Scope(SB): If Scope(SA) < Scope(D), then prefer SB and > otherwise prefer SA. Similarly, if Scope(SB) < Scope(SA): If > Scope(SB) < Scope(D), then prefer SA and otherwise prefer SB. Our current implementation doesn't do that. It just checks if the scope of a possible source is lesser than the scope of the destination (which involves the second "If" in the rule). This fix grants points according to the scope of an address. If the scope matches, they get the highest points, ensuring that the selected source will always be reachable from the destination. [RFC6724]: https://tools.ietf.org/html/rfc6724 --- sys/net/gnrc/netif/gnrc_netif.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index dc75dcfe69..0c66105949 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -987,10 +987,7 @@ static int _create_candidate_set(const gnrc_netif_t *netif, /* number of "points" assigned to an source address candidate with equal scope * than destination address */ -#define RULE_2A_PTS (4) -/* number of "points" assigned to an source address candidate with smaller scope - * than destination address */ -#define RULE_2B_PTS (2) +#define RULE_2_PTS (IPV6_ADDR_MCAST_SCP_GLOBAL + 1) /* number of "points" assigned to an source address candidate in preferred state */ #define RULE_3_PTS (1) @@ -1051,7 +1048,7 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif_t *netif, DEBUG("Checking address: %s\n", ipv6_addr_to_str(addr_str, ptr, sizeof(addr_str))); - /* entries which are not part of the candidate set can be ignored */ + /* entries which are not part of the candidate set can be ignored */ if (!(bf_isset(candidate_set, i))) { DEBUG("Not part of the candidate set - skipping\n"); continue; @@ -1067,11 +1064,26 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif_t *netif, uint8_t candidate_scope = _get_scope(ptr); if (candidate_scope == dst_scope) { DEBUG("winner for rule 2 (same scope) found\n"); - winner_set[i] += RULE_2A_PTS; + winner_set[i] += (dst_scope + RULE_2_PTS); } - else if (candidate_scope < dst_scope) { + else if (candidate_scope > dst_scope) { + DEBUG("winner for rule 2 (larger scope) found\n"); + /* From https://tools.ietf.org/html/rfc6724#section-5: + * > Rule 2: Prefer appropriate scope. + * > If Scope(SA) < Scope(SB): If Scope(SA) < Scope(D), then prefer + * > SB and otherwise prefer SA. + * Meaning give address with larger scope than `dst` but closest to + * `dst` precedence. + * As the if above already ensures that the scope is larger than + * the scope of the destination address we give the address with the + * smallest scope that lands here the highest score */ + winner_set[i] += (dst_scope + (RULE_2_PTS - candidate_scope)); + } + else { DEBUG("winner for rule 2 (smaller scope) found\n"); - winner_set[i] += RULE_2B_PTS; + /* don't add `dst_scope` here to keep it smaller than larger and + * equal scope */ + winner_set[i] += candidate_scope; } /* Rule 3: Avoid deprecated addresses. */ From 85737a04367063cef4c425cccf70c9c4e383b5ea Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Fri, 10 Jan 2020 18:13:58 +0100 Subject: [PATCH 2/3] gnrc_netif: remove misleading comment The comment exists since the introduction of the [original implementation], but its meaning is unclear and misleading, as the code doesn't do anything with link-local. [original implementation]: https://github.com/RIOT-OS/RIOT/pull/3561 --- sys/net/gnrc/netif/gnrc_netif.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 0c66105949..718af5a74e 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -1060,7 +1060,6 @@ static ipv6_addr_t *_src_addr_selection(gnrc_netif_t *netif, return ptr; } /* Rule 2: Prefer appropriate scope. */ - /* both link local */ uint8_t candidate_scope = _get_scope(ptr); if (candidate_scope == dst_scope) { DEBUG("winner for rule 2 (same scope) found\n"); From 018e3dd437162fd30af0beebe9476e8dd537f134 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Mon, 13 Jan 2020 14:43:59 +0100 Subject: [PATCH 3/3] gnrc_netif: use scope directly from address for multicast --- sys/net/gnrc/netif/gnrc_netif.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 718af5a74e..31ec00386f 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -892,7 +892,12 @@ static int _match_to_idx(const gnrc_netif_t *netif, static uint8_t _get_scope(const ipv6_addr_t *addr) { - if (ipv6_addr_is_link_local(addr)) { + if (ipv6_addr_is_multicast(addr)) { + /* return multicast scope as is, see + * https://tools.ietf.org/html/rfc4291#section-2.7*/ + return addr->u8[1] & 0x0f; + } + else if (ipv6_addr_is_link_local(addr)) { return IPV6_ADDR_MCAST_SCP_LINK_LOCAL; } else if (ipv6_addr_is_site_local(addr)) {