Skip to content
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: include RIO with all subnets in downstream RA #19644

Merged
merged 2 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions sys/include/net/gnrc/ipv6/nib/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
fabian18 marked this conversation as resolved.
Show resolved Hide resolved
#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
Expand Down
113 changes: 81 additions & 32 deletions sys/net/gnrc/network_layer/ipv6/nib/_nib-router.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
* Copyright (C) 2021 ML!PA Consulting GmbH
*
Expand Down