-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gnrc_ipv6_nib: clean up _resolve_addr() #18939
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1251,25 +1251,88 @@ static void _handle_nbr_adv(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, | |||||
} | ||||||
} | ||||||
|
||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) | ||||||
static gnrc_pktqueue_t *_alloc_queue_entry(gnrc_pktsnip_t *pkt) | ||||||
{ | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) | ||||||
for (int i = 0; i < CONFIG_GNRC_IPV6_NIB_NUMOF; i++) { | ||||||
if (_queue_pool[i].pkt == NULL) { | ||||||
_queue_pool[i].pkt = pkt; | ||||||
return &_queue_pool[i]; | ||||||
} | ||||||
} | ||||||
#else | ||||||
(void)pkt; | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ | ||||||
return NULL; | ||||||
} | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ | ||||||
|
||||||
static bool _resolve_addr_from_nc(_nib_onl_entry_t *entry, gnrc_netif_t *netif, | ||||||
gnrc_ipv6_nib_nc_t *nce) | ||||||
{ | ||||||
if (entry == NULL) { | ||||||
return false; | ||||||
} | ||||||
|
||||||
if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM)) { | ||||||
if (!_is_reachable(entry)) { | ||||||
return false; | ||||||
} | ||||||
|
||||||
if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE) { | ||||||
_set_nud_state(netif, entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); | ||||||
_evtimer_add(entry, GNRC_IPV6_NIB_DELAY_TIMEOUT, | ||||||
&entry->nud_timeout, NDP_DELAY_FIRST_PROBE_MS); | ||||||
} | ||||||
} | ||||||
|
||||||
_nib_nc_get(entry, nce); | ||||||
return true; | ||||||
} | ||||||
|
||||||
static bool _enqueue_for_resolve(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, | ||||||
_nib_onl_entry_t *entry) | ||||||
{ | ||||||
if (!IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) || | ||||||
_get_nud_state(entry) != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) { | ||||||
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, pkt); | ||||||
gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); | ||||||
return true; | ||||||
} | ||||||
|
||||||
gnrc_pktqueue_t *queue_entry = _alloc_queue_entry(pkt); | ||||||
|
||||||
if (queue_entry == NULL) { | ||||||
DEBUG("nib: can't allocate entry for packet queue " | ||||||
"dropping packet\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
return false; | ||||||
} | ||||||
|
||||||
if (netif != NULL) { | ||||||
gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0); | ||||||
|
||||||
if (netif_hdr == NULL) { | ||||||
DEBUG("nib: can't allocate netif header for queue\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
queue_entry->pkt = NULL; | ||||||
return false; | ||||||
} | ||||||
gnrc_netif_hdr_set_netif(netif_hdr->data, netif); | ||||||
queue_entry->pkt = gnrc_pkt_prepend(queue_entry->pkt, netif_hdr); | ||||||
} | ||||||
|
||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) | ||||||
gnrc_pktqueue_add(&entry->pktqueue, queue_entry); | ||||||
#else | ||||||
(void)entry; | ||||||
#endif | ||||||
return true; | ||||||
} | ||||||
|
||||||
static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, | ||||||
gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce, | ||||||
_nib_onl_entry_t *entry) | ||||||
{ | ||||||
bool res = false; | ||||||
|
||||||
if ((netif != NULL) && (netif->device_type == NETDEV_TYPE_SLIP)) { | ||||||
/* XXX: Linux doesn't do neighbor discovery for SLIP so no use sending | ||||||
* NS and since SLIP doesn't have link-layer addresses anyway, we can | ||||||
|
@@ -1279,107 +1342,57 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, | |||||
nce->l2addr_len = 0; | ||||||
return true; | ||||||
} | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) | ||||||
if ((entry != NULL) && _is_reachable(entry)) { | ||||||
if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE) { | ||||||
_set_nud_state(netif, entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); | ||||||
_evtimer_add(entry, GNRC_IPV6_NIB_DELAY_TIMEOUT, | ||||||
&entry->nud_timeout, NDP_DELAY_FIRST_PROBE_MS); | ||||||
} | ||||||
|
||||||
/* first check if address is cached */ | ||||||
if (_resolve_addr_from_nc(entry, netif, nce)) { | ||||||
DEBUG("nib: resolve address %s%%%u from neighbor cache\n", | ||||||
ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), | ||||||
_nib_onl_get_if(entry)); | ||||||
_nib_nc_get(entry, nce); | ||||||
res = true; | ||||||
return true; | ||||||
} | ||||||
#else /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
if (entry != NULL) { | ||||||
DEBUG("nib: resolve address %s%%%u from neighbor cache\n", | ||||||
ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), | ||||||
_nib_onl_get_if(entry)); | ||||||
_nib_nc_get(entry, nce); | ||||||
res = true; | ||||||
|
||||||
/* directly resolve address if it uses 6lo addressing mode */ | ||||||
if (_resolve_addr_from_ipv6(dst, netif, nce)) { | ||||||
DEBUG("nib: resolve l2 address from IPv6 address\n"); | ||||||
return true; | ||||||
} | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
else if (!(res = _resolve_addr_from_ipv6(dst, netif, nce))) { | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) | ||||||
bool reset = false; | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
|
||||||
DEBUG("nib: resolve address %s by probing neighbors\n", | ||||||
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); | ||||||
bool reset = false; | ||||||
DEBUG("nib: resolve address %s by probing neighbors\n", | ||||||
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); | ||||||
if (entry == NULL) { | ||||||
entry = _nib_nc_add(dst, netif ? netif->pid : 0, | ||||||
GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); | ||||||
if (entry == NULL) { | ||||||
entry = _nib_nc_add(dst, (netif != NULL) ? netif->pid : 0, | ||||||
GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); | ||||||
if (entry == NULL) { | ||||||
DEBUG("nib: can't resolve address, neighbor cache full\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
return false; | ||||||
} | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ROUTER) | ||||||
if (netif != NULL) { | ||||||
_call_route_info_cb(netif, | ||||||
GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, | ||||||
dst, | ||||||
(void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); | ||||||
} | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ROUTER */ | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) | ||||||
reset = true; | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
DEBUG("nib: can't resolve address, neighbor cache full\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
return false; | ||||||
} | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) | ||||||
else if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE) { | ||||||
/* reduce back-off to possibly resolve neighbor sooner again */ | ||||||
entry->ns_sent = 3; | ||||||
} | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
if (pkt != NULL) { | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) | ||||||
if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) { | ||||||
gnrc_pktqueue_t *queue_entry = _alloc_queue_entry(pkt); | ||||||
|
||||||
if (queue_entry != NULL) { | ||||||
if (netif != NULL) { | ||||||
gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build( | ||||||
NULL, 0, NULL, 0 | ||||||
); | ||||||
if (netif_hdr == NULL) { | ||||||
DEBUG("nib: can't allocate netif header for queue\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
queue_entry->pkt = NULL; | ||||||
return false; | ||||||
} | ||||||
gnrc_netif_hdr_set_netif(netif_hdr->data, netif); | ||||||
queue_entry->pkt = gnrc_pkt_prepend(queue_entry->pkt, | ||||||
netif_hdr); | ||||||
} | ||||||
gnrc_pktqueue_add(&entry->pktqueue, queue_entry); | ||||||
} | ||||||
else { | ||||||
DEBUG("nib: can't allocate entry for packet queue " | ||||||
"dropping packet\n"); | ||||||
gnrc_pktbuf_release(pkt); | ||||||
return false; | ||||||
} | ||||||
} | ||||||
/* pkt != NULL already checked above */ | ||||||
else { | ||||||
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, | ||||||
pkt); | ||||||
gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); | ||||||
} | ||||||
#else /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ | ||||||
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, | ||||||
pkt); | ||||||
gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ | ||||||
if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ROUTER) && netif != NULL) { | ||||||
_call_route_info_cb(netif, | ||||||
GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, | ||||||
dst, | ||||||
(void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); | ||||||
} | ||||||
reset = true; | ||||||
} | ||||||
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) | ||||||
else if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE) { | ||||||
/* reduce back-off to possibly resolve neighbor sooner again */ | ||||||
entry->ns_sent = 3; | ||||||
} | ||||||
#endif | ||||||
|
||||||
/* queue packet as we have to do address resolution first */ | ||||||
if (pkt != NULL && !_enqueue_for_resolve(netif, pkt, entry)) { | ||||||
return false; | ||||||
} | ||||||
|
||||||
if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM)) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a feeling that this should in fact be
Suggested change
but I'll leave this PR to cleanups only. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it shoud still be possible to activate the ARSM optionally on 6Lo nodes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (also resolution by address generation reversal is also a nice feature for non-6Lo-nodes to have (and will become necessary with SCHC at some point too). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But that would be a separate config then, right? Because right now we only have So the BR will do ARSM on the 6lo interface (because it needs it on the upstream interface) but the 6lo nodes do not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my opinion,
6LN actually do NUD and additionally include an
For some things like joining the Solicited-node multicast address and multicast L2 address resolution, we just exclude 6LN interfaces. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
hm might this be the reason for #17327 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. very hard to tell... To be honest I am not very familiar with RPL. I have to catch up here. |
||||||
_probe_nbr(entry, reset); | ||||||
#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ | ||||||
} | ||||||
return res; | ||||||
|
||||||
return false; | ||||||
} | ||||||
|
||||||
static void _handle_snd_na(gnrc_pktsnip_t *pkt) | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, this
if
clause could use a niceDEBUG()
message too.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this should be moved above
_resolve_addr_from_nc()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be, maybe, but not necessarily.
And if
_resolve_addr_from_nc()
fails to resolve the L2 address, we know we don´t have an NC entry and we have to add one, or it existed but was UNREACHABLE. Also having (netif
+dst
) andentry
as input is a bit redundant.... I don´t know, maybe the clean up could propagate upwards, but not without changing too much I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand what you want me to do 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I misread your last comment. I thought you wanted to merge
_resolve_addr_from_nc()
and_resolve_addr_from_ipv6()
into one function. Then I thought about how this would look like.Ok, moving
_resolve_addr_from_ipv6()
above_resolve_addr_from_nc()
and keeping them as they are now,would mean that every link-local destination address would be resolved immediately by reverse translation.
This would mean that link local addresses would not have to be registered. But this is somewhat required if the link local address is a private address (CGA or SLAAC pivacy extension) .
Let´s say
R
is the upstream router of hostH
.H
implements the SLAAC privacy extension and builds a private link local address that it registers toR
where due to an SLLA option an NCA is created there.If
R
would not examine the NCE when it sends something to the private SLAAC address ofH
, it would put the wrong L2 address in the frame.In fact, in my
SEND
branch, I added this:to
_resolve_addr_from_ipv6()
.