mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
gnrc_ipv6_nib: include RIO with all subnets in downstream RA
This commit is contained in:
parent
4c27aff295
commit
41f9c2593d
@ -143,6 +143,22 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Include a Route Information Option for subnets
|
||||
* on other interfaces in normal Router Advertisements
|
||||
* generated by @ref gnrc_ipv6_nib_change_rtr_adv_iface
|
||||
*
|
||||
* This is only needed if your node is an upstream router,
|
||||
* but not the default router, but you want to propagate
|
||||
* the information that the custom subnets it knows about
|
||||
* should be routed through it instead of the default route.
|
||||
*
|
||||
* Requires the `gnrc_ipv6_nib_rio` module.
|
||||
*/
|
||||
#ifndef CONFIG_GNRC_IPV6_NIB_ADD_RIO_IN_RA
|
||||
#define CONFIG_GNRC_IPV6_NIB_ADD_RIO_IN_RA 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Include a Route Information Option for subnets
|
||||
* on other interfaces in the last Router Advertisement
|
||||
|
@ -144,6 +144,78 @@ static inline uint16_t _nib_abr_entry_valid_offset(const _nib_abr_entry_t *abr)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if a different prefix already includes the prefix of the entry */
|
||||
static bool _has_better_match(const _nib_offl_entry_t *entry)
|
||||
{
|
||||
_nib_offl_entry_t *candidate = NULL;
|
||||
|
||||
while ((candidate = _nib_offl_iter(candidate))) {
|
||||
|
||||
if (candidate == entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(entry->mode & (_PL | _FT))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate->pfx_len >= entry->pfx_len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ipv6_addr_match_prefix(&entry->pfx, &candidate->pfx) == candidate->pfx_len) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gnrc_pktsnip_t *_add_rio(gnrc_netif_t *netif, gnrc_pktsnip_t *ext_opts, bool offl)
|
||||
{
|
||||
_nib_offl_entry_t *entry = NULL;
|
||||
uint32_t now = evtimer_now_msec();
|
||||
|
||||
while ((entry = _nib_offl_iter(entry))) {
|
||||
|
||||
unsigned id = netif->pid;
|
||||
if (_nib_onl_get_if(entry->next_hop) == id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry->pfx_len == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (offl && _has_better_match(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool local_pfx = (entry->mode & _PL) && (entry->flags & _PFX_ON_LINK);
|
||||
bool routed_pfx = (entry->mode & _FT);
|
||||
|
||||
if (local_pfx || (offl && routed_pfx)) {
|
||||
|
||||
DEBUG("nib: adding downstream subnet to RA\n");
|
||||
uint32_t valid_ltime = (entry->valid_until == UINT32_MAX) ? UINT32_MAX :
|
||||
((entry->valid_until - now) / MS_PER_SEC);
|
||||
gnrc_pktsnip_t *snip = gnrc_ndp_opt_ri_build(&entry->pfx,
|
||||
entry->pfx_len,
|
||||
valid_ltime,
|
||||
NDP_OPT_RI_FLAGS_PRF_ZERO,
|
||||
ext_opts);
|
||||
if (snip != NULL) {
|
||||
ext_opts = snip;
|
||||
} else {
|
||||
DEBUG_PUTS("nib: can't add RIO to RA - out of memory");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ext_opts;
|
||||
}
|
||||
|
||||
static gnrc_pktsnip_t *_build_ext_opts(gnrc_netif_t *netif,
|
||||
_nib_abr_entry_t *abr)
|
||||
{
|
||||
@ -232,6 +304,12 @@ static gnrc_pktsnip_t *_build_ext_opts(gnrc_netif_t *netif,
|
||||
}
|
||||
}
|
||||
|
||||
/* advertise route to off-link subnets */
|
||||
if (CONFIG_GNRC_IPV6_NIB_ADD_RIO_IN_RA) {
|
||||
DEBUG("nib: add RIO to RA on interface %u\n", netif->pid);
|
||||
ext_opts = _add_rio(netif, ext_opts, true);
|
||||
}
|
||||
|
||||
return ext_opts;
|
||||
}
|
||||
|
||||
@ -243,39 +321,10 @@ static gnrc_pktsnip_t *_build_ext_opts(gnrc_netif_t *netif,
|
||||
static gnrc_pktsnip_t *_build_final_ext_opts(gnrc_netif_t *netif)
|
||||
{
|
||||
gnrc_pktsnip_t *ext_opts = NULL;
|
||||
_nib_offl_entry_t *entry = NULL;
|
||||
|
||||
if (!IS_USED(MODULE_GNRC_IPV6_NIB_RIO) ||
|
||||
!IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ADD_RIO_IN_LAST_RA)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG("nib: sending final RA on interface %u\n", netif->pid);
|
||||
|
||||
uint32_t now = evtimer_now_msec();
|
||||
while ((entry = _nib_offl_iter(entry))) {
|
||||
|
||||
unsigned id = netif->pid;
|
||||
if (_nib_onl_get_if(entry->next_hop) == id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((entry->mode & _PL) && (entry->flags & _PFX_ON_LINK)) {
|
||||
DEBUG("nib: adding downstream subnet to RA\n");
|
||||
uint32_t valid_ltime = (entry->valid_until == UINT32_MAX) ? UINT32_MAX :
|
||||
((entry->valid_until - now) / MS_PER_SEC);
|
||||
gnrc_pktsnip_t *snip = gnrc_ndp_opt_ri_build(&entry->pfx,
|
||||
entry->pfx_len,
|
||||
valid_ltime,
|
||||
NDP_OPT_RI_FLAGS_PRF_ZERO,
|
||||
ext_opts);
|
||||
if (snip != NULL) {
|
||||
ext_opts = snip;
|
||||
} else {
|
||||
DEBUG_PUTS("nib: can't add RIO to RA - out of memory");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CONFIG_GNRC_IPV6_NIB_ADD_RIO_IN_LAST_RA) {
|
||||
DEBUG("nib: add RIO to final RA on interface %u\n", netif->pid);
|
||||
ext_opts = _add_rio(netif, ext_opts, false);
|
||||
}
|
||||
|
||||
return ext_opts;
|
||||
|
Loading…
Reference in New Issue
Block a user