1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #3721 from cgundogan/pr/rpl/gnrc_rpl_p2p

rpl: introducing P2P-RPL
This commit is contained in:
Oleg Hahm 2016-03-29 19:04:27 +02:00
commit 376874284b
12 changed files with 1011 additions and 5 deletions

View File

@ -83,6 +83,10 @@ ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
USEMODULE += gnrc_rpl
endif
ifneq (,$(filter gnrc_rpl,$(USEMODULE)))
USEMODULE += fib
USEMODULE += gnrc_ipv6_router_default

View File

@ -0,0 +1,180 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup net_rpl_p2p Reactive Discovery of P2P Routes in LLNs
* @ingroup net_gnrc_rpl
* @brief Implementation of P2P-RPL
* @see <a href="https://tools.ietf.org/html/rfc6997">
* RFC 6997
* </a>
* @{
*
* @file
* @brief Definititions for P2P-RPL
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#ifndef GNRC_RPL_P2P_H_
#define GNRC_RPL_P2P_H_
#include "net/ipv6/addr.h"
#include "net/gnrc.h"
#include "net/gnrc/rpl/structs.h"
#include "net/gnrc/rpl/p2p_structs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief P2P-RPL Mode of Operation
*/
#define GNRC_RPL_P2P_MOP (0x04)
/**
* @brief Default lifetime of the P2P-RPL DODAG, encoded
* @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
* RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
* </a>
*/
#define GNRC_RPL_P2P_LIFETIME (0x02)
/**
* @brief Number of elided prefix octets from the target field and address vector
* @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
* RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
* </a>
*/
#define GNRC_RPL_P2P_COMPR (0)
/**
* @brief Maximum rank in the DODAG during the route discovery
* @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
* RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
* </a>
*/
#define GNRC_RPL_P2P_MAX_RANK (0)
/**
* @name Trickle parameters
* @see <a href="https://tools.ietf.org/html/rfc6997#section-6.1">
* RFC 6997, section 6.1, Setting a P2P Mode DIO
* </a>
* @{
*/
#define GNRC_RPL_P2P_DEFAULT_DIO_INTERVAL_MIN (6)
#define GNRC_RPL_P2P_DEFAULT_DIO_REDUNDANCY_CONSTANT (1)
/** @} */
/**
* @name Default parent and route entry lifetime
* default lifetime will be multiplied by the lifetime unit to obtain the resulting lifetime
* @{
*/
#define GNRC_RPL_P2P_DEFAULT_LIFETIME (0xFF)
#define GNRC_RPL_P2P_LIFETIME_UNIT (0xFFFF)
/** @} */
/**
* @brief P2P-RPL RDO DIO option type
* @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
* RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
* </a>
*/
#define GNRC_RPL_P2P_OPT_RDO (0x0A)
/**
* @brief DRO ICMPv6 code
* @see <a href="https://tools.ietf.org/html/rfc6997#section-8">
* RFC 6997, section 8, The P2P Discovery Reply Object (P2P-DRO)
* </a>
*/
#define GNRC_RPL_P2P_ICMPV6_CODE_DRO (0x04)
/**
* @brief DRO-ACK ICMPv6 code
* @see <a href="https://tools.ietf.org/html/rfc6997#section-10">
* RFC 6997, section 10, The P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
* </a>
*/
#define GNRC_RPL_P2P_ICMPV6_CODE_DRO_ACK (0x05)
/**
* @brief Time in seconds to wait before sending a DRO
*/
#define GNRC_RPL_P2P_DRO_DELAY (4)
/**
* @brief Message type for handling DRO sending
*/
#define GNRC_RPL_P2P_MSG_TYPE_DRO_HANDLE (0x09A0)
/**
* @brief Lookup table used to decode/encode the lifetime values
*/
extern const uint8_t gnrc_rpl_p2p_lifetime_lookup[4];
/**
* @brief Initialization of a P2P-RPL Instance as root node.
*
* @param[in] instance_id Id of the instance
* @param[in] dodag_id Id of the DODAG
* @param[in] target Target of the P2P-RPL routes discovery
* @param[in] gen_inst_id Flag indicating whether to generate a local isntance id.
* If true, @p instance_id will be ignored
*
* @return Pointer to the new Instance, on success.
* @return NULL, otherwise.
*/
gnrc_rpl_instance_t *gnrc_rpl_p2p_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
ipv6_addr_t *target, bool gen_inst_id);
/**
* @brief Build an RDO
*
* @param[in,out] pkt The RDO will be added to the @p pkt
* @param[in] p2p_ext Pointer to the P2P-RPL DODAG extension
*/
gnrc_pktsnip_t *gnrc_rpl_p2p_rdo_build(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext);
/**
* @brief Parse an RDO
*
* @param[in] rdo The RDO to parse from.
* @param[in] p2p_ext Pointer to the P2P-RPL DODAG extension
*/
void gnrc_rpl_p2p_rdo_parse(gnrc_rpl_p2p_opt_rdo_t *rdo, gnrc_rpl_p2p_ext_t *p2p_ext);
/**
* @brief Send a DRO control message
*
* @param[in] pkt The ICMPv6 packet to send. Can be NULL.
* @param[in] p2p_ext Pointer to the P2P-RPL DODAG extension
*/
void gnrc_rpl_p2p_send_DRO(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext);
/**
* @brief Receive and parse a DRO control message
*
* @param[in] pkt The ICMPv6 packet to parse.
* @param[in] src The source address of the IPv6 packet.
*/
void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src);
/**
* @brief Updates the lifetime of the P2P Dodag and the delay of the DRO
*/
void gnrc_rpl_p2p_update(void);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_RPL_P2P_H_ */
/** @} */

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup net_gnrc_rpl_p2p
* @{
*
* @file
* @brief DODAG-related functions for P2P-RPL
*
* Header file, which defines all public known DODAG-related functions for P2P-RPL.
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#ifndef GNRC_RPL_P2P_DODAG_H_
#define GNRC_RPL_P2P_DODAG_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "net/gnrc/rpl/p2p_structs.h"
/**
* @brief Number of P2P RPL DODAG extensions
*/
#ifndef GNRC_RPL_P2P_EXTS_NUMOF
#define GNRC_RPL_P2P_EXTS_NUMOF (1)
#endif
/**
* @brief P2P-RPL DODAG extensions table
*/
extern gnrc_rpl_p2p_ext_t gnrc_rpl_p2p_exts[GNRC_RPL_P2P_EXTS_NUMOF];
/**
* @brief Allocate a free P2P-RPL DODAG extension
*
* @return Pointer to a free P2P-RPL DODAG extension
* @return NULL, if no free P2P-RPL DODAG extension is available
*/
gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_new(gnrc_rpl_dodag_t *dodag);
/**
* @brief Free the P2P-RPL DODAG extension of @p dodag
*
* @param[in] dodag Pointer to a P2P-RPL DODAG
*/
void gnrc_rpl_p2p_ext_remove(gnrc_rpl_dodag_t *dodag);
/**
* @brief Get the appropriate P2P-RPL DODAG extension of the @p dodag
*
* @param[in] dodag Pointer to a P2P-RPL DODAG
*
* @return Pointer to a P2P-RPL DODAG extension
* @return NULL, if no P2P-RPL DODAG extension is available for @p dodag
*/
gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_get(gnrc_rpl_dodag_t *dodag);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_RPL_P2P_DODAG_H_ */
/**
* @}
*/

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup net_gnrc_rpl_p2p
* @{
*
* @file
* @brief P2P-RPL data structs
*
* Header file, which defines all structs used by P2P-RPL.
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#ifndef GNRC_RPL_P2P_STRUCTS_H_
#define GNRC_RPL_P2P_STRUCTS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "net/ipv6/addr.h"
#include "net/gnrc/rpl/structs.h"
/**
* @brief Address vector length in RDO DIO options and maximal hop count for the P2P-DODAG
*/
#define GNRC_RPL_P2P_ADDR_VEC_NUMOF (8)
/**
* @brief P2P Route Discovery Object (RDO) Option
* @see <a href="https://tools.ietf.org/html/rfc6997#section-7">
* RFC 6997, section 7, P2P Route Discovery Option (P2P-RDO)
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; /**< Option Type: 0x0a */
uint8_t length; /**< length of option, not including first two bytes */
uint8_t compr_flags; /**< flags and number of elided prefix octets */
uint8_t lmn; /**< lifetime, maxrank/nexthop */
ipv6_addr_t target; /**< target address */
} gnrc_rpl_p2p_opt_rdo_t;
/**
* @brief P2P Discovery Reply Object (P2P-DRO)
* @see <a href="https://tools.ietf.org/html/rfc6997#section-8">
* RFC 6997, section 8, P2P Discovery Reply Object (P2P-DRO)
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t instance_id; /**< id of the instance */
uint8_t version_number; /**< version number of the DODAG */
network_uint16_t flags_rev; /**< flags and reserved */
ipv6_addr_t dodag_id; /**< id of the dodag */
} gnrc_rpl_p2p_dro_t;
/**
* @brief P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
* @see <a href="https://tools.ietf.org/html/rfc6997#section-10">
* RFC 6997, section 10, P2P Discovery Reply Object Acknowledgement (P2P-DRO-ACK)
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t instance_id; /**< id of the instance */
uint8_t version_number; /**< version number of the DODAG */
network_uint16_t seq_rev; /**< sequence number and reserved */
ipv6_addr_t dodag_id; /**< id of the dodag */
} gnrc_rpl_p2p_dro_ack_t;
/**
* @brief Extended DODAG information for P2P-RPL
*/
typedef struct {
bool state; /**< state: used / unused */
gnrc_rpl_dodag_t *dodag;/**< DODAG, which owns this P2P extension */
uint8_t compr; /**< number of elided prefix octets */
uint8_t routes_numof; /**< number of requested routes */
bool hop_by_hop; /**< request hop-by-hop routes or source routes */
bool stop; /**< stop route discovery */
bool reply; /**< request P2P-DRO */
bool dro_ack; /**< request P2P-DRO-ACK */
uint8_t lifetime_enc; /**< encoded lifetime of the P2P-DODAG */
int8_t lifetime_sec; /**< lifetime of the P2P-DODAG in seconds */
uint8_t maxrank; /**< maximum rank the P2P-DODAG should span */
uint8_t dro_seq; /**< sequence number of the P2P-DRO */
ipv6_addr_t target; /**< target of the P2P route discovery */
bool for_me; /**< true if this node is the target */
uint8_t addr_numof; /**< number of addresses in the address vector */
int8_t dro_delay; /**< delay DRO after it was requested in seconds */
ipv6_addr_t addr_vec[GNRC_RPL_P2P_ADDR_VEC_NUMOF]; /**< address vector */
} gnrc_rpl_p2p_ext_t;
#ifdef __cplusplus
}
#endif
#endif /* GNRC_RPL_P2P_STRUCTS_H_ */
/**
* @}
*/

View File

@ -85,6 +85,9 @@ endif
ifneq (,$(filter gnrc_rpl_srh,$(USEMODULE)))
DIRS += routing/rpl/srh
endif
ifneq (,$(filter gnrc_rpl_p2p,$(USEMODULE)))
DIRS += routing/rpl/p2p
endif
ifneq (,$(filter gnrc_sixlowpan,$(USEMODULE)))
DIRS += network_layer/sixlowpan
endif

View File

@ -21,6 +21,10 @@
#include "mutex.h"
#include "net/gnrc/rpl.h"
#ifdef MODULE_GNRC_RPL_P2P
#include "net/gnrc/rpl/p2p.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
@ -157,6 +161,24 @@ static void _receive(gnrc_pktsnip_t *icmpv6)
gnrc_rpl_recv_DAO_ACK((gnrc_rpl_dao_ack_t *)(icmpv6_hdr + 1), iface,
byteorder_ntohs(ipv6_hdr->len));
break;
#ifdef MODULE_GNRC_RPL_P2P
case GNRC_RPL_P2P_ICMPV6_CODE_DRO:
DEBUG("RPL: P2P DRO received\n");
gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_add(NULL, NULL, icmpv6->size,
GNRC_NETTYPE_ICMPV6);
if (icmpv6_snip == NULL) {
DEBUG("RPL-P2P: cannot copy ICMPv6 packet\n");
break;
}
memcpy(icmpv6_snip->data, icmpv6->data, icmpv6->size);
gnrc_rpl_p2p_recv_DRO(icmpv6_snip, &ipv6_hdr->src);
break;
case GNRC_RPL_P2P_ICMPV6_CODE_DRO_ACK:
DEBUG("RPL: P2P DRO-ACK received\n");
break;
#endif
default:
DEBUG("RPL: Unknown ICMPV6 code received\n");
break;
@ -265,6 +287,10 @@ void _update_lifetime(void)
}
}
#ifdef MODULE_GNRC_RPL_P2P
gnrc_rpl_p2p_update();
#endif
xtimer_set_msg(&_lt_timer, _lt_time, &_lt_msg, gnrc_rpl_pid);
}
@ -284,6 +310,11 @@ void gnrc_rpl_long_delay_dao(gnrc_rpl_dodag_t *dodag)
void _dao_handle_send(gnrc_rpl_dodag_t *dodag)
{
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
return;
}
#endif
if ((dodag->dao_ack_received == false) && (dodag->dao_counter < GNRC_RPL_DAO_SEND_RETRIES)) {
dodag->dao_counter++;
gnrc_rpl_send_DAO(dodag->instance, NULL, dodag->default_lifetime);

View File

@ -25,6 +25,12 @@
#include "net/gnrc/rpl.h"
#ifdef MODULE_GNRC_RPL_P2P
#include "net/gnrc/rpl/p2p_structs.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#include "net/gnrc/rpl/p2p.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
@ -161,6 +167,18 @@ void gnrc_rpl_send_DIO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
gnrc_pktsnip_t *pkt = NULL, *tmp;
gnrc_rpl_dio_t *dio;
#ifdef MODULE_GNRC_RPL_P2P
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
if (!p2p_ext->for_me) {
if ((pkt = gnrc_rpl_p2p_rdo_build(pkt, p2p_ext)) == NULL) {
return;
}
}
dodag->dio_opts &= ~GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO;
}
#endif
#ifndef GNRC_RPL_WITHOUT_PIO
if (dodag->dio_opts & GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO) {
if ((pkt = _dio_prefix_info_build(pkt, dodag)) == NULL) {
@ -265,6 +283,12 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, kernel_pid_t iface, ipv6_addr_t *src
if ((gnrc_rpl_instances[i].state != 0)
/* a leaf node should only react to unicast DIS */
&& (gnrc_rpl_instances[i].dodag.node_status != GNRC_RPL_LEAF_NODE)) {
#ifdef MODULE_GNRC_RPL_P2P
if (gnrc_rpl_instances[i].mop == GNRC_RPL_P2P_MOP) {
DEBUG("RPL: Not responding to DIS for P2P-RPL DODAG\n");
continue;
}
#endif
trickle_reset_timer(&(gnrc_rpl_instances[i].dodag.trickle));
}
}
@ -497,6 +521,11 @@ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt
first_target = NULL;
break;
#ifdef MODULE_GNRC_RPL_P2P
case (GNRC_RPL_P2P_OPT_RDO):
gnrc_rpl_p2p_rdo_parse((gnrc_rpl_p2p_opt_rdo_t *) opt, gnrc_rpl_p2p_ext_get(dodag));
break;
#endif
}
l += opt->length + sizeof(gnrc_rpl_opt_t);
opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
@ -635,6 +664,13 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src
return;
}
#ifdef MODULE_GNRC_RPL_P2P
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
if ((dodag->instance->mop == GNRC_RPL_P2P_MOP) && (p2p_ext->lifetime_sec <= 0)) {
return;
}
#endif
if (GNRC_RPL_COUNTER_GREATER_THAN(dio->version_number, dodag->version)) {
if (dodag->node_status == GNRC_RPL_ROOT_NODE) {
dodag->version = GNRC_RPL_COUNTER_INCREMENT(dio->version_number);
@ -760,6 +796,12 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
return;
}
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
return;
}
#endif
if (destination == NULL) {
if (dodag->parents == NULL) {
DEBUG("RPL: dodag has no preferred parent\n");
@ -781,14 +823,12 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
return;
}
fib_entry_t *fentry = NULL;
ipv6_addr_t *addr = NULL;
mutex_lock(&(gnrc_ipv6_fib_table.mtx_access));
/* add external and RPL FIB entries */
for (size_t i = 0; i < gnrc_ipv6_fib_table.size; ++i) {
fentry = &gnrc_ipv6_fib_table.data.entries[i];
ipv6_addr_t *addr;
fib_entry_t *fentry = &gnrc_ipv6_fib_table.data.entries[i];
if (fentry->lifetime != 0) {
if (!(fentry->next_hop_flags & FIB_FLAG_RPL_ROUTE)) {
ptr = &tmp;
@ -1003,6 +1043,12 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src
return;
}
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
return;
}
#endif
uint32_t included_opts = 0;
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, inst, opts, len, src, &included_opts)) {
DEBUG("RPL: Error encountered during DAO option parsing - ignore DAO\n");

View File

@ -24,6 +24,10 @@
#include "utlist.h"
#include "net/gnrc/rpl.h"
#ifdef MODULE_GNRC_RPL_P2P
#include "net/gnrc/rpl/p2p.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
@ -46,6 +50,16 @@ static void _rpl_trickle_send_dio(void *args)
return;
}
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
if (p2p_ext && (p2p_ext->for_me || ((p2p_ext->lifetime_sec <= 0) || p2p_ext->stop))) {
trickle_stop(&dodag->trickle);
return;
}
}
#endif
gnrc_rpl_send_DIO(inst, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes);
DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", inst->id,
ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));
@ -97,6 +111,9 @@ bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
{
gnrc_rpl_dodag_t *dodag = &inst->dodag;
#ifdef MODULE_GNRC_RPL_P2P
gnrc_rpl_p2p_ext_remove(dodag);
#endif
gnrc_rpl_dodag_remove_all_parents(dodag);
trickle_stop(&dodag->trickle);
memset(inst, 0, sizeof(gnrc_rpl_instance_t));
@ -140,6 +157,14 @@ bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, ipv6_addr_t *dodag_id, k
dodag->iface = iface;
dodag->netif_addr = netif_addr;
#ifdef MODULE_GNRC_RPL_P2P
if ((instance->mop == GNRC_RPL_P2P_MOP) && (gnrc_rpl_p2p_ext_new(dodag) == NULL)) {
DEBUG("RPL: could not allocate new P2P-RPL DODAG extension. Remove DODAG\n");
gnrc_rpl_instance_remove(instance);
return false;
}
#endif
return true;
}
@ -149,6 +174,7 @@ void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag)
LL_FOREACH_SAFE(dodag->parents, elt, tmp) {
gnrc_rpl_parent_remove(elt);
}
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
}
bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
@ -243,6 +269,9 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
/* update Parent lifetime */
if (parent != NULL) {
parent->lifetime = (now / SEC_IN_USEC) + ((dodag->default_lifetime * dodag->lifetime_unit));
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
#endif
if (parent == dodag->parents) {
fib_add_entry(&gnrc_ipv6_fib_table,
dodag->iface,
@ -254,6 +283,9 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
FIB_FLAG_RPL_ROUTE,
(dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS);
}
#ifdef MODULE_GNRC_RPL_P2P
}
#endif
}
if (_gnrc_rpl_find_preferred_parent(dodag) == NULL) {
@ -291,11 +323,16 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
if (new_best != old_best) {
LL_DELETE(dodag->parents, new_best);
LL_PREPEND(dodag->parents, new_best);
if (dodag->instance->mop != GNRC_RPL_MOP_NO_DOWNWARD_ROUTES) {
/* no-path DAOs only for the storing mode */
if ((dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_NO_MC) ||
(dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_MC)) {
gnrc_rpl_send_DAO(dodag->instance, &old_best->addr, 0);
gnrc_rpl_delay_dao(dodag);
}
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop != GNRC_RPL_P2P_MOP) {
#endif
fib_add_entry(&gnrc_ipv6_fib_table,
dodag->iface,
(uint8_t *) ipv6_addr_unspecified.u8,
@ -305,6 +342,10 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
sizeof(ipv6_addr_t),
FIB_FLAG_RPL_ROUTE,
(dodag->default_lifetime * dodag->lifetime_unit) * SEC_IN_MS);
#ifdef MODULE_GNRC_RPL_P2P
}
#endif
}
dodag->my_rank = dodag->instance->of->calc_rank(dodag->parents, 0);

View File

@ -0,0 +1,3 @@
MODULE = gnrc_rpl_p2p
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,386 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#include "net/icmpv6.h"
#include "net/gnrc/ipv6.h"
#include "net/gnrc/icmpv6.h"
#include "net/gnrc.h"
#include "net/gnrc/rpl/structs.h"
#include "net/gnrc/rpl/dodag.h"
#include "net/gnrc/rpl/p2p.h"
#include "net/gnrc/rpl/p2p_structs.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if ENABLE_DEBUG
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
#endif
#define GNRC_RPL_P2P_RDO_LEN (18)
#define GNRC_RPL_P2P_RDO_FLAGS_LIFETIME (6)
#define GNRC_RPL_P2P_RDO_FLAGS_HBH (6)
#define GNRC_RPL_P2P_RDO_FLAGS_REPLY (7)
#define GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM (4)
#define GNRC_RPL_P2P_RDO_FLAGS_COMPR (0x0F)
#define GNRC_RPL_P2P_RDO_FLAGS_MAXRANK (0x3F)
#define GNRC_RPL_P2P_RDO_FLAGS_NEXT_HOP (GNRC_RPL_P2P_RDO_FLAGS_MAXRANK)
#define GNRC_RPL_P2P_DRO_FLAGS_SEQ (12)
#define GNRC_RPL_P2P_DRO_FLAGS_ACK (14)
#define GNRC_RPL_P2P_DRO_FLAGS_STOP (15)
gnrc_rpl_p2p_ext_t gnrc_rpl_p2p_exts[GNRC_RPL_P2P_EXTS_NUMOF];
const uint8_t gnrc_rpl_p2p_lifetime_lookup[4] = { 1, 4, 16, 64 };
void gnrc_rpl_p2p_update(void)
{
gnrc_rpl_p2p_ext_t *p2p_ext;
for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
p2p_ext = &gnrc_rpl_p2p_exts[i];
if ((p2p_ext->state) && (p2p_ext->lifetime_sec > 0)) {
p2p_ext->lifetime_sec -= GNRC_RPL_LIFETIME_UPDATE_STEP;
if (p2p_ext->lifetime_sec <= 0) {
gnrc_rpl_dodag_remove_all_parents(p2p_ext->dodag);
p2p_ext->dodag->instance->cleanup = GNRC_RPL_CLEANUP_TIME;
continue;
}
p2p_ext->dro_delay -= GNRC_RPL_LIFETIME_UPDATE_STEP;
if (p2p_ext->reply && (p2p_ext->dro_delay < 0) && (p2p_ext->for_me)) {
gnrc_rpl_p2p_send_DRO(NULL, p2p_ext);
}
}
}
}
gnrc_rpl_instance_t *gnrc_rpl_p2p_root_init(uint8_t instance_id, ipv6_addr_t *dodag_id,
ipv6_addr_t *target, bool gen_inst_id)
{
if (gen_inst_id) {
instance_id = gnrc_rpl_gen_instance_id(true);
}
gnrc_rpl_dodag_t *dodag = NULL;
gnrc_rpl_instance_t *instance = gnrc_rpl_root_instance_init(instance_id, dodag_id,
GNRC_RPL_P2P_MOP);
if (!instance) {
return NULL;
}
dodag = &instance->dodag;
instance->max_rank_inc = 0;
dodag->dtsn = 0;
dodag->prf = 0;
dodag->dio_interval_doubl = GNRC_RPL_DEFAULT_DIO_INTERVAL_DOUBLINGS;
dodag->dio_min = GNRC_RPL_P2P_DEFAULT_DIO_INTERVAL_MIN;
dodag->dio_redun = GNRC_RPL_P2P_DEFAULT_DIO_REDUNDANCY_CONSTANT;
dodag->default_lifetime = GNRC_RPL_P2P_DEFAULT_LIFETIME;
dodag->lifetime_unit = GNRC_RPL_P2P_LIFETIME_UNIT;
dodag->version = 0;
dodag->grounded = 1;
dodag->node_status = GNRC_RPL_ROOT_NODE;
dodag->my_rank = GNRC_RPL_ROOT_RANK;
dodag->dio_opts |= GNRC_RPL_REQ_DIO_OPT_DODAG_CONF;
dodag->dio_opts &= ~GNRC_RPL_REQ_DIO_OPT_PREFIX_INFO;
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
p2p_ext->target = *target;
p2p_ext->compr = GNRC_RPL_P2P_COMPR;
p2p_ext->routes_numof = 0;
p2p_ext->hop_by_hop = true;
p2p_ext->reply = true;
p2p_ext->lifetime_enc = GNRC_RPL_P2P_LIFETIME;
p2p_ext->lifetime_sec = gnrc_rpl_p2p_lifetime_lookup[p2p_ext->lifetime_enc];
p2p_ext->maxrank = GNRC_RPL_P2P_MAX_RANK;
p2p_ext->dro_delay = -1;
trickle_start(gnrc_rpl_pid, &dodag->trickle, GNRC_RPL_MSG_TYPE_TRICKLE_INTERVAL,
GNRC_RPL_MSG_TYPE_TRICKLE_CALLBACK, (1 << dodag->dio_min),
dodag->dio_interval_doubl, dodag->dio_redun);
return instance;
}
gnrc_pktsnip_t *gnrc_rpl_p2p_rdo_build(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext)
{
gnrc_rpl_p2p_opt_rdo_t *rdo;
gnrc_pktsnip_t *opt_snip;
size_t addr_len = (sizeof(ipv6_addr_t) - p2p_ext->compr);
for (uint8_t i = p2p_ext->addr_numof; i > 0; i--) {
if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, addr_len, GNRC_NETTYPE_UNDEF)) == NULL) {
DEBUG("RPL: BUILD RDO - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
memcpy(opt_snip->data, &p2p_ext->addr_vec[i-1], addr_len);
pkt = opt_snip;
}
if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_opt_rdo_t),
GNRC_NETTYPE_UNDEF)) == NULL) {
DEBUG("RPL: BUILD RDO - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
rdo = opt_snip->data;
rdo->type = GNRC_RPL_P2P_OPT_RDO;
rdo->length = GNRC_RPL_P2P_RDO_LEN +
p2p_ext->addr_numof * (sizeof(ipv6_addr_t) - p2p_ext->compr);
rdo->compr_flags = (p2p_ext->reply << GNRC_RPL_P2P_RDO_FLAGS_REPLY) |
(p2p_ext->hop_by_hop << GNRC_RPL_P2P_RDO_FLAGS_HBH)
| ((p2p_ext->routes_numof & 0x3) << GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM)
| (p2p_ext->compr & GNRC_RPL_P2P_RDO_FLAGS_COMPR);
rdo->lmn = ((p2p_ext->lifetime_enc & 0x3) << GNRC_RPL_P2P_RDO_FLAGS_LIFETIME) |
(p2p_ext->maxrank & GNRC_RPL_P2P_RDO_FLAGS_MAXRANK);
rdo->target = p2p_ext->target;
return opt_snip;
}
void gnrc_rpl_p2p_rdo_parse(gnrc_rpl_p2p_opt_rdo_t *rdo, gnrc_rpl_p2p_ext_t *p2p_ext)
{
DEBUG("RPL: Route Discovery DIO option parsed\n");
uint8_t addr_num = (rdo->length - GNRC_RPL_P2P_RDO_LEN)
/ (sizeof(ipv6_addr_t) - p2p_ext->compr);
if (addr_num >= GNRC_RPL_P2P_ADDR_VEC_NUMOF) {
DEBUG("RPL: cannot parse RDO - too many hops\n");
return;
}
p2p_ext->for_me = (gnrc_ipv6_netif_find_by_addr(NULL, &rdo->target) != KERNEL_PID_UNDEF);
p2p_ext->reply = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_REPLY))
>> GNRC_RPL_P2P_RDO_FLAGS_REPLY;
p2p_ext->hop_by_hop = (rdo->compr_flags & (1 << GNRC_RPL_P2P_RDO_FLAGS_HBH))
>> GNRC_RPL_P2P_RDO_FLAGS_HBH;
p2p_ext->routes_numof = (rdo->compr_flags & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM))
>> GNRC_RPL_P2P_RDO_FLAGS_ADDRNUM;
p2p_ext->compr = rdo->compr_flags & GNRC_RPL_P2P_RDO_FLAGS_COMPR;
p2p_ext->lifetime_enc = (rdo->lmn & (0x3 << GNRC_RPL_P2P_RDO_FLAGS_LIFETIME))
>> GNRC_RPL_P2P_RDO_FLAGS_LIFETIME;
if (p2p_ext->lifetime_sec == INT8_MIN) {
p2p_ext->lifetime_sec = gnrc_rpl_p2p_lifetime_lookup[p2p_ext->lifetime_enc];
}
p2p_ext->maxrank = rdo->lmn & GNRC_RPL_P2P_RDO_FLAGS_MAXRANK;
p2p_ext->target = rdo->target;
memset(&p2p_ext->addr_vec, 0, sizeof(ipv6_addr_t) * GNRC_RPL_P2P_ADDR_VEC_NUMOF);
p2p_ext->addr_numof = 0;
uint8_t *tmp = (uint8_t *) (rdo + 1);
uint8_t *addr = NULL;
uint8_t addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr;
uint8_t i = 0;
for (i = 0; i < addr_num; i++) {
addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr;
memcpy(addr, tmp, addr_len);
tmp += addr_len;
p2p_ext->addr_numof++;
}
if (!p2p_ext->for_me) {
ipv6_addr_t *me = NULL;
if(gnrc_ipv6_netif_find_by_prefix(&me, &p2p_ext->dodag->dodag_id) == KERNEL_PID_UNDEF) {
DEBUG("RPL: no address configured\n");
return;
}
addr = ((uint8_t *) &p2p_ext->addr_vec[i]) + p2p_ext->compr;
memcpy(addr, ((uint8_t *) me) + p2p_ext->compr, addr_len);
p2p_ext->addr_numof++;
}
else if (p2p_ext->reply) {
p2p_ext->stop = true;
p2p_ext->dro_ack = true;
p2p_ext->dro_delay = GNRC_RPL_P2P_DRO_DELAY;
}
}
static gnrc_pktsnip_t *_build_initial_DRO(gnrc_rpl_p2p_ext_t *p2p_ext)
{
gnrc_pktsnip_t *pkt = NULL, *opt_snip = NULL;
gnrc_rpl_p2p_dro_t *dro = NULL;
gnrc_rpl_p2p_opt_rdo_t *rdo = NULL;
size_t addr_len = (sizeof(ipv6_addr_t) - p2p_ext->compr);
uint8_t addr_size = p2p_ext->addr_numof * addr_len;
for (uint8_t i = p2p_ext->addr_numof; i > 0; i--) {
if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, addr_len, GNRC_NETTYPE_UNDEF)) == NULL) {
DEBUG("RPL-P2P: cannot add addresses to RDO - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
memcpy(opt_snip->data, &p2p_ext->addr_vec[i-1], addr_len);
pkt = opt_snip;
}
if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_opt_rdo_t),
GNRC_NETTYPE_UNDEF)) == NULL) {
DEBUG("RPL-P2P: cannot allocate DRO - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
rdo = opt_snip->data;
rdo->type = GNRC_RPL_P2P_OPT_RDO;
rdo->length = GNRC_RPL_P2P_RDO_LEN + addr_size;
rdo->compr_flags = (p2p_ext->hop_by_hop << GNRC_RPL_P2P_RDO_FLAGS_HBH) |
(p2p_ext->compr & GNRC_RPL_P2P_RDO_FLAGS_COMPR);
/* rdo->length does not include the first two bytes, thus we have to add them manually */
rdo->lmn = (((rdo->length + 2 - sizeof(*rdo)) / addr_len) & GNRC_RPL_P2P_RDO_FLAGS_NEXT_HOP);
rdo->target = p2p_ext->target;
pkt = opt_snip;
if ((opt_snip = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_rpl_p2p_dro_t),
GNRC_NETTYPE_UNDEF)) == NULL) {
DEBUG("RPL-P2P: cannot allocate RDO - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
dro = opt_snip->data;
dro->instance_id = p2p_ext->dodag->instance->id;
dro->version_number = 0;
dro->flags_rev = byteorder_htons((((p2p_ext->stop << 1) | (p2p_ext->dro_ack << 0))
<< GNRC_RPL_P2P_DRO_FLAGS_ACK) |
((p2p_ext->dro_seq & 0x3) << GNRC_RPL_P2P_DRO_FLAGS_SEQ));
dro->dodag_id = p2p_ext->dodag->dodag_id;
pkt = opt_snip;
if ((opt_snip = gnrc_icmpv6_build(pkt, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO,
sizeof(icmpv6_hdr_t))) == NULL) {
DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
pkt = opt_snip;
return pkt;
}
void gnrc_rpl_p2p_send_DRO(gnrc_pktsnip_t *pkt, gnrc_rpl_p2p_ext_t *p2p_ext)
{
assert(p2p_ext != NULL);
if (pkt == NULL) {
if ((pkt = _build_initial_DRO(p2p_ext)) == NULL) {
DEBUG("RPL-P2P: BUILD INITIAL DRO - no space left in packet buffer\n");
return;
}
}
gnrc_rpl_send(pkt, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);
return;
}
void gnrc_rpl_p2p_recv_DRO(gnrc_pktsnip_t *pkt, ipv6_addr_t *src)
{
gnrc_pktsnip_t *icmpv6_snip = gnrc_pktbuf_mark(pkt, sizeof(icmpv6_hdr_t), GNRC_NETTYPE_ICMPV6);
gnrc_pktsnip_t *dro_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_dro_t),
GNRC_NETTYPE_UNDEF);
gnrc_pktsnip_t *rdo_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_rpl_p2p_opt_rdo_t),
GNRC_NETTYPE_UNDEF);
gnrc_pktsnip_t *addr_snip = pkt;
gnrc_rpl_instance_t *inst;
gnrc_rpl_dodag_t *dodag;
gnrc_rpl_p2p_ext_t *p2p_ext;
gnrc_rpl_p2p_dro_t *dro;
gnrc_rpl_p2p_opt_rdo_t *rdo;
uint8_t *addr_vec;
uint16_t flags;
size_t addr_len;
if (!rdo_snip || !dro_snip) {
DEBUG("RPL-P2P: Error - No DRO or RDO received\n");
gnrc_pktbuf_release(pkt);
return;
}
dro = dro_snip->data;
if ((inst = gnrc_rpl_instance_get(dro->instance_id)) == NULL) {
DEBUG("RPL-P2P: Error - Instance (%d) does not exist\n", dro->instance_id);
return;
}
dodag = &inst->dodag;
if ((p2p_ext = gnrc_rpl_p2p_ext_get(dodag)) == NULL) {
DEBUG("RPL-P2P: Error - No P2P-RPL DODAG extension found\n");
return;
}
if (p2p_ext->for_me) {
DEBUG("RPL-P2P: Ignore DRO\n");
return;
}
flags = byteorder_ntohs(dro->flags_rev);
p2p_ext->stop = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_STOP)) >> GNRC_RPL_P2P_DRO_FLAGS_STOP;
p2p_ext->dro_ack = (flags & (1 << GNRC_RPL_P2P_DRO_FLAGS_ACK)) >> GNRC_RPL_P2P_DRO_FLAGS_ACK;
p2p_ext->dro_seq = (flags & (0x3 << GNRC_RPL_P2P_DRO_FLAGS_SEQ)) >> GNRC_RPL_P2P_DRO_FLAGS_SEQ;
addr_len = sizeof(ipv6_addr_t) - p2p_ext->compr;
ipv6_addr_t addr = p2p_ext->dodag->dodag_id;
ipv6_addr_t *me = NULL;
addr_vec = addr_snip->data;
rdo = rdo_snip->data;
if (rdo->lmn > 0) {
rdo->lmn--;
memcpy(&addr.u8[p2p_ext->compr], &addr_vec[addr_len * rdo->lmn], addr_len);
}
if (gnrc_ipv6_netif_find_by_addr(&me, &addr) == dodag->iface) {
fib_add_entry(&gnrc_ipv6_fib_table, dodag->iface, p2p_ext->target.u8,
sizeof(ipv6_addr_t), FIB_FLAG_NET_PREFIX, src->u8,
sizeof(ipv6_addr_t), FIB_FLAG_RPL_ROUTE,
p2p_ext->dodag->default_lifetime *
p2p_ext->dodag->lifetime_unit * SEC_IN_MS);
if (p2p_ext->dodag->node_status != GNRC_RPL_ROOT_NODE) {
if ((rdo_snip = gnrc_pktbuf_start_write(rdo_snip)) == NULL) {
DEBUG("RPL-P2P: Error - Cannot allocate new RDO\n");
return;
}
addr_snip->next = NULL;
rdo_snip->next = addr_snip;
dro_snip->next = rdo_snip;
icmpv6_snip = gnrc_icmpv6_build(dro_snip, ICMPV6_RPL_CTRL, GNRC_RPL_P2P_ICMPV6_CODE_DRO,
sizeof(icmpv6_hdr_t));
if (icmpv6_snip == NULL) {
DEBUG("RPL-P2P: cannot allocate ICMPv6 - no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return;
}
gnrc_rpl_send(icmpv6_snip, p2p_ext->dodag->iface, NULL, NULL, &p2p_ext->dodag->dodag_id);
return;
}
}
gnrc_pktbuf_release(pkt);
return;
}
/**
* @}
*/

View File

@ -0,0 +1,63 @@
/**
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#include <string.h>
#include "net/gnrc/rpl/structs.h"
#include "net/gnrc/rpl/p2p.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#include "net/gnrc/rpl/p2p_structs.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_new(gnrc_rpl_dodag_t *dodag)
{
for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
if (!gnrc_rpl_p2p_exts[i].state) {
gnrc_rpl_p2p_exts[i].state = true;
gnrc_rpl_p2p_exts[i].dodag = dodag;
gnrc_rpl_p2p_exts[i].dro_delay = -1;
gnrc_rpl_p2p_exts[i].lifetime_sec = INT8_MIN;
return &gnrc_rpl_p2p_exts[i];
}
}
/* no space available to allocate a P2P-RPL DODAG extension */
DEBUG("RPL-P2P: Could not a new P2P-RPL DODAG extension\n");
return NULL;
}
void gnrc_rpl_p2p_ext_remove(gnrc_rpl_dodag_t *dodag)
{
for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
if ((gnrc_rpl_p2p_exts[i].state) && (gnrc_rpl_p2p_exts[i].dodag == dodag)) {
memset(&gnrc_rpl_p2p_exts[i], 0, sizeof(gnrc_rpl_p2p_ext_t));
return;
}
}
}
gnrc_rpl_p2p_ext_t *gnrc_rpl_p2p_ext_get(gnrc_rpl_dodag_t *dodag)
{
for (uint8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
if ((gnrc_rpl_p2p_exts[i].state) && (gnrc_rpl_p2p_exts[i].dodag == dodag)) {
return &gnrc_rpl_p2p_exts[i];
}
}
return NULL;
}
/**
* @}
*/

View File

@ -23,6 +23,11 @@
#include "net/gnrc/rpl/dodag.h"
#include "utlist.h"
#include "trickle.h"
#ifdef MODULE_GNRC_RPL_P2P
#include "net/gnrc/rpl/p2p.h"
#include "net/gnrc/rpl/p2p_dodag.h"
#include "net/gnrc/rpl/p2p_structs.h"
#endif
int _gnrc_rpl_init(char *arg)
{
@ -63,6 +68,35 @@ int _gnrc_rpl_dodag_root(char *arg1, char *arg2)
return 0;
}
#ifdef MODULE_GNRC_RPL_P2P
int _gnrc_rpl_find(char *arg1, char *arg2)
{
uint8_t instance_id = (uint8_t) atoi(arg1);
ipv6_addr_t dodag_id;
ipv6_addr_t target;
if (ipv6_addr_from_str(&dodag_id, arg1) == NULL) {
puts("<dodag_id> must be a valid IPv6 address");
return 1;
}
if (ipv6_addr_from_str(&target, arg2) == NULL) {
puts("<target> must be a valid IPv6 address");
return 1;
}
if (gnrc_rpl_p2p_root_init(0, &dodag_id, &target, true) == NULL) {
char addr_str[IPV6_ADDR_MAX_STR_LEN];
printf("error: could not add DODAG (%s) to instance (%d)\n",
ipv6_addr_to_str(addr_str, &dodag_id, sizeof(addr_str)), instance_id);
return 1;
}
printf("successfully initiated a P2P-RPL Route Discovery\n");
return 0;
}
#endif
int _gnrc_rpl_instance_remove(char *arg1)
{
uint8_t instance_id = (uint8_t) atoi(arg1);
@ -173,7 +207,22 @@ int _gnrc_rpl_dodag_show(void)
}
putchar('\t');
}
putchar('\n');
#ifdef MODULE_GNRC_RPL_P2P
printf("p2p-rpl table:\t");
for (int8_t i = 0; i < GNRC_RPL_P2P_EXTS_NUMOF; ++i) {
if (gnrc_rpl_p2p_exts[i].state == 0) {
printf("[ ]");
}
else {
printf("[X]");
}
putchar('\t');
}
#endif
putchar('\n');
gnrc_rpl_dodag_t *dodag = NULL;
@ -211,6 +260,16 @@ int _gnrc_rpl_dodag_show(void)
(int) cleanup, (1 << dodag->dio_min), dodag->dio_interval_doubl, dodag->trickle.k,
dodag->trickle.c, (uint32_t) (tc & 0xFFFFFFFF), (uint32_t) (ti & 0xFFFFFFFF));
#ifdef MODULE_GNRC_RPL_P2P
if (dodag->instance->mop == GNRC_RPL_P2P_MOP) {
gnrc_rpl_p2p_ext_t *p2p_ext = gnrc_rpl_p2p_ext_get(dodag);
printf("\tP2P-Ext [%s | HBH: %s | R: %s | L: %us]\n",
ipv6_addr_to_str(addr_str, &p2p_ext->target, sizeof(addr_str)),
p2p_ext->hop_by_hop ? "True" : "False",
p2p_ext->reply ? "True" : "False", p2p_ext->lifetime_sec);
}
#endif
gnrc_rpl_parent_t *parent;
LL_FOREACH(gnrc_rpl_instances[i].dodag.parents, parent) {
printf("\t\tparent [addr: %s | rank: %d | lifetime: %" PRIu32 "s]\n",
@ -317,7 +376,17 @@ int _gnrc_rpl(int argc, char **argv)
#endif
}
}
#ifdef MODULE_GNRC_RPL_P2P
else if (strcmp(argv[1], "find") == 0) {
if (argc == 4) {
return _gnrc_rpl_find(argv[2], argv[3]);
}
}
#endif
#ifdef MODULE_GNRC_RPL_P2P
puts("* find <dodag_id> <target>\t\t\t- initiate a P2P-RPL route discovery");
#endif
puts("* help\t\t\t\t\t- show usage");
puts("* init <if_id>\t\t\t\t- initialize RPL on the given interface");
puts("* leaf <instance_id>\t\t\t- operate as leaf in the instance");