2014-07-08 16:54:54 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013, 2014 INRIA.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
/**
|
2014-07-08 16:54:54 +02:00
|
|
|
* @ingroup rpl
|
|
|
|
* @{
|
2013-06-22 05:11:53 +02:00
|
|
|
*
|
2014-07-08 16:54:54 +02:00
|
|
|
* @file rpl.c
|
|
|
|
* @brief Implementation of the RPL-core.
|
2013-06-22 05:11:53 +02:00
|
|
|
*
|
2014-07-08 16:54:54 +02:00
|
|
|
* Implementation of core RPL-functions. Normally it shouldn't be necessary to
|
|
|
|
* modify this file.
|
2013-06-22 05:11:53 +02:00
|
|
|
*
|
2014-07-08 16:54:54 +02:00
|
|
|
* @author Eric Engel <eric.engel@fu-berlin.de>
|
|
|
|
* @author Fabian Brandt <fabianbr@zedat.fu-berlin.de>
|
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"
|
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
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
#if RPL_DEFAULT_MOP == RPL_MOP_STORING_MODE_NO_MC
|
2014-08-06 13:48:18 +02:00
|
|
|
#include "rpl/rpl_storing.h"
|
2015-01-06 08:29:27 +01:00
|
|
|
#elif RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE
|
2014-07-08 16:54:54 +02:00
|
|
|
#include "rpl/rpl_nonstoring.h"
|
2014-06-18 12:11:12 +02:00
|
|
|
#else
|
2014-08-06 13:48:18 +02:00
|
|
|
#include "rpl/rpl_storing.h"
|
2014-06-18 12:11:12 +02:00
|
|
|
#endif
|
|
|
|
|
2013-11-19 21:23:52 +01:00
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#if ENABLE_DEBUG
|
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-08-06 09:44:31 +02:00
|
|
|
kernel_pid_t rpl_process_pid = KERNEL_PID_UNDEF;
|
2014-06-18 12:11:12 +02:00
|
|
|
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-10-14 08:14:45 +02:00
|
|
|
static timex_t rt_time;
|
|
|
|
static vtimer_t rt_timer;
|
|
|
|
|
|
|
|
static void _dao_handle_send(rpl_dodag_t *dodag);
|
|
|
|
static void _rpl_update_routing_table(void);
|
2012-03-26 00:04:21 +02:00
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
#if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE
|
2015-02-01 19:09:27 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2015-02-01 16:01:56 +01:00
|
|
|
static uint8_t srh_buffer[BUFFER_SIZE];
|
2015-02-01 19:09:27 +01:00
|
|
|
#endif
|
2015-02-01 16:01:56 +01:00
|
|
|
static uint8_t srh_send_buffer[BUFFER_SIZE];
|
|
|
|
static ipv6_addr_t *down_next_hop;
|
|
|
|
static ipv6_srh_t *srh_header;
|
|
|
|
static msg_t srh_m_send, srh_m_recv;
|
2014-07-08 16:54:54 +02:00
|
|
|
#endif
|
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2015-02-01 16:01:56 +01:00
|
|
|
static rpl_routing_entry_t rpl_routing_table[RPL_MAX_ROUTING_ENTRIES];
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2014-07-08 16:54:54 +02:00
|
|
|
uint8_t rpl_max_routing_entries;
|
2015-02-01 16:01:56 +01:00
|
|
|
static ipv6_addr_t my_address;
|
2014-07-08 16:54:54 +02:00
|
|
|
|
2014-06-18 12:11:12 +02:00
|
|
|
/* IPv6 message buffer */
|
2015-01-23 19:43:31 +01:00
|
|
|
static ipv6_hdr_t *ipv6_buf;
|
2012-02-26 19:30:48 +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
|
|
|
{
|
2013-11-22 23:57:33 +01:00
|
|
|
rpl_instances_init();
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
/* initialize routing table */
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-12-09 10:06:08 +01:00
|
|
|
rpl_max_routing_entries = RPL_MAX_ROUTING_ENTRIES;
|
2013-06-22 05:11:53 +02:00
|
|
|
rpl_clear_routing_table();
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2014-07-08 16:54:54 +02:00
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
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
|
|
|
|
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 */
|
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);
|
2015-01-06 08:29:27 +01:00
|
|
|
#if (RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE)
|
2014-07-08 16:54:54 +02:00
|
|
|
ipv6_iface_set_srh_indicator(rpl_is_root);
|
2015-01-06 18:04:54 +01:00
|
|
|
#endif
|
2014-07-08 16:54:54 +02:00
|
|
|
ipv6_iface_set_routing_provider(rpl_get_next_hop);
|
|
|
|
DEBUGF("All addresses set!\n");
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-04-30 14:41:00 +02:00
|
|
|
/* initialize objective function manager */
|
|
|
|
rpl_of_manager_init(&my_address);
|
2014-12-04 10:46:59 +01:00
|
|
|
rpl_init_mode(&my_address);
|
2014-10-14 08:14:45 +02:00
|
|
|
|
|
|
|
rt_time = timex_set(RPL_LIFETIME_STEP, 0);
|
|
|
|
vtimer_set_msg(&rt_timer, rt_time, rpl_process_pid, RPL_MSG_TYPE_ROUTING_ENTRY_UPDATE, NULL);
|
|
|
|
|
2013-09-23 18:01:23 +02:00
|
|
|
return SIXLOWERROR_SUCCESS;
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_init_root(void)
|
|
|
|
{
|
2015-01-06 08:29:27 +01:00
|
|
|
#if (RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE)
|
2014-12-09 10:06:08 +01:00
|
|
|
#ifndef RPL_NODE_IS_ROOT
|
|
|
|
puts("\n############################## ERROR ###############################");
|
|
|
|
puts("This configuration has NO ROUTING TABLE available for the root node!");
|
|
|
|
puts("The root will NOT be INITIALIZED.");
|
|
|
|
puts("Please build the binary for root in non-storing MOP with:");
|
|
|
|
puts("\t\t'make RPL_NODE_IS_ROOT=1'");
|
|
|
|
puts("############################## ERROR ###############################\n");
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
#endif
|
2014-06-18 12:11:12 +02:00
|
|
|
rpl_init_root_mode();
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
uint8_t rpl_is_root(void)
|
|
|
|
{
|
|
|
|
return rpl_is_root_mode();
|
|
|
|
}
|
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
#if (RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE)
|
2014-07-08 16:54:54 +02:00
|
|
|
void internal_srh_process(ipv6_srh_t *srh_header)
|
|
|
|
{
|
2014-10-14 08:14:45 +02:00
|
|
|
/* modify it accordingly - the number of entries is not depending on padding,
|
|
|
|
* because there is none.
|
|
|
|
*/
|
2014-07-08 16:54:54 +02:00
|
|
|
uint8_t n = srh_header->hdrextlen / sizeof(ipv6_addr_t);
|
|
|
|
|
|
|
|
if (srh_header->segments_left > n) {
|
|
|
|
memset(&down_next_hop, 0, sizeof(ipv6_addr_t));
|
|
|
|
DEBUGF("[Error] source-routing header is invalid.\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uint8_t segs = srh_header->segments_left;
|
|
|
|
DEBUGF("SRH-length: %d\n", srh_header->hdrextlen);
|
|
|
|
down_next_hop = &srh_header->route[n - segs];
|
|
|
|
srh_header->segments_left = segs - 1;
|
|
|
|
DEBUGF("Segments left after reduction: %d\n", srh_header->segments_left);
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("Next hop is: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, down_next_hop));
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
rpl_dodag_t *dodag;
|
|
|
|
trickle_t *trickle;
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
while (1) {
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_receive(&m_recv);
|
2014-07-08 16:54:54 +02:00
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
if (m_recv.type > ICMP_CODE_END) {
|
|
|
|
switch (m_recv.type) {
|
|
|
|
case RPL_MSG_TYPE_DAO_HANDLE:
|
|
|
|
dodag = (rpl_dodag_t *) m_recv.content.ptr;
|
|
|
|
if (dodag->joined) {
|
|
|
|
_dao_handle_send(dodag);
|
|
|
|
}
|
2014-07-08 16:54:54 +02:00
|
|
|
break;
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
case RPL_MSG_TYPE_ROUTING_ENTRY_UPDATE:
|
|
|
|
_rpl_update_routing_table();
|
2014-07-08 16:54:54 +02:00
|
|
|
break;
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
case RPL_MSG_TYPE_TRICKLE_INTERVAL:
|
|
|
|
trickle = (trickle_t *) m_recv.content.ptr;
|
|
|
|
if (trickle->callback.func != NULL) {
|
|
|
|
trickle_interval(trickle);
|
|
|
|
}
|
2014-07-08 16:54:54 +02:00
|
|
|
break;
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
case RPL_MSG_TYPE_TRICKLE_CALLBACK:
|
|
|
|
trickle = (trickle_t *) m_recv.content.ptr;
|
|
|
|
if (trickle->callback.func != NULL) {
|
|
|
|
trickle_callback(trickle);
|
|
|
|
}
|
2014-07-08 16:54:54 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
2014-10-14 08:14:45 +02:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
2014-10-14 08:14:45 +02:00
|
|
|
/* This is an RPL-related message. */
|
|
|
|
else {
|
|
|
|
/* differentiate packet types */
|
|
|
|
ipv6_buf = (ipv6_hdr_t *) m_recv.content.ptr;
|
|
|
|
memcpy(&rpl_buffer, ipv6_buf, NTOHS(ipv6_buf->length) + IPV6_HDR_LEN);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) {
|
|
|
|
|
|
|
|
/* get code for message-interpretation and process message */
|
|
|
|
DEBUGF("Received RPL information of type %04X and length %u\n",
|
|
|
|
m_recv.type, NTOHS(ipv6_buf->length));
|
|
|
|
|
|
|
|
switch (m_recv.type) {
|
|
|
|
case (ICMP_CODE_DIS): {
|
|
|
|
rpl_recv_DIS();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case (ICMP_CODE_DIO): {
|
|
|
|
rpl_recv_DIO();
|
|
|
|
break;
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
2014-10-14 08:14:45 +02:00
|
|
|
|
|
|
|
case (ICMP_CODE_DAO): {
|
|
|
|
rpl_recv_DAO();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case (ICMP_CODE_DAO_ACK): {
|
|
|
|
rpl_recv_DAO_ACK();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
2014-10-14 08:14:45 +02:00
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
#if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE
|
2014-10-14 08:14:45 +02:00
|
|
|
/* If the message is not RPL-type, it relates to non-storing mode */
|
2015-01-06 08:29:27 +01:00
|
|
|
else if (RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE) {
|
2014-10-14 08:14:45 +02:00
|
|
|
|
|
|
|
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_SRH) {
|
|
|
|
srh_header = ((ipv6_srh_t *)(m_recv.content.ptr + IPV6_HDR_LEN));
|
|
|
|
|
|
|
|
/* if there are no segments left, the routing is finished */
|
|
|
|
if (srh_header->segments_left == 0) {
|
|
|
|
DEBUGF("Source routing finished with next header: %02X.\n",
|
|
|
|
srh_header->nextheader);
|
|
|
|
DEBUGF("Size of srh: %d\n", srh_header->hdrextlen);
|
|
|
|
uint8_t *payload = ((uint8_t *)(m_recv.content.ptr +
|
|
|
|
IPV6_HDR_LEN + sizeof(ipv6_srh_t)+srh_header->hdrextlen));
|
|
|
|
rpl_remove_srh_header(ipv6_buf, payload, srh_header->nextheader);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
internal_srh_process(srh_header);
|
|
|
|
if (down_next_hop != NULL) {
|
|
|
|
uint8_t *payload = ((uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN));
|
|
|
|
rpl_srh_sendto(payload, NTOHS(ipv6_buf->length), &ipv6_buf->srcaddr,
|
|
|
|
down_next_hop, srh_header, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-10-14 08:14:45 +02:00
|
|
|
else {
|
|
|
|
srh_header = rpl_get_srh_header(ipv6_buf);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
if (srh_header != NULL) {
|
|
|
|
uint8_t *payload = ((uint8_t *)(m_recv.content.ptr + IPV6_HDR_LEN));
|
|
|
|
rpl_srh_sendto(payload, NTOHS(ipv6_buf->length),
|
|
|
|
&ipv6_buf->srcaddr, &ipv6_buf->destaddr, srh_header,
|
|
|
|
srh_header->hdrextlen + sizeof(ipv6_srh_t));
|
|
|
|
}
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
2014-10-14 08:14:45 +02:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_send_DIO(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
if (destination) {
|
|
|
|
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-07-08 16:54:54 +02:00
|
|
|
rpl_send_DIO_mode(destination);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
void rpl_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-07-08 16:54:54 +02:00
|
|
|
if (destination) {
|
|
|
|
DEBUGF("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-07-08 16:54:54 +02:00
|
|
|
rpl_send_DAO_mode(destination, lifetime, default_lifetime, start_index);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_send_DIS(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
if (destination) {
|
|
|
|
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-07-08 16:54:54 +02:00
|
|
|
rpl_send_DIS_mode(destination);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_send_DAO_ACK(ipv6_addr_t *destination)
|
2013-06-22 05:11:53 +02:00
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
if (destination) {
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("Send DAO ACK to %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination));
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
rpl_send_DAO_ACK_mode(destination);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_recv_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-07-08 16:54:54 +02:00
|
|
|
rpl_recv_DIO_mode();
|
2014-06-18 12:11:12 +02:00
|
|
|
}
|
2012-03-26 00:04:21 +02:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_recv_DAO(void)
|
2014-06-18 12:11:12 +02:00
|
|
|
{
|
|
|
|
DEBUGF("DAO received\n");
|
2013-11-20 23:41:21 +01:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
rpl_recv_DAO_mode();
|
2014-06-18 12:11:12 +02:00
|
|
|
}
|
2013-07-16 13:41:23 +02:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_recv_DIS(void)
|
2014-06-18 12:11:12 +02:00
|
|
|
{
|
|
|
|
DEBUGF("DIS received\n");
|
2012-02-14 22:22:01 +01:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
rpl_recv_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-07-08 16:54:54 +02:00
|
|
|
void rpl_recv_DAO_ACK(void)
|
2014-06-18 12:11:12 +02:00
|
|
|
{
|
|
|
|
DEBUGF("DAO ACK received\n");
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
rpl_recv_dao_ack_mode();
|
2014-06-18 12:11:12 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
void _rpl_update_routing_table(void) {
|
|
|
|
rpl_dodag_t *my_dodag = rpl_get_my_dodag();
|
|
|
|
rpl_routing_entry_t *rt;
|
|
|
|
if (my_dodag != NULL) {
|
|
|
|
rt = rpl_get_routing_table();
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < rpl_max_routing_entries; i++) {
|
|
|
|
if (rt[i].used) {
|
|
|
|
if (rt[i].lifetime <= 1) {
|
|
|
|
memset(&rt[i], 0, sizeof(rt[i]));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rt[i].lifetime = rt[i].lifetime - RPL_LIFETIME_STEP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parent is NULL for root too */
|
|
|
|
if (my_dodag->my_preferred_parent != NULL) {
|
|
|
|
if (my_dodag->my_preferred_parent->lifetime <= 1) {
|
|
|
|
DEBUGF("parent lifetime timeout\n");
|
|
|
|
rpl_parent_update(NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
my_dodag->my_preferred_parent->lifetime =
|
|
|
|
my_dodag->my_preferred_parent->lifetime - RPL_LIFETIME_STEP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vtimer_remove(&rt_timer);
|
|
|
|
vtimer_set_msg(&rt_timer, rt_time, rpl_process_pid, RPL_MSG_TYPE_ROUTING_ENTRY_UPDATE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_delay_dao(rpl_dodag_t *dodag)
|
|
|
|
{
|
|
|
|
dodag->dao_time = timex_set(DEFAULT_DAO_DELAY, 0);
|
|
|
|
dodag->dao_counter = 0;
|
|
|
|
dodag->ack_received = false;
|
|
|
|
vtimer_remove(&dodag->dao_timer);
|
|
|
|
vtimer_set_msg(&dodag->dao_timer, dodag->dao_time,
|
|
|
|
rpl_process_pid, RPL_MSG_TYPE_DAO_HANDLE, dodag);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is used for regular update of the routes.
|
|
|
|
* The Timer can be overwritten, as the normal delay_dao function gets called
|
|
|
|
*/
|
|
|
|
void long_delay_dao(rpl_dodag_t *dodag)
|
|
|
|
{
|
|
|
|
dodag->dao_time = timex_set(REGULAR_DAO_INTERVAL, 0);
|
|
|
|
dodag->dao_counter = 0;
|
|
|
|
dodag->ack_received = false;
|
|
|
|
vtimer_remove(&dodag->dao_timer);
|
|
|
|
vtimer_set_msg(&dodag->dao_timer, dodag->dao_time,
|
|
|
|
rpl_process_pid, RPL_MSG_TYPE_DAO_HANDLE, dodag);
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpl_dao_ack_received(rpl_dodag_t *dodag)
|
|
|
|
{
|
|
|
|
dodag->ack_received = true;
|
|
|
|
long_delay_dao(dodag);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _dao_handle_send(rpl_dodag_t *dodag) {
|
|
|
|
if ((dodag->ack_received == false) && (dodag->dao_counter < DAO_SEND_RETRIES)) {
|
|
|
|
dodag->dao_counter++;
|
|
|
|
rpl_send_DAO(NULL, 0, true, 0);
|
|
|
|
dodag->dao_time = timex_set(DEFAULT_WAIT_FOR_DAO_ACK, 0);
|
|
|
|
vtimer_remove(&dodag->dao_timer);
|
|
|
|
vtimer_set_msg(&dodag->dao_timer, dodag->dao_time,
|
|
|
|
rpl_process_pid, RPL_MSG_TYPE_DAO_HANDLE, dodag);
|
|
|
|
}
|
|
|
|
else if (dodag->ack_received == false) {
|
|
|
|
long_delay_dao(dodag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t *addr)
|
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("Looking up the next hop to %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr));
|
2014-07-08 16:54:54 +02:00
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-07-08 16:54:54 +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) {
|
2014-10-14 08:14:45 +02:00
|
|
|
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-07-08 16:54:54 +02:00
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
if ((RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE) && rpl_is_root()) {
|
2014-07-08 16:54:54 +02:00
|
|
|
if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) {
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("found %d: %s\n", i,
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN,
|
|
|
|
&rpl_routing_table[i].address));
|
2014-07-08 16:54:54 +02:00
|
|
|
return &rpl_routing_table[i].address;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) {
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("found %d: %s\n", i,
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN,
|
|
|
|
&rpl_routing_table[i].next_hop));
|
2014-07-08 16:54:54 +02:00
|
|
|
return &rpl_routing_table[i].next_hop;
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#else
|
|
|
|
(void) addr;
|
|
|
|
#endif
|
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
|
|
|
}
|
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
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;
|
|
|
|
}
|
|
|
|
|
2014-07-08 16:54:54 +02:00
|
|
|
DEBUGF("Adding routing entry %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr));
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2013-06-22 05:11:53 +02:00
|
|
|
void rpl_del_routing_entry(ipv6_addr_t *addr)
|
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
DEBUGF("Deleting routing entry %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr));
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2013-06-22 05:11:53 +02:00
|
|
|
rpl_routing_entry_t *rpl_find_routing_entry(ipv6_addr_t *addr)
|
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
DEBUGF("Finding routing entry %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr));
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2013-06-22 05:11:53 +02:00
|
|
|
void rpl_clear_routing_table(void)
|
|
|
|
{
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
for (uint8_t i = 0; i < rpl_max_routing_entries; i++) {
|
|
|
|
memset(&rpl_routing_table[i], 0, sizeof(rpl_routing_table[i]));
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
rpl_routing_entry_t *rpl_get_routing_table(void)
|
|
|
|
{
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-06-18 12:11:12 +02:00
|
|
|
return rpl_routing_table;
|
2015-01-08 11:36:26 +01:00
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2012-02-22 00:50:40 +01:00
|
|
|
}
|
2014-06-18 12:11:12 +02:00
|
|
|
|
2015-01-06 08:29:27 +01:00
|
|
|
#if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE
|
2014-07-08 16:54:54 +02:00
|
|
|
/* everything from here on is non-storing mode related */
|
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-07-08 16:54:54 +02:00
|
|
|
void rpl_add_srh_entry(ipv6_addr_t *child, ipv6_addr_t *parent, uint16_t lifetime)
|
|
|
|
{
|
|
|
|
|
|
|
|
rpl_routing_entry_t *entry = rpl_find_routing_entry(child);
|
|
|
|
|
|
|
|
/* If we already have this entry and the parent from parent/child is the same as already
|
|
|
|
* registered, we only update the lifetime. If only the parent of the child changes, we
|
|
|
|
* delete the previous entry and add it below.
|
|
|
|
*/
|
|
|
|
if (entry != NULL) {
|
|
|
|
if (ipv6_addr_is_equal(parent, &entry->next_hop)) {
|
|
|
|
entry->lifetime = lifetime;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rpl_del_routing_entry(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
/* This maybe a bit confusing since the root also using the standard routing table,
|
|
|
|
* but in this case the code stays cleaner - especially for rt_over_timer from trickle.c.
|
|
|
|
* Just keep in mind that address is now child (unique, iteration variable) and parent is
|
|
|
|
* now next_hop. The whole routing table transforms to a list of children and their parents,
|
|
|
|
* so that route aggregation can be done properly.
|
2014-07-08 16:54:54 +02:00
|
|
|
*/
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("Adding source-routing entry child: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, child));
|
|
|
|
DEBUGF("Adding source-routing entry parent: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, parent));
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
for (uint8_t i = 0; i < rpl_max_routing_entries; i++) {
|
|
|
|
if (!rpl_routing_table[i].used) {
|
|
|
|
memcpy(&rpl_routing_table[i].address, child, sizeof(ipv6_addr_t));
|
|
|
|
memcpy(&rpl_routing_table[i].next_hop, parent, sizeof(ipv6_addr_t));
|
|
|
|
rpl_routing_table[i].lifetime = lifetime;
|
|
|
|
rpl_routing_table[i].used = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Checks if two IPv6 host suffixes are equal.
|
|
|
|
*
|
|
|
|
* @param[in] a An IPv6 address.
|
|
|
|
* @param[in] b Another IPv6 address.
|
|
|
|
*
|
|
|
|
* @return 1 if *a* and *b* are equal for host suffixes, 0 otherwise.
|
|
|
|
*/
|
|
|
|
int ipv6_suffix_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b)
|
|
|
|
{
|
|
|
|
return (a->uint32[2] == b->uint32[2]) &&
|
|
|
|
(a->uint32[3] == b->uint32[3]);
|
|
|
|
}
|
|
|
|
|
2015-01-08 11:36:26 +01:00
|
|
|
#if RPL_MAX_ROUTING_ENTRIES != 0
|
2014-07-08 16:54:54 +02:00
|
|
|
ipv6_srh_t *rpl_get_srh_header(ipv6_hdr_t *act_ipv6_hdr)
|
|
|
|
{
|
|
|
|
uint8_t route_length = RPL_MAX_SRH_PATH_LENGTH;
|
|
|
|
ipv6_addr_t rev_route[route_length];
|
|
|
|
ipv6_addr_t *actual_node;
|
|
|
|
uint8_t counter = 0;
|
|
|
|
uint8_t traceable;
|
|
|
|
ipv6_srh_t *srh_header = (ipv6_srh_t *)(&srh_buffer);
|
|
|
|
|
|
|
|
/* init source route with child */
|
|
|
|
actual_node = &(act_ipv6_hdr->destaddr);
|
|
|
|
DEBUGF("DESTINATION NODE: %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, actual_node));
|
|
|
|
|
|
|
|
while (!(rpl_equal_id(actual_node, &my_address))) {
|
2014-10-14 08:14:45 +02:00
|
|
|
/* set check variable - this is reversed,
|
|
|
|
* if a child/parent-relation is found in one iteration of the routing table */
|
2014-07-08 16:54:54 +02:00
|
|
|
traceable = 0;
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < rpl_max_routing_entries; i++) {
|
2014-10-14 08:14:45 +02:00
|
|
|
if (rpl_routing_table[i].used
|
|
|
|
&& ipv6_suffix_is_equal(&rpl_routing_table[i].address, actual_node)) {
|
|
|
|
DEBUGF("[INFO] Found parent-child relation with P: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN,
|
|
|
|
&rpl_routing_table[i].next_hop));
|
|
|
|
DEBUGF(" and C: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, actual_node));
|
2014-07-08 16:54:54 +02:00
|
|
|
memcpy(&rev_route[counter], actual_node, sizeof(ipv6_addr_t));
|
|
|
|
|
|
|
|
actual_node = &rpl_routing_table[i].next_hop;
|
|
|
|
counter++;
|
|
|
|
traceable = 1;
|
|
|
|
|
|
|
|
if (counter > route_length) {
|
|
|
|
DEBUGF("[INFO] Both lengths are %d and %d\n", counter, route_length);
|
|
|
|
DEBUGF("Error with computing source routing header.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (traceable == 0) {
|
|
|
|
DEBUGF("No route to destination.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
/* build real route based on reversed route.
|
|
|
|
* After building it starts with the node next to destination
|
|
|
|
*/
|
2014-07-08 16:54:54 +02:00
|
|
|
if (counter > 1) {
|
|
|
|
for (uint8_t i = 0; i < counter-1; i++) {
|
|
|
|
memcpy(&srh_header->route[i], &rev_route[counter-i-2], sizeof(ipv6_addr_t));
|
|
|
|
}
|
|
|
|
srh_header->hdrextlen = sizeof(ipv6_addr_t)*(counter-1);
|
|
|
|
memcpy(&(act_ipv6_hdr->destaddr), &rev_route[counter-1], sizeof(ipv6_addr_t));
|
|
|
|
DEBUGF("Route size: %d\n", srh_header->hdrextlen);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
srh_header->hdrextlen = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* actually build SRH-header */
|
|
|
|
memcpy(&srh_header->nextheader, &(act_ipv6_hdr->nextheader), sizeof(uint8_t));
|
|
|
|
srh_header->routing_type = 3;
|
|
|
|
srh_header->segments_left = counter - 1;
|
|
|
|
/* cmpri & cmpre are both 0, because by now there is only support for full addresses */
|
|
|
|
srh_header->cmpri = 0;
|
|
|
|
srh_header->cmpre = 0;
|
|
|
|
/* since the route has exactly the length of its intermediate nodes, padding is zero. */
|
|
|
|
srh_header->pad = 0;
|
|
|
|
srh_header->reserved = 0;
|
|
|
|
/* set the destination-address in ipv6-buf->destaddr, which is the pointer of child */
|
|
|
|
return srh_header;
|
|
|
|
}
|
2015-01-08 11:36:26 +01:00
|
|
|
#endif
|
2014-07-08 16:54:54 +02:00
|
|
|
|
|
|
|
void rpl_remove_srh_header(ipv6_hdr_t *ipv6_header, const void *buf, uint8_t nextheader)
|
|
|
|
{
|
|
|
|
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&srh_send_buffer));
|
|
|
|
uint8_t *payload = &srh_send_buffer[IPV6_HDR_LEN];
|
|
|
|
memcpy(temp_ipv6_header, ipv6_header, sizeof(ipv6_hdr_t));
|
|
|
|
int msg_length = NTOHS(ipv6_header->length) - sizeof(ipv6_srh_t);
|
|
|
|
temp_ipv6_header->length = HTONS(msg_length);
|
|
|
|
temp_ipv6_header->nextheader = nextheader;
|
|
|
|
memcpy(payload, buf, msg_length);
|
|
|
|
DEBUGF("Source routing header extraction finished.\n");
|
2014-10-14 08:14:45 +02:00
|
|
|
DEBUGF("Dest is now: %s\n",
|
|
|
|
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &temp_ipv6_header->destaddr));
|
2014-07-08 16:54:54 +02:00
|
|
|
srh_m_send.content.ptr = (char *) srh_send_buffer;
|
2015-01-08 09:31:30 +01:00
|
|
|
msg_send_receive(&srh_m_send, &srh_m_recv, ip_process_pid);
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
int rpl_srh_sendto(const void *buf, uint16_t len,
|
|
|
|
ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_srh_t *srh_header, uint8_t srh_length)
|
2014-07-08 16:54:54 +02:00
|
|
|
{
|
|
|
|
ipv6_hdr_t *temp_ipv6_header = ((ipv6_hdr_t *)(&srh_send_buffer));
|
|
|
|
ipv6_srh_t *current_packet = ((ipv6_srh_t *)(&srh_send_buffer[IPV6_HDR_LEN]));
|
|
|
|
uint8_t *payload = &srh_send_buffer[IPV6_HDR_LEN + srh_length];
|
|
|
|
memcpy(&(temp_ipv6_header->destaddr), dest, sizeof(ipv6_addr_t));
|
|
|
|
memcpy(&(temp_ipv6_header->srcaddr), src, sizeof(ipv6_addr_t));
|
|
|
|
memcpy(current_packet, srh_header, srh_length);
|
|
|
|
memcpy(payload, buf, len);
|
|
|
|
uint16_t plength = srh_length + len;
|
|
|
|
|
|
|
|
DEBUGF("Build SRH package finished. Going to send it.\n");
|
|
|
|
DEBUGF("SRH-length: %d\n", current_packet->hdrextlen);
|
|
|
|
DEBUGF("My payload length: %d\n", plength);
|
|
|
|
|
2014-10-14 08:14:45 +02:00
|
|
|
return ipv6_sendto(&temp_ipv6_header->destaddr, IPV6_PROTO_NUM_SRH,
|
|
|
|
(uint8_t *)current_packet, plength, &temp_ipv6_header->destaddr);
|
2014-07-08 16:54:54 +02:00
|
|
|
}
|
|
|
|
#endif
|