Skip to content

Commit

Permalink
gnrc/ipv6_auto_subnets: add gnrc_ipv6_auto_subnets_eui
Browse files Browse the repository at this point in the history
  • Loading branch information
benpicco committed Jan 10, 2025
1 parent 64c10f3 commit 1f3c056
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ PSEUDOMODULES += gnrc_dhcpv6_client_simple_pd
## @}
## @}
PSEUDOMODULES += gnrc_ipv6_auto_subnets_auto_init
PSEUDOMODULES += gnrc_ipv6_auto_subnets_eui
PSEUDOMODULES += gnrc_ipv6_auto_subnets_simple
PSEUDOMODULES += gnrc_ipv6_classic
PSEUDOMODULES += gnrc_ipv6_default
Expand Down
4 changes: 4 additions & 0 deletions sys/net/gnrc/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ ifneq (,$(filter gnrc_rpl,$(USEMODULE)))
USEMODULE += evtimer
endif

ifneq (,$(filter gnrc_ipv6_auto_subnets_eui,$(USEMODULE)))
USEMODULE += gnrc_ipv6_auto_subnets_simple
endif

ifneq (,$(filter gnrc_ipv6_auto_subnets_simple,$(USEMODULE)))
USEMODULE += gnrc_ipv6_auto_subnets
endif
Expand Down
56 changes: 55 additions & 1 deletion sys/net/gnrc/routing/ipv6_auto_subnets/gnrc_ipv6_auto_subnets.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,24 @@
* The upstream network will be automatically chosen as the one that first
* receives a router advertisement.
*
* If only a single level of downstream routers exists and a sufficiently small
* upstream prefix is provided, we can skip the synchronisation and instead derive
* the *prefix* from the EUI of the downstream interface.
*
* e.g. given a prefix `fd12::/16` a router with a downstream interface with the
* layer 2 address `12:84:0C:87:1F:B7` would create the prefix `fd12:1284:c87:1fb7::/64`
* for the downstream network.
*
* To enable this behavior, chose the `gnrc_ipv6_auto_subnets_eui` module.
*
* @{
*
* @file
* @author Benjamin Valentin <[email protected]>
*/

#include "compiler_hints.h"
#include "macros/utils.h"
#include "net/gnrc/ipv6.h"
#include "net/gnrc/netif.h"
#include "net/gnrc/netif/hdr.h"
Expand Down Expand Up @@ -305,6 +316,35 @@ static void _init_sub_prefix(ipv6_addr_t *out,
out->u8[bytes] |= idx << shift;
}

static void _init_sub_prefix_eui(ipv6_addr_t *out,
const ipv6_addr_t *prefix, uint8_t bits,
const uint8_t *eui, uint8_t eui_len)
{
assert(eui_len <= sizeof(uint64_t));

/* If the EUI is too large, discard most significant bits as
those are typically manufacturer ID */
uint64_t mask = ~((1ULL << bits) - 1);
union {
uint64_t u64;
uint8_t u8[8];
} eui64 = {};

/* If EUI is small, we want to preserve leftover unused bits at the end */
uint8_t bits_total = bits + 8 * eui_len;
uint8_t shift = bits_total < 64
? 64 - bits_total
: 0;

/* treat EUI as a EUI-64 with unused bytes set to 0 */
memcpy(&eui64.u8[sizeof(uint64_t) - eui_len], eui, eui_len);

/* create downstream prefix from upstream prefix + masked EUI64 */
out->u64[0].u64 = prefix->u64[0].u64
| ((eui64.u64 & mask) >> shift);
out->u64[1].u64 = 0;
}

/* returns true if a new prefix was added, false if nothing changed */
static bool _remove_old_prefix(gnrc_netif_t *netif,
const ipv6_addr_t *pfx, uint8_t pfx_len,
Expand Down Expand Up @@ -393,7 +433,21 @@ static void _configure_subnets(uint8_t subnets, uint8_t start_idx, gnrc_netif_t
}

/* create subnet from upstream prefix */
_init_sub_prefix(&new_prefix, prefix, prefix_len, ++start_idx, subnet_len);
if (IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_EUI)) {
uint8_t hwaddr[GNRC_NETIF_L2ADDR_MAXLEN];
int hwaddr_len = netif_get_opt(&downstream->netif, NETOPT_ADDRESS, 0,
hwaddr, sizeof(hwaddr));
if (hwaddr_len <= 0) {
DEBUG("auto_subnets: can't get l2 address from netif %u\n", downstream->pid);
continue;
}
_init_sub_prefix_eui(&new_prefix, prefix, prefix_len, hwaddr, hwaddr_len);

new_prefix_len = prefix_len + 8 * hwaddr_len;
new_prefix_len = MAX(new_prefix_len, CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN);
} else {
_init_sub_prefix(&new_prefix, prefix, prefix_len, ++start_idx, subnet_len);
}

DEBUG("auto_subnets: configure prefix %s/%u on %u\n",
ipv6_addr_to_str(addr_str, &new_prefix, sizeof(addr_str)),
Expand Down

0 comments on commit 1f3c056

Please sign in to comment.