gnrc_netif: only use prefix matching as tie-breaker in source selection#12408
Conversation
|
After thinking about this some more, I think using |
|
Done. |
| unsigned match; | ||
|
|
||
| if ((netif->ipv6.addrs_flags[i] == 0) || | ||
| ((filter != NULL) && _addr_anycast(netif, i)) || |
There was a problem hiding this comment.
See RFC 6724, page 30, point 3: This can be removed without alternative.
|
I added a test for the corner case, that popped up due to the fix in #12404. |
279a079 to
9d98410
Compare
|
Squashed, rebased, added the commit from #12404 and added some more test cases. |
|
@fjmolinas @kb2ma can one of you maybe give this a look? |
|
@kaspar030 made me aware off-line of section 2.2 in RFC 6724 regarding the function "commonPrefixLen()" that is used in rule 8. I adapted the code accordingly. |
|
Looking into this now. The decision to merge this PR is the last issue before generation of the 2019.10 release branch. |
|
Pushed a bit too early and added some fixes to that function now. |
|
Sorry, yet another issue... I'll just say when I'm done... :( |
|
No worries, @miri64. I need a little time to understand the issues anyway. |
|
Section 2.2 in RFC 6724 actually makes one of the test cases invalid, so I removed it. The tests are now passing again. Sorry for these last minute changes. |
|
@kb2ma do you mind if I squash? I somehow messed up my fixup commits, I just noticed... |
|
Go right ahead. I would likely skip over the intermediate results anyway. |
64fbe48 to
be51b00
Compare
|
Squashed
At least for the review I think it helps if you go through it commit-wise (not all tests work for all commits though), as I tried to make my thinking process clearer with the history. Additionally, the PR contains some clean-up of now unnecessary code, that resulted from fixing the bugs and adapting it more in line with RFC 6724. |
be51b00 to
2ad840e
Compare
|
(I'm now done, btw) |
|
Sounds good. I've got a basic handle on the issues. Is the testing procedure in the PR description still valid? |
|
Yepp |
|
Except for the merging of #12404 part in (2), as that one is part of this PR now ;-). |
9c81c73 to
d7c4eec
Compare
|
Rebased to current master, no longer waiting for other PR. |
| * address. | ||
| * (so don't consider tentative addresses for source address | ||
| * selection) */ | ||
| gnrc_netif_ipv6_addr_dad_trans(netif, i)) { |
There was a problem hiding this comment.
I know this line is not part of this PR, but could you clarify why addresses are not considered that have gnrc_netif_ipv6_addr_dad_trans() != 0? According to the doc of this function, the return value is:
the number of duplicate address detection transmissions already performed
How can we deduce that the address is tentative from that result?
There was a problem hiding this comment.
The number of DAD transmissions is encoded in the tentative state in our DAD implementation (that's why you see TNT[1..3] with the ifconfig command, not just TNT). So a value of 0 for already performed DAD transmissions means the address is not tentative. As the NS for DAD is sent as soon as the address is added, this is also true if you don't have the knowledge of such GNRC internals ;)
There was a problem hiding this comment.
See also doc for tentative state:
RIOT/sys/include/net/gnrc/netif/ipv6.h
Lines 48 to 55 in 55adbee
fjmolinas
left a comment
There was a problem hiding this comment.
Testing:
- Pinging the link-local address between two native instances should still select the link-local address of the sender
- pinging fd00:dead:beef::1 from a examples/gnrc_networking node via an examples/gnrc_border_router node should still work
ping6 fd00:dead:beef::1
2019-10-22 13:59:44,921 # ping6 fd00:dead:beef::1
2019-10-22 13:59:45,987 # 12 bytes from fd00:dead:beef::1: icmp_seq=1 ttl=63 rssi=-33 dBm time=59.327 ms
2019-10-22 13:59:46,963 # 12 bytes from fd00:dead:beef::1: icmp_seq=2 ttl=63 rssi=-32 dBm time=36.240 ms
2019-10-22 13:59:47,920 #
2019-10-22 13:59:47,924 # --- fd00:dead:beef::1 PING statistics ---
2019-10-22 13:59:47,929 # 3 packets transmitted, 2 packets received, 33% packet loss
2019-10-22 13:59:47,933 # round-trip min/avg/max = 36.240/47.783/59.327 ms
- make -C tests/gnrc_netif flash test should still work for a board of your choice
.......................................................................
OK (71 tests)
Also this seems to fix the issue pointed out in #11818, it is always selecting the first lla EUI64 address.
@miri64 just to be sure after new commits have been added, can you point out the hash of the two commits to revert? |
Sorry only noticed the activity in this PR now. I'll have a look at your review and then update :-). |
completed test procedure... |
|
Note, because I was confused for a moment: The test is supposed to fail... |
|
@miri64 please squash! |
Lets trigger tests in murdock as well! |
When source address selection is done, both RFC and comments in the code state, that a longest prefix match should *only* be used as a tie-breaker between more than one viable candidate. If there is only one address, there is a) no need for a tie-breaker b) in the case of either the destination address or the single remaining address being ULAs ([which are considered to be of global scope] [RFC4193]) possibly not matching, as `fd00::/7` and e.g. `2001::/8` do not have a common prefix. (b) in fact causes the match function to return -1, causing the source address selection to return -1, causing the outer function to return the first address it found (which most often is the link-local address), causing e.g. a ping to an ULA to fail, even is there is a global address. [RFC4193]: https://tools.ietf.org/html/rfc4193
`_match_to_idx()` was removed from source address selection (which was the only one setting the filter parameter to a non-NULL value), so it is the parameter is not needed anymore.
- ULA destination with global address on interface - Deprecated addresses
|
Squashed. |
eea3cf1 to
fa14eea
Compare
fa14eea to
020af41
Compare
|
Removed the empty commit that happened somehow due to squashing the revert commit on the original. |
fjmolinas
left a comment
There was a problem hiding this comment.
Murdock si happy! ACK!
|
Thanks for the review! |
Thanks for the fix! |

Contribution description
When source address selection is done, both RFC and comments in the code state, that a longest prefix match should only be used as a tie-breaker between more than one viable candidate. If there is only one address, there is
a) no need for a tie-breaker
b) in the case of either the destination address or the single remaining address being ULAs (which are considered to be of global scope) possibly not matching, as
fd00::/7and e.g.2001::/8do not have a common prefix.(b) in fact causes the match function to return -1, causing the source address selection to return -1, causing the outer function to return the first address it found (which most often is the link-local address), causing e.g. a ping to an ULA to fail, even is there is a global address.
I also piggy-backed a reduction of code duplication (so I can set
idxjust at one point) and added some doc on candidate creation, because some things were unclear to me when I tried to wrap my head around the problem.Testing procedure
examples/gnrc_networkingonnativeand sniffedtapbr0while pinging):fd00:dead:beef::1from aexamples/gnrc_networkingnode via anexamples/gnrc_border_routernode should still work (after the global addresses are set up on all nodes).make -C tests/gnrc_netif flash testshould still work for a board of your choice and should not work if you revert the fix to the prefix matching:git revert HEAD~2; git revert HEAD~4; make -C tests/gnrc_netifIssues/PRs references
Fixes an issue in source address selection with ULAs becoming obvious in #12404. Required to make #12404 mergable.(#12404 now is included here)Requires #12425 for address resolution to still work fully (and
tests/gnrc_ipv6_nibto pass)