117#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PORT 
  118#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PORT          (16179) 
  124#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX 
  125#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX     (4) 
  131#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_TX_PER_PERIOD 
  132#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TX_PER_PERIOD (3) 
  139#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_TIMEOUT_MS 
  140#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TIMEOUT_MS    (50) 
  152#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_FIX_LEN 
  153#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_FIX_LEN (0) 
  160#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN 
  161#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN (0) 
  173#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF 
  174#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF         (1) 
  185#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC 
  186#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC        (0) 
  192#define SERVER_THREAD_STACKSIZE                     (THREAD_STACKSIZE_DEFAULT) 
  193#define SERVER_MSG_QUEUE_SIZE                       (CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX) 
  194#define SERVER_MSG_TYPE_TIMEOUT                     (0x8fae) 
  196#define ENABLE_DEBUG 0 
  201#if !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) 
  206typedef struct __attribute__((packed)) {
 
  209} _auto_subnets_request_v0_t;
 
  216static char auto_subnets_stack[SERVER_THREAD_STACKSIZE];
 
  217static msg_t server_queue[SERVER_MSG_QUEUE_SIZE];
 
  230    for (
unsigned i = 0; i < 
ARRAY_SIZE(_pio_cache); ++i) {
 
  231        if (_pio_cache[i].len == 0) {
 
  232            _pio_cache[i] = *pio;
 
  244                     uint16_t port, 
const void *data, 
size_t len)
 
  250    if (payload == NULL) {
 
  251        DEBUG(
"auto_subnets: unable to copy data to packet buffer\n");
 
  258        DEBUG(
"auto_subnets: unable to allocate UDP header\n");
 
  266        DEBUG(
"auto_subnets: unable to allocate IPv6 header\n");
 
  274        if (netif_hdr == NULL) {
 
  275            DEBUG(
"auto_subnets: unable to allocate netif header\n");
 
  287        DEBUG(
"auto_subnets: unable to locate UDP thread\n");
 
  298                             uint8_t idx, uint8_t idx_bits)
 
  300    uint8_t bytes = bits / 8;
 
  301    uint8_t rem   = bits % 8;
 
  302    int8_t shift  = 8 - rem - idx_bits;
 
  305    memset(out, 0, 
sizeof(*out));
 
  310        out->
u8[bytes] |= idx >> -shift;
 
  311        out->
u8[++bytes] = 0;
 
  316    out->
u8[bytes] |= idx << shift;
 
  319static uint8_t _init_sub_prefix_eui(
ipv6_addr_t *out,
 
  321                                    const uint8_t *eui, uint8_t eui_len)
 
  323    assert(eui_len <= 
sizeof(uint64_t));
 
  327    uint64_t mask = UINT64_MAX >> bits;
 
  336    uint8_t bits_total = bits + 8 * eui_len;
 
  337    uint8_t shift = bits_total < 64
 
  342    memcpy(&eui64.u8[
sizeof(uint64_t) - eui_len], eui, eui_len);
 
  343    eui64.u64 = 
ntohll(eui64.u64) & mask;
 
  349    return MIN(64, bits_total);
 
  368        if (match_len >= pfx_len && pfx_len == entry.
pfx_len) {
 
  373        if (match_len > old_pfx_len) {
 
  384    DEBUG(
"auto_subnets: remove old prefix %s/%u\n",
 
  400static void _configure_subnets(uint8_t subnets, uint8_t start_idx, 
gnrc_netif_t *upstream,
 
  409    uint8_t new_prefix_len, subnet_len;
 
  411    DEBUG(
"auto_subnets: create %u subnets, start with %u\n", subnets, start_idx);
 
  418    subnet_len = 32 - __builtin_clz(subnets);
 
  419    new_prefix_len = prefix_len + subnet_len;
 
  421    if (new_prefix_len > 64) {
 
  422        DEBUG(
"auto_subnets: can't split /%u into %u subnets\n", prefix_len, subnets);
 
  435        if (downstream == upstream) {
 
  440        if (
IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_EUI)) {
 
  443                                           hwaddr, 
sizeof(hwaddr));
 
  444            if (hwaddr_len <= 0) {
 
  445                DEBUG(
"auto_subnets: can't get l2 address from netif %u\n", downstream->
pid);
 
  448            new_prefix_len = _init_sub_prefix_eui(&new_prefix, prefix, prefix_len, hwaddr, hwaddr_len);
 
  451            _init_sub_prefix(&new_prefix, prefix, prefix_len, ++start_idx, subnet_len);
 
  454        DEBUG(
"auto_subnets: configure prefix %s/%u on %u\n",
 
  456              new_prefix_len, downstream->
pid);
 
  459        if (_remove_old_prefix(downstream, &new_prefix, new_prefix_len, &ext_opts)) {
 
  462            idx = gnrc_netif_ipv6_add_prefix(downstream, &new_prefix, new_prefix_len,
 
  463                                         valid_ltime, pref_ltime);
 
  465                DEBUG(
"auto_subnets: adding prefix to %u failed\n", downstream->
pid);
 
  480            DEBUG(
"auto_subnets: No space left in packet buffer. Not adding RIO\n");
 
  490        DEBUG(
"auto_subnets: Options empty, not sending RA\n");
 
  513#if IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) 
  515    if (!gnrc_netif_is_6ln(upstream)) {
 
  519    _configure_subnets(subnets, 0, upstream, pio, src);
 
  524    if (!_store_pio(pio)) {
 
  525        DEBUG(
"auto_subnets: no space left in PIO cache, increase CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF\n");
 
  528    _upstream  = upstream;
 
  532        .type = SERVER_MSG_TYPE_TIMEOUT
 
  539#if !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) 
  548static bool _all_zero(
const uint8_t *addr, 
size_t len)
 
  550    for (
const uint8_t *end = addr + len; addr != end; ++addr) {
 
  568static int _alloc_l2addr_entry(
const void *addr, 
size_t len)
 
  572        if (_all_zero(l2addrs[i], len)) {
 
  576        if (memcmp(addr, l2addrs[i], len) == 0) {
 
  585    memcpy(l2addrs[empty], addr, len);
 
  606    const void *src_addr;
 
  615    if (netif_hdr == NULL) {
 
  620    hdr = netif_hdr->
data;
 
  627    if (src_addr == NULL) {
 
  632    if (_alloc_l2addr_entry(src_addr, iface->
l2addr_len) == 0) {
 
  639static void _receive_announce(
gnrc_pktsnip_t *pkt, uint8_t *subnets, uint8_t *idx_start)
 
  641    _auto_subnets_request_v0_t *request = pkt->
data;
 
  645    int res = _get_my_l2addr_rank(_upstream, pkt);
 
  648        *subnets += request->num_subnets;
 
  650        DEBUG(
"auto_subnets: %u new remote subnets, total %u\n",
 
  651              request->num_subnets, *subnets);
 
  656            *idx_start += request->num_subnets;
 
  663static void _send_announce(uint8_t local_subnets, 
xtimer_t *timer, 
msg_t *msg)
 
  666    _auto_subnets_request_v0_t request = {
 
  667        .num_subnets = local_subnets,
 
  673              &request, 
sizeof(request));
 
  680    DEBUG(
"auto_subnets: announce sent, next timeout in %" PRIu32 
" µs\n", timeout_us);
 
  683static void _process_pio_cache(uint8_t subnets, uint8_t idx_start, 
gnrc_netif_t *upstream)
 
  687    for (
unsigned i = 0; i < 
ARRAY_SIZE(_pio_cache); ++i) {
 
  688        if (!_pio_cache[i].len) {
 
  693        _configure_subnets(subnets, idx_start, upstream, &_pio_cache[i], NULL);
 
  696        _pio_cache[i].
len = 0;
 
  702static void *_eventloop(
void *arg)
 
  707    msg_t msg, timeout_msg = { .type = SERVER_MSG_TYPE_TIMEOUT };
 
  710    uint8_t idx_start = 0;
 
  711    uint8_t subnets = local_subnets;
 
  716    uint8_t subnets_old = 0;
 
  718    DEBUG(
"auto_subnets: %u local subnets\n", subnets);
 
  736            _receive_announce(msg.
content.
ptr, &subnets, &idx_start);
 
  738        case SERVER_MSG_TYPE_TIMEOUT:
 
  741                _send_announce(local_subnets, &timeout_timer, &timeout_msg);
 
  747                    if (subnets < subnets_old) {
 
  748                        subnets = subnets_old;
 
  753                        subnets_old = subnets;
 
  759                _process_pio_cache(subnets, idx_start, _upstream);
 
  763                memset(l2addrs, 0, 
sizeof(l2addrs));
 
  765                subnets = local_subnets;
 
  775void gnrc_ipv6_auto_subnets_init(
void)
 
  778    _server_pid = 
thread_create(auto_subnets_stack, 
sizeof(auto_subnets_stack),
 
  780                                _eventloop, NULL, 
"auto_subnets");
 
#define assert(cond)
abort the program if assertion is false
 
static uint64_t ntohll(uint64_t v)
Convert from network byte order to host byte order, 64 bit.
 
static uint32_t byteorder_ntohl(network_uint32_t v)
Convert from network byte order to host byte order, 32 bit.
 
static network_uint64_t byteorder_htonll(uint64_t v)
Convert from host byte order to network byte order, 64 bit.
 
static uint64_t byteorder_ntohll(network_uint64_t v)
Convert from network byte order to host byte order, 64 bit.
 
Common macros and compiler attributes/pragmas configuration.
 
static unsigned may_be_zero(unsigned n)
Wrapper function to silence "comparison is always false due to limited         range of data type" ty...
 
#define ARRAY_SIZE(a)
Calculate the number of elements in a static array.
 
#define MIN(a, b)
Get the minimum of the two parameters.
 
#define MAX(a, b)
Get the maximum of the two parameters.
 
#define DEBUG(...)
Print debug information to stdout.
 
Definitions for GNRC's IPv6 implementation.
 
GNRC-specific neighbor discovery definitions.
 
Definition for GNRC's network interfaces.
 
void msg_init_queue(msg_t *array, int num)
Initialize the current thread's message queue.
 
int msg_send(msg_t *m, kernel_pid_t target_pid)
Send a message (blocking).
 
int msg_receive(msg_t *m)
Receive a message.
 
int16_t kernel_pid_t
Unique process identifier.
 
#define KERNEL_PID_UNDEF
Canonical identifier for an invalid PID.
 
void mutex_unlock(mutex_t *mutex)
Unlocks the mutex.
 
static void mutex_lock(mutex_t *mutex)
Locks a mutex, blocking.
 
kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority, int flags, thread_task_func_t task_func, void *arg, const char *name)
Creates a new thread.
 
static kernel_pid_t thread_getpid(void)
Returns the process ID of the currently running thread.
 
#define ENETUNREACH
Network unreachable.
 
#define ENOBUFS
No buffer space available.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX
Max number of other routers on the same link.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TIMEOUT_MS
How long to wait for other routers announcements before resending or creating subnets when the retry ...
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC
Enable this if you have a static network that might experience high packet loss under certain conditi...
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PORT
Port for the custom UDP sync protocol.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TX_PER_PERIOD
How often the number subnets should be announced by the routers.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN
Minimal length of a new prefix.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_FIX_LEN
How many bits of a new prefix have to match the old prefix for it to be considered for replacement.
 
#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF
Number of subnets that can be configured.
 
gnrc_pktsnip_t * gnrc_ipv6_hdr_build(gnrc_pktsnip_t *payload, const ipv6_addr_t *src, const ipv6_addr_t *dst)
Builds an IPv6 header for sending and adds it to the packet buffer.
 
#define CONFIG_GNRC_IPV6_NIB_L2ADDR_MAX_LEN
Maximum link-layer address length (aligned)
 
bool gnrc_ipv6_nib_pl_iter(unsigned iface, void **state, gnrc_ipv6_nib_pl_t *ple)
Iterates over all prefix list entries in the NIB.
 
void gnrc_ipv6_nib_pl_del(unsigned iface, const ipv6_addr_t *pfx, unsigned pfx_len)
Deletes prefix from NIB.
 
void gnrc_ipv6_nib_change_rtr_adv_iface(gnrc_netif_t *netif, bool enable)
Changes the state if an interface advertises itself as a router or not.
 
void gnrc_ndp_rtr_adv_send(gnrc_netif_t *netif, const ipv6_addr_t *src, const ipv6_addr_t *dst, bool fin, gnrc_pktsnip_t *ext_opts)
Send pre-compiled router advertisement depending on a given network interface.
 
gnrc_pktsnip_t * gnrc_ndp_opt_ri_build(const ipv6_addr_t *prefix, uint8_t prefix_len, uint32_t route_ltime, uint8_t flags, gnrc_pktsnip_t *next)
Builds the route information option.
 
static int gnrc_netapi_dispatch_send(gnrc_nettype_t type, uint32_t demux_ctx, gnrc_pktsnip_t *pkt)
Sends a GNRC_NETAPI_MSG_TYPE_SND command to all subscribers to (type, demux_ctx).
 
#define GNRC_NETAPI_MSG_TYPE_RCV
Messaging / IPC type for passing a Packet up the network stack
 
#define GNRC_NETIF_L2ADDR_MAXLEN
Maximum length of the link-layer address.
 
static uint8_t * gnrc_netif_hdr_get_src_addr(const gnrc_netif_hdr_t *hdr)
Get the source address from the given header.
 
static void gnrc_netif_hdr_set_netif(gnrc_netif_hdr_t *hdr, const gnrc_netif_t *netif)
Convenience function to set the interface of an interface header, given the network interface.
 
gnrc_pktsnip_t * gnrc_netif_hdr_build(const uint8_t *src, uint8_t src_len, const uint8_t *dst, uint8_t dst_len)
Builds a generic network interface header for sending and adds it to the packet buffer.
 
gnrc_netif_t * gnrc_netif_iter(const gnrc_netif_t *prev)
Iterate over all network interfaces.
 
unsigned gnrc_netif_numof(void)
Get number of network interfaces actually allocated.
 
#define GNRC_NETREG_DEMUX_CTX_ALL
Demux context value to get all packets of a certain type.
 
static void gnrc_netreg_entry_init_pid(gnrc_netreg_entry_t *entry, uint32_t demux_ctx, kernel_pid_t pid)
Initializes a netreg entry dynamically with PID.
 
struct gnrc_netreg_entry gnrc_netreg_entry_t
Entry to the Network protocol registry.
 
#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid)
Initializes a netreg entry statically with PID.
 
int gnrc_netreg_register(gnrc_nettype_t type, gnrc_netreg_entry_t *entry)
Registers a thread to the registry.
 
@ GNRC_NETTYPE_NETIF
Protocol is as defined in gnrc_netif_hdr_t.
 
@ GNRC_NETTYPE_UDP
Protocol is UDP.
 
@ GNRC_NETTYPE_UNDEF
Protocol is undefined.
 
static gnrc_pktsnip_t * gnrc_pkt_prepend(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *snip)
Prepends a snip to a packet.
 
gnrc_pktsnip_t * gnrc_pktsnip_search_type(gnrc_pktsnip_t *pkt, gnrc_nettype_t type)
Searches the packet for a packet snip of a specific type.
 
struct gnrc_pktsnip gnrc_pktsnip_t
Type to represent parts (either headers or payload) of a packet, called snips.
 
gnrc_pktsnip_t * gnrc_pktbuf_add(gnrc_pktsnip_t *next, const void *data, size_t size, gnrc_nettype_t type)
Adds a new gnrc_pktsnip_t and its packet to the packet buffer.
 
static void gnrc_pktbuf_release(gnrc_pktsnip_t *pkt)
Decreases gnrc_pktsnip_t::users of pkt atomically and removes it if it reaches 0 and reports GNRC_NET...
 
void gnrc_rpl_configure_root(gnrc_netif_t *netif, const ipv6_addr_t *dodag_id)
Convenience function to start a RPL root using the default configuration.
 
gnrc_pktsnip_t * gnrc_udp_hdr_build(gnrc_pktsnip_t *payload, uint16_t src, uint16_t dst)
Allocate and initialize a fresh UDP header in the packet buffer.
 
const ipv6_addr_t ipv6_addr_all_routers_link_local
 
char * ipv6_addr_to_str(char *result, const ipv6_addr_t *addr, uint8_t result_len)
Converts an IPv6 address to its string representation.
 
#define IPV6_ADDR_MAX_STR_LEN
Maximum length of an IPv6 address as string.
 
void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, uint8_t bits)
Sets IPv6 address out with the first bits taken from prefix and leaves the remaining bits untouched.
 
uint8_t ipv6_addr_match_prefix(const ipv6_addr_t *a, const ipv6_addr_t *b)
Checks up to which bit-count two IPv6 addresses match in their prefix.
 
#define NDP_OPT_RI_FLAGS_PRF_ZERO
zero preference
 
#define NDP_OPT_PI_FLAGS_A
autonomous address configuration
 
int netif_get_opt(const netif_t *netif, netopt_t opt, uint16_t context, void *value, size_t max_len)
Gets option from an interface.
 
@ NETOPT_ADDRESS
(byte array, see below) link layer address in network byte order
 
uint32_t random_uint32_range(uint32_t a, uint32_t b)
generates a random number r with a <= r < b.
 
#define US_PER_MS
The number of microseconds per millisecond.
 
static void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
Set a timer that sends a message.
 
struct xtimer xtimer_t
xtimer timer structure
 
#define IS_USED(module)
Checks whether a module is being used or not.
 
Generic network interface header.
 
Common interface to the software PRNG.
 
Prefix list entry view on NIB.
 
uint8_t pfx_len
length of gnrc_ipv6_nib_pl_t::pfx in bits
 
Generic network interface header.
 
kernel_pid_t if_pid
PID of network interface.
 
ipv6_addr_t addrs[CONFIG_GNRC_NETIF_IPV6_ADDRS_NUMOF]
IPv6 unicast and anycast addresses of the interface.
 
Representation of a network interface.
 
netif_t netif
network interface descriptor
 
uint8_t l2addr_len
Length in bytes of gnrc_netif_t::l2addr.
 
kernel_pid_t pid
PID of the network interface's thread.
 
uint8_t l2addr[GNRC_NETIF_L2ADDR_MAXLEN]
The link-layer address currently used as the source address on this interface.
 
gnrc_netif_ipv6_t ipv6
IPv6 component.
 
void * data
pointer to the data of the snip
 
Describes a message object which can be sent between threads.
 
union msg_t::@320015036040264217111030043207077155207261357035 content
Content of the message.
 
void * ptr
Pointer content field.
 
Prefix information option format.
 
uint8_t prefix_len
prefix length
 
network_uint32_t pref_ltime
preferred lifetime
 
network_uint32_t valid_ltime
valid lifetime
 
uint8_t len
length in units of 8 octets
 
#define THREAD_PRIORITY_MAIN
Priority of the main thread.
 
uint32_t u32
32 bit representation
 
Data type to represent an IPv6 address.
 
uint8_t u8[16]
divided by 16 8-bit words.
 
network_uint64_t u64[2]
divided by 2 64-bit words.
 
xtimer interface definitions