Loading...
Searching...
No Matches
gnrc_ipv6_auto_subnets.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021 ML!PA Consulting GmbH
3 *
4 * This file is subject to the terms and conditions of the GNU Lesser
5 * General Public License v2.1. See the file LICENSE in the top level
6 * directory for more details.
7 */
8
92#include "compiler_hints.h"
93#include "net/gnrc/ipv6.h"
94#include "net/gnrc/netif.h"
95#include "net/gnrc/netif/hdr.h"
96#include "net/gnrc/udp.h"
97#include "net/gnrc/ipv6/nib.h"
98#include "net/gnrc/ndp.h"
99#include "net/gnrc/rpl.h"
100#include "random.h"
101#include "xtimer.h"
102
106#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PORT
107#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PORT (16179)
108#endif
109
113#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX
114#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX (4)
115#endif
116
120#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_TX_PER_PERIOD
121#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TX_PER_PERIOD (3)
122#endif
123
128#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_TIMEOUT_MS
129#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_TIMEOUT_MS (50)
130#endif
131
141#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_FIX_LEN
142#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_FIX_LEN (0)
143#endif
144
149#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN
150#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_PREFIX_MIN_LEN (0)
151#endif
152
162#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF
163#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF (1)
164#endif
165
174#ifndef CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC
175#define CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC (0)
176#endif
177
178/* Code below should not be included by Doxygen */
179#ifndef DOXYGEN
180
181#define SERVER_THREAD_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
182#define SERVER_MSG_QUEUE_SIZE (CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX)
183#define SERVER_MSG_TYPE_TIMEOUT (0x8fae)
184
185#define ENABLE_DEBUG 0
186#include "debug.h"
187
188static char addr_str[IPV6_ADDR_MAX_STR_LEN];
189
190#if !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE)
191
195typedef struct __attribute__((packed)) {
196 uint8_t version;
197 uint8_t num_subnets;
198} _auto_subnets_request_v0_t;
199
200/* keep a copy of PIO information in memory */
201static gnrc_netif_t *_upstream;
203static mutex_t _pio_cache_lock;
204
205static char auto_subnets_stack[SERVER_THREAD_STACKSIZE];
206static msg_t server_queue[SERVER_MSG_QUEUE_SIZE];
207
208/* store neighbor routers l2 address to ignore duplicate packets */
209static uint8_t l2addrs[CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX]
211
212/* PID of the event thread */
213static kernel_pid_t _server_pid;
214
215static bool _store_pio(const ndp_opt_pi_t *pio)
216{
217 mutex_lock(&_pio_cache_lock);
218
219 for (unsigned i = 0; i < ARRAY_SIZE(_pio_cache); ++i) {
220 if (_pio_cache[i].len == 0) {
221 _pio_cache[i] = *pio;
222
223 mutex_unlock(&_pio_cache_lock);
224 return true;
225 }
226 }
227
228 mutex_unlock(&_pio_cache_lock);
229 return false;
230}
231
232static int _send_udp(gnrc_netif_t *netif, const ipv6_addr_t *addr,
233 uint16_t port, const void *data, size_t len)
234{
235 gnrc_pktsnip_t *payload, *udp, *ip;
236
237 /* allocate payload */
238 payload = gnrc_pktbuf_add(NULL, data, len, GNRC_NETTYPE_UNDEF);
239 if (payload == NULL) {
240 DEBUG("auto_subnets: unable to copy data to packet buffer\n");
241 return -ENOBUFS;
242 }
243
244 /* allocate UDP header, set source port := destination port */
245 udp = gnrc_udp_hdr_build(payload, port, port);
246 if (udp == NULL) {
247 DEBUG("auto_subnets: unable to allocate UDP header\n");
248 gnrc_pktbuf_release(payload);
249 return -ENOBUFS;
250 }
251
252 /* allocate IPv6 header */
253 ip = gnrc_ipv6_hdr_build(udp, NULL, addr);
254 if (ip == NULL) {
255 DEBUG("auto_subnets: unable to allocate IPv6 header\n");
257 return -ENOBUFS;
258 }
259
260 /* add netif header, if interface was given */
261 if (netif != NULL) {
262 gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
263 if (netif_hdr == NULL) {
264 DEBUG("auto_subnets: unable to allocate netif header\n");
266 return -ENOBUFS;
267 }
268
269 gnrc_netif_hdr_set_netif(netif_hdr->data, netif);
270 ip = gnrc_pkt_prepend(ip, netif_hdr);
271 }
272
273 /* send packet */
276 DEBUG("auto_subnets: unable to locate UDP thread\n");
278 return -ENETUNREACH;
279 }
280
281 return 0;
282}
283#endif /* !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) */
284
285static void _init_sub_prefix(ipv6_addr_t *out,
286 const ipv6_addr_t *prefix, uint8_t bits,
287 uint8_t idx, uint8_t idx_bits)
288{
289 uint8_t bytes = bits / 8;
290 uint8_t rem = bits % 8;
291 int8_t shift = 8 - rem - idx_bits;
292
293 /* first copy old prefix */
294 memset(out, 0, sizeof(*out));
295 ipv6_addr_init_prefix(out, prefix, bits);
296
297 /* if new bits are between bytes, first copy over the most significant bits */
298 if (shift < 0) {
299 out->u8[bytes] |= idx >> -shift;
300 out->u8[++bytes] = 0;
301 shift += 8;
302 }
303
304 /* shift remaining bits at the end of the prefix */
305 out->u8[bytes] |= idx << shift;
306}
307
308/* returns true if a new prefix was added, false if nothing changed */
309static bool _remove_old_prefix(gnrc_netif_t *netif,
310 const ipv6_addr_t *pfx, uint8_t pfx_len,
311 gnrc_pktsnip_t **ext_opts)
312{
313 gnrc_ipv6_nib_pl_t entry;
314 gnrc_pktsnip_t *tmp;
315 void *state = NULL;
316 ipv6_addr_t old_pfx;
318
319 /* iterate prefix list to see if the prefix already exists */
320 while (gnrc_ipv6_nib_pl_iter(netif->pid, &state, &entry)) {
321 uint8_t match_len = ipv6_addr_match_prefix(&entry.pfx, pfx);
322
323 /* The prefix did not change - nothing to do here */
324 if (match_len >= pfx_len && pfx_len == entry.pfx_len) {
325 return false;
326 }
327
328 /* find prefix that is closest to the new prefix */
329 if (match_len > old_pfx_len) {
330 old_pfx_len = entry.pfx_len;
331 old_pfx = entry.pfx;
332 }
333 }
334
335 /* no prefix found */
337 return true;
338 }
339
340 DEBUG("auto_subnets: remove old prefix %s/%u\n",
341 ipv6_addr_to_str(addr_str, &old_pfx, sizeof(addr_str)), old_pfx_len);
342
343 /* invalidate old prefix in RIO */
344 tmp = gnrc_ndp_opt_ri_build(&old_pfx, old_pfx_len, 0,
345 NDP_OPT_RI_FLAGS_PRF_ZERO, *ext_opts);
346 if (tmp) {
347 *ext_opts = tmp;
348 }
349
350 /* remove the prefix */
351 gnrc_ipv6_nib_pl_del(netif->pid, &old_pfx, old_pfx_len);
352
353 return true;
354}
355
356static void _configure_subnets(uint8_t subnets, uint8_t start_idx, gnrc_netif_t *upstream,
357 const ndp_opt_pi_t *pio)
358{
359 gnrc_netif_t *downstream = NULL;
360 gnrc_pktsnip_t *ext_opts = NULL;
361 const ipv6_addr_t *prefix = &pio->prefix;
362 uint32_t valid_ltime = byteorder_ntohl(pio->valid_ltime);
363 uint32_t pref_ltime = byteorder_ntohl(pio->pref_ltime);
364 const uint8_t prefix_len = pio->prefix_len;
365 uint8_t new_prefix_len, subnet_len;
366
367 DEBUG("auto_subnets: create %u subnets, start with %u\n", subnets, start_idx);
368
369 /* Calculate remaining prefix length.
370 * For n subnets we consume floor(log_2 n) + 1 bits.
371 * To calculate floor(log_2 n) quickly, find the position of the
372 * most significant set bit by counting leading zeros.
373 */
374 subnet_len = 32 - __builtin_clz(subnets);
375 new_prefix_len = prefix_len + subnet_len;
376
377 if (new_prefix_len > 64) {
378 DEBUG("auto_subnets: can't split /%u into %u subnets\n", prefix_len, subnets);
379 return;
380 }
381
384 }
385
386 while ((downstream = gnrc_netif_iter(downstream))) {
387 gnrc_pktsnip_t *tmp;
388 ipv6_addr_t new_prefix;
389 int idx;
390
391 if (downstream == upstream) {
392 continue;
393 }
394
395 /* create subnet from upstream prefix */
396 _init_sub_prefix(&new_prefix, prefix, prefix_len, ++start_idx, subnet_len);
397
398 DEBUG("auto_subnets: configure prefix %s/%u on %u\n",
399 ipv6_addr_to_str(addr_str, &new_prefix, sizeof(addr_str)),
400 new_prefix_len, downstream->pid);
401
402 /* first remove old prefix if the prefix changed */
403 if (_remove_old_prefix(downstream, &new_prefix, new_prefix_len, &ext_opts)) {
404
405 /* configure subnet on downstream interface */
406 idx = gnrc_netif_ipv6_add_prefix(downstream, &new_prefix, new_prefix_len,
407 valid_ltime, pref_ltime);
408 if (idx < 0) {
409 DEBUG("auto_subnets: adding prefix to %u failed\n", downstream->pid);
410 continue;
411 }
412
413 /* start advertising subnet */
414 gnrc_ipv6_nib_change_rtr_adv_iface(downstream, true);
415
416 /* configure RPL root if applicable */
417 gnrc_rpl_configure_root(downstream, &downstream->ipv6.addrs[idx]);
418 }
419
420 /* add route information option with new subnet */
421 tmp = gnrc_ndp_opt_ri_build(&new_prefix, new_prefix_len, valid_ltime,
422 NDP_OPT_RI_FLAGS_PRF_ZERO, ext_opts);
423 if (tmp == NULL) {
424 DEBUG("auto_subnets: No space left in packet buffer. Not adding RIO\n");
425 } else {
426 ext_opts = tmp;
427 }
428 }
429
430 /* immediately send an RA with RIO */
431 if (ext_opts) {
432 gnrc_ndp_rtr_adv_send(upstream, NULL, NULL, true, ext_opts);
433 } else {
434 DEBUG("auto_subnets: Options empty, not sending RA\n");
435 }
436}
437
438void gnrc_ipv6_nib_rtr_adv_pio_cb(gnrc_netif_t *upstream, const ndp_opt_pi_t *pio)
439{
440 /* create a subnet for each downstream interface */
441 unsigned subnets = gnrc_netif_numof() - 1;
442
443 if (subnets == 0) {
444 return;
445 }
446
447 if (pio->valid_ltime.u32 == 0) {
448 return;
449 }
450
451 /* only consider prefix meant for autonomous address configuration */
452 if (!(pio->flags & NDP_OPT_PI_FLAGS_A)) {
453 return;
454 }
455
456#if IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE)
457 /* if we are the only router on this bus, we can directly choose a prefix */
458 _configure_subnets(subnets, 0, upstream, pio);
459#else
460
461 /* store PIO information for later use */
462 if (!_store_pio(pio)) {
463 DEBUG("auto_subnets: no space left in PIO cache, increase CONFIG_GNRC_IPV6_AUTO_SUBNETS_NUMOF\n");
464 return;
465 }
466 _upstream = upstream;
467
468 /* start advertising by sending timeout message to the server thread */
469 msg_t m = {
470 .type = SERVER_MSG_TYPE_TIMEOUT
471 };
472
473 msg_send(&m, _server_pid);
474#endif /* !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) */
475}
476
477#if !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE)
486static bool _all_zero(const uint8_t *addr, size_t len)
487{
488 for (const uint8_t *end = addr + len; addr != end; ++addr) {
489 if (*addr) {
490 return false;
491 }
492 }
493 return true;
494}
495
506static int _alloc_l2addr_entry(const void *addr, size_t len)
507{
508 int empty = -1;
509 for (unsigned i = 0; i < CONFIG_GNRC_IPV6_AUTO_SUBNETS_PEERS_MAX; ++i) {
510 if (_all_zero(l2addrs[i], len)) {
511 empty = i;
512 continue;
513 }
514 if (memcmp(addr, l2addrs[i], len) == 0) {
515 return 0;
516 }
517 }
518
519 if (empty < 0) {
520 return -1;
521 }
522
523 memcpy(l2addrs[empty], addr, len);
524 return 1;
525}
526
542static int _get_my_l2addr_rank(gnrc_netif_t *iface, gnrc_pktsnip_t *pkt)
543{
544 const void *src_addr;
545 gnrc_pktsnip_t *netif_hdr;
546 gnrc_netif_hdr_t *hdr;
547
548 if (iface == NULL) {
549 return 0;
550 }
551
553 if (netif_hdr == NULL) {
554 return 0;
555 }
556
557 /* ignore packet if it was received on the wrong interface */
558 hdr = netif_hdr->data;
559 if (iface->pid != hdr->if_pid) {
560 return 0;
561 }
562
563 /* ignore packets without source address */
564 src_addr = gnrc_netif_hdr_get_src_addr(hdr);
565 if (src_addr == NULL) {
566 return 0;
567 }
568
569 /* check if we have seen the host before */
570 if (_alloc_l2addr_entry(src_addr, iface->l2addr_len) == 0) {
571 return 0;
572 }
573
574 return memcmp(iface->l2addr, src_addr, iface->l2addr_len);
575}
576
577static void _receive_announce(gnrc_pktsnip_t *pkt, uint8_t *subnets, uint8_t *idx_start)
578{
579 _auto_subnets_request_v0_t *request = pkt->data;
580
581 /* Check if we already got an announcement from that host, */
582 /* in this case, res will be 0. */
583 int res = _get_my_l2addr_rank(_upstream, pkt);
584 if (res) {
585 /* calculate total number of subnets */
586 *subnets += request->num_subnets;
587
588 DEBUG("auto_subnets: %u new remote subnets, total %u\n",
589 request->num_subnets, *subnets);
590
591 /* If other host is before us in order of MAC addresses, add
592 * their subnets to our offset */
593 if (res > 0) {
594 *idx_start += request->num_subnets;
595 }
596 }
597
599}
600
601static void _send_announce(uint8_t local_subnets, xtimer_t *timer, msg_t *msg)
602{
603 uint32_t timeout_us;
604 _auto_subnets_request_v0_t request = {
605 .num_subnets = local_subnets,
606 };
607
608 /* broadcast the number of subnets we want to create */
609 _send_udp(_upstream, &ipv6_addr_all_routers_link_local,
611 &request, sizeof(request));
612
613 /* configure timeout for resend */
614 timeout_us = random_uint32_range(
617 xtimer_set_msg(timer, timeout_us, msg, _server_pid);
618 DEBUG("auto_subnets: announce sent, next timeout in %" PRIu32 " µs\n", timeout_us);
619}
620
621static void _process_pio_cache(uint8_t subnets, uint8_t idx_start, gnrc_netif_t *upstream)
622{
623 mutex_lock(&_pio_cache_lock);
624
625 for (unsigned i = 0; i < ARRAY_SIZE(_pio_cache); ++i) {
626 if (!_pio_cache[i].len) {
627 continue;
628 }
629
630 /* use PIO for prefix configuration */
631 _configure_subnets(subnets, idx_start, upstream, &_pio_cache[i]);
632
633 /* invalidate entry */
634 _pio_cache[i].len = 0;
635 }
636
637 mutex_unlock(&_pio_cache_lock);
638}
639
640static void *_eventloop(void *arg)
641{
642 (void)arg;
643
644 xtimer_t timeout_timer;
645 msg_t msg, timeout_msg = { .type = SERVER_MSG_TYPE_TIMEOUT };
647 const uint8_t local_subnets = gnrc_netif_numof() - 1;
648 uint8_t idx_start = 0;
649 uint8_t subnets = local_subnets;
651
652 /* only used with CONFIG_GNRC_IPV6_AUTO_SUBNETS_STATIC set */
653 uint8_t idx_old = 0;
654 uint8_t subnets_old = 0;
655
656 DEBUG("auto_subnets: %u local subnets\n", subnets);
657
658 if (subnets == 0) {
659 return NULL;
660 }
661
662 /* setup the message queue */
663 msg_init_queue(server_queue, SERVER_MSG_QUEUE_SIZE);
664
665 /* register server to receive messages from given port */
668
669 while (1) {
670 msg_receive(&msg);
671
672 switch (msg.type) {
674 _receive_announce(msg.content.ptr, &subnets, &idx_start);
675 break;
676 case SERVER_MSG_TYPE_TIMEOUT:
677 if (tx_period--) {
678 /* send subnet announcement */
679 _send_announce(local_subnets, &timeout_timer, &timeout_msg);
680 } else {
681
682 /* don't re-enumerate subnets of a downstream router goes down */
684 /* If we got less subnets than before, use the old value */
685 if (subnets < subnets_old) {
686 subnets = subnets_old;
687 idx_start = idx_old;
688 }
689 /* Store subnet high water mark for later use */
690 else {
691 subnets_old = subnets;
692 idx_old = idx_start;
693 }
694 }
695
696 /* config round done, configure subnets */
697 _process_pio_cache(subnets, idx_start, _upstream);
698
699 /* start a new round of counting */
701 memset(l2addrs, 0, sizeof(l2addrs));
702 idx_start = 0;
703 subnets = local_subnets;
704 }
705 break;
706 }
707 }
708
709 /* never reached */
710 return NULL;
711}
712
713void gnrc_ipv6_auto_subnets_init(void)
714{
715 /* initiate auto_subnets thread */
716 _server_pid = thread_create(auto_subnets_stack, sizeof(auto_subnets_stack),
718 _eventloop, NULL, "auto_subnets");
719}
720#endif /* !IS_USED(MODULE_GNRC_IPV6_AUTO_SUBNETS_SIMPLE) */
721#endif /* !DOXYGEN */
static uint32_t byteorder_ntohl(network_uint32_t v)
Convert from network byte order to host byte order, 32 bit.
Definition byteorder.h:511
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" t...
#define ARRAY_SIZE(a)
Calculate the number of elements in a static array.
Definition container.h:83
Debug-header.
#define DEBUG(...)
Print debug information to stdout.
Definition debug.h:118
Definitions for GNRC's IPv6 implementation.
GNRC-specific neighbor discovery definitions.
Definition for GNRC's network interfaces.
UDP GNRC definition.
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.
Definition sched.h:139
#define KERNEL_PID_UNDEF
Canonical identifier for an invalid PID.
Definition sched.h:110
void mutex_unlock(mutex_t *mutex)
Unlocks the mutex.
static void mutex_lock(mutex_t *mutex)
Locks a mutex, blocking.
Definition mutex.h:312
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.
Definition thread.h:393
#define ENETUNREACH
Network unreachable.
Definition errno.h:109
#define ENOBUFS
No buffer space available.
Definition errno.h:111
#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)
Definition conf.h:261
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).
Definition netapi.h:181
#define GNRC_NETAPI_MSG_TYPE_RCV
Messaging / IPC type for passing a Packet up the network stack
Definition netapi.h:74
static uint8_t * gnrc_netif_hdr_get_src_addr(const gnrc_netif_hdr_t *hdr)
Get the source address from the given header.
Definition hdr.h:198
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.
Definition hdr.h:396
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.
Definition netreg.h:80
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.
Definition netreg.h:272
#define GNRC_NETREG_ENTRY_INIT_PID(demux_ctx, pid)
Initializes a netreg entry statically with PID.
Definition netreg.h:101
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.
Definition nettype.h:61
@ GNRC_NETTYPE_UDP
Protocol is UDP.
Definition nettype.h:135
@ GNRC_NETTYPE_UNDEF
Protocol is undefined.
Definition nettype.h:62
static gnrc_pktsnip_t * gnrc_pkt_prepend(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *snip)
Prepends a snip to a packet.
Definition pkt.h:196
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.
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...
Definition pktbuf.h:196
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.
Definition addr.h:53
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
Definition ndp.h:114
#define NDP_OPT_PI_FLAGS_A
autonomous address configuration
Definition ndp.h:104
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.
Definition time_units.h:90
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.
Generic network interface header.
NIB definitions.
Common interface to the software PRNG.
RPL header.
Prefix list entry view on NIB.
Definition pl.h:38
uint8_t pfx_len
length of gnrc_ipv6_nib_pl_t::pfx in bits
Definition pl.h:40
ipv6_addr_t pfx
prefix
Definition pl.h:39
Generic network interface header.
Definition hdr.h:126
kernel_pid_t if_pid
PID of network interface.
Definition hdr.h:129
ipv6_addr_t addrs[CONFIG_GNRC_NETIF_IPV6_ADDRS_NUMOF]
IPv6 unicast and anycast addresses of the interface.
Definition ipv6.h:93
Representation of a network interface.
Definition netif.h:135
uint8_t l2addr_len
Length in bytes of gnrc_netif_t::l2addr.
Definition netif.h:199
kernel_pid_t pid
PID of the network interface's thread.
Definition netif.h:226
uint8_t l2addr[GNRC_NETIF_L2ADDR_MAXLEN]
The link-layer address currently used as the source address on this interface.
Definition netif.h:192
gnrc_netif_ipv6_t ipv6
IPv6 component.
Definition netif.h:147
Entry to the Network protocol registry.
Definition netreg.h:167
Type to represent parts (either headers or payload) of a packet, called snips.
Definition pkt.h:108
void * data
pointer to the data of the snip
Definition pkt.h:111
Describes a message object which can be sent between threads.
Definition msg.h:196
uint16_t type
Type field.
Definition msg.h:199
union msg_t::@1 content
Content of the message.
void * ptr
Pointer content field.
Definition msg.h:201
Mutex structure.
Definition mutex.h:146
Prefix information option format.
Definition ndp.h:312
uint8_t flags
flags
Definition ndp.h:316
uint8_t prefix_len
prefix length
Definition ndp.h:315
network_uint32_t pref_ltime
preferred lifetime
Definition ndp.h:318
network_uint32_t valid_ltime
valid lifetime
Definition ndp.h:317
uint8_t len
length in units of 8 octets
Definition ndp.h:314
ipv6_addr_t prefix
prefix
Definition ndp.h:320
xtimer timer structure
Definition xtimer.h:97
#define THREAD_PRIORITY_MAIN
Priority of the main thread.
uint32_t u32
32 bit representation
Definition byteorder.h:85
Data type to represent an IPv6 address.
Definition addr.h:72
uint8_t u8[16]
divided by 16 8-bit words.
Definition addr.h:73
xtimer interface definitions