gnrc_ipv6_nib: consider all prefixes when deciding on-link next hop

Consider the following configuration:

    nib prefix
    2001:16b8:4569:88fc::/62 dev #7  expires 7081 sec deprecates 3481 sec
    2001:16b8:4569:88fe::/63 dev #6

If `_on_link()` stops at the first match, a packet received from #7 with a
destination in the downstream subnet in #6 would always be sent back via #7
if this happens to be the first entry in the list.

Instead, consider all prefixes and return the one that is the closest match.
This commit is contained in:
Benjamin Valentin 2021-06-07 12:53:17 +02:00
parent 029cc50e72
commit d2b6f79143

View File

@ -168,6 +168,7 @@ void gnrc_ipv6_nib_init_iface(gnrc_netif_t *netif)
static bool _on_link(const ipv6_addr_t *dst, unsigned *iface)
{
_nib_offl_entry_t *entry = NULL;
uint8_t best_pfx = 0;
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN)
if (*iface != 0) {
@ -178,11 +179,15 @@ static bool _on_link(const ipv6_addr_t *dst, unsigned *iface)
#endif /* CONFIG_GNRC_IPV6_NIB_6LN */
while ((entry = _nib_offl_iter(entry))) {
if ((entry->mode & _PL) && (entry->flags & _PFX_ON_LINK) &&
(ipv6_addr_match_prefix(dst, &entry->pfx) >= entry->pfx_len)) {
(ipv6_addr_match_prefix(dst, &entry->pfx) >= entry->pfx_len) &&
(entry->pfx_len > best_pfx)) {
*iface = _nib_onl_get_if(entry->next_hop);
return true;
best_pfx = entry->pfx_len;
}
}
if (best_pfx) {
return true;
}
return ipv6_addr_is_link_local(dst);
}