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