1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

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
This commit is contained in:
Martine S. Lenders 2019-10-09 18:23:29 +02:00
parent 0364c39694
commit 46fd632e91
No known key found for this signature in database
GPG Key ID: CCD317364F63286F

View File

@ -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. */