2013-06-22 05:11:53 +02:00
|
|
|
/**
|
2013-08-08 13:39:00 +02:00
|
|
|
* RPL implementation
|
2013-06-22 05:11:53 +02:00
|
|
|
*
|
|
|
|
* Copyright (C) 2013 INRIA.
|
|
|
|
*
|
2013-11-22 20:47:05 +01:00
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
2013-06-22 05:11:53 +02:00
|
|
|
* Public License. See the file LICENSE in the top level directory for more
|
|
|
|
* details.
|
|
|
|
*
|
2013-08-08 13:39:00 +02:00
|
|
|
* @ingroup rpl
|
2013-06-22 05:11:53 +02:00
|
|
|
* @{
|
2013-08-08 13:39:00 +02:00
|
|
|
* @file rpl.c
|
|
|
|
* @brief basic RPL functions
|
2013-06-22 05:11:53 +02:00
|
|
|
* @author Eric Engel <eric.engel@fu-berlin.de>
|
2013-09-17 19:46:50 +02:00
|
|
|
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
2013-06-22 05:11:53 +02:00
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2012-01-19 17:35:50 +01:00
|
|
|
#include <string.h>
|
2013-12-16 17:54:58 +01:00
|
|
|
#include "vtimer.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "mutex.h"
|
2013-08-09 03:13:37 +02:00
|
|
|
|
2012-01-26 20:26:55 +01:00
|
|
|
#include "msg.h"
|
2012-01-19 17:35:50 +01:00
|
|
|
#include "rpl.h"
|
2013-03-15 17:48:13 +01:00
|
|
|
#include "etx_beaconing.h"
|
2012-01-26 20:26:55 +01:00
|
|
|
#include "of0.h"
|
2013-03-15 17:48:13 +01:00
|
|
|
#include "of_mrhof.h"
|
2012-02-02 21:31:28 +01:00
|
|
|
#include "trickle.h"
|
2012-01-19 17:35:50 +01:00
|
|
|
|
2013-08-05 16:10:54 +02:00
|
|
|
#include "sixlowpan.h"
|
2013-11-20 23:41:21 +01:00
|
|
|
#include "net_help.h"
|
2012-01-19 17:35:50 +01:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/* You can only run Storing Mode by now. Other unsupported modes lead to default (Storing Mode) */
|
|
|
|
#if RPL_DEFAULT_MOP == RPL_STORING_MODE_NO_MC
|
|
|
|
#include "rpl_storing.h"
|
|
|
|
#else
|
|
|
|
#include "rpl_storing.h"
|
|
|
|
#endif
|
|
|
|
|
2013-11-19 21:23:52 +01:00
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#if ENABLE_DEBUG
|
|
|
|
#undef TRICKLE_TIMER_STACKSIZE
|
|
|
|
#define TRICKLE_TIMER_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN)
|
2014-02-27 13:52:13 +01:00
|
|
|
char addr_str[IPV6_MAX_ADDR_STR_LEN];
|
2013-11-19 21:23:52 +01:00
|
|
|
#endif
|
|
|
|
#include "debug.h"
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
/* global variables */
|
2014-06-18 12:11:12 +02:00
|
|
|
rpl_of_t *rpl_objective_functions[NUMBER_IMPLEMENTED_OFS];
|
|
|
|
rpl_routing_entry_t rpl_routing_table[RPL_MAX_ROUTING_ENTRIES];
|
2012-01-26 20:26:55 +01:00
|
|
|
unsigned int rpl_process_pid;
|
2012-03-26 00:04:21 +02:00
|
|
|
mutex_t rpl_recv_mutex;
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_t rpl_send_mutex;
|
|
|
|
msg_t rpl_msg_queue[RPL_PKT_RECV_BUF_SIZE];
|
|
|
|
char rpl_process_buf[RPL_PROCESS_STACKSIZE];
|
2012-03-26 00:04:21 +02:00
|
|
|
uint8_t rpl_buffer[BUFFER_SIZE - LL_HDR_LEN];
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/* IPv6 message buffer */
|
|
|
|
ipv6_hdr_t *ipv6_buf;
|
2012-02-26 19:30:48 +01:00
|
|
|
|
2013-07-16 13:41:23 +02:00
|
|
|
/* find implemented OF via objective code point */
|
2013-06-22 05:11:53 +02:00
|
|
|
rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp)
|
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint16_t i = 0; i < NUMBER_IMPLEMENTED_OFS; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
if (ocp == rpl_objective_functions[i]->ocp) {
|
|
|
|
return rpl_objective_functions[i];
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2012-01-26 20:26:55 +01:00
|
|
|
}
|
|
|
|
|
2014-02-13 13:57:59 +01:00
|
|
|
uint8_t rpl_init(int if_id)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
|
|
|
mutex_init(&rpl_send_mutex);
|
|
|
|
mutex_init(&rpl_recv_mutex);
|
2013-11-22 23:57:33 +01:00
|
|
|
rpl_instances_init();
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
/* initialize routing table */
|
|
|
|
rpl_clear_routing_table();
|
|
|
|
init_trickle();
|
|
|
|
rpl_process_pid = thread_create(rpl_process_buf, RPL_PROCESS_STACKSIZE,
|
|
|
|
PRIORITY_MAIN - 1, CREATE_STACKTEST,
|
2014-03-04 20:20:01 +01:00
|
|
|
rpl_process, NULL, "rpl_process");
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
/* INSERT NEW OBJECTIVE FUNCTIONS HERE */
|
2014-06-18 12:11:12 +02:00
|
|
|
rpl_objective_functions[0] = rpl_get_of0();
|
|
|
|
rpl_objective_functions[1] = rpl_get_of_mrhof();
|
2012-02-14 22:22:01 +01:00
|
|
|
|
2014-02-13 13:57:59 +01:00
|
|
|
sixlowpan_lowpan_init_interface(if_id);
|
2013-07-16 13:41:23 +02:00
|
|
|
/* need link local prefix to query _our_ corresponding address */
|
2014-06-18 12:11:12 +02:00
|
|
|
ipv6_addr_t my_address;
|
2013-06-22 05:11:53 +02:00
|
|
|
ipv6_addr_t ll_address;
|
2013-08-13 06:41:05 +02:00
|
|
|
ipv6_addr_set_link_local_prefix(&ll_address);
|
2014-02-13 13:57:59 +01:00
|
|
|
ipv6_net_if_get_best_src_addr(&my_address, &ll_address);
|
2013-08-13 06:41:05 +02:00
|
|
|
ipv6_register_rpl_handler(rpl_process_pid);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-07-16 13:41:23 +02:00
|
|
|
/* initialize ETX-calculation if needed */
|
2013-08-08 13:39:00 +02:00
|
|
|
if (RPL_DEFAULT_OCP == 1) {
|
2014-04-09 01:09:26 +02:00
|
|
|
DEBUGF("INIT ETX BEACONING\n");
|
2013-03-15 17:48:13 +01:00
|
|
|
etx_init_beaconing(&my_address);
|
2013-06-28 17:53:21 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
rpl_init_mode(&my_address);
|
|
|
|
|
2013-09-23 18:01:23 +02:00
|
|
|
return SIXLOWERROR_SUCCESS;
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_init_root(void)
|
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
rpl_init_root_mode();
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-03-04 20:20:01 +01:00
|
|
|
void *rpl_process(void *arg)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-03-04 20:20:01 +01:00
|
|
|
(void) arg;
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_t m_recv;
|
2014-06-18 12:11:12 +02:00
|
|
|
msg_init_queue(rpl_msg_queue, RPL_PKT_RECV_BUF_SIZE);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
while (1) {
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_receive(&m_recv);
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_lock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
uint8_t *code;
|
|
|
|
code = ((uint8_t *)m_recv.content.ptr);
|
2013-07-16 13:41:23 +02:00
|
|
|
/* differentiate packet types */
|
2013-08-13 06:41:05 +02:00
|
|
|
ipv6_buf = ipv6_get_buf();
|
2014-02-27 13:52:44 +01:00
|
|
|
memcpy(&rpl_buffer, ipv6_buf, NTOHS(ipv6_buf->length) + IPV6_HDR_LEN);
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUGF("Received RPL information of type %04X and length %u\n", *code, NTOHS(ipv6_buf->length));
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-08-08 13:39:00 +02:00
|
|
|
switch (*code) {
|
2013-06-24 22:37:35 +02:00
|
|
|
case (ICMP_CODE_DIS): {
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DIS();
|
2013-08-04 04:06:31 +02:00
|
|
|
mutex_unlock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
case (ICMP_CODE_DIO): {
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DIO();
|
2013-08-04 04:06:31 +02:00
|
|
|
mutex_unlock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
case (ICMP_CODE_DAO): {
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DAO();
|
2013-08-04 04:06:31 +02:00
|
|
|
mutex_unlock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
case (ICMP_CODE_DAO_ACK): {
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DAO_ACK();
|
2013-08-04 04:06:31 +02:00
|
|
|
mutex_unlock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2013-08-04 04:06:31 +02:00
|
|
|
mutex_unlock(&rpl_recv_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/**************************************************************/
|
|
|
|
/* General RPL-send & -receive functions. Call mode-functions */
|
|
|
|
/**************************************************************/
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void send_DIO(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUGF("Send DIO to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination));
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_lock(&rpl_send_mutex);
|
|
|
|
send_DIO_mode(destination);
|
|
|
|
mutex_unlock(&rpl_send_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUG("Send DAO to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination));
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_lock(&rpl_send_mutex);
|
|
|
|
send_DAO_mode(destination, lifetime, default_lifetime, start_index);
|
|
|
|
mutex_unlock(&rpl_send_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void send_DIS(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUGF("Send DIS to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination));
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_lock(&rpl_send_mutex);
|
|
|
|
send_DIS_mode(destination);
|
|
|
|
mutex_unlock(&rpl_send_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void send_DAO_ACK(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUGF("Send DAO ACK to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination));
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
mutex_lock(&rpl_send_mutex);
|
|
|
|
send_DAO_ACK_mode(destination);
|
|
|
|
mutex_unlock(&rpl_send_mutex);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void recv_rpl_DIO(void)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
DEBUGF("DIO received\n");
|
2012-03-26 00:04:21 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DIO_mode();
|
|
|
|
}
|
2012-03-26 00:04:21 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void recv_rpl_DAO(void)
|
|
|
|
{
|
|
|
|
DEBUGF("DAO received\n");
|
2013-11-20 23:41:21 +01:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DAO_mode();
|
|
|
|
}
|
2013-07-16 13:41:23 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void recv_rpl_DIS(void)
|
|
|
|
{
|
|
|
|
DEBUGF("DIS received\n");
|
2012-02-14 22:22:01 +01:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_DIS_mode();
|
2012-02-14 22:22:01 +01:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
void recv_rpl_DAO_ACK(void)
|
|
|
|
{
|
|
|
|
DEBUGF("DAO ACK received\n");
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
recv_rpl_dao_ack_mode();
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/**************************************************************/
|
|
|
|
/**************************************************************/
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
/* Routing related functions are obsolete and will be replaced in near future */
|
|
|
|
/******************************************************************************/
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t *addr)
|
|
|
|
{
|
2014-04-09 01:09:26 +02:00
|
|
|
DEBUGF("looking up the next hop to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr));
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
if (rpl_routing_table[i].used) {
|
|
|
|
DEBUGF("checking %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].address));
|
2014-03-16 20:51:29 +01:00
|
|
|
}
|
2014-06-18 12:11:12 +02:00
|
|
|
if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) {
|
|
|
|
DEBUGF("found %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].next_hop));
|
|
|
|
return &rpl_routing_table[i].next_hop;
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-22 02:12:15 +01:00
|
|
|
return (rpl_get_my_preferred_parent());
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_add_routing_entry(ipv6_addr_t *addr, ipv6_addr_t *next_hop, uint16_t lifetime)
|
|
|
|
{
|
|
|
|
rpl_routing_entry_t *entry = rpl_find_routing_entry(addr);
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (entry != NULL) {
|
2013-06-22 05:11:53 +02:00
|
|
|
entry->lifetime = lifetime;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
if (!rpl_routing_table[i].used) {
|
|
|
|
memcpy(&rpl_routing_table[i].address, addr, sizeof(ipv6_addr_t));
|
|
|
|
memcpy(&rpl_routing_table[i].next_hop, next_hop, sizeof(ipv6_addr_t));
|
|
|
|
rpl_routing_table[i].lifetime = lifetime;
|
|
|
|
rpl_routing_table[i].used = 1;
|
2013-06-22 05:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_del_routing_entry(ipv6_addr_t *addr)
|
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) {
|
|
|
|
memset(&rpl_routing_table[i], 0, sizeof(rpl_routing_table[i]));
|
2013-06-22 05:11:53 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rpl_routing_entry_t *rpl_find_routing_entry(ipv6_addr_t *addr)
|
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) {
|
|
|
|
return &rpl_routing_table[i];
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_clear_routing_table(void)
|
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) {
|
2014-06-18 12:11:12 +02:00
|
|
|
memset(&rpl_routing_table[i], 0, sizeof(rpl_routing_table[i]));
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
rpl_routing_entry_t *rpl_get_routing_table(void)
|
|
|
|
{
|
2014-06-18 12:11:12 +02:00
|
|
|
return rpl_routing_table;
|
2012-02-22 00:50:40 +01:00
|
|
|
}
|
2014-06-18 12:11:12 +02:00
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|