diff --git a/sys/include/net/ng_rpl.h b/sys/include/net/ng_rpl.h index 6b6d578f16342a9a4ff3f1a218a6ae6bfc3d3602..48f446269c9c2b74be313202f8f9164348ab5dac 100644 --- a/sys/include/net/ng_rpl.h +++ b/sys/include/net/ng_rpl.h @@ -208,6 +208,16 @@ static inline bool NG_RPL_COUNTER_GREATER_THAN(uint8_t A, uint8_t B) */ #define NG_RPL_LIFETIME_STEP (2) +/** + * @brief Default prefix length for the DODAG id + */ +#define NG_RPL_DEFAULT_PREFIX_LEN (64) + +/** + * @brief Default prefix valid and preferred time for the DODAG id + */ +#define NG_RPL_DEFAULT_PREFIX_LIFETIME (0xFFFFFFFF) + /** * @brief A DODAG can be grounded or floating * @see <a href="https://tools.ietf.org/html/rfc6550#section-3.2.4"> diff --git a/sys/include/net/ng_rpl/structs.h b/sys/include/net/ng_rpl/structs.h index 4e601c335990d84e7e2233d01068cfa18841aaed..3507b228823bae8e0d5c19400b966aef5aaa89a2 100644 --- a/sys/include/net/ng_rpl/structs.h +++ b/sys/include/net/ng_rpl/structs.h @@ -147,6 +147,23 @@ typedef struct __attribute__((packed)) { uint8_t path_lifetime; /**< lifetime of routes */ } ng_rpl_opt_transit_t; +/** + * @brief Prefix Information Option + * @see <a href="https://tools.ietf.org/html/rfc6550#section-6.7.10"> + * RFC6550, section 6.7.10, Prefix Information + * </a> + */ +typedef struct __attribute__((packed)) { + uint8_t type; /**< option type */ + uint8_t length; /**< option length without the first two bytes */ + uint8_t prefix_len; /**< prefix length */ + uint8_t LAR_flags; /**< flags and resereved */ + uint32_t valid_lifetime; /**< valid lifetime */ + uint32_t pref_lifetime; /**< preferred lifetime */ + uint32_t reserved; /**< reserved */ + ipv6_addr_t prefix; /**< prefix used for Stateless Address Autoconfiguration */ +} ng_rpl_opt_prefix_info_t; + typedef struct ng_rpl_dodag ng_rpl_dodag_t; typedef struct ng_rpl_parent ng_rpl_parent_t; @@ -201,6 +218,9 @@ struct ng_rpl_dodag { ng_rpl_dodag_t *next; /**< pointer to the next dodag */ ng_rpl_parent_t *parents; /**< pointer to the parents list of this DODAG */ ipv6_addr_t dodag_id; /**< id of the DODAG */ + uint8_t prefix_len; /**< length of the prefix for the DODAG id */ + uint32_t addr_preferred; /**< time in seconds the DODAG id is preferred */ + uint32_t addr_valid; /**< time in seconds the DODAG id is valid */ uint8_t state; /**< 0 for unused, 1 for used */ uint8_t dtsn; /**< DAO Trigger Sequence Number */ uint8_t prf; /**< preferred flag */ diff --git a/sys/net/routing/ng_rpl/ng_rpl.c b/sys/net/routing/ng_rpl/ng_rpl.c index 79dd8256aa48fc9f8610f076aa1c348d592d341f..e336a8203e97a5774742100820f304ca57f7a3dd 100644 --- a/sys/net/routing/ng_rpl/ng_rpl.c +++ b/sys/net/routing/ng_rpl/ng_rpl.c @@ -106,6 +106,7 @@ static ng_rpl_dodag_t *_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_ } ipv6_addr_t *configured_addr; + ng_ipv6_netif_addr_t *netif_addr = NULL; ng_rpl_instance_t *inst = NULL; ng_rpl_dodag_t *dodag = NULL; @@ -120,6 +121,12 @@ static ng_rpl_dodag_t *_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_ return NULL; } + if ((netif_addr = ng_ipv6_netif_addr_get(configured_addr)) == NULL) { + DEBUG("RPL: no netif address found for %s\n", ipv6_addr_to_str(addr_str, configured_addr, + sizeof(addr_str))); + return NULL; + } + if (ng_rpl_instance_add(instance_id, &inst)) { inst->of = (ng_rpl_of_t *) ng_rpl_get_of_for_ocp(NG_RPL_DEFAULT_OCP); inst->mop = mop; @@ -141,6 +148,10 @@ static ng_rpl_dodag_t *_root_dodag_init(uint8_t instance_id, ipv6_addr_t *dodag_ return NULL; } + dodag->prefix_len = netif_addr->prefix_len; + dodag->addr_preferred = netif_addr->preferred; + dodag->addr_valid = netif_addr->valid; + return dodag; } diff --git a/sys/net/routing/ng_rpl/ng_rpl_control_messages.c b/sys/net/routing/ng_rpl/ng_rpl_control_messages.c index 9c2028032aaab2b118c9a72968feec7411d727d6..394e2037101fc35e1cf69f072fc09fd23c5ea1f0 100644 --- a/sys/net/routing/ng_rpl/ng_rpl_control_messages.c +++ b/sys/net/routing/ng_rpl/ng_rpl_control_messages.c @@ -19,6 +19,7 @@ #include "net/ng_icmpv6.h" #include "net/ng_rpl.h" #include "inet_ntop.h" +#include "net/eui64.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -30,8 +31,10 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN]; #define NG_RPL_GROUNDED_SHIFT (7) #define NG_RPL_MOP_SHIFT (3) #define NG_RPL_OPT_DODAG_CONF_LEN (14) +#define NG_RPL_OPT_PREFIX_INFO_LEN (30) #define NG_RPL_SHIFTED_MOP_MASK (0x7) #define NG_RPL_PRF_MASK (0x7) +#define NG_RPL_PREFIX_AUTO_ADDRESS_BIT (1 << 6) void _ng_rpl_send(ng_pktsnip_t *pkt, ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *dodag_id) @@ -100,6 +103,7 @@ void ng_rpl_send_DIO(ng_rpl_dodag_t *dodag, ipv6_addr_t *destination) if ((dodag->dodag_conf_counter % 3) == 0) { size += sizeof(ng_rpl_opt_dodag_conf_t); + size += sizeof(ng_rpl_opt_prefix_info_t); } if ((pkt = ng_icmpv6_build(NULL, ICMPV6_RPL_CTRL, NG_RPL_ICMPV6_CODE_DIO, size)) == NULL) { @@ -137,6 +141,21 @@ void ng_rpl_send_DIO(ng_rpl_dodag_t *dodag, ipv6_addr_t *destination) dodag_conf->reserved = 0; dodag_conf->default_lifetime = dodag->default_lifetime; dodag_conf->lifetime_unit = byteorder_htons(dodag->lifetime_unit); + pos += sizeof(*dodag_conf); + + ng_rpl_opt_prefix_info_t *prefix_info; + prefix_info = (ng_rpl_opt_prefix_info_t *) pos; + prefix_info->type = NG_RPL_OPT_PREFIX_INFO; + prefix_info->length = NG_RPL_OPT_PREFIX_INFO_LEN; + /* auto-address configuration */ + prefix_info->LAR_flags = NG_RPL_PREFIX_AUTO_ADDRESS_BIT; + prefix_info->valid_lifetime = dodag->addr_valid; + prefix_info->pref_lifetime = dodag->addr_preferred; + prefix_info->prefix_len = dodag->prefix_len; + prefix_info->reserved = 0; + + memset(&prefix_info->prefix, 0, sizeof(prefix_info->prefix)); + ipv6_addr_init_prefix(&prefix_info->prefix, &dodag->dodag_id, dodag->prefix_len); } dodag->dodag_conf_counter++; @@ -198,6 +217,7 @@ bool _parse_options(int msg_type, ng_rpl_dodag_t *dodag, ng_rpl_opt_t *opt, uint { uint16_t l = 0; ng_rpl_opt_target_t *first_target = NULL; + eui64_t iid; while(l < len) { if ((opt->type != NG_RPL_OPT_PAD1) && (len < opt->length + sizeof(ng_rpl_opt_t) + l)) { /* return false to delete the dodag, @@ -243,6 +263,25 @@ bool _parse_options(int msg_type, ng_rpl_dodag_t *dodag, ng_rpl_opt_t *opt, uint dodag->trickle.k = dodag->dio_redun; break; } + case (NG_RPL_OPT_PREFIX_INFO): { + if (msg_type != NG_RPL_ICMPV6_CODE_DIO) { + DEBUG("RPL: Ignore Prefix Information DIO option\n"); + return true; + } + DEBUG("RPL: Prefix Information DIO option parsed\n"); + ng_rpl_opt_prefix_info_t *pi = (ng_rpl_opt_prefix_info_t *) opt; + ipv6_addr_t all_RPL_nodes = NG_IPV6_ADDR_ALL_RPL_NODES; + kernel_pid_t if_id = ng_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes); + /* check for the auto address-configuration flag */ + if ((ng_netapi_get(if_id, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0) && + !(pi->LAR_flags & NG_RPL_PREFIX_AUTO_ADDRESS_BIT)) { + break; + } + ipv6_addr_set_aiid(&pi->prefix, iid.uint8); + ng_ipv6_netif_add_addr(if_id, &pi->prefix, pi->prefix_len, 0); + + break; + } case (NG_RPL_OPT_TARGET): { if (msg_type != NG_RPL_ICMPV6_CODE_DAO) { DEBUG("RPL: Ignore RPL TARGET DAO option\n"); diff --git a/sys/net/routing/ng_rpl/ng_rpl_dodag.c b/sys/net/routing/ng_rpl/ng_rpl_dodag.c index fb8190dfa183c5a9b30111216394df5d22a84418..bb96665fe333c93db8016c8efc57b70844d6da87 100644 --- a/sys/net/routing/ng_rpl/ng_rpl_dodag.c +++ b/sys/net/routing/ng_rpl/ng_rpl_dodag.c @@ -20,6 +20,7 @@ #include "net/ng_rpl/dodag.h" #include "net/ng_rpl/structs.h" #include "utlist.h" +#include "net/ng_rpl.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -136,6 +137,9 @@ bool ng_rpl_dodag_add(ng_rpl_instance_t *instance, ipv6_addr_t *dodag_id, ng_rpl LL_APPEND(instance->dodags, *dodag); (*dodag)->state = 1; (*dodag)->dodag_id = *dodag_id; + (*dodag)->prefix_len = NG_RPL_DEFAULT_PREFIX_LEN; + (*dodag)->addr_preferred = NG_RPL_DEFAULT_PREFIX_LIFETIME; + (*dodag)->addr_valid = NG_RPL_DEFAULT_PREFIX_LIFETIME; (*dodag)->my_rank = NG_RPL_INFINITE_RANK; (*dodag)->trickle.callback.func = &rpl_trickle_send_dio; (*dodag)->trickle.callback.args = *dodag;