1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-18 11:03:50 +01:00

Merge pull request #21454 from benpicco/gnrc_ipv6_nib_get_next_hop_l2addr-cleanup

gnrc/ipv6/nib: clean up `gnrc_ipv6_nib_get_next_hop_l2addr()`
This commit is contained in:
benpicco 2025-07-24 11:35:14 +00:00 committed by GitHub
commit cdfdd215f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -304,102 +304,105 @@ int gnrc_ipv6_nib_get_next_hop_l2addr(const ipv6_addr_t *dst,
DEBUG("nib: get next hop link-layer address of %s%%%u\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)),
(netif != NULL) ? (unsigned)netif->pid : 0U);
netif ? (unsigned)netif->pid : 0);
gnrc_netif_acquire(netif);
_nib_acquire();
do { /* XXX: hidden goto ;-) */
_nib_onl_entry_t *node = _nib_onl_nc_get(dst,
(netif == NULL) ? 0 : netif->pid);
/* consider neighbor cache entries first */
unsigned iface = (node == NULL) ? 0 : _nib_onl_get_if(node);
if ((node != NULL) || _on_link(dst, &iface)) {
DEBUG("nib: %s is %s, start address resolution\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)),
node ? "in NC" : "on-link");
/* on-link prefixes return their interface */
if (!ipv6_addr_is_link_local(dst) && (iface != 0)) {
/* release pre-assumed netif */
gnrc_netif_release(netif);
netif = _acquire_new_iface(iface);
/* get node from proper interface */
if (netif != NULL) {
node = _nib_onl_nc_get(dst, netif->pid);
}
}
if ((netif == NULL) ||
!_resolve_addr(dst, netif, pkt, nce, node)) {
DEBUG("nib: host unreachable\n");
/* _resolve_addr releases pkt only if not queued (in which case
* we also shouldn't release), but if netif is not defined we
* should release in any case. */
if ((netif == NULL) && (pkt != NULL)) {
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR,
pkt);
gnrc_pktbuf_release_error(pkt, EHOSTUNREACH);
}
res = -EHOSTUNREACH;
break;
_nib_onl_entry_t *node = _nib_onl_nc_get(dst, netif ? netif->pid : 0);
/* consider neighbor cache entries first */
unsigned iface = (node == NULL) ? 0 : _nib_onl_get_if(node);
if ((node != NULL) || _on_link(dst, &iface)) {
DEBUG("nib: %s is %s, start address resolution\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)),
node ? "in NC" : "on-link");
/* on-link prefixes return their interface */
if (!ipv6_addr_is_link_local(dst) && (iface != 0)) {
/* release pre-assumed netif */
gnrc_netif_release(netif);
netif = _acquire_new_iface(iface);
/* get node from proper interface */
if (netif != NULL) {
node = _nib_onl_nc_get(dst, netif->pid);
}
}
else {
gnrc_ipv6_nib_ft_t route;
if ((netif == NULL) ||
!_resolve_addr(dst, netif, pkt, nce, node)) {
DEBUG("nib: host unreachable\n");
/* _resolve_addr releases pkt only if not queued (in which case
* we also shouldn't release), but if netif is not defined we
* should release in any case. */
if ((netif == NULL) && (pkt != NULL)) {
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR,
pkt);
gnrc_pktbuf_release_error(pkt, EHOSTUNREACH);
}
res = -EHOSTUNREACH;
}
goto out;
}
DEBUG("nib: %s is off-link, resolve route\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)));
res = _nib_get_route(dst, pkt, &route);
if ((res < 0) || ipv6_addr_is_unspecified(&route.next_hop)) {
DEBUG("nib: no route to %s found or is prefix list entry, "
"search neighbor cache\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)));
gnrc_ipv6_nib_ft_t route;
if ((res == 0) &&
/* If ARSM is not active only use link-local as next hop */
(IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) ||
ipv6_addr_is_link_local(dst))) {
DEBUG("nib: prefix list entry => taking dst as next hop\n");
memcpy(&route.next_hop, dst, sizeof(route.next_hop));
}
else {
res = -ENETUNREACH;
if (pkt != NULL) {
gnrc_icmpv6_error_dst_unr_send(
ICMPV6_ERROR_DST_UNR_NO_ROUTE,
pkt
);
gnrc_pktbuf_release_error(pkt, ENETUNREACH);
}
break;
}
}
if ((netif != NULL) && (netif->pid != (int)route.iface)) {
/* release pre-assumed netif */
gnrc_netif_release(netif);
}
if ((netif == NULL) || (netif->pid != (int)route.iface)) {
/* get actual netif */
netif = _acquire_new_iface(route.iface);
}
node = _nib_onl_nc_get(&route.next_hop,
(netif != NULL) ? netif->pid : 0);
if (_resolve_addr(&route.next_hop, netif, pkt, nce, node)) {
_call_route_info_cb(netif,
GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RN,
&route.dst,
(void *)((intptr_t)route.dst_len));
DEBUG("nib: %s is off-link, resolve route\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)));
res = _nib_get_route(dst, pkt, &route);
/* If ARSM is not active only use link-local as next hop */
if (!IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) &&
ipv6_addr_is_unspecified(&route.next_hop) &&
!ipv6_addr_is_link_local(dst)) {
res = -ENETUNREACH;
}
if (res < 0) {
DEBUG("nib: no route to %s found or is prefix list entry, "
"search neighbor cache\n",
ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)));
if (pkt != NULL) {
gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_NO_ROUTE, pkt);
gnrc_pktbuf_release_error(pkt, ENETUNREACH);
}
res = -ENETUNREACH;
goto out;
}
if (ipv6_addr_is_unspecified(&route.next_hop)) {
DEBUG("nib: prefix list entry => taking dst as next hop\n");
memcpy(&route.next_hop, dst, sizeof(route.next_hop));
}
if ((netif != NULL) && (netif->pid != (int)route.iface)) {
/* release pre-assumed netif */
gnrc_netif_release(netif);
}
if ((netif == NULL) || (netif->pid != (int)route.iface)) {
/* get actual netif */
netif = _acquire_new_iface(route.iface);
}
node = _nib_onl_nc_get(&route.next_hop, netif ? netif->pid : 0);
if (_resolve_addr(&route.next_hop, netif, pkt, nce, node)) {
_call_route_info_cb(netif,
GNRC_IPV6_NIB_ROUTE_INFO_TYPE_RN,
&route.dst,
(void *)((intptr_t)route.dst_len));
#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_DC)
_nib_dc_add(&route.next_hop, netif->pid, dst);
_nib_dc_add(&route.next_hop, netif->pid, dst);
#endif /* CONFIG_GNRC_IPV6_NIB_DC */
}
else {
/* _resolve_addr releases pkt if not queued (in which case
* we also shouldn't release */
res = -EHOSTUNREACH;
}
}
} while (0);
}
else {
/* _resolve_addr releases pkt if not queued (in which case
* we also shouldn't release */
res = -EHOSTUNREACH;
}
out:
_nib_release();
gnrc_netif_release(netif);
return res;
}