1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 22:13:52 +01:00

Merge pull request #133 from authmillenon/sixlowpan_refactor

Refactor 6LoWPAN module
This commit is contained in:
Oleg Hahm 2013-08-15 00:55:06 -07:00
commit 9fdae28876
59 changed files with 3864 additions and 2128 deletions

View File

@ -14,3 +14,4 @@ clean:
doc:
make -BC doc/doxygen

View File

@ -39,4 +39,7 @@ ifneq (,$(findstring sixlowpan,$(USEMODULE)))
ifeq (,$(findstring ieee802154,$(USEMODULE)))
USEMODULE += ieee802154
endif
ifeq (,$(findstring net_help,$(USEMODULE)))
USEMODULE += net_help
endif
endif

View File

@ -1,4 +1,4 @@
MODULE:=$(shell basename $(CURDIR))
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/net
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/net/destiny -I$(RIOTBASE)/sys/net/sixlowpan/include -I$(RIOTBASE)/sys/net/net_help/
include $(RIOTBASE)/Makefile.base

View File

@ -40,7 +40,7 @@ void init_transport_layer(void)
int udp_thread_pid = thread_create(udp_stack_buffer, UDP_STACK_SIZE,
PRIORITY_MAIN, CREATE_STACKTEST,
udp_packet_handler,"udp_packet_handler");
set_udp_packet_handler_pid(udp_thread_pid);
ipv6_register_next_header_handler(IPV6_PROTO_NUM_UDP, udp_thread_pid);
/* TCP */
timex_t now;
@ -55,7 +55,7 @@ void init_transport_layer(void)
int tcp_thread_pid = thread_create(tcp_stack_buffer, TCP_STACK_SIZE,
PRIORITY_MAIN, CREATE_STACKTEST,
tcp_packet_handler, "tcp_packet_handler");
set_tcp_packet_handler_pid(tcp_thread_pid);
ipv6_register_next_header_handler(IPV6_PROTO_NUM_TCP, tcp_thread_pid);
thread_create(tcp_timer_stack, TCP_TIMER_STACKSIZE, PRIORITY_MAIN + 1,
CREATE_STACKTEST, tcp_general_timer, "tcp_general_timer");

View File

@ -13,7 +13,8 @@
*/
/*
* Protocols (RFC 1700)
* Protocols (RFC 1700) TODO: may be deleted due to some double definition
* in sys/net/sixlowpan/include/sixlowpan/ip.h
*/
#define IPPROTO_IP (0) /* dummy for IP */
#define IPPROTO_HOPOPTS (0) /* IP6 hop-by-hop options */

View File

@ -21,6 +21,7 @@
#include <stdlib.h>
#include <inttypes.h>
#include <math.h>
#include "ipv6.h"
#include "udp.h"
#include "tcp.h"
#include "socket.h"
@ -99,12 +100,13 @@ void print_tcp_cb(tcp_cb_t *cb)
void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header,
tcp_hdr_t *tcp_header, socket_t *tcp_socket)
{
char addr_str[IPV6_MAX_ADDR_STR_LEN];
printf("--- %s TCP packet: ---\n",
(in_or_out == INC_PACKET ? "Incoming" : "Outgoing"));
printf("IPv6 Source:");
ipv6_print_addr(&ipv6_header->srcaddr);
printf("IPv6 Dest:");
ipv6_print_addr(&ipv6_header->destaddr);
printf("IPv6 Source: %s\n",
ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr));
printf("IPv6 Dest: %s\n",
ipv6_addr_to_str(addr_str, &ipv6_header->destaddr));
printf("TCP Length: %x\n", ipv6_header->length - TCP_HDR_LEN);
printf("Source Port: %x, Dest. Port: %x\n",
NTOHS(tcp_header->src_port), NTOHS(tcp_header->dst_port));
@ -123,12 +125,17 @@ void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header,
void print_socket(socket_t *current_socket)
{
char addr_str[IPV6_MAX_ADDR_STR_LEN];
printf("Domain: %i, Type: %i, Protocol: %i \n",
current_socket->domain,
current_socket->type,
current_socket->protocol);
ipv6_print_addr(&current_socket->local_address.sin6_addr);
ipv6_print_addr(&current_socket->foreign_address.sin6_addr);
printf("Local address: %s\n",
ipv6_addr_to_str(addr_str,
&current_socket->local_address.sin6_addr));
printf("Foreign address: %s\n",
ipv6_addr_to_str(addr_str,
&current_socket->foreign_address.sin6_addr));
printf("Local Port: %u, Foreign Port: %u\n",
NTOHS(current_socket->local_address.sin6_port),
NTOHS(current_socket->foreign_address.sin6_port));
@ -293,11 +300,11 @@ socket_internal_t *get_udp_socket(ipv6_hdr_t *ipv6_header, udp_hdr_t *udp_header
bool is_four_touple(socket_internal_t *current_socket, ipv6_hdr_t *ipv6_header,
tcp_hdr_t *tcp_header)
{
return ((ipv6_get_addr_match(&current_socket->socket_values.local_address.sin6_addr,
&ipv6_header->destaddr) == 128) &&
return (ipv6_addr_is_equal(&current_socket->socket_values.local_address.sin6_addr,
&ipv6_header->destaddr) &&
(current_socket->socket_values.local_address.sin6_port == tcp_header->dst_port) &&
(ipv6_get_addr_match(&current_socket->socket_values.foreign_address.sin6_addr,
&ipv6_header->srcaddr) == 128) &&
ipv6_addr_is_equal(&current_socket->socket_values.foreign_address.sin6_addr,
&ipv6_header->srcaddr) &&
(current_socket->socket_values.foreign_address.sin6_port == tcp_header->src_port));
}
@ -469,15 +476,15 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet,
return -1;
}
sixlowpan_send(&current_tcp_socket->foreign_address.sin6_addr,
(uint8_t *)(current_tcp_packet), compressed_size,
IPPROTO_TCP);
ipv6_sendto(&current_tcp_socket->foreign_address.sin6_addr,
IPPROTO_TCP, (uint8_t *)(current_tcp_packet),
compressed_size);
return 1;
#else
switch_tcp_packet_byte_order(current_tcp_packet);
sixlowpan_send(&current_tcp_socket->foreign_address.sin6_addr,
(uint8_t *)(current_tcp_packet),
header_length * 4 + payload_length, IPPROTO_TCP);
ipv6_sendto(&current_tcp_socket->foreign_address.sin6_addr,
IPPROTO_TCP, (uint8_t *)(current_tcp_packet),
header_length * 4 + payload_length);
return 1;
#endif
}
@ -515,7 +522,7 @@ int connect(int socket, sockaddr6_t *addr, uint32_t addrlen)
current_int_tcp_socket->recv_pid = thread_getpid();
/* Local address information */
ipv6_get_saddr(&src_addr, &addr->sin6_addr);
ipv6_iface_get_best_src_addr(&src_addr, &addr->sin6_addr);
set_socket_address(&current_tcp_socket->local_address, PF_INET6,
HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr);
@ -978,7 +985,7 @@ int32_t sendto(int s, const void *msg, uint32_t len, int flags,
uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN];
memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16);
ipv6_get_saddr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr));
ipv6_iface_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr));
current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP);
current_udp_packet->dst_port = to->sin6_port;
@ -991,8 +998,9 @@ int32_t sendto(int s, const void *msg, uint32_t len, int flags,
current_udp_packet->checksum = ~udp_csum(temp_ipv6_header,
current_udp_packet);
sixlowpan_send(&to->sin6_addr, (uint8_t *)(current_udp_packet),
current_udp_packet->length, IPPROTO_UDP);
ipv6_sendto(&to->sin6_addr, IPPROTO_UDP,
(uint8_t *)(current_udp_packet),
current_udp_packet->length);
return current_udp_packet->length;
}
else {

View File

@ -20,10 +20,11 @@
#define SOCKET_H_
#include <stdint.h>
#include "ipv6.h"
#include "tcp.h"
#include "udp.h"
#include "in.h"
#include "../sixlowpan/sixlowip.h"
#include "ipv6.h"
/*
* POSIX compatibility

View File

@ -30,7 +30,7 @@
#include "socket.h"
#include "../net_help/net_help.h"
#include "../net_help/msg_help.h"
#include "../sixlowpan/sixlowpan.h"
#include "sixlowpan.h"
void printTCPHeader(tcp_hdr_t *tcp_header)
{

View File

@ -78,7 +78,7 @@ enum tcp_codes {
#define TCP_STACK_SIZE 1024
#include "../sixlowpan/sixlowip.h"
#include "ipv6.h"
typedef struct __attribute__((packed)) tcp_mms_o_t {
uint8_t kind;

View File

@ -23,7 +23,7 @@
#include "tcp_hc.h"
#include "socket.h"
#include "tcp.h"
#include "../sixlowpan/sixlowip.h"
#include "ipv6.h"
#include "../net_help/net_help.h"
#ifdef TCP_HC
@ -37,10 +37,10 @@ socket_internal_t *get_tcp_socket_by_context(ipv6_hdr_t *current_ipv6_header,
temp_socket = getSocket(i);
if ((temp_socket != NULL) &&
(ipv6_get_addr_match(&temp_socket->socket_values.foreign_address.sin6_addr,
&current_ipv6_header->srcaddr) == 128) &&
(ipv6_get_addr_match(&temp_socket->socket_values.local_address.sin6_addr,
&current_ipv6_header->destaddr) == 128) &&
ipv6_addr_is_equal(&temp_socket->socket_values.foreign_address.sin6_addr,
&current_ipv6_header->srcaddr) &&
ipv6_addr_is_equal(&temp_socket->socket_values.local_address.sin6_addr,
&current_ipv6_header->destaddr) &&
(temp_socket->socket_values.tcp_control.tcp_context.context_id ==
current_context)) {
return temp_socket;

View File

@ -9,7 +9,7 @@
#define TCP_HC_H_
#include "tcp.h"
#include "../sixlowpan/sixlowip.h"
#include "sixlowpan.h"
#include "socket.h"
#ifdef TCP_HC

View File

@ -26,8 +26,8 @@
#include "thread.h"
#include "destiny.h"
#include "socket.h"
#include "net_help/msg_help.h"
#include "../sixlowpan/sixlowpan.h"
#include "../net_help/msg_help.h"
#include "sixlowpan.h"
void handle_synchro_timeout(socket_internal_t *current_socket)
{

View File

@ -22,8 +22,8 @@
#include "udp.h"
#include "msg.h"
#include "../sixlowpan/sixlowip.h"
#include "../sixlowpan/sixlowpan.h"
#include "ipv6.h"
#include "sixlowpan.h"
#include "socket.h"
#include "in.h"
#include "../net_help/net_help.h"

View File

@ -29,7 +29,7 @@
#define UDP_STACK_SIZE 512
#include "../sixlowpan/sixlowip.h"
#include "ipv6.h"
typedef struct __attribute__((packed)) udp_h_t {
uint16_t src_port;

View File

@ -1,4 +1,4 @@
MODULE:=$(shell basename $(CURDIR))
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/sys/net/sixlowpan/include
include $(RIOTBASE)/Makefile.base

View File

@ -15,11 +15,11 @@
#include <thread.h>
#include <transceiver.h>
#include "sixlowpan/sixlowmac.h"
#include "sixlowpan.h"
#include "ieee802154/ieee802154_frame.h"
//prototytpes
static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate);
static uint8_t etx_count_packet_tx(etx_neighbor_t *candidate);
static void etx_set_packets_received(void);
static bool etx_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2);
@ -89,37 +89,42 @@ transceiver_command_t tcmd;
msg_t mesg;
//RPL-address
static ipv6_addr_t * own_address;
static ipv6_addr_t *own_address;
static etx_probe_t * etx_get_send_buf(void) {
static etx_probe_t *etx_get_send_buf(void)
{
return ((etx_probe_t *) &(etx_send_buf[0]));
}
static etx_probe_t * etx_get_rec_buf(void) {
static etx_probe_t *etx_get_rec_buf(void)
{
return ((etx_probe_t *) &(etx_rec_buf[0]));
}
void show_candidates(void) {
etx_neighbor_t * candidate;
void show_candidates(void)
{
etx_neighbor_t *candidate;
etx_neighbor_t *end;
for (candidate = &candidates[0], end = candidates
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
candidate++) {
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
candidate++) {
if (candidate->used == 0) {
break;
}
printf("Candidates Addr:%d\n"
"\t cur_etx:%f\n"
"\t packets_rx:%d\n"
"\t packets_tx:%d\n"
"\t used:%d\n", candidate->addr.uint8[ETX_IPV6_LAST_BYTE],
candidate->cur_etx, candidate->packets_rx,
etx_count_packet_tx(candidate),
candidate->used);
"\t cur_etx:%f\n"
"\t packets_rx:%d\n"
"\t packets_tx:%d\n"
"\t used:%d\n", candidate->addr.uint8[ETX_IPV6_LAST_BYTE],
candidate->cur_etx, candidate->packets_rx,
etx_count_packet_tx(candidate),
candidate->used);
}
}
void etx_init_beaconing(ipv6_addr_t * address) {
void etx_init_beaconing(ipv6_addr_t *address)
{
mutex_init(&etx_mutex);
own_address = address;
//set code
@ -127,29 +132,30 @@ void etx_init_beaconing(ipv6_addr_t * address) {
etx_send_buf[0] = ETX_PKT_OPTVAL;
etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE,
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_beacon, "etx_beacon");
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_beacon, "etx_beacon");
etx_radio_pid = thread_create(etx_radio_buf, ETX_RADIO_STACKSIZE,
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_radio, "etx_radio");
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_radio, "etx_radio");
etx_clock_pid = thread_create(etx_clock_buf, ETX_CLOCK_STACKSIZE,
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_clock, "etx_clock");
PRIORITY_MAIN - 1, CREATE_STACKTEST,
etx_clock, "etx_clock");
//register at transceiver
transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid);
puts("...[DONE]");
}
void etx_beacon(void) {
void etx_beacon(void)
{
/*
* Sends a message every ETX_INTERVAL +/- a jitter-value (default is 10%) .
* A correcting variable is needed to stay at a base interval of
* ETX_INTERVAL between the wakeups. It takes the old jittervalue in account
* and modifies the time to wait accordingly.
*/
etx_probe_t * packet = etx_get_send_buf();
etx_probe_t *packet = etx_get_send_buf();
uint8_t p_length = 0;
/*
@ -165,47 +171,55 @@ void etx_beacon(void) {
mutex_lock(&etx_mutex);
//Build etx packet
p_length = 0;
for (uint8_t i = 0; i < ETX_BEST_CANDIDATES; i++) {
if (candidates[i].used != 0) {
packet->data[i * ETX_TUPLE_SIZE] =
candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE];
candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE];
packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] =
etx_count_packet_tx(&candidates[i]);
etx_count_packet_tx(&candidates[i]);
p_length = p_length + ETX_PKT_HDR_LEN;
}
}
packet->length = p_length;
send_ieee802154_frame(&empty_addr, &etx_send_buf[0],
ETX_DATA_MAXLEN+ETX_PKT_HDR_LEN, 1);
ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1);
DEBUG("sent beacon!\n");
etx_set_packets_received();
cur_round++;
if (cur_round == ETX_WINDOW) {
if (reached_window != 1) {
//first round is through
reached_window = 1;
}
cur_round = 0;
}
mutex_unlock(&etx_mutex);
}
}
etx_neighbor_t * etx_find_candidate(ipv6_addr_t * address) {
etx_neighbor_t *etx_find_candidate(ipv6_addr_t *address)
{
/*
* find the candidate with address address and returns it, or returns NULL
* if no candidate having this address was found.
*/
for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) {
if (candidates[i].used
&& (etx_equal_id(&candidates[i].addr, address))) {
&& (etx_equal_id(&candidates[i].addr, address))) {
return &candidates[i];
}
}
return NULL ;
}
void etx_clock(void) {
void etx_clock(void)
{
/*
* Manages the etx_beacon thread to wake up every full second +- jitter
*/
@ -217,7 +231,7 @@ void etx_clock(void) {
* That is why they are multiplied by 1000 when used for hwtimer_wait.
*/
uint8_t jittercorrection = ETX_DEF_JIT_CORRECT;
uint8_t jitter = (uint8_t) (rand() % ETX_JITTER_MOD);
uint8_t jitter = (uint8_t)(rand() % ETX_JITTER_MOD);
while (true) {
thread_wakeup(etx_beacon_pid);
@ -227,32 +241,37 @@ void etx_clock(void) {
* for now.
*/
vtimer_usleep(
((ETX_INTERVAL - ETX_MAX_JITTER)*MS)+ jittercorrection*MS + jitter*MS - ETX_CLOCK_ADJUST);
((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection * MS + jitter * MS - ETX_CLOCK_ADJUST);
//hwtimer_wait(
// HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS - ETX_CLOCK_ADJUST));
jittercorrection = (ETX_MAX_JITTER) - jitter;
jitter = (uint8_t) (rand() % ETX_JITTER_MOD);
jitter = (uint8_t)(rand() % ETX_JITTER_MOD);
}
}
double etx_get_metric(ipv6_addr_t * address) {
etx_neighbor_t * candidate = etx_find_candidate(address);
if (candidate != NULL ) {
double etx_get_metric(ipv6_addr_t *address)
{
etx_neighbor_t *candidate = etx_find_candidate(address);
if (candidate != NULL) {
if (etx_count_packet_tx(candidate) > 0) {
//this means the current etx_value is not outdated
return candidate->cur_etx;
} else {
}
else {
//The last time I received a packet is too long ago to give a
//good estimate of the etx value
return 0;
}
}
return 0;
}
etx_neighbor_t * etx_add_candidate(ipv6_addr_t * address) {
etx_neighbor_t *etx_add_candidate(ipv6_addr_t *address)
{
DEBUG("add candidate\n");
/*
* Pre-Condition: etx_add_candidate should only be called when the
@ -275,16 +294,17 @@ etx_neighbor_t * etx_add_candidate(ipv6_addr_t * address) {
* Returns the pointer to the candidate if it was added, or a NULL-pointer
* otherwise.
*/
etx_neighbor_t * candidate;
etx_neighbor_t * end;
etx_neighbor_t *candidate;
etx_neighbor_t *end;
for (candidate = &candidates[0], end = candidates
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
candidate++) {
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
candidate++) {
if (candidate->used) {
//skip
continue;
} else {
}
else {
//We still have a free place add the new candidate
memset(candidate, 0, sizeof(*candidate));
candidate->addr = *address;
@ -294,27 +314,31 @@ etx_neighbor_t * etx_add_candidate(ipv6_addr_t * address) {
return candidate;
}
}
return NULL ;
}
void etx_handle_beacon(ipv6_addr_t * candidate_address) {
void etx_handle_beacon(ipv6_addr_t *candidate_address)
{
/*
* Handle the ETX probe that has been received and update all infos.
* If the candidate address is unknown, try to add it to my struct.
*/
DEBUG(
"ETX beacon package received with following values:\n"
"\tPackage Option:%x\n"
"\t Data Length:%u\n"
"\tSource Address:%d\n\n", etx_rec_buf[ETX_PKT_OPT], etx_rec_buf[ETX_PKT_LEN],
candidate_address->uint8[ETX_IPV6_LAST_BYTE]);
"ETX beacon package received with following values:\n"
"\tPackage Option:%x\n"
"\t Data Length:%u\n"
"\tSource Address:%d\n\n", etx_rec_buf[ETX_PKT_OPT], etx_rec_buf[ETX_PKT_LEN],
candidate_address->uint8[ETX_IPV6_LAST_BYTE]);
etx_neighbor_t* candidate = etx_find_candidate(candidate_address);
if (candidate == NULL ) {
etx_neighbor_t *candidate = etx_find_candidate(candidate_address);
if (candidate == NULL) {
//Candidate was not found in my list, I should add it
candidate = etx_add_candidate(candidate_address);
if (candidate == NULL ) {
if (candidate == NULL) {
puts("[ERROR] Candidate could not get added");
puts("Increase the constant ETX_MAX_CANDIDATE_NEIHGBORS");
return;
@ -327,18 +351,18 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) {
// If i find my address in this probe, update the packet_rx value for
// this candidate.
etx_probe_t * rec_pkt = etx_get_rec_buf();
etx_probe_t *rec_pkt = etx_get_rec_buf();
for (uint8_t i = 0; i < rec_pkt->length / ETX_TUPLE_SIZE; i++) {
DEBUG("\tIPv6 short Addr:%u\n"
"\tPackets f. Addr:%u\n\n", rec_pkt->data[i * ETX_TUPLE_SIZE],
rec_pkt->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]);
"\tPackets f. Addr:%u\n\n", rec_pkt->data[i * ETX_TUPLE_SIZE],
rec_pkt->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]);
if (rec_pkt->data[i * ETX_TUPLE_SIZE]
== own_address->uint8[ETX_IPV6_LAST_BYTE]) {
== own_address->uint8[ETX_IPV6_LAST_BYTE]) {
candidate->packets_rx = rec_pkt->data[i * ETX_TUPLE_SIZE
+ ETX_PKT_REC_OFFSET];
+ ETX_PKT_REC_OFFSET];
}
}
@ -346,7 +370,8 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) {
etx_update(candidate);
}
void etx_radio(void) {
void etx_radio(void)
{
msg_t m;
radio_packet_t *p;
@ -357,13 +382,14 @@ void etx_radio(void) {
ipv6_addr_t ll_address;
ipv6_addr_t candidate_addr;
ipv6_set_ll_prefix(&ll_address);
ipv6_get_saddr(&candidate_addr, &ll_address);
ipv6_addr_set_link_local_prefix(&ll_address);
ipv6_iface_get_best_src_addr(&candidate_addr, &ll_address);
while (1) {
msg_receive(&m);
if (m.type == PKT_PENDING) {
p = (radio_packet_t*) m.content.ptr;
p = (radio_packet_t *) m.content.ptr;
read_802154_frame(p->data, &frame, p->length);
@ -392,7 +418,8 @@ void etx_radio(void) {
}
}
void etx_update(etx_neighbor_t * candidate) {
void etx_update(etx_neighbor_t *candidate)
{
DEBUG("update!\n");
/*
* Update the current ETX value of a candidate
@ -400,7 +427,7 @@ void etx_update(etx_neighbor_t * candidate) {
double d_f;
double d_r;
if (reached_window != 1 || candidate == NULL ) {
if (reached_window != 1 || candidate == NULL) {
//We will wait at least ETX_WINDOW beacons until we decide to
//calculate an ETX value, so that we have a good estimate
return;
@ -419,24 +446,26 @@ void etx_update(etx_neighbor_t * candidate) {
/*
* Calculate the current ETX value for my link to this candidate.
*/
if (d_f * d_r != 0) {
if (d_f *d_r != 0) {
candidate->cur_etx = 1 / (d_f * d_r);
} else {
}
else {
candidate->cur_etx = 0;
}
DEBUG(
"Estimated ETX Metric is %f for candidate w/ addr %d\n"
"Estimated PDR_forward is %f\n"
"Estimated PDR_backwrd is %f\n"
"\n"
"Received Packets: %d\n"
"Sent Packets : %d\n\n",
candidate->cur_etx, candidate->addr.uint8[ETX_IPV6_LAST_BYTE],
d_f, d_r, candidate->packets_rx, etx_count_packet_tx(candidate));
"Estimated ETX Metric is %f for candidate w/ addr %d\n"
"Estimated PDR_forward is %f\n"
"Estimated PDR_backwrd is %f\n"
"\n"
"Received Packets: %d\n"
"Sent Packets : %d\n\n",
candidate->cur_etx, candidate->addr.uint8[ETX_IPV6_LAST_BYTE],
d_f, d_r, candidate->packets_rx, etx_count_packet_tx(candidate));
}
static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) {
static uint8_t etx_count_packet_tx(etx_neighbor_t *candidate)
{
/*
* Counts the number of packets that were received for this candidate
* in the last ETX_WINDOW intervals.
@ -444,38 +473,46 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) {
DEBUG("counting packets");
uint8_t pkt_count = 0;
DEBUG("[");
for (uint8_t i = 0; i < ETX_WINDOW; i++) {
if (i != cur_round) {
pkt_count = pkt_count + candidate->packets_tx[i];
DEBUG("%d",candidate->packets_tx[i]);
DEBUG("%d", candidate->packets_tx[i]);
if (i < ETX_WINDOW - 1) {
DEBUG(",");
}
} else {
}
else {
//Check if I received something for the current round
if (candidate->tx_cur_round == 0) {
//Didn't receive a packet, zero the field and don't add
candidate->packets_tx[i] = 0;
DEBUG("%d!",candidate->packets_tx[i]);
DEBUG("%d!", candidate->packets_tx[i]);
if (i < ETX_WINDOW - 1) {
DEBUG(",");
}
} else {
}
else {
//Add 1 and set field
pkt_count = pkt_count + 1;
candidate->packets_tx[i] = 1;
DEBUG("%d!",candidate->packets_tx[i]);
DEBUG("%d!", candidate->packets_tx[i]);
if (i < ETX_WINDOW - 1) {
DEBUG(",");
}
}
}
}
DEBUG("]\n");
return pkt_count;
}
static void etx_set_packets_received(void) {
static void etx_set_packets_received(void)
{
/*
* Set for all candidates if they received a packet this round or not
*/
@ -489,12 +526,14 @@ static void etx_set_packets_received(void) {
}
}
bool etx_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2){
for(uint8_t i=0;i<4;i++){
if(id1->uint32[i] != id2->uint32[i]){
bool etx_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2)
{
for (uint8_t i = 0; i < 4; i++) {
if (id1->uint32[i] != id2->uint32[i]) {
return false;
}
}
return true;
}

View File

@ -9,20 +9,20 @@
#ifndef ETX_BEACONING_H_
#define ETX_BEACONING_H_
#include "sys/net/sixlowpan/sixlowip.h"
#include "ipv6.h"
//For debugging purposes
#define ENABLE_DEBUG (0)
#include <debug.h>
#if ENABLE_DEBUG
#define ETX_BEACON_STACKSIZE (4500)
#define ETX_RADIO_STACKSIZE (4500)
#define ETX_CLOCK_STACKSIZE (500)
#define ETX_BEACON_STACKSIZE (4500)
#define ETX_RADIO_STACKSIZE (4500)
#define ETX_CLOCK_STACKSIZE (500)
#else
#define ETX_BEACON_STACKSIZE (2500) //TODO optimize, maybe 2000 is enough
#define ETX_RADIO_STACKSIZE (2500) //TODO optimize, maybe 2000 is enough
#define ETX_CLOCK_STACKSIZE (500) //TODO optimize, maybe 250 is enough
#define ETX_BEACON_STACKSIZE (2500) //TODO optimize, maybe 2000 is enough
#define ETX_RADIO_STACKSIZE (2500) //TODO optimize, maybe 2000 is enough
#define ETX_CLOCK_STACKSIZE (500) //TODO optimize, maybe 250 is enough
#endif
//[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs
@ -36,9 +36,9 @@
* In my tests, the maximum count of neighbors was around 30-something
*/
#if ENABLE_DEBUG
#define ETX_MAX_CANDIDATE_NEIGHBORS (15) //Stacksizes are huge in debug mode, so memory is rare
#define ETX_MAX_CANDIDATE_NEIGHBORS (15) //Stacksizes are huge in debug mode, so memory is rare
#else
#define ETX_MAX_CANDIDATE_NEIGHBORS (40)
#define ETX_MAX_CANDIDATE_NEIGHBORS (40)
#endif
//ETX Interval parameters
#define MS (1000)
@ -86,7 +86,7 @@
* information.
* The information processed shall not exceed the value set in Option Length.
*/
typedef struct __attribute__((packed)) etx_probe_t{
typedef struct __attribute__((packed)) etx_probe_t {
uint8_t code;
uint8_t length;
uint8_t data[30];
@ -102,11 +102,11 @@ typedef struct etx_neighbor_t {
} etx_neighbor_t;
//prototypes
void etx_init_beaconing(ipv6_addr_t * address);
void etx_init_beaconing(ipv6_addr_t *address);
void etx_beacon(void);
void etx_clock(void);
double etx_get_metric(ipv6_addr_t * address);
void etx_update(etx_neighbor_t * neighbor);
double etx_get_metric(ipv6_addr_t *address);
void etx_update(etx_neighbor_t *neighbor);
void etx_radio(void);
#define ETX_PKT_OPT (0) //Position of Option-Type-Byte

View File

@ -1,5 +1,5 @@
/**
* Objective function 0 for RPL implementation
* Objective function 0 for RPL implementation
*
* Copyright (C) 2013 INRIA.
*
@ -7,10 +7,10 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file of0.c
* @brief RPL objective function 0
* @file of0.c
* @brief RPL objective function 0
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/

View File

@ -9,33 +9,37 @@ static uint16_t calc_rank(rpl_parent_t *, uint16_t);
static rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *);
static rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *);
static void reset(rpl_dodag_t *);
static uint16_t calc_path_cost(rpl_parent_t * parent);
static uint16_t calc_path_cost(rpl_parent_t *parent);
uint16_t cur_min_path_cost = MAX_PATH_COST;
rpl_parent_t * cur_preferred_parent = NULL;
rpl_parent_t *cur_preferred_parent = NULL;
rpl_of_t rpl_of_mrhof = {
0x1,
calc_rank,
which_parent,
which_dodag,
reset,
NULL
};
0x1,
calc_rank,
which_parent,
which_dodag,
reset,
NULL
};
rpl_of_t * rpl_get_of_mrhof(void) {
rpl_of_t *rpl_get_of_mrhof(void)
{
return &rpl_of_mrhof;
}
void reset(rpl_dodag_t *dodag) {
void reset(rpl_dodag_t *dodag)
{
}
static uint16_t calc_path_cost(rpl_parent_t * parent) {
static uint16_t calc_path_cost(rpl_parent_t *parent)
{
puts("calc_pathcost");
/*
* Calculates the path cost through the parent, for now, only for ETX
*/
if (parent == NULL ) {
if (parent == NULL) {
// Shouldn't ever happen since this function is supposed to be always
// run with a parent. If it does happen, we can assume a root called it.
puts("[WARNING] calc_path_cost called without parent!");
@ -44,6 +48,7 @@ static uint16_t calc_path_cost(rpl_parent_t * parent) {
double etx_value = etx_get_metric(&(parent->addr));
printf("Metric for parent returned: %f", etx_value);
if (etx_value != 0) {
/*
* (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor
@ -60,14 +65,16 @@ static uint16_t calc_path_cost(rpl_parent_t * parent) {
}
if (etx_value * ETX_RANK_MULTIPLIER + parent->rank
< parent->rank) {
< parent->rank) {
//Overflow
return MAX_PATH_COST;
}
//TODO runden
return etx_value * ETX_RANK_MULTIPLIER
+ parent->rank;
} else {
+ parent->rank;
}
else {
// IMPLEMENT HANDLING OF OTHER METRICS HERE
// if it is 0, it hasn't been computed, thus we cannot compute a path
// cost
@ -75,8 +82,10 @@ static uint16_t calc_path_cost(rpl_parent_t * parent) {
}
}
static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) {
static uint16_t calc_rank(rpl_parent_t *parent, uint16_t base_rank)
{
puts("calc_rank");
/*
* Return the rank for this node.
*
@ -84,7 +93,7 @@ static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) {
* putation will always be assumed to be done for the ETX metric.
* Baserank is pretty much only used to find out if a node is a root or not.
*/
if (parent == NULL ) {
if (parent == NULL) {
if (base_rank == 0) {
//No parent, no rank, a root node would have a rank != 0
return INFINITE_RANK;
@ -97,7 +106,8 @@ static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) {
* (see rpl.c, function global_repair), we can assume this node is root.
*/
return DEFAULT_MIN_HOP_RANK_INCREASE;
} else {
}
else {
/*
* We have a parent and are a non-root node, calculate the path cost for
* the parent and choose the maximum of that value and the advertised
@ -107,19 +117,22 @@ static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) {
if (calculated_pcost < MAX_PATH_COST) {
if ((parent->rank + parent->dodag->minhoprankincrease)
> calculated_pcost) {
> calculated_pcost) {
return parent->rank + parent->dodag->minhoprankincrease;
} else {
}
else {
return calculated_pcost;
}
} else {
}
else {
//Path costs are greater than allowed
return INFINITE_RANK;
}
}
}
static rpl_parent_t * which_parent(rpl_parent_t * p1, rpl_parent_t * p2) {
static rpl_parent_t *which_parent(rpl_parent_t *p1, rpl_parent_t *p2)
{
puts("which_parent");
/*
* Return the parent with the lowest path cost.
@ -130,12 +143,12 @@ static rpl_parent_t * which_parent(rpl_parent_t * p1, rpl_parent_t * p2) {
uint16_t path_p1 = calc_path_cost(p1);
uint16_t path_p2 = calc_path_cost(p2);
if(cur_preferred_parent != NULL){
if (cur_preferred_parent != NULL) {
//test if the parent from which we got this path is still active
if(cur_preferred_parent->used != 0){
if (cur_preferred_parent->used != 0) {
// Test, if the current best path is better than both parents given
if(cur_min_path_cost < path_p1 + PARENT_SWITCH_THRESHOLD
&& cur_min_path_cost < path_p2 + PARENT_SWITCH_THRESHOLD){
if (cur_min_path_cost < path_p1 + PARENT_SWITCH_THRESHOLD
&& cur_min_path_cost < path_p2 + PARENT_SWITCH_THRESHOLD) {
return cur_preferred_parent;
}
}
@ -149,12 +162,14 @@ static rpl_parent_t * which_parent(rpl_parent_t * p1, rpl_parent_t * p2) {
cur_preferred_parent = p1;
return p1;
}
cur_min_path_cost = path_p2;
cur_preferred_parent = p2;
return p2;
}
//Not used yet, as the implementation only makes use of one dodag for now.
static rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) {
static rpl_dodag_t *which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2)
{
return d1;
}

View File

@ -1,5 +1,5 @@
/**
* RPL implementation
* RPL implementation
*
* Copyright (C) 2013 INRIA.
*
@ -7,10 +7,10 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file rpl.c
* @brief basic RPL functions
* @file rpl.c
* @brief basic RPL functions
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/
@ -19,6 +19,7 @@
#include <vtimer.h>
#include <thread.h>
#include <mutex.h>
#include "msg.h"
#include "rpl.h"
#include "etx_beaconing.h"
@ -26,11 +27,8 @@
#include "of_mrhof.h"
#include "trickle.h"
#include "sys/net/sixlowpan/sixlowmac.h"
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowpan.h"
#include "sys/net/sixlowpan/sixlownd.h"
#include "sys/net/sixlowpan/sixlowerror.h"
#include "sixlowpan.h"
#include "ipv6.h"
char rpl_process_buf[RPL_PROCESS_STACKSIZE];
/* global variables */
@ -74,7 +72,7 @@ static rpl_opt_transit_t *rpl_opt_transit_buf;
/* SEND BUFFERS */
static ipv6_hdr_t *get_rpl_send_ipv6_buf(void)
{
return ((ipv6_hdr_t *)&(rpl_send_buffer[0]));
return ((ipv6_hdr_t *) &(rpl_send_buffer[0]));
}
static uint8_t *get_rpl_send_payload_buf(uint8_t ext_len)
@ -82,95 +80,86 @@ static uint8_t *get_rpl_send_payload_buf(uint8_t ext_len)
return &(rpl_send_buffer[IPV6_HDR_LEN + ext_len]);
}
static struct icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len)
{
return ((struct icmpv6_hdr_t *)&(rpl_send_buffer[IPV6_HDR_LEN + ext_len]));
static struct icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len) {
return ((struct icmpv6_hdr_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ext_len]));
}
static struct rpl_dio_t *get_rpl_send_dio_buf(void)
{
return ((struct rpl_dio_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dio_t *get_rpl_send_dio_buf(void) {
return ((struct rpl_dio_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static struct rpl_dao_t *get_rpl_send_dao_buf(void)
{
return ((struct rpl_dao_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dao_t *get_rpl_send_dao_buf(void) {
return ((struct rpl_dao_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void)
{
return ((struct rpl_dao_ack_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void) {
return ((struct rpl_dao_ack_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static struct rpl_dis_t *get_rpl_send_dis_buf(void)
{
return ((struct rpl_dis_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dis_t *get_rpl_send_dis_buf(void) {
return ((struct rpl_dis_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static rpl_opt_dodag_conf_t *get_rpl_send_opt_dodag_conf_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_dodag_conf_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_dodag_conf_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_target_t *get_rpl_send_opt_target_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_target_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_target_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_transit_t *get_rpl_send_opt_transit_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_transit_t *)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_transit_t *) &(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
/* RECEIVE BUFFERS */
static ipv6_hdr_t *get_rpl_ipv6_buf(void)
{
return ((ipv6_hdr_t *)&(rpl_buffer[0]));
return ((ipv6_hdr_t *) &(rpl_buffer[0]));
}
static struct rpl_dio_t *get_rpl_dio_buf(void)
{
return ((struct rpl_dio_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dio_t *get_rpl_dio_buf(void) {
return ((struct rpl_dio_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static struct rpl_dao_t *get_rpl_dao_buf(void)
{
return ((struct rpl_dao_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dao_t *get_rpl_dao_buf(void) {
return ((struct rpl_dao_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void)
{
return ((struct rpl_dao_ack_t *)&(buffer[LLHDR_ICMPV6HDR_LEN]));
static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void) {
return ((struct rpl_dao_ack_t *) &(buffer[LLHDR_ICMPV6HDR_LEN]));
}
static struct rpl_dis_t *get_rpl_dis_buf(void)
{
return ((struct rpl_dis_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
static struct rpl_dis_t *get_rpl_dis_buf(void) {
return ((struct rpl_dis_t *) & (rpl_buffer[IPV6HDR_ICMPV6HDR_LEN]));
}
static rpl_opt_t *get_rpl_opt_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_dodag_conf_t *get_rpl_opt_dodag_conf_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_dodag_conf_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_dodag_conf_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_solicited_t *get_rpl_opt_solicited_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_solicited_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_solicited_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_target_t *get_rpl_opt_target_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_target_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_target_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
static rpl_opt_transit_t *get_rpl_opt_transit_buf(uint8_t rpl_msg_len)
{
return ((rpl_opt_transit_t *)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
return ((rpl_opt_transit_t *) &(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN + rpl_msg_len]));
}
/* find implemented OF via objective code point */
@ -205,15 +194,15 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address)
objective_functions[0] = rpl_get_of0();
/* objective_functions[1] = rpl_get_of_ETX() */
sixlowpan_init(trans, rpl_address, 0);
sixlowpan_lowpan_init(trans, rpl_address, 0);
/* need link local prefix to query _our_ corresponding address */
ipv6_addr_t ll_address;
ipv6_set_ll_prefix(&ll_address);
ipv6_get_saddr(&my_address, &ll_address);
set_rpl_process_pid(rpl_process_pid);
ipv6_addr_set_link_local_prefix(&ll_address);
ipv6_iface_get_best_src_addr(&my_address, &ll_address);
ipv6_register_rpl_handler(rpl_process_pid);
/* initialize ETX-calculation if needed */
if(RPL_DEFAULT_OCP == 1){
if (RPL_DEFAULT_OCP == 1) {
DEBUG("INIT ETX BEACONING\n");
etx_init_beaconing(&my_address);
}
@ -239,7 +228,7 @@ void rpl_init_root(void)
dodag = rpl_new_dodag(RPL_DEFAULT_INSTANCE, &my_address);
if (dodag != NULL) {
dodag->of = (struct rpl_of_t*) rpl_get_of_for_ocp(RPL_DEFAULT_OCP);
dodag->of = (struct rpl_of_t *) rpl_get_of_for_ocp(RPL_DEFAULT_OCP);
dodag->instance = inst;
dodag->mop = RPL_DEFAULT_MOP;
dodag->dtsn = 1;
@ -284,9 +273,9 @@ void send_DIO(ipv6_addr_t *destination)
return;
}
icmp_send_buf->type = ICMP_RPL_CONTROL;
icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL;
icmp_send_buf->code = ICMP_CODE_DIO;
icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6);
rpl_send_dio_buf = get_rpl_send_dio_buf();
memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf));
@ -320,7 +309,7 @@ void send_DIO(ipv6_addr_t *destination)
uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len;
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL);
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL);
mutex_unlock(&rpl_send_mutex);
}
@ -329,14 +318,14 @@ void send_DIS(ipv6_addr_t *destination)
mutex_lock(&rpl_send_mutex);
icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len);
icmp_send_buf->type = ICMP_RPL_CONTROL;
icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL;
icmp_send_buf->code = ICMP_CODE_DIS;
icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6);
rpl_send_dis_buf = get_rpl_send_dis_buf();
uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN;
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL);
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL);
mutex_unlock(&rpl_send_mutex);
}
@ -361,9 +350,9 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime,
icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len);
icmp_send_buf->type = ICMP_RPL_CONTROL;
icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL;
icmp_send_buf->code = ICMP_CODE_DAO;
icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6);
if (my_dodag == NULL) {
mutex_unlock(&rpl_send_mutex);
@ -427,7 +416,7 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime,
opt_len += RPL_OPT_TRANSIT_LEN + 2;
uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len;
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL);
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL);
mutex_unlock(&rpl_send_mutex);
if (continue_index > 1) {
@ -437,7 +426,8 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime,
void send_DAO_ACK(ipv6_addr_t *destination)
{
ipv6_print_addr(destination);
char addr_str[IPV6_MAX_ADDR_STR_LEN];
printf("%s\n", ipv6_addr_to_str(addr_str, destination));
rpl_dodag_t *my_dodag;
my_dodag = rpl_get_my_dodag();
@ -448,9 +438,9 @@ void send_DAO_ACK(ipv6_addr_t *destination)
mutex_lock(&rpl_send_mutex);
icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len);
icmp_send_buf->type = ICMP_RPL_CONTROL;
icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL;
icmp_send_buf->code = ICMP_CODE_DAO_ACK;
icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6);
rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf();
rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id;
@ -459,7 +449,7 @@ void send_DAO_ACK(ipv6_addr_t *destination)
rpl_send_dao_ack_buf->status = 0;
uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN;
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL);
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL);
mutex_unlock(&rpl_send_mutex);
}
@ -474,10 +464,10 @@ void rpl_process(void)
uint8_t *code;
code = ((uint8_t *)m_recv.content.ptr);
/* differentiate packet types */
ipv6_buf = get_ipv6_buf();
ipv6_buf = ipv6_get_buf();
memcpy(&rpl_buffer, ipv6_buf, ipv6_buf->length + IPV6_HDR_LEN);
switch(*code) {
switch (*code) {
case (ICMP_CODE_DIS): {
recv_rpl_dis();
mutex_unlock(&rpl_recv_mutex);
@ -533,11 +523,11 @@ void recv_rpl_dio(void)
}
}
else if (my_inst->id != dio_inst->id) {
/* TODO: Add support support for several instances. */
/* TODO: Add support support for several instances. */
/* At the moment, nodes can only join one instance, this is
* the instance they join first.
* Instances cannot be switched later on. */
/* At the moment, nodes can only join one instance, this is
* the instance they join first.
* Instances cannot be switched later on. */
DEBUG("Ignoring instance - we are %d and got %d\n", my_inst->id, dio_inst->id);
return;
@ -556,14 +546,14 @@ void recv_rpl_dio(void)
uint8_t has_dodag_conf_opt = 0;
/* Parse until all options are consumed.
* ipv6_buf->length contains the packet length minus ipv6 and
* icmpv6 header, so only ICMPV6_HDR_LEN remains to be
* subtracted. */
/* Parse until all options are consumed.
* ipv6_buf->length contains the packet length minus ipv6 and
* icmpv6 header, so only ICMPV6_HDR_LEN remains to be
* subtracted. */
while (len < (ipv6_buf->length - ICMPV6_HDR_LEN)) {
rpl_opt_buf = get_rpl_opt_buf(len);
switch(rpl_opt_buf->type) {
switch (rpl_opt_buf->type) {
case (RPL_OPT_PAD1): {
len += 1;
@ -601,7 +591,7 @@ void recv_rpl_dio(void)
dio_dodag.minhoprankincrease = rpl_opt_dodag_conf_buf->MinHopRankIncrease;
dio_dodag.default_lifetime = rpl_opt_dodag_conf_buf->default_lifetime;
dio_dodag.lifetime_unit = rpl_opt_dodag_conf_buf->lifetime_unit;
dio_dodag.of = (struct rpl_of_t*) rpl_get_of_for_ocp(rpl_opt_dodag_conf_buf->ocp);
dio_dodag.of = (struct rpl_of_t *) rpl_get_of_for_ocp(rpl_opt_dodag_conf_buf->ocp);
len += RPL_OPT_DODAG_CONF_LEN + 2;
break;
}
@ -648,8 +638,9 @@ void recv_rpl_dio(void)
}
if (rpl_dio_buf->rank != INFINITE_RANK) {
char addr_str[IPV6_MAX_ADDR_STR_LEN];
DEBUG("Will join DODAG\n");
ipv6_print_addr(&dio_dodag.dodag_id);
printf("%s", ipv6_addr_to_str(addr_str, &dio_dodag.dodag_id));
rpl_join_dodag(&dio_dodag, &ipv6_buf->srcaddr, rpl_dio_buf->rank);
}
else {
@ -685,7 +676,7 @@ void recv_rpl_dio(void)
reset_trickletimer();
}
/* We are root, all done! */
/* We are root, all done! */
if (my_dodag->my_rank == ROOT_RANK) {
if (rpl_dio_buf->rank != INFINITE_RANK) {
trickle_increment_counter();
@ -739,7 +730,7 @@ void recv_rpl_dis(void)
while (len < (ipv6_buf->length - ICMPV6_HDR_LEN)) {
rpl_opt_buf = get_rpl_opt_buf(len);
switch(rpl_opt_buf->type) {
switch (rpl_opt_buf->type) {
case (RPL_OPT_PAD1): {
len += 1;
break;
@ -808,7 +799,7 @@ void recv_rpl_dao(void)
while (len < (ipv6_buf->length - ICMPV6_HDR_LEN)) {
rpl_opt_buf = get_rpl_opt_buf(len);
switch(rpl_opt_buf->type) {
switch (rpl_opt_buf->type) {
case (RPL_OPT_PAD1): {
len += 1;
@ -899,7 +890,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_
uint8_t *p_ptr;
ipv6_send_buf = get_rpl_send_ipv6_buf();
p_ptr = get_rpl_send_payload_buf(ipv6_ext_hdr_len);
packet_length = 0;
uint16_t packet_length = 0;
ipv6_send_buf->version_trafficclass = IPV6_VER;
ipv6_send_buf->trafficclass_flowlabel = 0;
@ -909,7 +900,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_
ipv6_send_buf->length = p_len;
memcpy(&(ipv6_send_buf->destaddr), destination, 16);
ipv6_get_saddr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr));
ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr));
/* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used.
* Therefore memcpy is not needed because the payload is at the
@ -921,8 +912,10 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_
packet_length = IPV6_HDR_LEN + p_len;
if (ipv6_prefix_mcast_match(&ipv6_send_buf->destaddr)) {
lowpan_init((ieee_802154_long_t *)&(ipv6_send_buf->destaddr.uint16[4]), (uint8_t *)ipv6_send_buf);
if (ipv6_addr_is_multicast(&ipv6_send_buf->destaddr)) {
sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_send_buf->destaddr.uint16[4]),
(uint8_t *)ipv6_send_buf,
packet_length);
}
else {
/* find appropriate next hop before sending */
@ -943,7 +936,9 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_
}
}
lowpan_init((ieee_802154_long_t *)&(next_hop->uint16[4]), (uint8_t *)ipv6_send_buf);
sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(next_hop->uint16[4]),
(uint8_t *)ipv6_send_buf,
packet_length);
}
}

View File

@ -1,5 +1,5 @@
/**
* RPL constants and prototypes
* RPL constants and prototypes
*
* Copyright (C) 2013 INRIA.
*
@ -7,7 +7,7 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file rpl.h
* @brief RPL header
@ -20,7 +20,7 @@
#include <vtimer.h>
#include <mutex.h>
#include <transceiver.h>
#include "sixlowpan/sixlowip.h"
#include "ipv6.h"
#include "rpl_dodag.h"
#define CC1100_RADIO_MODE CC1100_MODE_WOR

View File

@ -1,5 +1,5 @@
/**
* RPL dodag implementation
* RPL dodag implementation
*
* Copyright (C) 2013 INRIA.
*
@ -7,10 +7,10 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file rpl_dodag.c
* @brief RPL dodag functions
* @brief RPL dodag functions
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/
@ -179,7 +179,7 @@ void rpl_delete_parent(rpl_parent_t *parent)
rpl_dodag_t *my_dodag = rpl_get_my_dodag();
if ((my_dodag != NULL) && rpl_equal_id(&my_dodag->my_preferred_parent->addr,
&parent->addr)) {
&parent->addr)) {
my_dodag->my_preferred_parent = NULL;
}
@ -275,7 +275,7 @@ void rpl_parent_update(rpl_parent_t *parent)
}
if (rpl_calc_rank(old_rank, my_dodag->minhoprankincrease) !=
rpl_calc_rank(my_dodag->my_rank, my_dodag->minhoprankincrease)) {
rpl_calc_rank(my_dodag->my_rank, my_dodag->minhoprankincrease)) {
if (my_dodag->my_rank < my_dodag->min_rank) {
my_dodag->min_rank = my_dodag->my_rank;
}
@ -348,7 +348,7 @@ void rpl_global_repair(rpl_dodag_t *dodag, ipv6_addr_t *p_addr, uint16_t rank)
else {
/* Calc new Rank */
my_dodag->my_rank = my_dodag->of->calc_rank(my_dodag->my_preferred_parent,
my_dodag->my_rank);
my_dodag->my_rank);
my_dodag->min_rank = my_dodag->my_rank;
reset_trickletimer();
delay_dao();

View File

@ -1,5 +1,5 @@
/**
* RPL dodag prototypes
* RPL dodag prototypes
*
* Copyright (C) 2013 INRIA.
*
@ -7,15 +7,16 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file rpl_dodag.h
* @brief RPL dodag header
* @brief RPL dodag header
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/
#include <string.h>
#include "ipv6.h"
#include "rpl_structs.h"
rpl_instance_t *rpl_new_instance(uint8_t instanceid);

View File

@ -1,5 +1,5 @@
/**
* RPL data structs
* RPL data structs
*
* Copyright (C) 2013 INRIA.
*
@ -7,7 +7,7 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file rpl_structs.h
* @brief RPL data structs
@ -16,7 +16,7 @@
*/
#include <string.h>
#include "sixlowpan/sixlowip.h"
#include "ipv6.h"
#ifndef RPL_STRUCTS_H_INCLUDED
#define RPL_STRUCTS_H_INCLUDED
@ -219,12 +219,12 @@ struct rpl_dodag_t;
typedef struct {
ipv6_addr_t addr;
uint16_t rank;
uint8_t dtsn;
uint8_t dtsn;
struct rpl_dodag_t *dodag;
uint16_t lifetime;
double link_metric;
uint8_t link_metric_type;
uint8_t used;
uint16_t lifetime;
double link_metric;
uint8_t link_metric_type;
uint8_t used;
} rpl_parent_t;
struct rpl_of_t;
@ -264,13 +264,13 @@ typedef struct rpl_dodag_t {
typedef struct rpl_of_t {
uint16_t ocp;
uint16_t (*calc_rank)(rpl_parent_t * parent, uint16_t base_rank);
uint16_t (*calc_rank)(rpl_parent_t *parent, uint16_t base_rank);
rpl_parent_t *(*which_parent)(rpl_parent_t *, rpl_parent_t *);
rpl_dodag_t *(*which_dodag)(rpl_dodag_t *, rpl_dodag_t *);
void (*reset)(rpl_dodag_t *);
void (*parent_state_callback)(rpl_parent_t *, int, int);
void (*init) (void); //OF specific init function
void (*process_dio) (void); //DIO processing callback (acc. to OF0 spec, chpt 5)
void (*init)(void); //OF specific init function
void (*process_dio)(); //DIO processing callback (acc. to OF0 spec, chpt 5)
} rpl_of_t;
typedef struct {

View File

@ -7,7 +7,7 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file trickle.c
* @brief Trickle implementation
@ -25,9 +25,9 @@
#include "rpl/rpl.h"
//TODO in pointer umwandeln, speicher mit malloc holen
char * timer_over_buf;
char * interval_over_buf;
char * dao_delay_over_buf;
char *timer_over_buf;
char *interval_over_buf;
char *dao_delay_over_buf;
char routing_table_buf[RT_STACKSIZE];
int timer_over_pid;
int interval_over_pid;
@ -71,18 +71,23 @@ void reset_trickletimer(void)
void init_trickle(void)
{
timer_over_buf = calloc(TRICKLE_TIMER_STACKSIZE,sizeof(char));
if(timer_over_buf == NULL){
timer_over_buf = calloc(TRICKLE_TIMER_STACKSIZE, sizeof(char));
if (timer_over_buf == NULL) {
puts("[ERROR] Could not allocate enough memory for timer_over_buf!");
return;
}
interval_over_buf = calloc(TRICKLE_INTERVAL_STACKSIZE,sizeof(char));
if(interval_over_buf == NULL){
interval_over_buf = calloc(TRICKLE_INTERVAL_STACKSIZE, sizeof(char));
if (interval_over_buf == NULL) {
puts("[ERROR] Could not allocate enough memory for interval_over_buf!");
return;
}
dao_delay_over_buf = calloc(DAO_DELAY_STACKSIZE,sizeof(char));
if(dao_delay_over_buf == NULL){
dao_delay_over_buf = calloc(DAO_DELAY_STACKSIZE, sizeof(char));
if (dao_delay_over_buf == NULL) {
puts("[ERROR] Could not allocate enough memory for interval_over_buf!");
return;
}
@ -135,7 +140,7 @@ void trickle_increment_counter(void)
void trickle_timer_over(void)
{
ipv6_addr_t mcast;
ipv6_set_all_nds_mcast_addr(&mcast);
ipv6_addr_set_all_nodes_addr(&mcast);
while (1) {
thread_sleep();

View File

@ -7,10 +7,10 @@
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup rpl
* @ingroup rpl
* @{
* @file trickle.h
* @brief Trickle
* @brief Trickle
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/

View File

@ -1,4 +1,4 @@
MODULE:=$(shell basename $(CURDIR))
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/net -I$(RIOTBASE)/cpu/arm_common/include/
INCLUDES = -I$(RIOTBASE) -I$(RIOTBASE)/sys/include -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/cpu/arm_common/include -I$(RIOTBASE)/sys/net/sixlowpan/include/
include $(RIOTBASE)/Makefile.base

View File

@ -1,5 +1,5 @@
/**
* 6lowpan border router implementation
* 6lowpan border router implementation
*
* Copyright (C) 2013 INRIA.
*
@ -10,7 +10,7 @@
* @ingroup sixlowpan
* @{
* @file sixlowborder.c
* @brief constraint node implementation for a 6lowpan border router
* @brief constraint node implementation for a 6lowpan border router
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
@ -19,24 +19,25 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <mutex.h>
#include <thread.h>
#include <msg.h>
#include <posix_io.h>
#include <board_uart0.h>
#include "mutex.h"
#include "thread.h"
#include "msg.h"
#include "posix_io.h"
#include "board_uart0.h"
#include "sixlowpan/error.h"
#include "bordermultiplex.h"
#include "ieee802154/ieee802154_frame.h"
#include "flowcontrol.h"
#include "sixlowborder.h"
#include "sixlowip.h"
#include "sixlownd.h"
#include "border.h"
#include "ip.h"
#include "icmp.h"
#include "serialnumber.h"
#include "sixlowerror.h"
#include "sys/net/ieee802154/ieee802154_frame.h"
#include "sys/net/net_help/net_help.h"
#define READER_STACK_SIZE 512
#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
ipv6_addr_t abr_addr;
@ -86,7 +87,7 @@ void serial_reader_f(void)
bytes = readpacket(get_serial_in_buffer(0), BORDER_BUFFER_SIZE);
if (bytes < 0) {
switch(bytes) {
switch (bytes) {
case (-SIXLOWERROR_ARRAYFULL): {
printf("ERROR: Array was full\n");
break;
@ -119,7 +120,8 @@ void serial_reader_f(void)
}
}
uint8_t border_initialize(transceiver_type_t trans, ipv6_addr_t *border_router_addr)
uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans,
const ipv6_addr_t *border_router_addr)
{
ipv6_addr_t addr;
@ -139,9 +141,9 @@ uint8_t border_initialize(transceiver_type_t trans, ipv6_addr_t *border_router_a
* -- for now
*/
if (border_router_addr->uint16[4] != HTONS(IEEE_802154_PAN_ID ^ 0x0200) ||
border_router_addr->uint16[5] != HTONS(0x00FF) ||
border_router_addr->uint16[6] != HTONS(0xFE00)
) {
border_router_addr->uint16[5] != HTONS(0x00FF) ||
border_router_addr->uint16[6] != HTONS(0xFE00)
) {
return SIXLOWERROR_ADDRESS;
}
@ -152,26 +154,13 @@ uint8_t border_initialize(transceiver_type_t trans, ipv6_addr_t *border_router_a
memcpy(&(abr_addr.uint8[0]), &(border_router_addr->uint8[0]), 16);
sixlowpan_init(trans, border_router_addr->uint8[15], 1);
sixlowpan_lowpan_init(trans, border_router_addr->uint8[15], 1);
ipv6_init_iface_as_router();
return SUCCESS;
}
void border_send_ipv6_over_lowpan(ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag)
{
uint16_t offset = IPV6_HDR_LEN + HTONS(packet->length);
packet->flowlabel = HTONS(packet->flowlabel);
packet->length = HTONS(packet->length);
memset(buffer, 0, BUFFER_SIZE);
memcpy(buffer + LL_HDR_LEN, packet, offset);
lowpan_init((ieee_802154_long_t *)&(packet->destaddr.uint16[4]), (uint8_t *)packet);
}
void border_process_lowpan(void)
{
msg_t m;
@ -181,10 +170,10 @@ void border_process_lowpan(void)
msg_receive(&m);
ipv6_buf = (ipv6_hdr_t *)m.content.ptr;
if (ipv6_buf->nextheader == PROTO_NUM_ICMPV6) {
struct icmpv6_hdr_t *icmp_buf = (struct icmpv6_hdr_t *)(((uint8_t *)ipv6_buf) + IPV6_HDR_LEN);
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) {
icmpv6_hdr_t *icmp_buf = (icmpv6_hdr_t *)(((uint8_t *)ipv6_buf) + IPV6_HDR_LEN);
if (icmp_buf->type == ICMP_REDIRECT) {
if (icmp_buf->type == ICMPV6_TYPE_REDIRECT) {
continue;
}

View File

@ -10,7 +10,7 @@
* @ingroup sixlowpan
* @{
* @file sixlowborder.h
* @brief header for 6lowpan border router
* @brief header for 6lowpan border router
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
@ -18,14 +18,15 @@
/* 6LoWPAN Border Router header file */
#ifndef SIXLOWBORDER_H
#define SIXLOWBORDER_H
#ifndef _SIXLOWPAN_BORDER_H
#define _SIXLOWPAN_BORDER_H
#include <stdint.h>
#include <mutex.h>
#include <transceiver.h>
#include "sixlowip.h"
#include "mutex.h"
#include "transceiver.h"
#include "ip.h"
#include "semaphore.h"
extern ipv6_addr_t abr_addr;
@ -35,8 +36,6 @@ uint16_t border_get_serial_reader(void);
uint8_t *get_serial_out_buffer(int offset);
uint8_t *get_serial_in_buffer(int offset);
uint8_t border_initialize(transceiver_type_t trans, ipv6_addr_t *border_router_addr);
void border_send_ipv6_over_lowpan(ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag);
void border_process_lowpan(void);
#endif /* SIXLOWBORDER_H*/
#endif /* _SIXLOWPAN_BORDER_H*/

View File

@ -19,24 +19,24 @@
#include <stdio.h>
#include <string.h>
#include <board_uart0.h>
#include "board_uart0.h"
#include "sixlowpan/error.h"
#include "flowcontrol.h"
#include "sixlowpan.h"
#include "sixlownd.h"
#include "sixlowborder.h"
#include "sixlowerror.h"
#include "lowpan.h"
#include "icmp.h"
#include "border.h"
#include "bordermultiplex.h"
#define END 0xC0
#define ESC 0xDB
#define END_ESC 0xDC
#define ESC_ESC 0xDD
#define END (0xC0)
#define ESC (0xDB)
#define END_ESC (0xDC)
#define ESC_ESC (0xDD)
void demultiplex(border_packet_t *packet, int len)
{
switch(packet->type) {
switch (packet->type) {
case (BORDER_PACKET_RAW_TYPE): {
fputs(((char *)packet) + sizeof(border_packet_t), stdin);
break;
@ -45,10 +45,10 @@ void demultiplex(border_packet_t *packet, int len)
case (BORDER_PACKET_L3_TYPE): {
border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet;
switch(l3_header_buf->ethertype) {
switch (l3_header_buf->ethertype) {
case (BORDER_ETHERTYPE_IPV6): {
ipv6_hdr_t *ipv6_buf = (ipv6_hdr_t *)(((unsigned char *)packet) + sizeof(border_l3_header_t));
border_send_ipv6_over_lowpan(ipv6_buf, 1, 1);
ipv6_send_bytes(ipv6_buf);
break;
}
@ -63,11 +63,11 @@ void demultiplex(border_packet_t *packet, int len)
case (BORDER_PACKET_CONF_TYPE): {
border_conf_header_t *conf_header_buf = (border_conf_header_t *)packet;
switch(conf_header_buf->conftype) {
switch (conf_header_buf->conftype) {
case (BORDER_CONF_CONTEXT): {
border_context_packet_t *context = (border_context_packet_t *)packet;
ipv6_addr_t target_addr;
ipv6_set_all_nds_mcast_addr(&target_addr);
ipv6_addr_set_all_nodes_addr(&target_addr);
mutex_lock(&lowpan_context_mutex);
lowpan_context_update(
context->context.cid,
@ -148,7 +148,7 @@ int readpacket(uint8_t *packet_buf, size_t size)
if (esc) {
esc = 0;
switch(byte) {
switch (byte) {
case (END_ESC): {
*line_buf_ptr++ = END;
continue;
@ -184,7 +184,7 @@ int writepacket(uint8_t *packet_buf, size_t size)
return -1;
}
switch(*byte_ptr) {
switch (*byte_ptr) {
case (END): {
*byte_ptr = END_ESC;
uart0_putc(ESC);

View File

@ -1,5 +1,5 @@
/**
* 6lowpan border router multiplexer
* 6lowpan border router multiplexer
*
* Copyright (C) 2013 INRIA.
*
@ -9,32 +9,32 @@
*
* @ingroup sixlowpan
* @{
* @file bordermultiplex.h
* @file bordermultiplex.h
* @brief data structs for border router multiplexing
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
*/
#ifndef BORDERMULTIPLEX_H
#define BORDERMULTIPLEX_H
#ifndef _SIXLOWPAN_BORDERMULTIPLEX_H
#define _SIXLOWPAN_BORDERMULTIPLEX_H
#include <stdint.h>
#include <stdlib.h>
#include "sixlowip.h"
#include "ip.h"
/* packet types of uart-packets */
#define BORDER_PACKET_RAW_TYPE 0
#define BORDER_PACKET_CONF_TYPE 2
#define BORDER_PACKET_L3_TYPE 3
#define BORDER_PACKET_RAW_TYPE (0)
#define BORDER_PACKET_CONF_TYPE (2)
#define BORDER_PACKET_L3_TYPE (3)
/* configuration types */
#define BORDER_CONF_CONTEXT 2
#define BORDER_CONF_IPADDR 3
#define BORDER_CONF_CONTEXT (2)
#define BORDER_CONF_IPADDR (3)
/* ethertypes for L3 packets */
#define BORDER_ETHERTYPE_IPV6 0x86DD
#define BORDER_ETHERTYPE_IPV6 (0x86DD)
typedef struct __attribute__((packed)) {
uint8_t empty;
@ -80,7 +80,7 @@ typedef struct __attribute__((packed)) {
} context;
} border_context_packet_t;
#define BORDER_BUFFER_SIZE (sizeof(border_l3_header_t) + MTU)
#define BORDER_BUFFER_SIZE (sizeof(border_l3_header_t) + IPV6_MTU)
void demultiplex(border_packet_t *packet, int len);
void multiplex_send_ipv6_over_uart(ipv6_hdr_t *packet);
@ -89,4 +89,4 @@ void multiplex_send_addr_over_uart(ipv6_addr_t *addr);
int readpacket(uint8_t *packet_buf, size_t size);
int writepacket(uint8_t *packet_buf, size_t size);
#endif /* BORDERMULTIPLEX_H*/
#endif /* _SIXLOWPAN_BORDERMULTIPLEX_H*/

View File

@ -1,5 +1,5 @@
/**
* 6lowpan border router flow control
* 6lowpan border router flow control
*
* Copyright (C) 2013 INRIA.
*
@ -10,7 +10,7 @@
* @ingroup sixlowpan
* @{
* @file flowcontrol.c
* @brief flowcontrol for constraint node border router implementation
* @brief flowcontrol for constraint node border router implementation
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}
@ -125,7 +125,7 @@ static int in_window(uint8_t seq_num, uint8_t min, uint8_t max)
{
uint8_t pos = seq_num - min;
uint8_t maxpos = max - min + 1;
return pos < maxpos;
return (pos < maxpos);
}
void flowcontrol_send_over_uart(border_packet_t *packet, int len)
@ -181,8 +181,8 @@ void flowcontrol_deliver_from_uart(border_packet_t *packet, int len)
slot = &(slwin_stat.recv_win[packet->seq_num % BORDER_RWS]);
if (!in_window(packet->seq_num,
slwin_stat.next_exp,
slwin_stat.next_exp + BORDER_RWS - 1)) {
slwin_stat.next_exp,
slwin_stat.next_exp + BORDER_RWS - 1)) {
return;
}

View File

@ -1,5 +1,5 @@
/**
* 6lowpan border router flow control
* 6lowpan border router flow control
*
* Copyright (C) 2013 INRIA.
*
@ -16,29 +16,30 @@
* @}
*/
#ifndef FLOWCONTROL_H
#define FLOWCONTROL_H
#ifndef _SIXLOWPAN_FLOWCONTROL_H
#define _SIXLOWPAN_FLOWCONTROL_H
#include <stdint.h>
#include <vtimer.h>
#include "vtimer.h"
#include "semaphore.h"
#include "sixlowip.h"
#include "sixlowborder.h"
#include "ip.h"
#include "border.h"
#include "bordermultiplex.h"
/* packet types for flowcontrol */
#define BORDER_PACKET_ACK_TYPE 1
#define BORDER_PACKET_ACK_TYPE (1)
/* configuration types for flowcontrol */
#define BORDER_CONF_SYN 0
#define BORDER_CONF_SYNACK 1
#define BORDER_CONF_SYN (0)
#define BORDER_CONF_SYNACK (1)
#define BORDER_SWS 1
#define BORDER_RWS 1
#define BORDER_SL_TIMEOUT 500 // microseconds, maybe smaller
#define BORDER_SWS (1)
#define BORDER_RWS (1)
#define BORDER_SL_TIMEOUT (500) // microseconds, maybe smaller
#define SENDING_SLOT_STACK_SIZE (256)
#define SENDING_SLOT_STACK_SIZE (MINIMUM_STACK_SIZE + 256)
typedef struct {
/* Sender state */
@ -73,4 +74,4 @@ ipv6_addr_t flowcontrol_init(void);
void flowcontrol_send_over_uart(border_packet_t *packet, int len);
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len);
#endif /* FLOWCONTROL_H*/
#endif /* _SIXLOWPAN_FLOWCONTROL_H*/

File diff suppressed because it is too large Load Diff

64
sys/net/sixlowpan/icmp.h Normal file
View File

@ -0,0 +1,64 @@
/*
* 6lowpan neighbor discovery
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlownd.h
* @brief 6lowpan neighbor discovery constants, data structs, and prototypes
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
#ifndef _SIXLOWPAN_ICMP_H
#define _SIXLOWPAN_ICMP_H
#include <stdint.h>
#include "vtimer.h"
#include "sixlowpan/icmp.h"
#include "sixlowpan/ndp.h"
#include "sixlowpan/types.h"
#include "lowpan.h"
#include "ip.h"
enum option_types_t {
OPT_SLLAO = 1,
OPT_TLLAO,
OPT_PI,
OPT_MTU,
OPT_ARO,
OPT_6CO,
OPT_ABRO,
OPT_DAR,
OPT_DAC,
};
extern unsigned int nd_nbr_cache_rem_pid;
void recv_echo_req(void);
void recv_echo_repl(void);
void recv_rtr_sol(void);
void recv_rtr_adv(void);
void recv_nbr_adv(void);
void recv_nbr_sol(void);
void nbr_cache_auto_rem(void);
int8_t plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1);
ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr,
uint8_t cid);
void abr_remove_context(uint8_t cid);
uint16_t icmpv6_csum(uint8_t proto);
#endif /* _SIXLOWPAN_ICMP_H*/

View File

@ -0,0 +1,31 @@
/**
* ipv6.h - Wraps all API types, constants and functions of
* 6LoWPAN in layer 3.
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief IPv6 and ICMP functions
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef IPV6_H
#define IPV6_H
#include "sixlowpan/error.h"
#include "sixlowpan/types.h"
#include "sixlowpan/ip.h"
#include "sixlowpan/icmp.h"
#include "sixlowpan/ndp.h"
#include "../icmp.h" /* TODO: remove if not needed anymore */
/**
* @}
*/
#endif /* IPV6_H */

View File

@ -0,0 +1,52 @@
/**
* sixlowpan.h - Wraps all API types, constants and functions
* of 6LoWPAN concerning layers under 3.
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @defgroup sixlowpan 6LoWPAN
* @ingroup net
* @brief 6LoWPAN module implements (parts of) the 6LoWPAN adaption layer
* for IPv6 over Low Power Wireless Personal Area Networks
* (6LoWPANs)
* @see <a href="http://tools.ietf.org/html/rfc4919">
* RFC 4919 - IPv6 over Low-Power Wireless Personal Area
* Networks (6LoWPANs): Overview, Assumptions, Problem
* Statement, and Goals
* </a>
* @see <a href="http://tools.ietf.org/html/rfc4944">
* RFC 4944 - Transmission of IPv6 Packets over
* IEEE 802.15.4 Networks
* </a>
* @see <a href="http://tools.ietf.org/html/rfc6282">
* RFC 6282 - Compression Format for IPv6 Datagrams over
* IEEE 802.15.4-Based Networks
* </a>
* @see <a href="http://tools.ietf.org/html/rfc6775">
* RFC 6775 - Neighbor Discovery Optimization for IPv6
* over Low-Power Wireless Personal Area Networks
* (6LoWPANs)
* </a>
* @{
* @file
* @brief 6lowpan link layer and lowpan functions
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef SIXLOWPAN_H
#define SIXLOWPAN_H
#include "sixlowpan/error.h"
#include "sixlowpan/types.h"
#include "sixlowpan/lowpan.h"
#include "sixlowpan/mac.h"
/**
* @}
*/
#endif /* SIXLOWPAN_H */

View File

@ -0,0 +1,102 @@
/**
* sixlowpan/error.h - 6LoWPAN error codes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN error codes
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @}
*/
#ifndef SIXLOWPAN_ERROR_H
#define SIXLOWPAN_ERROR_H
#ifndef SUCCESS
/**
* Functions return this if call was success. Only defined if not
* already defined by other header.
*/
#define SUCCESS (0)
#endif
/**
* Error code that signals that array is full.
*/
#define SIXLOWERROR_ARRAYFULL (132)
/**
* Error code that signals a NULL pointer error.
*/
#define SIXLOWERROR_NULLPTR (133)
/**
* Error code that signals an illegal value.
*/
#define SIXLOWERROR_VALUE (134)
/**
* Error code that signals an illegal address.
*/
#define SIXLOWERROR_ADDRESS (135)
/**
* Error code that signals an unknown 6LoWPAN dispatch
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5">
* RFC 4944, Section 5: LoWPAN Adaptation Layer and Frame Format
* </a>
*/
#define SIXLOWERROR_DISPATCH (136)
/**
* Error code that signals that the first 6LoWPAN fragment was
* not received
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5.3">
* RFC 4944, Section 5.3: Fragmentation Type and Header
* </a>
*/
#define SIXLOWERROR_FSTFRAG (137)
/**
* Error code that signals that an invalid 6LoWPAN fragment was
* received.
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5.3">
* RFC 4944, Section 5.3: Fragmentation Type and Header
* </a>
*/
#define SIXLOWERROR_INVFRAG (138)
/**
* Error code that signals that the source context identifier was not
* found.
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1">
* RFC 6282, Section 3.1: LOWPAN_IPHC Encoding format
* </a>
*/
#define SIXLOWERROR_SCI (139)
/**
* Error code that signals that the destination context identifier was
* not found.
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1">
* RFC 6282, Section 3.1: LOWPAN_IPHC Encoding format
* </a>
*/
#define SIXLOWERROR_DCI (140)
/**
* Error code that signals that the destination context identifier was
* not found.
*/
#define SIXLOWERROR_CSUM (141)
/**
* @}
*/
#endif /* SIXLOWPAN_ERROR_H */

View File

@ -0,0 +1,236 @@
/**
* sixlowpan/icmp.h - 6LoWPAN constants, data structs, and prototypes
* related to ICMP
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN ICMP related header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_ICMP_H
#define SIXLOWPAN_ICMP_H
#include <stdint.h>
#include "sixlowpan/types.h"
/**
* @brief ICMPv6 packet type for parameter problem message.
* @see <a href="http://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>
*/
#define ICMPV6_TYPE_PARAMETER_PROB (4)
/**
* @brief ICMPv6 packet type for an echo request.
* @see <a href="http://tools.ietf.org/html/rfc4443#section-4.1">
* RFC 4443, section 4.1
* </a>
*/
#define ICMPV6_TYPE_ECHO_REQUEST (128)
/**
* @brief ICMPv6 packet type for an echo reply.
* @see <a href="http://tools.ietf.org/html/rfc4443#section-4.2">
* RFC 4443, section 4.2
* </a>
*/
#define ICMPV6_TYPE_ECHO_REPLY (129)
/**
* @brief ICMPv6 packet type for a router solicitation.
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.1">
* RFC 4861, section 4.1
* </a>
*/
#define ICMPV6_TYPE_ROUTER_SOL (133)
/**
* @brief ICMPv6 packet type for a router advertisement.
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.2">
* RFC 4861, section 4.2
* </a>
*/
#define ICMPV6_TYPE_ROUTER_ADV (134)
/**
* @brief ICMPv6 packet type for a neighbor solicitation.
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.3">
* RFC 4861, section 4.3
* </a>
*/
#define ICMPV6_TYPE_NEIGHBOR_SOL (135)
/**
* @brief ICMPv6 packet type for a neighbor advertisement.
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.4">
* RFC 4861, section 4.4
* </a>
*/
#define ICMPV6_TYPE_NEIGHBOR_ADV (136)
/**
* @brief ICMPv6 packet type for a redirect message.
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.5">
* RFC 4861, section 4.5
* </a>
*/
#define ICMPV6_TYPE_REDIRECT (137)
/**
* @brief ICMPv6 packet type for a rpl control message.
* @note TODO: not RFC conform.
*/
#define ICMPV6_TYPE_RPL_CONTROL (155)
/**
* @brief ICMPv6 parameter problem message code for
* "Erroneous header field encountered".
* @see <a href="http://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>
*/
#define ICMPV6_PARAMETER_PROB_CODE_ERR (0)
/**
* @brief ICMPv6 parameter problem message code for
* "Unrecognized Next Header type encountered".
* @see <a href="http://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>
*/
#define ICMPV6_PARAMETER_PROB_CODE_NXT_HDR_UNREC (1)
/**
* @brief ICMPv6 parameter problem message code for
* "Unrecognized IPv6 option encountered".
* @see <a href="http://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>
*/
#define ICMPV6_PARAMETER_PROB_CODE_IPV6_OPT_UNREC (2)
/**
* @brief Send ICMPv6 parameter problem message.
*
* @param[in] src Source address for IPv6 header.
* @param[in] dest Destination address for IPv6 header.
* @param[in] code Value for code field of parameter problem
* message.
* @param[in] pointer Value for pointer field of parameter problem
* message.
* @param[in] packet Data payload for echo request.
* @param[in] packet_len Length of data payload.
*/
void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest,
uint8_t code, uint32_t pointer,
uint8_t *packet, uint8_t packet_len);
/**
* @brief Send ICMPv6 echo request.
*
* @param[in] destaddr Destination address for IPv6 header.
* @param[in] id Value for identifier field of echo request.
* @param[in] seq Value for sequence number field of echo request.
* @param[in] data Data payload for echo request.
* @param[in] data_len Length of data payload.
*/
void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id,
uint16_t seq, char *data,
size_t data_len);
/**
* @brief Send ICMPv6 echo reply.
*
* @param[in] destaddr Destination address for IPv6 header.
* @param[in] id Value for identifier field of echo reply.
* @param[in] seq Value for sequence number field of echo reply.
* @param[in] data Data payload for echo reply.
* @param[in] data_len Length of data payload.
*/
void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id,
uint16_t seq, char *data, size_t data_len);
/**
* @brief Send ICMPv6 router solicitation.
*
* @param[in] sllao Flag to include source link-layer address
* option. If *sllao* == OPT_SLLAO add it, else
* not.
*/
void icmpv6_send_router_sol(uint8_t sllao);
/**
* @brief Send ICMPv6 router advertisement.
*
* @param[in] addr Address of node to advertise router to. If
* NULL *addr* is set to the all nodes multicast
* address.
* @param[in] sllao Flag to include source link-layer address
* option. If *sllao* == OPT_SLLAO add it, else
* not.
* @param[in] mtu Flag to include MTU option. If *mtu* == OPT_MTU
* add it, else not.
* @param[in] pi Flag to include prefix information option. If
* *pi* == OPT_PI add it, else not.
* @param[in] sixco Flag to include 6LoWPAN context option. If
* *sixco* == OPT_6CO add it, else not.
* @param[in] abro Flag to include 6LoWPAN authoritive border
* router option. If *abro* == OPT_ABRO add it,
* else not.
*/
void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao,
uint8_t mtu, uint8_t pi, uint8_t sixco,
uint8_t abro);
/**
* @brief Send ICMPv6 neighbor solicitation.
*
* @param[in] src Source address for IPv6 header.
* @param[in] dest Destination address for IPv6 header.
* @param[in] targ Value for target address field of neighbor
* solicitation.
* @param[in] sllao Flag to include source link-layer address
* option. If *sllao* == OPT_SLLAO add it, else
* not.
* @param[in] aro Flag to include address registration option. If
* *aro* == OPT_ARO add it, else not.
*/
void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest,
ipv6_addr_t *targ, uint8_t slloa,
uint8_t aro);
/**
* @brief Send ICMPv6 neighbor advertisement.
*
* @param[in] src Source address for IPv6 header.
* @param[in] dest Destination address for IPv6 header.
* @param[in] targ Value for target address field of neighbor
* advertisement.
* @param[in] rso Value for flags field of neighbor advertisement.
* @param[in] sllao Flag to include source link-layer address
* option. If *sllao* == OPT_SLLAO add it, else
* not.
* @param[in] aro Flag to include address registration option. If
* *aro* == OPT_ARO add it, else not.
*/
void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst,
ipv6_addr_t *tgt, uint8_t rso,
uint8_t sllao, uint8_t aro);
/**
* @}
*/
#endif /* SIXLOWPAN_ICMP_H */

View File

@ -0,0 +1,355 @@
/**
* sixlowpan/ip.h - 6LoWPAN constants, data structs, and prototypes
* for network layer
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN network layer header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_IP_H
#define SIXLOWPAN_IP_H
#include <stdint.h>
#include "sixlowpan/types.h"
/**
* @brief IPv6 maximum transmission unit.
*/
#define IPV6_MTU (256)
/**
* @brief Maximum length of a IPv6 address represented as string.
*/
#define IPV6_MAX_ADDR_STR_LEN (40)
/**
* @brief L4 protocol number for TCP.
*/
#define IPV6_PROTO_NUM_TCP (6)
/**
* @brief L4 protocol number for UDP.
*/
#define IPV6_PROTO_NUM_UDP (17)
/**
* @brief L4 protocol number for ICMPv6.
*/
#define IPV6_PROTO_NUM_ICMPV6 (58)
/**
* @brief L4 protocol number for no L4 protocol in IPv6.
*/
#define IPV6_PROTO_NUM_NONE (59)
/**
* @brief L4 protocol number for IPv6 destination options.
*/
#define IPV6_PROTO_NUM_IPV6_OPTS (60)
/**
* @brief Get IPv6 send/receive buffer.
*
* @return Pointer to IPv6 header in send/receive bouffer.
* @note To be deleted in later releases. Here only because it is
* used by the rpl module.
*/
ipv6_hdr_t *ipv6_get_buf(void);
/**
* @brief Send IPv6 packet to dest.
*
* @param[in] dest Destination of this packet.
* @param[in] next_header Next header ID of payload.
* @param[in] payload Payload of the packet.
* @param[in] payload_length Length of payload.
*/
void ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header,
const uint8_t *payload, uint16_t payload_length);
/**
* @brief Determines if node is a router.
*
* @return 1 if node is router, 0 otherwise.
*/
uint8_t ipv6_is_router(void);
/**
* @brief Registers a handler thread for incoming IP packets.
*
* @param[in] pid PID of handler thread.
*
* @return 0 on success, ENOMEN if maximum number of registrable
* threads is exceeded.
*/
uint8_t ipv6_register_packet_handler(int pid);
/**
* @brief Registers a handler thread for L4 protocol.
*
* @param[in] next_header Next header ID of the L4 protocol.
* @param[in] pid PID of the handler thread
*/
void ipv6_register_next_header_handler(uint8_t next_header, int pid);
/**
* @brief Registers a handler thread for RPL options
*
* @param[in] pid PID of the handler thread.
*/
void ipv6_register_rpl_handler(int pid);
/**
* @brief Sets the first 64 bit of *ipv6_addr* to link local prefix.
*
* @param[in,out] ipv6_addr The address to set.
*/
void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr);
/**
* @brief Sets IPv6 address *out* according to the remaining
* parameters.
*
* @param[out] out The resulting address.
* @param[in] addr0 The first 16 bit of the new address.
* @param[in] addr1 The second 16 bit of the new address.
* @param[in] addr2 The third 16 bit of the new address.
* @param[in] addr3 The fourth 16 bit of the new address.
* @param[in] addr4 The fifth 16 bit of the new address.
* @param[in] addr5 The sixth 16 bit of the new address.
* @param[in] addr6 The seventh 16 bit of the new address.
* @param[in] addr7 The eighth 16 bit of the new address.
*/
void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7);
/**
* @brief Sets IPv6 address *out* using the given *prefix* and this
* nodes EUI-64 (i. e. interface must be initialized).
*
* @param[out] out Address to be set.
* @param[in] prefix 64-bit network prefix to be used for *out*
* (only the first 64 bit of the ipv6_addr_t type
* are copied to *out*)
*/
void ipv6_addr_set_by_eui64(ipv6_addr_t *out,
const ipv6_addr_t *prefix);
/**
* @brief Sets IPv6 address *out* with the first *bits* bit taken
* from *prefix* and the remaining bits to 0.
*
* @param[out] out Prefix to be set.
* @param[in] prefix Address to take prefix from.
* @param[in] bits Bits to be copied from *prefix* to *out*
* (set to 128 when greater than 128).
*/
void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix,
uint8_t bits);
/**
* @brief Set *ipv6_addr* to the loopback address.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[out] ipv6_addr Is set to the loopback address.
*/
void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr);
/**
* @brief Set *ipv6_addr* to a link-local all routers multicast
* address (ff02::/16 prefix).
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[out] ipv6_addr Is set to a link-local all routers multicast
* address.
*/
void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr);
/**
* @brief Set *ipv6_addr* to a link-local all nodes multicast address
* (ff02::/16 prefix).
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[out] ipv6_addr Is set to a link-local all nodes multicast
* address.
*/
void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr);
/**
* @brief Set *ipv6_addr_out* to the solicited-node multicast address
* computed from *ipv6_addr_in*.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[out] ipv6_addr_out Is set to solicited-node address of
* this node.
* @param[in] ipv6_addr_in The IPv6 address the solicited-node
* address.
*/
void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out,
const ipv6_addr_t *ipv6_addr_in);
/**
* @brief Converts IPv6 address into string (unabbrivated notation).
* Note that addr_str must allocate at least
* IPV6_MAX_ADDR_STR_LEN byte (40 byte).
*
* @param[out] addr_str The IPv6 address as string. Must allocate
* at least IPV6_MAX_ADDR_STR_LEN byte (40
* byte).
* @param[in] ipv6_addr IPv6 address to be converted.
*
* @return Pointer to addr_str.
*/
char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr);
/**
* @brief Checks if two IPv6 addresses are equal.
*
* @param[in] a An IPv6 address.
* @param[in] b Another IPv6 address.
*
* @return 1 if *a* and *b* are equal, 0 otherwise.
*/
int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b);
/**
* @brief Checks if *ipv6_addr* is unspecified (all zero).
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[in] ipv6_addr An IPv6 address.
*
* @return 1 if *ipv6_addr* is unspecified address, 0 otherwise.
*/
int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr);
/**
* @brief Check if *ipv6_addr* is a link-local address.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[in] ipv6_addr An IPv6 address.
*
* @return 1 if *ipv6_addr* is link-local address, 0 otherwise.
*/
int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr);
/**
* @brief Check if *ipv6_addr* is unique local unicast address.
*
* @see <a href="http://tools.ietf.org/html/rfc4193">
* RFC 4193
* </a>
*
* @param[in] ipv6_addr An IPv6 address.
*
* @return 1 if *ipv6_addr* is unique local unicast address,
* 0 otherwise.
*/
int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr);
/**
* @brief Check if *ipv6_addr* is a multicast address.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[in] ipv6_addr An IPv6 address.
*
* @return 1 if *ipv6_addr* is multicast address, 0 otherwise.
*/
int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr);
/**
* @brief Check if *ipv6_addr* is solicited-node multicast address.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*
* @param[in] ipv6_addr An IPv6 address.
*
* @return 1 if *ipv6_addr* is solicited-node multicast address,
* 0 otherwise.
*/
int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr);
/*
* TODO to wrap sixlowpan initialisations
* int ipv6_iface_init(transceiver_type_t trans, ..);
*/
/**
* @brief Add an IPv6 address to this nodes interface.
*
* @see <a href="http://tools.ietf.org/html/rfc4862">
* RFC 4862
* </a>
*
* @param[in] addr Address to be added to the interface.
* @param[in] type Type of this address.
* @param[in] state Initial state of the address.
* @param[in] val_ltime Valid lifetime of this address in seconds.
* @param[in] pref_ltime Preferred lifetime of this address in
* seconds.
*/
void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type,
ndp_addr_state_t state, uint32_t val_ltime,
uint32_t pref_ltime);
/**
* @brief Tries to determine best suitable source address attached to
* the interface of this node based on the given destination
* address. The use-case for this function is to find a
* suitable address for the source address field of an IPv6
* address upon sending. *src* may be empty (all zero) if there
* is no suitable address attached to the interface.
*
* @param[out] src The best source address for this node (may be
* all zero if ther is none).
* @param[in] dest The destination address for a packet we search
* the source address for.
*/
void ipv6_iface_get_best_src_addr(ipv6_addr_t *src,
const ipv6_addr_t *dest);
/**
* @brief Print all addresses attached to the interface to stdout.
*/
void ipv6_iface_print_addrs(void);
/**
* @}
*/
#endif /* SIXLOWPAN_IP_H */

View File

@ -0,0 +1,273 @@
/**
* sixlowpan/lowpan.h - 6LoWPAN constants, data structs, and
* prototypes for 6LoWPAN layer
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN LoWPAN layer header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_LOWPAN_H
#define SIXLOWPAN_LOWPAN_H
#include <stdint.h>
#include "transceiver.h"
#include "sixlowpan/types.h"
/**
* @brief 6LoWPAN dispatch value for uncompressed IPv6 packets.
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5.1">
* RFC 4944, section 5.1
* </a>
*/
#define SIXLOWPAN_IPV6_DISPATCH (0x41)
/**
* @brief 6LoWPAN dispatch value for IPv6 header compression (part of
* first byte of LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 4944, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC1_DISPATCH (0x60)
/**
* @brief Flag for Flow Label elision (part of first byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC1_FL_C (0x10)
/**
* @brief Flag for Traffic Class elision (part of first byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC1_TC_C (0x08)
/**
* @brief Flag for Next Header Compression (part of first byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC1_NH (0x04)
/**
* @brief Flag for Context Identifier Extention (part of second byte
* of LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_CID (0x80)
/**
* @brief Flag for Source Address Compression (part of second byte
* of LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_SAC (0x40)
/**
* @brief Bits for Source Address Mode (part of second byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_SAM (0x30)
/**
* @brief Flag for Destination Address Compression (part of second
* byte of LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_DAC (0x04)
/**
* @brief Bits for Destination Address Mode (part of second byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_DAM (0x03)
/**
* @brief Flag for Multicast Compression (part of second byte of
* LOWPAN_IPHC).
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1.1">
* RFC 6282, section 3.1.1
* </a>
*/
#define SIXLOWPAN_IPHC2_M (0x08)
/**
* 6LoWPAN dispatch value for fragmentation header (first fragment)
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5.1">
* RFC 4944, section 5.1
* </a>
*/
#define SIXLOWPAN_FRAG1_DISPATCH (0xc0)
/**
* 6LoWPAN dispatch value for fragmentation header (subsequent fragment)
* @see <a href="http://tools.ietf.org/html/rfc4944#section-5.1">
* RFC 4944, section 5.1
* </a>
*/
#define SIXLOWPAN_FRAGN_DISPATCH (0xe0)
/**
* 6LoWPAN fragmentation header length (first fragment)
*/
#define SIXLOWPAN_FRAG1_HDR_LEN (4)
/**
* 6LoWPAN fragmentation header length (subsequent fragment)
*/
#define SIXLOWPAN_FRAGN_HDR_LEN (5)
/**
* @brief Data type to configure 6LoWPAN IPv6 header compression.
*/
typedef enum __attribute__((packed))
{
LOWPAN_IPHC_DISABLE = 0, ///< header compression disabled
LOWPAN_IPHC_ENABLE = 1 ///< header compression enabled
}
sixlowpan_lowpan_iphc_status_t;
/**
* @brief Data type to represent an 6LoWPAN frame as byte stream.
*/
typedef struct __attribute__((packed)) {
uint8_t length; ///< length of the byte stream.
uint8_t *data; ///< the byte stream representing the 6LoWPAN frame.
} sixlowpan_lowpan_frame_t;
/**
* @brief Initializes 6LoWPAN.
*
* @param[in] trans Transceiver to use with 6LoWPAN.
* @param[in] r_addr PHY layer address.
* @param[in] as_border 1 if node should act as border router,
* 0 otherwise.
*/
void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr,
int as_border);
/**
* @brief Initializes a 6LoWPAN router with address prefix
*
* @param[in] trans transceiver to use with 6LoWPAN.
* @param[in] prefix the address prefix to advertise.
* @param[in] r_addr PHY layer address.
*/
void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans,
const ipv6_addr_t *prefix,
uint8_t r_addr);
/**
* @brief Initializes a 6LoWPAN border router with an address
*
* @note Currently only working with addresses generated from
* IEEE 802.15.4 16-bit short addresses.
*
* @param[in] trans transceiver to use with 6LoWPAN.
* @param[in] border_router_addr Address of this border router.
*
* @return SUCCESS on success, otherwise SIXLOWERROR_ADDRESS if
* address was not generated from IEEE 802.15.4 16-bit short
* address.
*/
uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans,
const ipv6_addr_t *border_router_addr);
/**
* @brief Send data via 6LoWPAN to destination node dest.
*
* @param[in] dest EUI-64 of destination node.
* @param[in] data Data to send to destination node (may be
* manipulated).
* @param[in] data_len Length of data.
*/
void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest,
uint8_t *data, uint16_t data_len);
/**
* @brief Set header compression status for 6LoWPAN.
*
* @param[in] status Header compression status to set to.
*/
void sixlowpan_lowpan_set_iphc_status(
sixlowpan_lowpan_iphc_status_t status);
/**
* @brief Initialize 6LoWPAN neighbor discovery (i.e. send
* router advertisement with Source Link-Layer Address Option)
*
* @see <a href="http://tools.ietf.org/html/rfc4861">
* RFC 4861
* </a>, <a href="http://tools.ietf.org/html/rfc6775">
* RFC 6775
* </a>
*
*/
void sixlowpan_lowpan_bootstrapping(void);
/**
* @brief Registers a thread to read received 6LoWPAN frames. The
* 6LoWPAN frames are delivered as sixlowpan_lowpan_frame_t
* structs.
*
* @param[in] pid The PID of the receiver thread.
*
* @return 1 on success, ENOMEM if maximum number of registrable
* threads is exceeded.
*/
uint8_t sixlowpan_lowpan_register(int pid);
#if ENABLE_DEBUG
/**
* @brief Print current buffer of assembled (i. e. not fragmented)
* 6LoWPAN packages.
*/
void sixlowpan_lowpan_print_fifo_buffers(void);
/**
* @brief Print current buffer for 6LoWPAN fragmentation reassembly.
*/
void sixlowpan_lowpan_print_reassembly_buffers(void);
#endif
/**
* @}
*/
#endif /* SIXLOWPAN_LOWPAN_H */

View File

@ -0,0 +1,92 @@
/**
* sixlowpan/mac.h - 6LoWPAN data structs, and prototypes for MAC layer
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN MAC layer header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_MAC_H
#define SIXLOWPAN_MAC_H
#include <stdint.h>
#include "transceiver.h"
#include "sixlowpan/types.h"
/**
* @brief Gets current radio transmitter address.
*
* @return Current radio address as 8-bit value.
*/
uint8_t sixlowpan_mac_get_radio_address(void);
/**
* @brief Sets radio transmitter address.
*
* @param[in] addr 8-bit radio address.
*/
void sixlowpan_mac_set_radio_address(uint8_t addr);
/**
* @brief Generates EUI-64 from IEEE 802.15.4 PAN ID and
* radio transceiver address.
*
* @param[out] laddr The EUI-64 address of this node.
*/
void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr);
/**
* @brief Generates IEEE 802.15.4 16-bit short address from radio
* transceiver address.
*
* @param[out] saddr The IEEE 802.15.4 16-bit short address of this
* node.
*/
void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr);
/**
* @brief Get pointer to potential EUI-64 bit of the IPv6 address.
*
* @param[in] ipaddr An IPv6 address of this node.
*
* @return The EUI-64 address of this node.
*/
ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr);
/**
* @brief Send an IEEE 802.15.4 frame.
*
* @param[in] addr The destination address of the frame.
* @param[in] payload The payload of the frame.
* @param[in] length The length of the payload.
* @param[in] mcast send frame as multicast frame (identical to
* give a destination address of 0).
*/
void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr,
const uint8_t *payload,
uint8_t length, uint8_t mcast);
/**
* @brief Initialise 6LoWPAN MAC interface
*
* @param[in] type Type of transceiver.
*/
void sixlowpan_mac_init(transceiver_type_t type);
/**
* @}
*/
#endif /* SIXLOWPAN_MAC_H */

View File

@ -0,0 +1,129 @@
/**
* sixlowpan/ndp.h - 6LoWPAN constants, data structs, and prototypes
* related to NDP
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file
* @brief 6LoWPAN NDP related header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_NDP_H
#define SIXLOWPAN_NDP_H
#include <stdint.h>
#include "timex.h"
#include "sixlowpan/types.h"
#define NDP_6LOWPAN_CONTEXT_MAX (16)
#define NDP_OPT_SLLAO_TYPE (1)
#define NDP_OPT_TLLAO_TYPE (2)
#define NDP_OPT_PI_VLIFETIME_INFINITE (0xffffffff)
#define NDP_OPT_ARO_STATE_SUCCESS (0)
#define NDP_OPT_ARO_STATE_DUP_ADDR (1)
#define NDP_OPT_ARO_STATE_NBR_CACHE_FULL (2)
/**
* @brief Neighbor cache entry state according to
* <a href="http://tools.ietf.org/html/rfc4861#section-7.3.2">
* RFC 4861, section 7.3.2
* </a>.
*/
typedef enum __attribute__((packed)) {
NDP_NCE_STATUS_INCOMPLETE,
NDP_NCE_STATUS_REACHABLE,
NDP_NCE_STATUS_STALE,
NDP_NCE_STATUS_DELAY,
NDP_NCE_STATUS_PROBE,
} ndp_nce_state_t;
/**
* @brief Neighbor cache entry type according to
* <a href="http://tools.ietf.org/html/rfc6775#section-3.5">
* RFC 6775, section 3.5
* </a>.
*/
typedef enum __attribute__((packed)) {
NDP_NCE_TYPE_GC = 1, ///< Garbage-collectible.
NDP_NCE_TYPE_REGISTERED, ///< Registered.
NDP_NCE_TYPE_TENTATIVE ///< Tentetive.
} ndp_nce_type_t;
/**
* @brief Prefix list type to store information spread by prefix
* information option.
*/
typedef struct __attribute__((packed)) {
uint8_t inuse; ///< Prefix is in in use.
uint8_t adv;
ipv6_addr_t addr; ///< The Prefix.
uint8_t length; ///< Length of the prefix.
uint8_t l_a_reserved1; ///< L and A flag of prefix information option
uint32_t val_ltime; ///< valid lifetime
uint32_t pref_ltime; ///< preferred lifetime
uint8_t infinite; ///< flag to set to infinite lifetime
} ndp_prefix_list_t;
/**
* @brief Default router list to store information spread by
* router advertisement.
*/
typedef struct __attribute__((packed)) {
ipv6_addr_t addr; ///< Address of router.
timex_t inval_time; ///< remaining time until this entry is
///< invalid.
} ndp_default_router_list_t;
/**
* @brief Neighbor cache as defined in
* <a href="http://tools.ietf.org/html/rfc4861#section-3.5#section-5.1">
* RFC 4861, section 5.1
* </a>.
*/
typedef struct __attribute__((packed)) {
ndp_nce_type_t type; ///< Type of neighbor cache entry.
ndp_nce_state_t state; ///< State of neighbor cache entry.
uint8_t isrouter; ///< Flag to signify that this neighbor
///< is a router.
ipv6_addr_t addr; ///< IPv6 address of the neighbor.
ieee_802154_long_t laddr; ///< EUI-64 of neighbor
ieee_802154_short_t saddr; ///< IEEE 802.15.4 16-bit short address
///< of neighbor.
timex_t ltime; ///< lifetime of entry.
} ndp_neighbor_cache_t;
/**
* @brief Authoritive border router cache as defined in
* <a href="http://tools.ietf.org/html/rfc6775">
* RFC 6775
* </a>.
*/
typedef struct __attribute__((packed)) {
uint16_t version; ///< version of entry.
ipv6_addr_t abr_addr; ///< Addres of ABR.
uint8_t cids[NDP_6LOWPAN_CONTEXT_MAX]; ///< context IDs.
} ndp_a6br_cache_t;
ndp_default_router_list_t *ndp_default_router_list_search(ipv6_addr_t *ipaddr);
ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr);
/*TODO: to implement*/
uint8_t ndp_prefix_list_search(ipv6_addr_t *addr);
ndp_a6br_cache_t *ndp_a6br_cache_get_most_current(void);
ndp_a6br_cache_t *ndp_a6br_cache_get_oldest(void);
/**
* @}
*/
#endif /* SIXLOWPAN_NDP_H */

View File

@ -0,0 +1,404 @@
/**
* 6LoWPAN data types
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowpan/types.h
* @brief 6LoWPAN data types
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
*/
#ifndef SIXLOWPAN_TYPES_H
#define SIXLOWPAN_TYPES_H
#include <stdint.h>
/**
* @brief Data type to represent an EUI-64.
*/
typedef union __attribute__((packed)) {
uint8_t uint8[8]; ///< devided by 8 8-bit words.
uint16_t uint16[4]; ///< devided by 4 16-bit words.
} ieee_802154_long_t;
/**
* @brief Data type to represent IEEE 802.15.4 short address.
*/
typedef union __attribute__((packed)) {
uint8_t uint8[2]; ///< devided by 2 8-bit words.
uint16_t uint16[1]; ///< as a 16-bit value.
} ieee_802154_short_t;
/**
* @brief Data type to represent an IPv6 address.
*/
typedef union __attribute__((packed)) {
uint8_t uint8[16]; ///< devided by 16 8-bit words.
uint16_t uint16[8]; ///< devided by 8 16-bit words.
uint32_t uint32[4]; ///< devided by 4 32-bit words.
} ipv6_addr_t;
/**
* @brief Data type to represent IPv6 address types.
*
* @see <a href="http://tools.ietf.org/html/rfc4291">
* RFC 4291
* </a>
*/
typedef enum __attribute__((packed))
{
IPV6_ADDR_TYPE_NONE, ///< address has no type/is invalid.
IPV6_ADDR_TYPE_UNICAST, ///< address is an unicast address.
IPV6_ADDR_TYPE_MULTICAST, ///< address is a multicast address.
IPV6_ADDR_TYPE_ANYCAST, ///< address is an anycast address.
IPV6_ADDR_TYPE_SOLICITED_NODE, ///< address is a solicitated node
///< multicast address.
IPV6_ADDR_TYPE_LOOPBACK, ///< address is a loopback address.
IPV6_ADDR_TYPE_LINK_LOCAL, ///< address is a link-local address.
IPV6_ADDR_TYPE_GLOBAL ///< address is a global address.
}
ipv6_addr_type_t;
/**
* @brief Data type to represent an IPv6 packet header
*
* @see <a href="http://tools.ietf.org/html/rfc2460">
* RFC 2460
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t version_trafficclass; ///< Version field + first 4 bit of Traffic Class.
uint8_t trafficclass_flowlabel; ///< last 4 bit of Traffic Class
///< and first 4 bit of Flow Label.
uint16_t flowlabel; ///< last 16 bit of Flow Label.
uint16_t length; ///< payload length of this packet.
uint8_t nextheader; ///< type of next header in this packet.
uint8_t hoplimit; ///< hop limit for this packet.
ipv6_addr_t srcaddr; ///< source address of this packet.
ipv6_addr_t destaddr; ///< destination address of this packet.
} ipv6_hdr_t;
/**
* @brief Data type to represent an ICMPv6 packet header.
*
* @see <a href="http://tools.ietf.org/html/rfc4443">
* RFC 4443
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t code; ///< code field.
uint16_t checksum; ///< checksum field.
} icmpv6_hdr_t;
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Parameter Problem Message.
*
* @see <a href="http://tools.ietf.org/html/rfc4443#section-3.4">
* RFC 4443, section 3.4
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t pointer;
} icmpv6_parameter_prob_hdr_t;
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Echo Request.
*
* @see <a href="http://tools.ietf.org/html/rfc4443#section-4.1">
* RFC 4443, section 4.1
* </a>
*/
typedef struct __attribute__((packed)) {
uint16_t id; ///< identifier field.
uint16_t seq; ///< sequence number field.
} icmpv6_echo_request_hdr_t;
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Echo Reply.
*
* @see <a href="http://tools.ietf.org/html/rfc4443#section-4.2">
* RFC 4443, section 4.2
* </a>
*/
typedef struct __attribute__((packed)) {
uint16_t id; ///< identifier field.
uint16_t seq; ///< sequence number field.
} icmpv6_echo_reply_hdr_t;
/*
* ICMPv6 Router Solicitation has no fields but reserved fields
* and is thus elided.
*/
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Router Advertisement.
*
* @see ICMPV6_ROUTER_ADV_FLAG_MANAGED
* @see ICMPV6_ROUTER_ADV_FLAG_OTHER
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.2">
* RFC 4861, section 4.2
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t hoplimit; ///< hop limit field.
uint8_t autoconfig_flags; ///< (M)anaged and (Other) flag.
uint16_t router_lifetime; ///< router lifetime field.
uint32_t reachable_time; ///< reachable time field.
uint32_t retrans_timer; ///< retrans timer field.
} icmpv6_router_adv_hdr_t;
/**
* @brief Bit for (M)anaged flag in Router Advertisement
* @see icmpv6_router_adv_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.2">
* RFC 4861, section 4.2
* </a>
*/
#define ICMPV6_ROUTER_ADV_FLAG_MANAGED (0x80)
/**
* @brief Bit for (O)ther flag in Router Advertisement
* @see icmpv6_router_adv_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.2">
* RFC 4861, section 4.2
* </a>
*/
#define ICMPV6_ROUTER_ADV_FLAG_OTHER (0x40)
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Neighbor Solicitation.
*
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.3">
* RFC 4861, section 4.3
* </a>
*/
typedef struct __attribute__((packed)) {
uint32_t reserved; ///< reserved field.
ipv6_addr_t target_addr; ///< target address field.
} icmpv6_neighbor_sol_hdr_t;
/**
* @brief Data type to represent the relevant sub-part of an
* ICMPv6 Neighbor Solicitation.
*
* @see ICMPV6_NEIGHBOR_ADV_FLAG_ROUTER
* @see ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED
* @see ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.4">
* RFC 4861, section 4.4
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t rso; ///< flags + first 5 bits of reserved field.
uint8_t reserved[3]; ///< rest of reserved field.
ipv6_addr_t target_addr; ///< target address field.
} icmpv6_neighbor_adv_hdr_t;
/**
* @brief Bit for (R)outer flag in Neighbor Advertisement
* @see icmpv6_neighbor_adv_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.4">
* RFC 4861, section 4.4
* </a>
*/
#define ICMPV6_NEIGHBOR_ADV_FLAG_ROUTER (0x80)
/**
* @brief Bit for (S)olicited flag in Neighbor Advertisement
* @see icmpv6_neighbor_adv_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.4">
* RFC 4861, section 4.4
* </a>
*/
#define ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED (0x40)
/**
* @brief Bit for (O)verride flag in Neighbor Advertisement
* @see icmpv6_neighbor_adv_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.4">
* RFC 4861, section 4.4
* </a>
*/
#define ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE (0x20)
/**
* @brief Data type to represent an IPv6 Neighbor Discover Option
* header.
*
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6">
* RFC 4861, section 4.6
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
} icmpv6_ndp_opt_hdr_t;
/**
* @brief Data type to represent a Source/Target Link-layer Option
* Address option. Link-layer address may be added in payload.
*
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6.1">
* RFC 4861, section 4.6.1
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
} icmpv6_ndp_opt_stllao_t;
/**
* @brief Data type to represent a Prefix Information option.
*
* @see ICMPV6_NDP_OPT_PI_FLAG_ON_LINK
* @see ICMPV6_NDP_OPT_PI_FLAG_AUTONOM
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6.2">
* RFC 4861, section 4.6.2
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
uint8_t prefix_length; ///< prefix length field.
uint8_t l_a_reserved1; ///< flags + reserved1 field.
uint32_t val_ltime; ///< valid lifetime field.
uint32_t pref_ltime; ///< preferred lifetime field.
uint32_t reserved2; ///< reserved2 field.
ipv6_addr_t addr; ///< prefix field.
} icmpv6_ndp_opt_pi_t;
/**
* @brief Bit for on-(L)ink flag in Prefix Information option.
* @see icmpv6_ndp_opt_pi_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6.2">
* RFC 4861, section 4.6.2
* </a>
*/
#define ICMPV6_NDP_OPT_PI_FLAG_ON_LINK (0x80)
/**
* @brief Bit for (A)utonoums address-configuration flag in Prefix
* Information option.
* @see icmpv6_ndp_opt_pi_t
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6.2">
* RFC 4861, section 4.6.2
* </a>
*/
#define ICMPV6_NDP_OPT_PI_FLAG_AUTONOM (0x40)
/**
* @brief Data type to represent a MTU option.
*
* @see <a href="http://tools.ietf.org/html/rfc4861#section-4.6.4">
* RFC 4861, section 4.6.4
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
uint16_t reserved; ///< reserved field.
uint32_t mtu; ///< MTU field.
} icmpv6_ndp_opt_mtu_t;
/**
* @brief Data type to represent an Address Registration Option.
*
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.1">
* RFC 6775, section 4.1
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
uint8_t status; ///< status field.
uint8_t reserved1; ///< reserved1 field.
uint16_t reserved2; ///< reserved2 field.
uint16_t reg_ltime; ///< registration lifetem field.
ieee_802154_long_t eui64; ///< EUI-64 field.
} icmpv6_ndp_opt_aro_t;
/**
* @brief Data type to represent an 6LoWPAN Context Option.
*
* @see ICMPV6_NDP_OPT_6CO_FLAG_CCOMPR
* @see ICMPV6_NDP_OPT_6CO_FLAG_CID
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2">
* RFC 6775, section 4.2
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
uint8_t c_length; ///< context length field.
uint8_t c_flags; ///< Res(erved) field + C flag + CID field.
uint16_t reserved; ///< reserved field.
uint16_t val_ltime; ///< valid lifetime field.
} icmpv6_ndp_opt_6co_hdr_t;
/**
* @brief Bit for context (C)ompression flag in 6LoWPAN Context
* Option.
* @see icmpv6_ndp_opt_6co_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2">
* RFC 6775, section 4.2
* </a>
*/
#define ICMPV6_NDP_OPT_6CO_FLAG_CCOMPR (0x10)
/**
* @brief Bitmask for Context Identifier in 6LoWPAN Context Option.
* @see icmpv6_ndp_opt_6co_hdr_t
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2">
* RFC 6775, section 4.2
* </a>
*/
#define ICMPV6_NDP_OPT_6CO_FLAG_CID (0x0F)
/**
* @brief Data type to represent an Authoritative Border Router Option.
* @note TODO not according to RFC.
*
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.3">
* RFC 6775, section 4.3
* </a>
*/
typedef struct __attribute__((packed)) {
uint8_t type; ///< type field.
uint8_t length; ///< length field.
uint16_t version; ///< version field.
uint32_t reserved; ///< reseverd field.
ipv6_addr_t addr; ///< 6LBR address field.
} icmpv6_ndp_opt_abro_t;
/**
* @brief Data type to represent address types according to
* <a href="http://tools.ietf.org/hmtl/rfc4862">RFC 4862</a>.
*/
typedef enum __attribute__((packed))
{
NDP_ADDR_STATE_TENTATIVE, ///< tentative address, uniqueness to be verified.
NDP_ADDR_STATE_PREFERRED, ///< preferred address, for unrestricted use.
NDP_ADDR_STATE_DEPRECATED, ///< deprecated address, use discouraged.
NDP_ADDR_STATE_ANY ///< addresses of this state are always permitted.
}
ndp_addr_state_t;
/**
* @}
*/
#endif /* SIXLOWPAN_TYPES_H */

671
sys/net/sixlowpan/ip.c Normal file
View File

@ -0,0 +1,671 @@
/**
* IPv6 implementation
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowip.c
* @brief 6lowpan IP layer functions
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "vtimer.h"
#include "mutex.h"
#include "msg.h"
#include "sixlowpan/mac.h"
#include "ip.h"
#include "icmp.h"
#include "lowpan.h"
#include "sys/net/destiny/socket.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
#define IP_PKT_RECV_BUF_SIZE (64)
#define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN)
uint8_t ip_send_buffer[BUFFER_SIZE];
uint8_t buffer[BUFFER_SIZE];
msg_t msg_queue[IP_PKT_RECV_BUF_SIZE];
ipv6_hdr_t *ipv6_buf;
icmpv6_hdr_t *icmp_buf;
uint8_t *nextheader;
uint8_t iface_addr_list_count = 0;
int udp_packet_handler_pid = 0;
int tcp_packet_handler_pid = 0;
int rpl_process_pid = 0;
/* registered upper layer threads */
int sixlowip_reg[SIXLOWIP_MAX_REGISTERED];
void ipv6_send_bytes(ipv6_hdr_t *bytes)
{
uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length);
bytes->flowlabel = HTONS(bytes->flowlabel);
bytes->length = HTONS(bytes->length);
memset(bytes, 0, BUFFER_SIZE);
memcpy(bytes + LL_HDR_LEN, bytes, offset);
sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(bytes->destaddr.uint16[4]),
(uint8_t *)bytes,
offset);
}
ipv6_hdr_t *ipv6_get_buf_send(void)
{
return ((ipv6_hdr_t *) &(ip_send_buffer[LL_HDR_LEN]));
}
uint8_t *get_payload_buf_send(uint8_t ext_len)
{
return &(ip_send_buffer[LLHDR_IPV6HDR_LEN + ext_len]);
}
ipv6_hdr_t *ipv6_get_buf(void)
{
return ((ipv6_hdr_t *) &(buffer[LL_HDR_LEN]));
}
icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len)
{
return ((icmpv6_hdr_t *) &(buffer[LLHDR_IPV6HDR_LEN + ext_len]));
}
uint8_t *get_payload_buf(uint8_t ext_len)
{
return &(buffer[LLHDR_IPV6HDR_LEN + ext_len]);
}
void ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header,
const uint8_t *payload, uint16_t payload_length)
{
uint8_t *p_ptr;
uint16_t packet_length;
if (next_header == IPV6_PROTO_NUM_TCP) {
p_ptr = get_payload_buf_send(ipv6_ext_hdr_len);
ipv6_buf = ipv6_get_buf_send();
}
else {
ipv6_buf = ipv6_get_buf();
p_ptr = get_payload_buf(ipv6_ext_hdr_len);
}
ipv6_buf->version_trafficclass = IPV6_VER;
ipv6_buf->trafficclass_flowlabel = 0;
ipv6_buf->flowlabel = 0;
ipv6_buf->nextheader = next_header;
ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT;
ipv6_buf->length = payload_length;
memcpy(&(ipv6_buf->destaddr), dest, 16);
ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));
memcpy(p_ptr, payload, payload_length);
packet_length = IPV6_HDR_LEN + payload_length;
sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_buf->destaddr.uint16[4]),
(uint8_t *)ipv6_buf, packet_length);
}
/* Register an upper layer thread */
uint8_t ipv6_register_packet_handler(int pid)
{
uint8_t i;
for (i = 0; ((sixlowip_reg[i] != pid) && (i < SIXLOWIP_MAX_REGISTERED) &&
(sixlowip_reg[i] != 0)); i++) {
;
}
if (i >= SIXLOWIP_MAX_REGISTERED) {
return ENOMEM;
}
else {
sixlowip_reg[i] = pid;
return 1;
}
}
int icmpv6_demultiplex(const icmpv6_hdr_t *hdr)
{
switch (hdr->type) {
case (ICMPV6_TYPE_ECHO_REQUEST): {
puts("INFO: packet type: icmp echo request");
/* processing echo request */
recv_echo_req();
break;
}
case (ICMPV6_TYPE_ECHO_REPLY): {
puts("INFO: packet type: icmp echo reply");
/* processing echo reply */
recv_echo_repl();
break;
}
case (ICMPV6_TYPE_ROUTER_SOL): {
puts("INFO: packet type: icmp router solicitation");
/* processing router solicitation */
recv_rtr_sol();
/* init solicited router advertisment*/
break;
}
case (ICMPV6_TYPE_ROUTER_ADV): {
puts("INFO: packet type: icmp router advertisment");
/* processing router advertisment */
recv_rtr_adv();
/* init neighbor solicitation */
break;
}
case (ICMPV6_TYPE_NEIGHBOR_SOL): {
puts("INFO: packet type: icmp neighbor solicitation");
recv_nbr_sol();
break;
}
case (ICMPV6_TYPE_NEIGHBOR_ADV): {
puts("INFO: packet type: icmp neighbor advertisment");
recv_nbr_adv();
break;
}
case (ICMPV6_TYPE_RPL_CONTROL): {
puts("INFO: packet type: RPL message");
if (rpl_process_pid != 0) {
msg_t m_send;
m_send.content.ptr = (char *) &hdr->code;
msg_send(&m_send, rpl_process_pid, 1);
}
else {
puts("INFO: no RPL handler registered");
}
break;
}
default:
return -1;
}
return 0;
}
uint8_t ipv6_get_addr_match(const ipv6_addr_t *src,
const ipv6_addr_t *dst)
{
uint8_t val = 0, xor;
for (int i = 0; i < 16; i++) {
/* if bytes are equal add 8 */
if (src->uint8[i] == dst->uint8[i]) {
val += 8;
}
else {
xor = src->uint8[i] ^ dst->uint8[i];
/* while bits from byte equal add 1 */
for (int j = 0; j < 8; j++) {
if ((xor & 0x80) == 0) {
val++;
xor = xor << 1;
}
else {
break;
}
}
}
}
return val;
}
void ipv6_process(void)
{
msg_t m_recv_lowpan, m_send_lowpan;
msg_t m_recv, m_send;
ipv6_addr_t myaddr;
uint8_t i;
uint16_t packet_length;
ipv6_addr_init(&myaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00,
sixlowpan_mac_get_radio_address());
while (1) {
msg_receive(&m_recv_lowpan);
ipv6_buf = (ipv6_hdr_t *)m_recv_lowpan.content.ptr;
/* identifiy packet */
nextheader = &ipv6_buf->nextheader;
if ((ipv6_get_addr_match(&myaddr, &ipv6_buf->destaddr) >= 112) &&
(ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) {
packet_length = IPV6_HDR_LEN + ipv6_buf->length;
memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length);
sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_buf->destaddr.uint16[4]),
(uint8_t *)ipv6_get_buf_send(),
packet_length);
}
else {
for (i = 0; i < SIXLOWIP_MAX_REGISTERED; i++) {
if (sixlowip_reg[i]) {
msg_t m_send;
m_send.content.ptr = (char *) &ipv6_buf;
msg_send(&m_send, sixlowip_reg[i], 1);
}
}
switch (*nextheader) {
case (IPV6_PROTO_NUM_ICMPV6): {
/* checksum test*/
if (icmpv6_csum(IPV6_PROTO_NUM_ICMPV6) != 0xffff) {
printf("ERROR: wrong checksum\n");
}
icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
icmpv6_demultiplex(icmp_buf);
break;
}
case (IPV6_PROTO_NUM_TCP): {
if (tcp_packet_handler_pid != 0) {
m_send.content.ptr = (char *) ipv6_buf;
msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid);
}
else {
printf("INFO: No TCP handler registered.\n");
}
break;
}
case (IPV6_PROTO_NUM_UDP): {
if (udp_packet_handler_pid != 0) {
m_send.content.ptr = (char *) ipv6_buf;
msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid);
}
else {
printf("INFO: No UDP handler registered.\n");
}
break;
}
case (IPV6_PROTO_NUM_NONE): {
printf("INFO: Packet with no Header following the IPv6 Header received.\n");
break;
}
default:
break;
}
}
msg_reply(&m_recv_lowpan, &m_send_lowpan);
}
}
void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type,
ndp_addr_state_t state, uint32_t val_ltime,
uint32_t pref_ltime)
{
if (ipv6_addr_is_unspecified(addr) == 128) {
printf("ERROR: unspecified address (::) can't be assigned to interface.\n");
return;
}
if (ipv6_iface_addr_match(addr) != 0) {
return;
}
if (iface_addr_list_count < IFACE_ADDR_LIST_LEN) {
memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]),
&(addr->uint8[0]), 16);
iface.addr_list[iface_addr_list_count].state = state;
timex_t valtime = {val_ltime, 0};
timex_t preftime = {pref_ltime, 0};
timex_t now;
vtimer_now(&now);
iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime);
iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime);
iface.addr_list[iface_addr_list_count].type = type;
iface_addr_list_count++;
/* Register to Solicited-Node multicast address according to RFC 4291 */
if (type == IPV6_ADDR_TYPE_ANYCAST || type == IPV6_ADDR_TYPE_LINK_LOCAL ||
type == IPV6_ADDR_TYPE_GLOBAL || type == IPV6_ADDR_TYPE_UNICAST) {
ipv6_addr_t sol_node_mcast_addr;
ipv6_addr_set_solicited_node_addr(&sol_node_mcast_addr, addr);
if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) {
ipv6_iface_add_addr(&sol_node_mcast_addr,
IPV6_ADDR_TYPE_SOLICITED_NODE,
state, val_ltime, pref_ltime);
}
}
}
}
addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr)
{
int i;
for (i = 0; i < iface_addr_list_count; i++) {
if (memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]), 16) == 0) {
return &(iface.addr_list[i]);
}
}
return NULL;
}
addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr)
{
int i;
for (i = 0; i < iface_addr_list_count; i++) {
if (memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]), 8) == 0) {
return &(iface.addr_list[i]);
}
}
return NULL;
}
void ipv6_iface_print_addrs(void)
{
for (int i = 0; i < iface_addr_list_count; i++) {
char addr_str[IPV6_MAX_ADDR_STR_LEN];
printf("%s\n", ipv6_addr_to_str(addr_str,
&(iface.addr_list[i].addr)));
}
}
void ipv6_addr_set_by_eui64(ipv6_addr_t *out, const ipv6_addr_t *prefix)
{
out->uint16[0] = prefix->uint16[0];
out->uint16[1] = prefix->uint16[1];
out->uint16[2] = prefix->uint16[2];
out->uint16[3] = prefix->uint16[3];
memcpy(&(out->uint8[8]), &(iface.laddr.uint8[0]), 8);
}
void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix,
uint8_t bits)
{
if (bits > 128) {
bits = 128;
}
uint8_t bytes = bits / 8, mask;
if (bits % 8) {
mask = 0xff << (bits - (bytes * 8));
}
else {
mask = 0x00;
}
bytes++;
memset(out, 0, 16);
memcpy(out, prefix, bytes);
out->uint8[bytes] = prefix->uint8[bytes] & mask;
}
void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr)
{
ipv6_addr->uint16[0] = HTONS(0xff02);
ipv6_addr->uint16[1] = 0;
ipv6_addr->uint16[2] = 0;
ipv6_addr->uint16[3] = 0;
ipv6_addr->uint16[4] = 0;
ipv6_addr->uint16[5] = 0;
ipv6_addr->uint16[6] = 0;
ipv6_addr->uint16[7] = HTONS(0x0002);
}
void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr)
{
ipv6_addr->uint16[0] = HTONS(0xff02);
ipv6_addr->uint16[1] = 0;
ipv6_addr->uint16[2] = 0;
ipv6_addr->uint16[3] = 0;
ipv6_addr->uint16[4] = 0;
ipv6_addr->uint16[5] = 0;
ipv6_addr->uint16[6] = 0;
ipv6_addr->uint16[7] = HTONS(0x0001);
}
void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr)
{
ipv6_addr->uint16[0] = 0;
ipv6_addr->uint16[1] = 0;
ipv6_addr->uint16[2] = 0;
ipv6_addr->uint16[3] = 0;
ipv6_addr->uint16[4] = 0;
ipv6_addr->uint16[5] = 0;
ipv6_addr->uint16[6] = 0;
ipv6_addr->uint16[7] = HTONS(0x0001);
}
void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest)
{
/* try to find best match if dest is not mcast or link local */
int8_t itmp = -1;
uint8_t tmp = 0;
uint8_t bmatch = 0;
if (!(ipv6_addr_is_link_local(dest)) && !(ipv6_addr_is_multicast(dest))) {
for (int i = 0; i < IFACE_ADDR_LIST_LEN; i++) {
if (iface.addr_list[i].state == NDP_ADDR_STATE_PREFERRED) {
if (!ipv6_addr_is_link_local(&(iface.addr_list[i].addr)) &&
!ipv6_addr_is_multicast(&(iface.addr_list[i].addr)) &&
!ipv6_addr_is_unique_local_unicast(&(iface.addr_list[i].addr))) {
tmp = ipv6_get_addr_match(dest, &(iface.addr_list[i].addr));
if (tmp >= bmatch) {
bmatch = tmp;
itmp = i;
}
}
}
}
}
else {
for (int j = 0; j < IFACE_ADDR_LIST_LEN; j++) {
if ((iface.addr_list[j].state == NDP_ADDR_STATE_PREFERRED) &&
ipv6_addr_is_link_local(&(iface.addr_list[j].addr)) &&
!ipv6_addr_is_multicast(&(iface.addr_list[j].addr))) {
itmp = j;
}
}
}
if (itmp == -1) {
memset(src, 0, 16);
}
else {
memcpy(src, &(iface.addr_list[itmp].addr), 16);
}
}
int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b)
{
return (ipv6_get_addr_match(a, b) == 128);
}
void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr)
{
ipv6_addr->uint16[0] = HTONS(0xfe80);
ipv6_addr->uint16[1] = 0;
ipv6_addr->uint16[2] = 0;
ipv6_addr->uint16[3] = 0;
}
void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7)
{
out->uint16[0] = HTONS(addr0);
out->uint16[1] = HTONS(addr1);
out->uint16[2] = HTONS(addr2);
out->uint16[3] = HTONS(addr3);
out->uint16[4] = HTONS(addr4);
out->uint16[5] = HTONS(addr5);
out->uint16[6] = HTONS(addr6);
out->uint16[7] = HTONS(addr7);
}
int ipv6_addr_is_link_local(const ipv6_addr_t *addr)
{
return (addr->uint8[0] == 0xfe && addr->uint8[0] == 0x80);
}
int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr)
{
return (addr->uint8[0] == 0xfc || addr->uint8[0] == 0xfd);
}
int ipv6_addr_is_multicast(const ipv6_addr_t *addr)
{
return (addr->uint8[0] == 0xff);
}
int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr)
{
return (ipv6_addr->uint32[0] == 0) && (ipv6_addr->uint32[1] == 0) &&
(ipv6_addr->uint32[2] == 0) && (ipv6_addr->uint32[3] == 0);
}
int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr)
{
return (ipv6_addr->uint8[0] == 0xFF) &&
(ipv6_addr->uint8[1] == 0x02) &&
(ipv6_addr->uint16[1] == 0x00) &&
(ipv6_addr->uint16[2] == 0x00) &&
(ipv6_addr->uint16[3] == 0x00) &&
(ipv6_addr->uint16[4] == 0x00) &&
(ipv6_addr->uint8[10] == 0x00) &&
(ipv6_addr->uint8[11] == 0x01) &&
(ipv6_addr->uint8[12] == 0xFF);
}
void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out,
const ipv6_addr_t *ipv6_addr_in)
{
/* copy only the last 24-bit of the ip-address that is beeing resolved */
ipv6_addr_out->uint16[0] = HTONS(0xff02);
ipv6_addr_out->uint16[1] = 0;
ipv6_addr_out->uint16[2] = 0;
ipv6_addr_out->uint16[3] = 0;
ipv6_addr_out->uint16[4] = 0;
ipv6_addr_out->uint16[5] = HTONS(0x0001);
ipv6_addr_out->uint8[12] = 0xff;
ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13];
ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7];
}
char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr)
{
sprintf(addr_str,
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
ipv6_addr->uint16[0], ipv6_addr->uint16[1],
ipv6_addr->uint16[2], ipv6_addr->uint16[3],
ipv6_addr->uint16[4], ipv6_addr->uint16[5],
ipv6_addr->uint16[6], ipv6_addr->uint16[7]);
return addr_str;
}
uint32_t get_remaining_time(timex_t *t)
{
timex_t now;
vtimer_now(&now);
return (timex_sub(*t, now).seconds);
}
void set_remaining_time(timex_t *t, uint32_t time)
{
timex_t tmp = {time, 0};
timex_t now;
vtimer_now(&now);
*t = timex_add(now, tmp);
}
void ipv6_init_iface_as_router(void)
{
ipv6_addr_t addr;
ipv6_addr_set_all_routers_addr(&addr);
ipv6_iface_add_addr(&addr, NDP_ADDR_STATE_PREFERRED, 0, 0, IPV6_ADDR_TYPE_MULTICAST);
}
uint8_t ipv6_is_router(void)
{
ipv6_addr_t addr;
ipv6_addr_set_all_routers_addr(&addr);
if (ipv6_iface_addr_match(&addr) != NULL) {
return 1;
}
return 0;
}
void set_tcp_packet_handler_pid(int pid)
{
tcp_packet_handler_pid = pid;
}
void set_udp_packet_handler_pid(int pid)
{
udp_packet_handler_pid = pid;
}
void ipv6_register_next_header_handler(uint8_t next_header, int pid)
{
switch (next_header) {
case (IPV6_PROTO_NUM_TCP):
set_tcp_packet_handler_pid(pid);
break;
case (IPV6_PROTO_NUM_UDP):
set_udp_packet_handler_pid(pid);
break;
default:
/* TODO */
break;
}
}
void ipv6_register_rpl_handler(int pid)
{
rpl_process_pid = pid;
}

91
sys/net/sixlowpan/ip.h Normal file
View File

@ -0,0 +1,91 @@
/**
* IPv6 constants, data structs, and prototypes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowip.h
* @brief 6lowpan IP layer header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
/* 6LoWPAN IP header file */
#ifndef _SIXLOWPAN_IP_H
#define _SIXLOWPAN_IP_H
#include <stdint.h>
#include "timex.h"
#include "mutex.h"
#include "sixlowpan/ip.h"
#include "sixlowpan/types.h"
/* IPv6 field values */
#define IPV6_VER (0x60)
/* size of global buffer */
#define BUFFER_SIZE (LL_HDR_LEN + IPV6_MTU)
#define MULTIHOP_HOPLIMIT (64)
#define SIXLOWIP_MAX_REGISTERED (4)
/* extern variables */
extern uint8_t ipv6_ext_hdr_len;
/* base header lengths */
#define LL_HDR_LEN (0x4)
#define ICMPV6_HDR_LEN (0x4)
#define IPV6_HDR_LEN (0x28)
#define IFACE_ADDR_LIST_LEN (10) // maybe to much
/* buffer */
extern uint8_t buffer[BUFFER_SIZE];
extern int sixlowip_reg[SIXLOWIP_MAX_REGISTERED];
typedef struct __attribute__((packed)) {
ipv6_addr_t addr;
ipv6_addr_type_t type;
ndp_addr_state_t state;
timex_t val_ltime;
timex_t pref_ltime;
} addr_list_t;
typedef struct __attribute__((packed)) {
ieee_802154_short_t saddr;
ieee_802154_long_t laddr;
addr_list_t addr_list[IFACE_ADDR_LIST_LEN];
uint8_t adv_cur_hop_limit;
uint32_t adv_reachable_time;
uint32_t adv_retrans_timer;
} iface_t;
extern iface_t iface;
/* function prototypes */
void ipv6_send_bytes(ipv6_hdr_t *bytes);
icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len);
uint8_t *get_payload_buf(uint8_t ext_len);
uint8_t *get_payload_buf_send(uint8_t ext_len);
int icmpv6_demultiplex(const icmpv6_hdr_t *hdr);
void ipv6_init_iface_as_router(void);
void ipv6_process(void);
addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr);
addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr);
uint32_t get_remaining_time(timex_t *t);
void set_remaining_time(timex_t *t, uint32_t time);
#endif /* _SIXLOWPAN_IP_H*/

View File

@ -10,7 +10,7 @@
* @ingroup sixlowpan
* @{
* @file sixlowpan.c
* @brief 6lowpan functions
* @brief 6lowpan functions
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
@ -18,11 +18,11 @@
* @}
*/
#include "sixlowip.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include "vtimer.h"
#include "timex.h"
@ -31,18 +31,61 @@
#include "mutex.h"
#include "hwtimer.h"
#include "msg.h"
#include "sixlowmac.h"
#include "sixlowpan.h"
#include "sixlowborder.h"
#include "sixlowip.h"
#include "sixlownd.h"
#include "transceiver.h"
#include "ieee802154/ieee802154_frame.h"
#include "sixlowpan/mac.h"
#include "sixlowpan/ndp.h"
#include "lowpan.h"
#include "border.h"
#include "ip.h"
#include "icmp.h"
#include "sys/net/ieee802154/ieee802154_frame.h"
#include "sys/net/destiny/in.h"
#include "sys/net/net_help/net_help.h"
uint16_t packet_length;
uint8_t packet_dispatch;
#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT * 6)
#define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
#define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
#define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
#define SIXLOWPAN_MAX_REGISTERED (4)
#define LOWPAN_REAS_BUF_TIMEOUT (15 * 1000 * 1000)
/* TODO: Set back to 3 * 1000 * (1000) */
#define IPV6_LL_ADDR_LEN (8)
#define SIXLOWPAN_FRAG_HDR_MASK (0xf8)
typedef struct lowpan_interval_list_t {
uint8_t start;
uint8_t end;
struct lowpan_interval_list_t *next;
} lowpan_interval_list_t;
typedef struct lowpan_reas_buf_t {
/* Source Address */
ieee_802154_long_t s_laddr;
/* Destination Address */
ieee_802154_long_t d_laddr;
/* Identification Number */
uint16_t ident_no;
/* Timestamp of last packet fragment */
long timestamp;
/* Size of reassembled packet with possible IPHC header */
uint16_t packet_size;
/* Additive size of currently already received fragments */
uint16_t current_packet_size;
/* Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte */
uint8_t *packet;
/* Pointer to list of intervals of received packet fragments (if any) */
lowpan_interval_list_t *interval_list_head;
/* Pointer to next reassembly buffer (if any) */
struct lowpan_reas_buf_t *next;
} lowpan_reas_buf_t;
extern mutex_t lowpan_context_mutex;
uint16_t tag;
uint8_t header_size = 0;
uint8_t max_frame = 0;
@ -50,7 +93,11 @@ uint8_t max_frag_initial = 0;
uint8_t position;
uint8_t max_frag;
static uint16_t packet_length;
static sixlowpan_lowpan_iphc_status_t iphc_status = LOWPAN_IPHC_ENABLE;
static ipv6_hdr_t *ipv6_buf;
static lowpan_reas_buf_t *head = NULL;
static lowpan_reas_buf_t *packet_fifo = NULL;
/* length of compressed packet */
uint16_t comp_len;
@ -59,8 +106,6 @@ uint8_t reas_buf[512];
uint8_t comp_buf[512];
uint8_t byte_offset;
uint8_t first_frag = 0;
lowpan_reas_buf_t *head = NULL;
lowpan_reas_buf_t *packet_fifo = NULL;
mutex_t fifo_mutex;
unsigned int ip_process_pid;
@ -71,36 +116,59 @@ unsigned int transfer_pid = 0;
iface_t iface;
ipv6_addr_t lladdr;
ieee_802154_long_t laddr;
mutex_t buf_mutex;
mutex_t lowpan_context_mutex;
/* registered upper layer threads */
int sixlowpan_reg[SIXLOWPAN_MAX_REGISTERED];
char ip_process_buf[IP_PROCESS_STACKSIZE];
char nc_buf[NC_STACKSIZE];
char con_buf[CON_STACKSIZE];
char lowpan_transfer_buf[LOWPAN_TRANSFER_BUF_STACKSIZE];
lowpan_context_t contexts[LOWPAN_CONTEXT_MAX];
lowpan_context_t contexts[NDP_6LOWPAN_CONTEXT_MAX];
uint8_t context_len = 0;
uint16_t local_address = 0;
void lowpan_context_auto_remove(void);
void lowpan_iphc_encoding(ieee_802154_long_t *dest,
ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr);
void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
void add_fifo_packet(lowpan_reas_buf_t *current_packet);
lowpan_reas_buf_t *collect_garbage_fifo(lowpan_reas_buf_t *current_buf);
lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf);
void init_reas_bufs(lowpan_reas_buf_t *buf);
void check_timeout(void);
lowpan_context_t *lowpan_context_lookup(ipv6_addr_t *addr);
void lowpan_ipv6_set_dispatch(uint8_t *data);
/* deliver packet to mac*/
void lowpan_init(ieee_802154_long_t *addr, uint8_t *data)
void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest,
uint8_t *data, uint16_t data_len)
{
uint8_t mcast = 0;
ipv6_buf = (ipv6_hdr_t *) data;
packet_length = data_len;
memcpy(&laddr.uint8[0], &addr->uint8[0], 8);
memcpy(&laddr.uint8[0], &dest->uint8[0], 8);
if (ipv6_prefix_mcast_match(&ipv6_buf->destaddr)) {
if (ipv6_addr_is_multicast(&ipv6_buf->destaddr)) {
/* send broadcast */
mcast = 1;
}
lowpan_iphc_encoding(&laddr, ipv6_buf, data);
data = &comp_buf[0];
packet_length = comp_len;
if (iphc_status == LOWPAN_IPHC_ENABLE) {
lowpan_iphc_encoding(&laddr, ipv6_buf, data);
data = &comp_buf[0];
packet_length = comp_len;
}
else {
lowpan_ipv6_set_dispatch(data);
}
/* check if packet needs to be fragmented */
if (packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) {
@ -113,13 +181,15 @@ void lowpan_init(ieee_802154_long_t *addr, uint8_t *data)
memcpy(fragbuf + 4, data, max_frag_initial);
fragbuf[0] = (((0xc0 << 8) | packet_length) >> 8) & 0xff;
fragbuf[1] = ((0xc0 << 8) | packet_length) & 0xff;
fragbuf[2] = (tag >> 8) & 0xff;
fragbuf[3] = tag & 0xff;
fragbuf[0] = ((SIXLOWPAN_FRAG1_DISPATCH << 8) | packet_length) >> 8;
fragbuf[1] = (SIXLOWPAN_FRAG1_DISPATCH << 8) | packet_length;
fragbuf[2] = tag >> 8;
fragbuf[3] = tag;
send_ieee802154_frame(&laddr, (uint8_t *)&fragbuf,
max_frag_initial + header_size + 4, mcast);
sixlowpan_mac_send_ieee802154_frame(&laddr,
(uint8_t *)&fragbuf,
max_frag_initial + header_size + 4,
mcast);
/* subsequent fragments */
position = max_frag_initial;
max_frag = ((max_frame - 5) / 8) * 8;
@ -130,14 +200,15 @@ void lowpan_init(ieee_802154_long_t *addr, uint8_t *data)
memset(&fragbuf, 0, packet_length + header_size);
memcpy(fragbuf + 5, data, max_frag);
fragbuf[0] = (((0xe0 << 8) | packet_length) >> 8) & 0xff;
fragbuf[1] = ((0xe0 << 8) | packet_length) & 0xff;
fragbuf[2] = (tag >> 8) & 0xff;
fragbuf[3] = tag & 0xff;
fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | packet_length) >> 8;
fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | packet_length;
fragbuf[2] = tag >> 8;
fragbuf[3] = tag;
fragbuf[4] = position / 8;
send_ieee802154_frame(&laddr, (uint8_t *)&fragbuf, max_frag + 5,
mcast);
sixlowpan_mac_send_ieee802154_frame(&laddr,
(uint8_t *)&fragbuf,
max_frag + 5, mcast);
data += max_frag;
position += max_frag;
@ -149,22 +220,32 @@ void lowpan_init(ieee_802154_long_t *addr, uint8_t *data)
memset(&fragbuf, 0, packet_length + header_size);
memcpy(fragbuf + 5, data, remaining);
fragbuf[0] = (((0xe0 << 8) | packet_length) >> 8) & 0xff;
fragbuf[1] = ((0xe0 << 8) | packet_length) & 0xff;
fragbuf[2] = (tag >> 8) & 0xff;
fragbuf[3] = tag & 0xff;
fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | packet_length) >> 8;
fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | packet_length;
fragbuf[2] = tag >> 8;
fragbuf[3] = tag;
fragbuf[4] = position / 8;
send_ieee802154_frame(&laddr, (uint8_t *)&fragbuf, remaining + 5, mcast);
sixlowpan_mac_send_ieee802154_frame(&laddr,
(uint8_t *)&fragbuf,
remaining + 5, mcast);
}
else {
send_ieee802154_frame(&laddr, data, packet_length, mcast);
sixlowpan_mac_send_ieee802154_frame(&laddr, data,
packet_length, mcast);
}
tag++;
}
void printLongLocalAddr(ieee_802154_long_t *saddr)
void sixlowpan_lowpan_set_iphc_status(
sixlowpan_lowpan_iphc_status_t status)
{
iphc_status = status;
}
#if ENABLE_DEBUG
void print_long_local_addr(ieee_802154_long_t *saddr)
{
printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
((uint8_t *)saddr)[0], ((uint8_t *)saddr)[1], ((uint8_t *)saddr)[2],
@ -172,7 +253,7 @@ void printLongLocalAddr(ieee_802154_long_t *saddr)
((uint8_t *)saddr)[6], ((uint8_t *)saddr)[7]);
}
void printReasBuffers(void)
void sixlowpan_lowpan_print_reassembly_buffers(void)
{
lowpan_reas_buf_t *temp_buffer;
lowpan_interval_list_t *temp_interval;
@ -181,7 +262,7 @@ void printReasBuffers(void)
printf("\n\n--- Reassembly Buffers ---\n");
while (temp_buffer != NULL) {
printLongLocalAddr(&temp_buffer->s_laddr);
print_long_local_addr(&temp_buffer->s_laddr);
printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %li\n",
temp_buffer->ident_no, temp_buffer->current_packet_size,
temp_buffer->packet_size, temp_buffer->timestamp);
@ -196,7 +277,7 @@ void printReasBuffers(void)
}
}
void printFIFOBuffers(void)
void sixlowpan_lowpan_print_fifo_buffers(void)
{
lowpan_reas_buf_t *temp_buffer;
lowpan_interval_list_t *temp_interval;
@ -205,9 +286,9 @@ void printFIFOBuffers(void)
printf("\n\n--- Reassembly Buffers ---\n");
while (temp_buffer != NULL) {
printLongLocalAddr(&temp_buffer->s_laddr);
print_long_local_addr(&temp_buffer->s_laddr);
printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %li\n",
temp_buffer->ident_no, temp_buffer->current_packet_size,
temp_buffer->ident_no, temp_buffer->current_packet_size,
temp_buffer->packet_size, temp_buffer->timestamp);
temp_interval = temp_buffer->interval_list_head;
@ -219,6 +300,7 @@ void printFIFOBuffers(void)
temp_buffer = temp_buffer->next;
}
}
#endif
void lowpan_transfer(void)
{
@ -236,20 +318,20 @@ void lowpan_transfer(void)
if (current_buf != NULL) {
mutex_unlock(&fifo_mutex);
if ((current_buf->packet)[0] == LOWPAN_IPV6_DISPATCH) {
ipv6_buf = get_ipv6_buf();
if ((current_buf->packet)[0] == SIXLOWPAN_IPV6_DISPATCH) {
ipv6_buf = ipv6_get_buf();
memcpy(ipv6_buf, (current_buf->packet) + 1, current_buf->packet_size - 1);
m_send.content.ptr = (char *)ipv6_buf;
packet_length = current_buf->packet_size - 1;
msg_send_receive(&m_send, &m_recv, ip_process_pid);
}
else if (((current_buf->packet)[0] & 0xe0) == LOWPAN_IPHC_DISPATCH) {
else if (((current_buf->packet)[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH) {
lowpan_iphc_decoding(current_buf->packet,
current_buf->packet_size,
&(current_buf->s_laddr),
&(current_buf->d_laddr));
ipv6_buf = get_ipv6_buf();
ipv6_buf = ipv6_get_buf();
m_send.content.ptr = (char *) ipv6_buf;
msg_send_receive(&m_send, &m_recv, ip_process_pid);
}
@ -315,8 +397,8 @@ lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size,
new_buf->packet = malloc(datagram_size);
if (new_buf->packet != NULL) {
memcpy(&new_buf->s_laddr, s_laddr, SIXLOWPAN_IPV6_LL_ADDR_LEN);
memcpy(&new_buf->d_laddr, d_laddr, SIXLOWPAN_IPV6_LL_ADDR_LEN);
memcpy(&new_buf->s_laddr, s_laddr, IPV6_LL_ADDR_LEN);
memcpy(&new_buf->d_laddr, d_laddr, IPV6_LL_ADDR_LEN);
new_buf->ident_no = datagram_tag;
new_buf->packet_size = datagram_size;
@ -353,10 +435,10 @@ lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size,
while (current_buf != NULL) {
if (((ll_get_addr_match(&current_buf->s_laddr, s_laddr)) == 64) &&
((ll_get_addr_match(&current_buf->d_laddr, d_laddr)) == 64) &&
(current_buf->packet_size == datagram_size) &&
(current_buf->ident_no == datagram_tag) &&
current_buf->interval_list_head != NULL) {
((ll_get_addr_match(&current_buf->d_laddr, d_laddr)) == 64) &&
(current_buf->packet_size == datagram_size) &&
(current_buf->ident_no == datagram_tag) &&
current_buf->interval_list_head != NULL) {
/* Found buffer for current packet fragment */
timex_t now;
vtimer_now(&now);
@ -372,14 +454,14 @@ lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size,
current_buf, temp_buf);
}
uint8_t isInInterval(uint8_t start1, uint8_t end1, uint8_t start2, uint8_t end2)
uint8_t is_in_interval(uint8_t start1, uint8_t end1, uint8_t start2, uint8_t end2)
{
/* 1: Interval 1 and 2 are the same or overlapping */
/* 0: Interval 1 and 2 are not overlapping or the same */
if (((start1 < start2) && (start2 <= end1)) ||
((start2 < start1) && (start1 <= end2)) ||
((start1 == start2) && (end1 == end2))) {
((start2 < start1) && (start1 <= end2)) ||
((start1 == start2) && (end1 == end2))) {
return 1;
}
else {
@ -396,7 +478,7 @@ uint8_t handle_packet_frag_interval(lowpan_reas_buf_t *current_buf,
current_interval = current_buf->interval_list_head;
while (current_interval != NULL) {
if (isInInterval(current_interval->start, current_interval->end, datagram_offset, datagram_offset + frag_size) == 1) {
if (is_in_interval(current_interval->start, current_interval->end, datagram_offset, datagram_offset + frag_size) == 1) {
/* Interval is overlapping or the same as one of a previous fragment, discard fragment */
return 0;
}
@ -505,7 +587,7 @@ lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf)
return return_buf;
}
void handle_packet_fragment(uint8_t *data, uint8_t datagram_offset,
void handle_packet_fragment(uint8_t *data, uint8_t datagram_offset,
uint16_t datagram_size, uint16_t datagram_tag,
ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr, uint8_t hdr_length,
@ -516,8 +598,8 @@ void handle_packet_fragment(uint8_t *data, uint8_t datagram_offset,
current_buf = get_packet_frag_buf(datagram_size, datagram_tag, s_laddr, d_laddr);
if ((current_buf != NULL) && (handle_packet_frag_interval(current_buf,
datagram_offset,
frag_size) == 1)) {
datagram_offset,
frag_size) == 1)) {
/* Copy fragment bytes into corresponding packet space area */
memcpy(current_buf->packet + datagram_offset, data + hdr_length, frag_size);
current_buf->current_packet_size += frag_size;
@ -614,6 +696,25 @@ void add_fifo_packet(lowpan_reas_buf_t *current_packet)
current_packet->next = NULL;
}
/* Register an upper layer thread */
uint8_t sixlowpan_lowpan_register(int pid)
{
uint8_t i;
for (i = 0; ((sixlowpan_reg[i] != pid) && (i < SIXLOWPAN_MAX_REGISTERED) &&
(sixlowpan_reg[i] != 0)); i++) {
;
}
if (i >= SIXLOWPAN_MAX_REGISTERED) {
return ENOMEM;
}
else {
sixlowpan_reg[i] = pid;
return 1;
}
}
void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr)
{
@ -622,27 +723,40 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
uint8_t datagram_offset = 0;
uint16_t datagram_size = 0;
uint16_t datagram_tag = 0;
short i;
sixlowpan_lowpan_frame_t current_frame;
check_timeout();
for (i = 0; i < SIXLOWPAN_MAX_REGISTERED; i++) {
if (sixlowpan_reg[i]) {
msg_t m_send;
current_frame.length = length;
current_frame.data = data;
m_send.content.ptr = (char *) &current_frame;
msg_send(&m_send, sixlowpan_reg[i], 1);
}
}
/* Fragmented Packet */
if (((data[0] & 0xf8) == (0xc0)) || ((data[0] & 0xf8) == (0xe0))) {
if (((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAG1_DISPATCH) ||
((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAGN_DISPATCH)) {
/* get 11-bit from first 2 byte*/
datagram_size = (((uint16_t)(data[0] << 8)) | data[1]) & 0x07ff;
/* get 16-bit datagram tag */
datagram_tag = (((uint16_t)(data[2] << 8)) | data[3]);
switch(data[0] & 0xf8) {
switch (data[0] & SIXLOWPAN_FRAG_HDR_MASK) {
/* First Fragment */
case (0xc0): {
case (SIXLOWPAN_FRAG1_DISPATCH): {
datagram_offset = 0;
hdr_length += 4;
break;
}
/* Subsequent Fragment */
case (0xe0): {
case (SIXLOWPAN_FRAGN_DISPATCH): {
datagram_offset = data[4];
hdr_length += 5;
break;
@ -665,7 +779,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
/* Regular Packet */
else {
lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_laddr,
d_laddr);
d_laddr);
/* Copy packet bytes into corresponding packet space area */
memcpy(current_buf->packet, data, length);
current_buf->current_packet_size += length;
@ -681,7 +795,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
void lowpan_ipv6_set_dispatch(uint8_t *data)
{
memmove(data + 1, data, packet_length);
data[0] = LOWPAN_IPV6_DISPATCH;
data[0] = SIXLOWPAN_IPV6_DISPATCH;
packet_length++;
}
@ -701,7 +815,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
memset(&lowpan_iphc, 0, 2);
/* set iphc dispatch */
lowpan_iphc[0] = LOWPAN_IPHC_DISPATCH;
lowpan_iphc[0] = SIXLOWPAN_IPHC1_DISPATCH;
/* TF: Traffic Class, Flow Label:
* first we need to change DSCP and ECN because in 6lowpan-nd-13 these
@ -711,14 +825,14 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
tc = (tc >> 2) | (tc << 6);
if ((ipv6_buf->flowlabel == 0) &&
(ipv6_buf->trafficclass_flowlabel & 0x0f) == 0) {
(ipv6_buf->trafficclass_flowlabel & 0x0f) == 0) {
/* flowlabel is elided */
lowpan_iphc[0] |= LOWPAN_IPHC_FL_C;
lowpan_iphc[0] |= SIXLOWPAN_IPHC1_FL_C;
if (((ipv6_buf->version_trafficclass & 0x0f) == 0) &&
((ipv6_buf->trafficclass_flowlabel & 0xf0) == 0)) {
((ipv6_buf->trafficclass_flowlabel & 0xf0) == 0)) {
/* traffic class is elided */
lowpan_iphc[0] |= LOWPAN_IPHC_TC_C;
lowpan_iphc[0] |= SIXLOWPAN_IPHC1_TC_C;
}
else {
/* ECN + DSCP (1 byte), Flow Label is elided */
@ -729,9 +843,9 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
else {
/* flowlabel not compressible */
if (((ipv6_buf->version_trafficclass & 0x0f) == 0) &&
((ipv6_buf->trafficclass_flowlabel & 0xf0) == 0)) {
((ipv6_buf->trafficclass_flowlabel & 0xf0) == 0)) {
/* traffic class is elided */
lowpan_iphc[0] |= LOWPAN_IPHC_TC_C;
lowpan_iphc[0] |= SIXLOWPAN_IPHC1_TC_C;
/* ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided */
ipv6_hdr_fields[hdr_pos] = ((tc & 0xc0) |
(ipv6_buf->trafficclass_flowlabel & 0x0f));
@ -752,7 +866,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
hdr_pos++;
/* HLIM: Hop Limit: */
switch(ipv6_buf->hoplimit) {
switch (ipv6_buf->hoplimit) {
case (1): {
/* 01: The Hop Limit field is compressed and the hop limit is 1. */
lowpan_iphc[0] |= 0x01;
@ -782,21 +896,21 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
/* CID: Context Identifier Extension: */
if ((lowpan_context_lookup(&ipv6_buf->srcaddr) != NULL) ||
(lowpan_context_lookup(&ipv6_buf->destaddr) != NULL)) {
lowpan_iphc[1] |= LOWPAN_IPHC_CID;
(lowpan_context_lookup(&ipv6_buf->destaddr) != NULL)) {
lowpan_iphc[1] |= SIXLOWPAN_IPHC2_CID;
memmove(&ipv6_hdr_fields[1], &ipv6_hdr_fields[0], hdr_pos);
hdr_pos++;
}
/* SAC: Source Address Compression */
if (ipv6_addr_unspec_match(&(ipv6_buf->srcaddr))) {
if (ipv6_addr_is_unspecified(&(ipv6_buf->srcaddr))) {
/* SAC = 1 and SAM = 00 */
lowpan_iphc[1] |= LOWPAN_IPHC_SAC;
lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC;
}
else if ((con = lowpan_context_lookup(&ipv6_buf->srcaddr)) != NULL) {
/* 1: Source address compression uses stateful, context-based
* compression. */
lowpan_iphc[1] |= LOWPAN_IPHC_SAC;
lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC;
ipv6_hdr_fields[0] |= (con->num << 4);
if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) {
@ -805,9 +919,9 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
lowpan_iphc[1] |= 0x30;
}
else if ((ipv6_buf->srcaddr.uint16[4] == 0) &&
(ipv6_buf->srcaddr.uint16[5] == 0) &&
(ipv6_buf->srcaddr.uint16[6] == 0) &&
((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) {
(ipv6_buf->srcaddr.uint16[5] == 0) &&
(ipv6_buf->srcaddr.uint16[6] == 0) &&
((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) {
/* 49-bit of interface identifier are 0, so we can compress
* source address-iid to 16-bit */
memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2);
@ -824,7 +938,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
lowpan_iphc[1] |= 0x10;
}
}
else if (ipv6_prefix_ll_match(&ipv6_buf->srcaddr)) {
else if (ipv6_addr_is_link_local(&ipv6_buf->srcaddr)) {
/* 0: Source address compression uses stateless compression.*/
if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) {
/* 0 bits. The address is derived using context information
@ -832,9 +946,9 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
lowpan_iphc[1] |= 0x30;
}
else if ((ipv6_buf->srcaddr.uint16[4] == 0) &&
(ipv6_buf->srcaddr.uint16[5] == 0) &&
(ipv6_buf->srcaddr.uint16[6] == 0) &&
((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) {
(ipv6_buf->srcaddr.uint16[5] == 0) &&
(ipv6_buf->srcaddr.uint16[6] == 0) &&
((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) {
/* 49-bit of interface identifier are 0, so we can compress
* source address-iid to 16-bit */
memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2);
@ -858,30 +972,30 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
}
/* M: Multicast Compression */
if (ipv6_prefix_mcast_match(&ipv6_buf->destaddr)) {
if (ipv6_addr_is_multicast(&ipv6_buf->destaddr)) {
/* 1: Destination address is a multicast address. */
lowpan_iphc[1] |= LOWPAN_IPHC_M;
lowpan_iphc[1] |= SIXLOWPAN_IPHC2_M;
/* just another cool if condition */
if ((ipv6_buf->destaddr.uint8[1] == 2) &&
(ipv6_buf->destaddr.uint16[1] == 0) &&
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
(ipv6_buf->destaddr.uint8[14] == 0)) {
(ipv6_buf->destaddr.uint16[1] == 0) &&
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
(ipv6_buf->destaddr.uint8[14] == 0)) {
/* 11: 8 bits. The address takes the form FF02::00XX. */
lowpan_iphc[1] |= 0x03;
ipv6_hdr_fields[hdr_pos] = ipv6_buf->destaddr.uint8[15];
hdr_pos++;
}
else if ((ipv6_buf->destaddr.uint16[1] == 0) &&
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint8[12] == 0)) {
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint8[12] == 0)) {
/* 10: 32 bits. The address takes the form FFXX::00XX:XXXX. */
lowpan_iphc[1] |= 0x02;
/* copy second and last 3 byte */
@ -891,10 +1005,10 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
hdr_pos += 3;
}
else if ((ipv6_buf->destaddr.uint16[1] == 0) &&
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint8[10] == 0)) {
(ipv6_buf->destaddr.uint16[2] == 0) &&
(ipv6_buf->destaddr.uint16[3] == 0) &&
(ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint8[10] == 0)) {
/* 01: 48 bits. The address takes the form FFXX::00XX:XXXX:XXXX */
lowpan_iphc[1] |= 0x01;
/* copy second and last 5 byte */
@ -913,7 +1027,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
if ((con = lowpan_context_lookup(&ipv6_buf->destaddr)) != NULL) {
/* 1: Destination address compression uses stateful, context-based
* compression. */
lowpan_iphc[1] |= LOWPAN_IPHC_DAC;
lowpan_iphc[1] |= SIXLOWPAN_IPHC2_DAC;
ipv6_hdr_fields[0] = con->num;
if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) {
@ -922,9 +1036,9 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
lowpan_iphc[1] |= 0x03;
}
else if ((ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) {
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) {
/* 49-bit of interface identifier are 0, so we can compress
* source address-iid to 16-bit */
memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->destaddr.uint16[7], 2);
@ -941,16 +1055,16 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
lowpan_iphc[1] |= 0x01;
}
}
else if (ipv6_prefix_ll_match(&ipv6_buf->destaddr)) {
else if (ipv6_addr_is_link_local(&ipv6_buf->destaddr)) {
if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) {
/* 0 bits. The address is derived using context information
* and possibly the link-layer addresses.*/
lowpan_iphc[1] |= 0x03;
}
else if ((ipv6_buf->destaddr.uint16[4] == 0) &&
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) {
(ipv6_buf->destaddr.uint16[5] == 0) &&
(ipv6_buf->destaddr.uint16[6] == 0) &&
((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) {
/* 49-bit of interface identifier are 0, so we can compress
* source address-iid to 16-bit */
memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->destaddr.uint16[7], 2);
@ -979,7 +1093,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra,
comp_buf[1] = lowpan_iphc[1];
/*uint8_t *ptr;
if (ipv6_buf->nextheader == IPPROTO_TCP)
if (ipv6_buf->nextheader == IPV6_PROTO_NUM_TCP)
{
ptr = get_payload_buf_send(ipv6_ext_hdr_len);
}
@ -1008,22 +1122,22 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
uint8_t m_prefix[2] = {0xff, 0x02};
lowpan_context_t *con = NULL;
ipv6_buf = get_ipv6_buf();
ipv6_buf = ipv6_get_buf();
lowpan_iphc[0] = ipv6_hdr_fields[0];
lowpan_iphc[1] = ipv6_hdr_fields[1];
hdr_pos += 2;
/* first check if CID flag is set */
if (lowpan_iphc[1] & LOWPAN_IPHC_CID) {
if (lowpan_iphc[1] & SIXLOWPAN_IPHC2_CID) {
hdr_pos++;
cid = 1;
}
/* TF: Traffic Class, Flow Label: */
if (lowpan_iphc[0] & LOWPAN_IPHC_FL_C) {
if (lowpan_iphc[0] & SIXLOWPAN_IPHC1_FL_C) {
/* flowlabel is elided */
if (lowpan_iphc[0] & LOWPAN_IPHC_TC_C) {
if (lowpan_iphc[0] & SIXLOWPAN_IPHC1_TC_C) {
/* traffic class is elided */
ipv6_buf->version_trafficclass = 0x60;
ipv6_buf->trafficclass_flowlabel = 0;
@ -1041,7 +1155,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
else {
/* flowlabel carried inline */
if (lowpan_iphc[0] & LOWPAN_IPHC_TC_C) {
if (lowpan_iphc[0] & SIXLOWPAN_IPHC1_TC_C) {
/* traffic class is elided */
ipv6_buf->version_trafficclass = 0x60;
/* ecn + 4 bit flowlabel*/
@ -1066,7 +1180,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
/* NH: Next Header: */
if (lowpan_iphc[0] & LOWPAN_IPHC_NH) {
if (lowpan_iphc[0] & SIXLOWPAN_IPHC1_NH) {
// TODO: next header decompression
}
else {
@ -1076,7 +1190,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
/* HLIM: Hop Limit: */
if (lowpan_iphc[0] & 0x03) {
switch(lowpan_iphc[0] & 0x03) {
switch (lowpan_iphc[0] & 0x03) {
case (0x01): {
ipv6_buf->hoplimit = 1;
break;
@ -1102,7 +1216,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
/* CID: Context Identifier Extension: + SAC: Source Address Compression */
if (lowpan_iphc[1] & LOWPAN_IPHC_SAC) {
if (lowpan_iphc[1] & SIXLOWPAN_IPHC2_SAC) {
/* 1: Source address compression uses stateful, context-based
* compression.*/
if (cid) {
@ -1112,7 +1226,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
mutex_lock(&lowpan_context_mutex);
/* check context number */
if (((lowpan_iphc[1] & LOWPAN_IPHC_SAM) >> 4) & 0x03) {
if (((lowpan_iphc[1] & SIXLOWPAN_IPHC2_SAM) >> 4) & 0x03) {
con = lowpan_context_num_lookup(sci);
}
@ -1121,7 +1235,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
return;
}
switch(((lowpan_iphc[1] & LOWPAN_IPHC_SAM) >> 4) & 0x03) {
switch (((lowpan_iphc[1] & SIXLOWPAN_IPHC2_SAM) >> 4) & 0x03) {
case (0x01): {
/* 64-bits */
memcpy(&(ipv6_buf->srcaddr.uint8[8]), &ipv6_hdr_fields[hdr_pos], 8);
@ -1163,7 +1277,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
mutex_unlock(&lowpan_context_mutex);
}
else {
switch(((lowpan_iphc[1] & LOWPAN_IPHC_SAM) >> 4) & 0x03) {
switch (((lowpan_iphc[1] & SIXLOWPAN_IPHC2_SAM) >> 4) & 0x03) {
case (0x01): {
/* 64-bits */
memcpy(&(ipv6_buf->srcaddr.uint8[0]), &ll_prefix[0], 2);
@ -1201,9 +1315,9 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
/* M: Multicast Compression + DAC: Destination Address Compression */
if (lowpan_iphc[1] & LOWPAN_IPHC_M) {
if (lowpan_iphc[1] & SIXLOWPAN_IPHC2_M) {
/* 1: Destination address is a multicast address. */
if (lowpan_iphc[1] & LOWPAN_IPHC_DAC) {
if (lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAC) {
/* 1: Destination address compression uses stateful, context-based
* compression.
* If M=1 and DAC=1: */
@ -1213,7 +1327,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
mutex_lock(&lowpan_context_mutex);
if ((lowpan_iphc[1] & LOWPAN_IPHC_DAM) & 0x03) {
if ((lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAM) & 0x03) {
con = lowpan_context_num_lookup(dci);
}
@ -1227,7 +1341,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
else {
/* If M=1 and DAC=0: */
switch(lowpan_iphc[1] & 0x03) {
switch (lowpan_iphc[1] & 0x03) {
case (0x01): {
m_prefix[1] = ipv6_hdr_fields[hdr_pos];
hdr_pos++;
@ -1244,7 +1358,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
break;
}
switch(lowpan_iphc[1] & 0x03) {
switch (lowpan_iphc[1] & 0x03) {
case (0x01): {
memcpy(&(ipv6_buf->destaddr.uint8[0]), &m_prefix[0], 2);
memset(&(ipv6_buf->destaddr.uint8[2]), 0, 9);
@ -1277,7 +1391,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
}
}
else {
if (lowpan_iphc[1] & LOWPAN_IPHC_DAC) {
if (lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAC) {
/* 1: Destination address compression uses stateful, context-based
* compression.
* If M=1 and DAC=1: */
@ -1287,7 +1401,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
mutex_lock(&lowpan_context_mutex);
if ((lowpan_iphc[1] & LOWPAN_IPHC_DAM) & 0x03) {
if ((lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAM) & 0x03) {
con = lowpan_context_num_lookup(dci);
}
@ -1296,7 +1410,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
return;
}
switch((lowpan_iphc[1] & LOWPAN_IPHC_DAM) & 0x03) {
switch ((lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAM) & 0x03) {
case (0x01): {
memcpy(&(ipv6_buf->destaddr.uint8[8]), &ipv6_hdr_fields[hdr_pos], 8);
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */
@ -1329,7 +1443,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
mutex_unlock(&lowpan_context_mutex);
}
else {
switch((lowpan_iphc[1] & LOWPAN_IPHC_DAM) & 0x03) {
switch ((lowpan_iphc[1] & SIXLOWPAN_IPHC2_DAM) & 0x03) {
case (0x01): {
memcpy(&(ipv6_buf->destaddr.uint8[0]), &ll_prefix[0], 2);
memset(&(ipv6_buf->destaddr.uint8[2]), 0, 6);
@ -1383,7 +1497,7 @@ void lowpan_context_remove(uint8_t num)
{
int i, j;
for (i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
for (i = 0; i < NDP_6LOWPAN_CONTEXT_MAX; i++) {
if (contexts[i].num == num) {
context_len--;
break;
@ -1392,7 +1506,7 @@ void lowpan_context_remove(uint8_t num)
abr_remove_context(num);
for (j = i; j < LOWPAN_CONTEXT_MAX; j++) {
for (j = i; j < NDP_6LOWPAN_CONTEXT_MAX; j++) {
contexts[j] = contexts[j + 1];
}
}
@ -1408,7 +1522,7 @@ lowpan_context_t *lowpan_context_update(uint8_t num, const ipv6_addr_t *prefix,
return NULL;
}
if (context_len == LOWPAN_CONTEXT_MAX) {
if (context_len == NDP_6LOWPAN_CONTEXT_MAX) {
return NULL;
}
@ -1441,7 +1555,7 @@ lowpan_context_t *lowpan_context_lookup(ipv6_addr_t *addr)
for (i = 0; i < lowpan_context_len(); i++) {
if (contexts[i].length > 0 && memcmp((void *)addr, &(contexts[i].prefix),
contexts[i].length) == 0) {
contexts[i].length) == 0) {
/* longer prefixes are always prefered */
if (context == NULL || context->length < contexts[i].length) {
context = &contexts[i];
@ -1469,7 +1583,7 @@ void lowpan_context_auto_remove(void)
{
timex_t minute = timex_set(60, 0);
int i;
int8_t to_remove[LOWPAN_CONTEXT_MAX];
int8_t to_remove[NDP_6LOWPAN_CONTEXT_MAX];
int8_t to_remove_size;
while (1) {
@ -1493,8 +1607,8 @@ void lowpan_context_auto_remove(void)
void init_reas_bufs(lowpan_reas_buf_t *buf)
{
memset(&buf->s_laddr, 0, SIXLOWPAN_IPV6_LL_ADDR_LEN);
memset(&buf->d_laddr, 0, SIXLOWPAN_IPV6_LL_ADDR_LEN);
memset(&buf->s_laddr, 0, IPV6_LL_ADDR_LEN);
memset(&buf->d_laddr, 0, IPV6_LL_ADDR_LEN);
buf->ident_no = 0;
buf->timestamp = 0;
buf->packet_size = 0;
@ -1504,19 +1618,20 @@ void init_reas_bufs(lowpan_reas_buf_t *buf)
buf->next = NULL;
}
void sixlowpan_init(transceiver_type_t trans, uint8_t r_addr, int as_border)
void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr,
int as_border)
{
ipv6_addr_t tmp;
short i;
/* init mac-layer and radio transceiver */
sixlowmac_init(trans);
sixlowpan_mac_init(trans);
/* init interface addresses */
memset(&iface, 0, sizeof(iface_t));
set_radio_address(r_addr);
init_802154_short_addr(&(iface.saddr));
init_802154_long_addr(&(iface.laddr));
/* init global buffer mutex */
mutex_init(&buf_mutex);
sixlowpan_mac_set_radio_address(r_addr);
sixlowpan_mac_init_802154_short_addr(&(iface.saddr));
sixlowpan_mac_init_802154_long_addr(&(iface.laddr));
/* init lowpan context mutex */
mutex_init(&lowpan_context_mutex);
@ -1527,20 +1642,20 @@ void sixlowpan_init(transceiver_type_t trans, uint8_t r_addr, int as_border)
local_address = r_addr;
/* init link-local address */
ipv6_set_ll_prefix(&lladdr);
ipv6_addr_set_link_local_prefix(&lladdr);
memcpy(&(lladdr.uint8[8]), &(iface.laddr.uint8[0]), 8);
ipv6_iface_add_addr(&lladdr, ADDR_STATE_PREFERRED, 0, 0,
ADDR_TYPE_LINK_LOCAL);
ipv6_set_loaddr(&tmp);
ipv6_iface_add_addr(&tmp, ADDR_STATE_PREFERRED, 0, 0,
ADDR_TYPE_LOOPBACK);
ipv6_set_all_nds_mcast_addr(&tmp);
ipv6_iface_add_addr(&tmp, ADDR_STATE_PREFERRED, 0, 0,
ADDR_TYPE_LOOPBACK);
ipv6_iface_add_addr(&lladdr, IPV6_ADDR_TYPE_LINK_LOCAL,
NDP_ADDR_STATE_PREFERRED, 0, 0);
ipv6_addr_set_loopback_addr(&tmp);
ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK,
NDP_ADDR_STATE_PREFERRED, 0, 0);
ipv6_addr_set_all_nodes_addr(&tmp);
ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK,
NDP_ADDR_STATE_PREFERRED, 0, 0);
ipv6_iface_add_addr(&lladdr, ADDR_STATE_PREFERRED, 0, 0,
ADDR_CONFIGURED_AUTO);
ipv6_iface_add_addr(&lladdr, IPV6_ADDR_TYPE_LINK_LOCAL,
NDP_ADDR_STATE_PREFERRED, 0, 0);
if (as_border) {
ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE,
@ -1563,14 +1678,29 @@ void sixlowpan_init(transceiver_type_t trans, uint8_t r_addr, int as_border)
transfer_pid = thread_create(lowpan_transfer_buf, LOWPAN_TRANSFER_BUF_STACKSIZE,
PRIORITY_MAIN - 1, CREATE_STACKTEST,
lowpan_transfer, "lowpan_transfer");
for (i = 0; i < SIXLOWIP_MAX_REGISTERED; i++) {
sixlowip_reg[i] = 0;
}
}
void sixlowpan_adhoc_init(transceiver_type_t trans, ipv6_addr_t *prefix,
uint8_t r_addr)
void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans,
const ipv6_addr_t *prefix,
uint8_t r_addr)
{
/* init network prefix */
ipv6_set_prefix(prefix, prefix);
plist_add(prefix, 64, OPT_PI_VLIFETIME_INFINITE, 0, 1, OPT_PI_FLAG_A);
ipv6_addr_t save_prefix;
ipv6_addr_init_prefix(&save_prefix, prefix, 64);
plist_add(&save_prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1,
ICMPV6_NDP_OPT_PI_FLAG_AUTONOM);
ipv6_init_iface_as_router();
sixlowpan_init(trans, r_addr, 0);
sixlowpan_lowpan_init(trans, r_addr, 0);
}
void sixlowpan_lowpan_bootstrapping(void)
{
icmpv6_send_router_sol(OPT_SLLAO);
}

View File

@ -0,0 +1,53 @@
/*
* 6LoWPAN constants, data structs, and prototypes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowpan.h
* @brief 6lowpan header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @author Eric Engel <eric.engel@fu-berlin.de>
*/
#ifndef _SIXLOWPAN_LOWPAN_H
#define _SIXLOWPAN_LOWPAN_H
#include "mutex.h"
#include "vtimer.h"
#include "sixlowpan/lowpan.h"
typedef struct {
uint8_t num;
ipv6_addr_t prefix;
uint8_t length;
uint8_t comp;
uint16_t lifetime;
} lowpan_context_t;
extern uint16_t local_address;
extern mutex_t lowpan_context_mutex;
void lowpan_read(uint8_t *data, uint8_t length,
ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
uint8_t lowpan_context_len(void);
lowpan_context_t *lowpan_context_update(uint8_t num,
const ipv6_addr_t *prefix,
uint8_t length, uint8_t comp,
uint16_t lifetime);
lowpan_context_t *lowpan_context_get(void);
lowpan_context_t *lowpan_context_num_lookup(uint8_t num);
/**
* @}
*/
#endif /* _SIXLOWPAN_LOWPAN_H */

View File

@ -9,8 +9,8 @@
*
* @ingroup sixlowpan
* @{
* @file sixlowmac.c
* @brief 6lowpan link layer functions
* @file sixlowmac.c
* @brief 6lowpan link layer functions
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
@ -21,26 +21,31 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include "sixlowmac.h"
#include "sixlowip.h"
#include "sixlownd.h"
#include "sixlowpan.h"
#include <ltc4150.h>
#include <hwtimer.h>
#include "ltc4150.h"
#include "hwtimer.h"
#include "thread.h"
#include "msg.h"
#include "radio/radio.h"
#include "transceiver.h"
#include "vtimer.h"
#include "ieee802154/ieee802154_frame.h"
#include "net_help/net_help.h"
#include "sixlowpan/mac.h"
#include "ip.h"
#include "icmp.h"
#include "lowpan.h"
#include "sys/net/ieee802154/ieee802154_frame.h"
#include "sys/net/net_help/net_help.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define RADIO_STACK_SIZE (MINIMUM_STACK_SIZE + 256)
#define RADIO_RCV_BUF_SIZE (64)
#define RADIO_SENDING_DELAY (1000)
char radio_stack_buffer[RADIO_STACK_SIZE];
msg_t msg_q[RADIO_RCV_BUF_SIZE];
@ -52,9 +57,8 @@ static radio_packet_t p;
static msg_t mesg;
int transceiver_type;
static transceiver_command_t tcmd;
uint16_t fragmentcounter = 0;
uint8_t get_radio_address(void)
uint8_t sixlowpan_mac_get_radio_address(void)
{
int16_t address;
@ -67,7 +71,7 @@ uint8_t get_radio_address(void)
return (uint8_t)address;
}
void set_radio_address(uint8_t addr)
void sixlowpan_mac_set_radio_address(uint8_t addr)
{
int16_t address = (int16_t)addr;
@ -97,18 +101,18 @@ void switch_to_rx(void)
msg_send(&mesg, transceiver_pid, 1);
}
void init_802154_short_addr(ieee_802154_short_t *saddr)
void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr)
{
saddr->uint8[0] = 0;
saddr->uint8[1] = get_radio_address();
saddr->uint8[1] = sixlowpan_mac_get_radio_address();
}
ieee_802154_long_t *mac_get_eui(ipv6_addr_t *ipaddr)
ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr)
{
return ((ieee_802154_long_t *) & (ipaddr->uint8[8]));
return ((ieee_802154_long_t *) &(ipaddr->uint8[8]));
}
void init_802154_long_addr(ieee_802154_long_t *laddr)
void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr)
{
// 16bit Pan-ID:16-zero-bits:16-bit-short-addr = 48bit
laddr->uint16[0] = IEEE_802154_PAN_ID;
@ -120,7 +124,7 @@ void init_802154_long_addr(ieee_802154_long_t *laddr)
laddr->uint8[4] = 0xFE;
laddr->uint8[5] = 0;
laddr->uint8[6] = 0;
laddr->uint8[7] = get_radio_address();
laddr->uint8[7] = sixlowpan_mac_get_radio_address();
}
void recv_ieee802154_frame(void)
@ -142,7 +146,6 @@ void recv_ieee802154_frame(void)
length = p->length - hdrlen;
/* deliver packet to network(6lowpan)-layer */
fragmentcounter++;
lowpan_read(frame.payload, length, (ieee_802154_long_t *)&frame.src_addr,
(ieee_802154_long_t *)&frame.dest_addr);
@ -180,8 +183,9 @@ void set_ieee802154_frame_values(ieee802154_frame_t *frame)
macdsn++;
}
void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
uint8_t length, uint8_t mcast)
void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr,
const uint8_t *payload,
uint8_t length, uint8_t mcast)
{
uint16_t daddr;
/* TODO: check if dedicated response struct is necessary */
@ -204,7 +208,7 @@ void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
memcpy(&(frame.src_addr[0]), &(iface.laddr.uint8[0]), 8);
daddr = HTONS(addr->uint16[3]);
frame.payload = payload;
frame.payload = (uint8_t *)payload; // payload won't be changed so cast is legal.
frame.payload_len = length;
uint8_t hdrlen = get_802154_hdr_len(&frame);
@ -213,9 +217,6 @@ void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
memcpy(&buf[hdrlen], frame.payload, frame.payload_len);
DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame->dest_pan_id, frame->src_pan_id, frame->seq_nr);
/* mutex unlock */
mutex_unlock(&buf_mutex);
p.length = hdrlen + frame.payload_len;
if (mcast == 0) {
@ -231,7 +232,7 @@ void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
hwtimer_wait(5000);
}
void sixlowmac_init(transceiver_type_t type)
void sixlowpan_mac_init(transceiver_type_t type)
{
int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE,
PRIORITY_MAIN - 2, CREATE_STACKTEST, recv_ieee802154_frame , "radio");

View File

@ -1,5 +1,5 @@
/**
* Semaphore implemenation
* Semaphore implemenation
*
* Copyright (C) 2013 INRIA.
*
@ -16,8 +16,6 @@
* @}
*/
#include <mutex.h>
#include "semaphore.h"
void sem_init(sem_t *sem, int8_t value)

View File

@ -16,11 +16,12 @@
* @}
*/
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
#ifndef _SIXLOWPAN_SEMAPHORE_H
#define _SIXLOWPAN_SEMAPHORE_H
#include <stdint.h>
#include <mutex.h>
#include "mutex.h"
typedef struct sem_t {
int8_t value;
@ -32,4 +33,4 @@ void sem_init(sem_t *sem, int8_t value);
int sem_wait(sem_t *sem);
int sem_signal(sem_t *sem);
#endif /* SEMAPHORE_H*/
#endif /* _SIXLOWPAN_SEMAPHORE_H*/

View File

@ -1,5 +1,5 @@
/**
* serial number arithmetics (corresponding RFC1982) for version field in ABRO
* serial number arithmetics (corresponding RFC1982) for version field in ABRO
*
* Copyright (C) 2013 INRIA.
*
@ -10,7 +10,7 @@
* @ingroup sixlowpan
* @{
* @file serialnumber.c
* @brief serial number arithmetics (corresponding RFC1982) for version field in ABRO
* @brief serial number arithmetics (corresponding RFC1982) for version field in ABRO
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @}

View File

@ -2,8 +2,8 @@
* Header file for serial number arithmetics [RFC1982]
*/
#ifndef SERIALNUMBER_H
#define SERIALNUMBER_H
#ifndef _SIXLOWPAN_SERIALNUMBER_H
#define _SIXLOWPAN_SERIALNUMBER_H
#include <stdint.h>
typedef enum serial_comp_res_t {
@ -79,4 +79,4 @@ serial_comp_res_t serial_comp16(uint16_t s1, uint16_t s2);
**/
serial_comp_res_t serial_comp32(uint32_t s1, uint32_t s2);
#endif /* SERIALNUMBER_H*/
#endif /* _SIXLOWPAN_SERIALNUMBER_H*/

View File

@ -1,16 +0,0 @@
#ifndef SIXLOWERROR_H
#define SIXLOWERROR_H
#define SUCCESS 0
#define SIXLOWERROR_ARRAYFULL 132 // array is full
#define SIXLOWERROR_NULLPTR 133 // null pointer error
#define SIXLOWERROR_VALUE 134 // illegal value
#define SIXLOWERROR_ADDRESS 135 // illegal address
#define SIXLOWERROR_DISPATCH 136 // lowpan dispatch unknown
#define SIXLOWERROR_FSTFRAG 137 // first lowpan fragment not received
#define SIXLOWERROR_INVFRAG 138 // invalid fragment received
#define SIXLOWERROR_SCI 139 // source context not found
#define SIXLOWERROR_DCI 140 // destination context not found
#define SIXLOWERROR_CSUM 141 // wrong checksum
#endif /* SIXLOWERROR_H*/

View File

@ -1,586 +0,0 @@
/**
* IPv6 implementation
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowip.c
* @brief 6lowpan IP layer functions
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
#include <stdio.h>
#include <string.h>
#include <vtimer.h>
#include <mutex.h>
#include "msg.h"
#include "sixlowip.h"
#include "sixlowmac.h"
#include "sixlownd.h"
#include "sixlowpan.h"
#include "sys/net/destiny/in.h"
#include "sys/net/destiny/socket.h"
#include "sys/net/net_help/net_help.h"
#include "sys/net/net_help/msg_help.h"
uint8_t ip_send_buffer[BUFFER_SIZE];
uint8_t buffer[BUFFER_SIZE];
msg_t msg_queue[IP_PKT_RECV_BUF_SIZE];
ipv6_hdr_t *ipv6_buf;
struct icmpv6_hdr_t *icmp_buf;
uint8_t *nextheader;
uint8_t iface_addr_list_count = 0;
int udp_packet_handler_pid = 0;
int tcp_packet_handler_pid = 0;
int rpl_process_pid = 0;
ipv6_hdr_t *get_ipv6_buf_send(void)
{
return ((ipv6_hdr_t *) & (ip_send_buffer[LL_HDR_LEN]));
}
uint8_t *get_payload_buf_send(uint8_t ext_len)
{
return &(ip_send_buffer[LLHDR_IPV6HDR_LEN + ext_len]);
}
ipv6_hdr_t *get_ipv6_buf(void)
{
return ((ipv6_hdr_t *)&(buffer[LL_HDR_LEN]));
}
struct icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len)
{
return ((struct icmpv6_hdr_t *) & (buffer[LLHDR_IPV6HDR_LEN + ext_len]));
}
uint8_t *get_payload_buf(uint8_t ext_len)
{
return &(buffer[LLHDR_IPV6HDR_LEN + ext_len]);
}
void sixlowpan_bootstrapping(void)
{
init_rtr_sol(OPT_SLLAO);
}
void sixlowpan_send(ipv6_addr_t *addr, uint8_t *payload, uint16_t p_len,
uint8_t next_header)
{
uint8_t *p_ptr;
if (next_header == IPPROTO_TCP) {
p_ptr = get_payload_buf_send(ipv6_ext_hdr_len);
ipv6_buf = get_ipv6_buf_send();
}
else {
ipv6_buf = get_ipv6_buf();
p_ptr = get_payload_buf(ipv6_ext_hdr_len);
}
icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
packet_length = 0;
ipv6_buf->version_trafficclass = IPV6_VER;
ipv6_buf->trafficclass_flowlabel = 0;
ipv6_buf->flowlabel = 0;
ipv6_buf->nextheader = next_header;
ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT;
ipv6_buf->length = p_len;
memcpy(&(ipv6_buf->destaddr), addr, 16);
ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));
memcpy(p_ptr, payload, p_len);
packet_length = IPV6_HDR_LEN + p_len;
lowpan_init((ieee_802154_long_t *)&(ipv6_buf->destaddr.uint16[4]),
(uint8_t *)ipv6_buf);
}
int icmpv6_demultiplex(const struct icmpv6_hdr_t *hdr)
{
switch(hdr->type) {
case (ICMP_RTR_SOL): {
puts("INFO: packet type: icmp router solicitation");
/* processing router solicitation */
recv_rtr_sol();
/* init solicited router advertisment*/
break;
}
case (ICMP_RTR_ADV): {
puts("INFO: packet type: icmp router advertisment");
/* processing router advertisment */
recv_rtr_adv();
/* init neighbor solicitation */
break;
}
case (ICMP_NBR_SOL): {
puts("INFO: packet type: icmp neighbor solicitation");
recv_nbr_sol();
break;
}
case (ICMP_NBR_ADV): {
puts("INFO: packet type: icmp neighbor advertisment");
recv_nbr_adv();
break;
}
case (ICMP_RPL_CONTROL): {
puts("INFO: packet type: RPL message");
if (rpl_process_pid != 0) {
msg_t m_send;
m_send.content.ptr = (char *) &hdr->code;
msg_send(&m_send, rpl_process_pid, 1);
}
else {
puts("INFO: no RPL handler registered");
}
break;
}
default:
return -1;
}
return 0;
}
void ipv6_process(void)
{
msg_t m_recv_lowpan, m_send_lowpan;
msg_t m_recv, m_send;
ipv6_addr_t myaddr;
ipv6_init_address(&myaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00,
get_radio_address());
while (1) {
msg_receive(&m_recv_lowpan);
ipv6_buf = (ipv6_hdr_t *)m_recv_lowpan.content.ptr;
/* identifiy packet */
nextheader = &ipv6_buf->nextheader;
if ((ipv6_get_addr_match(&myaddr, &ipv6_buf->destaddr) >= 112) &&
(ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) {
memcpy(get_ipv6_buf_send(), get_ipv6_buf(),
IPV6_HDR_LEN + ipv6_buf->length);
lowpan_init((ieee_802154_long_t *)&(ipv6_buf->destaddr.uint16[4]),
(uint8_t *)get_ipv6_buf_send());
}
else {
switch(*nextheader) {
case (PROTO_NUM_ICMPV6): {
/* checksum test*/
if (icmpv6_csum(PROTO_NUM_ICMPV6) != 0xffff) {
printf("ERROR: wrong checksum\n");
}
icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
icmpv6_demultiplex(icmp_buf);
break;
}
case (IPPROTO_TCP): {
if (tcp_packet_handler_pid != 0) {
m_send.content.ptr = (char *) ipv6_buf;
msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid);
}
else {
printf("INFO: No TCP handler registered.\n");
}
break;
}
case (IPPROTO_UDP): {
if (udp_packet_handler_pid != 0) {
m_send.content.ptr = (char *) ipv6_buf;
msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid);
}
else {
printf("INFO: No UDP handler registered.\n");
}
break;
}
case (PROTO_NUM_NONE): {
printf("INFO: Packet with no Header following the IPv6 Header received.\n");
break;
}
default:
break;
}
}
msg_reply(&m_recv_lowpan, &m_send_lowpan);
}
}
void ipv6_iface_add_addr(ipv6_addr_t *addr, uint8_t state, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t type)
{
if (ipv6_addr_unspec_match(addr) == 128) {
printf("ERROR: unspecified address (::) can't be assigned to interface.\n");
return;
}
if (ipv6_iface_addr_match(addr) != 0) {
return;
}
if (iface_addr_list_count < IFACE_ADDR_LIST_LEN) {
memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]),
&(addr->uint8[0]), 16);
iface.addr_list[iface_addr_list_count].state = state;
timex_t valtime = {val_ltime, 0};
timex_t preftime = {pref_ltime, 0};
timex_t now;
vtimer_now(&now);
iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime);
iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime);
iface.addr_list[iface_addr_list_count].type = type;
iface_addr_list_count++;
/* Register to Solicited-Node multicast address according to RFC 4291 */
if (type == ADDR_TYPE_ANYCAST || type == ADDR_TYPE_LINK_LOCAL ||
type == ADDR_TYPE_GLOBAL || type == ADDR_TYPE_UNICAST) {
ipv6_addr_t sol_node_mcast_addr;
ipv6_set_sol_node_mcast_addr(addr, &sol_node_mcast_addr);
if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) {
ipv6_iface_add_addr(&sol_node_mcast_addr, state, val_ltime, pref_ltime, ADDR_TYPE_SOL_NODE_MCAST);
}
}
}
}
addr_list_t *ipv6_iface_addr_match(ipv6_addr_t *addr)
{
int i;
for (i = 0; i < iface_addr_list_count; i++) {
if (memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]), 16) == 0) {
return &(iface.addr_list[i]);
}
}
return NULL;
}
addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr)
{
int i;
for (i = 0; i < iface_addr_list_count; i++) {
if (memcmp(&(iface.addr_list[i].addr.uint8[0]),
&(addr->uint8[0]), 8) == 0) {
return &(iface.addr_list[i]);
}
}
return NULL;
}
void ipv6_iface_print_addrs(void)
{
for (int i = 0; i < iface_addr_list_count; i++) {
ipv6_print_addr(&(iface.addr_list[i].addr));
}
}
void ipv6_init_addr_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix)
{
inout->uint16[0] = prefix->uint16[0];
inout->uint16[1] = prefix->uint16[1];
inout->uint16[2] = prefix->uint16[2];
inout->uint16[3] = prefix->uint16[3];
memcpy(&(inout->uint8[8]), &(iface.laddr.uint8[0]), 8);
}
void ipv6_set_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix)
{
inout->uint16[0] = prefix->uint16[0];
inout->uint16[1] = prefix->uint16[1];
inout->uint16[2] = prefix->uint16[2];
inout->uint16[3] = prefix->uint16[3];
inout->uint16[4] = 0;
inout->uint16[5] = 0;
inout->uint16[6] = 0;
inout->uint16[7] = 0;
}
void ipv6_set_all_rtrs_mcast_addr(ipv6_addr_t *ipaddr)
{
ipaddr->uint16[0] = HTONS(0xff02);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0002);
}
void ipv6_set_all_nds_mcast_addr(ipv6_addr_t *ipaddr)
{
ipaddr->uint16[0] = HTONS(0xff02);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0001);
}
void ipv6_set_loaddr(ipv6_addr_t *ipaddr)
{
ipaddr->uint16[0] = 0;
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
ipaddr->uint16[4] = 0;
ipaddr->uint16[5] = 0;
ipaddr->uint16[6] = 0;
ipaddr->uint16[7] = HTONS(0x0001);
}
void ipv6_get_saddr(ipv6_addr_t *src, ipv6_addr_t *dst)
{
/* try to find best match if dest is not mcast or link local */
int8_t itmp = -1;
uint8_t tmp = 0;
uint8_t bmatch = 0;
if (!(ipv6_prefix_ll_match(dst)) && !(ipv6_prefix_mcast_match(dst))) {
for (int i = 0; i < IFACE_ADDR_LIST_LEN; i++) {
if (iface.addr_list[i].state == ADDR_STATE_PREFERRED) {
if (!(ipv6_prefix_ll_match(&(iface.addr_list[i].addr)))) {
tmp = ipv6_get_addr_match(dst, &(iface.addr_list[i].addr));
if (tmp >= bmatch) {
bmatch = tmp;
itmp = i;
}
}
}
}
}
else {
for (int j = 0; j < IFACE_ADDR_LIST_LEN; j++) {
if ((iface.addr_list[j].state == ADDR_STATE_PREFERRED) &&
ipv6_prefix_ll_match(&(iface.addr_list[j].addr))) {
itmp = j;
}
}
}
if (itmp == -1) {
memset(src, 0, 16);
}
else {
memcpy(src, &(iface.addr_list[itmp].addr), 16);
}
}
uint8_t ipv6_get_addr_match(ipv6_addr_t *src, ipv6_addr_t *dst)
{
uint8_t val = 0, xor;
for (int i = 0; i < 16; i++) {
/* if bytes are equal add 8 */
if (src->uint8[i] == dst->uint8[i]) {
val += 8;
}
else {
xor = src->uint8[i] ^ dst->uint8[i];
/* while bits from byte equal add 1 */
for (int j = 0; j < 8; j++) {
if ((xor & 0x80) == 0) {
val++;
xor = xor << 1;
}
else {
break;
}
}
}
}
return val;
}
void ipv6_set_ll_prefix(ipv6_addr_t *ipaddr)
{
ipaddr->uint16[0] = HTONS(0xfe80);
ipaddr->uint16[1] = 0;
ipaddr->uint16[2] = 0;
ipaddr->uint16[3] = 0;
}
void ipv6_init_address(ipv6_addr_t *addr, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7)
{
addr->uint16[0] = HTONS(addr0);
addr->uint16[1] = HTONS(addr1);
addr->uint16[2] = HTONS(addr2);
addr->uint16[3] = HTONS(addr3);
addr->uint16[4] = HTONS(addr4);
addr->uint16[5] = HTONS(addr5);
addr->uint16[6] = HTONS(addr6);
addr->uint16[7] = HTONS(addr7);
}
uint8_t ipv6_prefix_ll_match(ipv6_addr_t *addr)
{
if (addr->uint8[0] == 0xfe && addr->uint8[1] == 0x80) {
return 1;
}
return 0;
}
uint8_t ipv6_prefix_mcast_match(ipv6_addr_t *addr)
{
if (addr->uint8[0] == 0xff && addr->uint8[1] == 0x02) {
return 1;
}
return 0;
}
uint8_t ipv6_addr_unspec_match(ipv6_addr_t *addr)
{
if ((addr->uint16[0] == 0) && (addr->uint16[1] == 0) &&
(addr->uint16[2] == 0) && (addr->uint16[3] == 0) &&
(addr->uint16[4] == 0) && (addr->uint16[5] == 0) &&
(addr->uint16[6] == 0) && (addr->uint16[7] == 0)) {
return 1;
}
return 0;
}
uint8_t ipv6_addr_sol_node_mcast_match(ipv6_addr_t *addr)
{
/* note: cool if-condition*/
if ((addr->uint8[0] == 0xFF) && (addr->uint8[1] == 0x02) &&
(addr->uint16[1] == 0x00) && (addr->uint16[2] == 0x00) &&
(addr->uint16[3] == 0x00) && (addr->uint16[4] == 0x00) &&
(addr->uint8[10] == 0x00) && (addr->uint8[11] == 0x01) &&
(addr->uint8[12] == 0xFF)) {
return 1;
}
return 0;
}
void ipv6_set_sol_node_mcast_addr(ipv6_addr_t *addr_in, ipv6_addr_t *addr_out)
{
/* copy only the last 24-bit of the ip-address that is beeing resolved */
addr_out->uint16[0] = HTONS(0xff02);
addr_out->uint16[1] = 0;
addr_out->uint16[2] = 0;
addr_out->uint16[3] = 0;
addr_out->uint16[4] = 0;
addr_out->uint16[5] = HTONS(0x0001);
addr_out->uint8[12] = 0xff;
addr_out->uint8[13] = addr_in->uint8[13];
addr_out->uint16[7] = addr_in->uint16[7];
}
void ipv6_print_addr(ipv6_addr_t *ipaddr)
{
printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
((uint8_t *)ipaddr)[0], ((uint8_t *)ipaddr)[1], ((uint8_t *)ipaddr)[2],
((uint8_t *)ipaddr)[3], ((uint8_t *)ipaddr)[4], ((uint8_t *)ipaddr)[5],
((uint8_t *)ipaddr)[6], ((uint8_t *)ipaddr)[7], ((uint8_t *)ipaddr)[8],
((uint8_t *)ipaddr)[9], ((uint8_t *)ipaddr)[10], ((uint8_t *)ipaddr)[11],
((uint8_t *)ipaddr)[12], ((uint8_t *)ipaddr)[13], ((uint8_t *)ipaddr)[14],
((uint8_t *)ipaddr)[15]);
}
uint8_t ipv6_next_hdr_unknown(uint8_t next_hdr)
{
return next_hdr == PROTO_NUM_ICMPV6 ||
next_hdr == PROTO_NUM_NONE;
}
uint32_t get_remaining_time(timex_t *t)
{
timex_t now;
vtimer_now(&now);
return (timex_sub(*t, now).seconds);
}
void set_remaining_time(timex_t *t, uint32_t time)
{
timex_t tmp = {time, 0};
timex_t now;
vtimer_now(&now);
*t = timex_add(now, tmp);
}
void ipv6_init_iface_as_router(void)
{
ipv6_addr_t addr;
ipv6_set_all_rtrs_mcast_addr(&addr);
ipv6_iface_add_addr(&addr, ADDR_STATE_PREFERRED, 0, 0, ADDR_TYPE_MULTICAST);
}
uint8_t ipv6_is_router(void)
{
ipv6_addr_t addr;
ipv6_set_all_rtrs_mcast_addr(&addr);
if (ipv6_iface_addr_match(&addr) != NULL) {
return 1;
}
return 0;
}
void set_tcp_packet_handler_pid(int pid)
{
tcp_packet_handler_pid = pid;
}
void set_udp_packet_handler_pid(int pid)
{
udp_packet_handler_pid = pid;
}
void set_rpl_process_pid(int pid)
{
rpl_process_pid = pid;
}

View File

@ -1,188 +0,0 @@
/**
* IPv6 constants, data structs, and prototypes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowip.h
* @brief 6lowpan IP layer header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
/* 6LoWPAN IP header file */
#ifndef SIXLOWIP_H
#define SIXLOWIP_H
#include <stdint.h>
#include <timex.h>
#include <mutex.h>
/* set maximum transmission unit */
#define MTU 256
/* IPv6 field values */
#define IPV6_VER 0x60
#define PROTO_NUM_ICMPV6 58
#define PROTO_NUM_NONE 59
#define ND_HOPLIMIT 0xFF
#define SIXLOWPAN_IPV6_LL_ADDR_LEN 8
/* size of global buffer */
#define BUFFER_SIZE (LL_HDR_LEN + MTU)
#define MULTIHOP_HOPLIMIT 64
#define IP_PKT_RECV_BUF_SIZE 64
#define DEBUGLINE printf("%s:%d\n",__FILE__,__LINE__)
/* extern variables */
extern uint8_t ipv6_ext_hdr_len;
extern uint8_t opt_hdr_len;
extern uint16_t packet_length;
extern uint8_t packet_dispatch;
extern uint8_t iface_addr_list_count;
extern mutex_t buf_mutex;
extern double start;
/* base header lengths */
#define LL_HDR_LEN 0x4
#define ICMPV6_HDR_LEN 0x4
#define IPV6_HDR_LEN 0x28
#define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN)
#define LLHDR_ICMPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN)
#define IPV6HDR_ICMPV6HDR_LEN (IPV6_HDR_LEN + ipv6_ext_hdr_len + ICMPV6_HDR_LEN)
#define IFACE_ADDR_LIST_LEN 10 // maybe to much
/* rfc 4862 section 2. address states */
#define ADDR_STATE_TENTATIVE 0
#define ADDR_STATE_PREFERRED 1
#define ADDR_STATE_DEPRECATED 2
/* addresses with this state are always permitted */
#define ADDR_STATE_ANY 4
/* how the address is configured */
#define ADDR_CONFIGURED_AUTO 1
#define ADDR_CONFIGURED_MANUAL 2
/* address types */
#define ADDR_TYPE_NONE 0
#define ADDR_TYPE_UNICAST 1
#define ADDR_TYPE_MULTICAST 2
#define ADDR_TYPE_ANYCAST 3
#define ADDR_TYPE_SOL_NODE_MCAST 4
#define ADDR_TYPE_LOOPBACK 5
#define ADDR_TYPE_LINK_LOCAL 6
#define ADDR_TYPE_GLOBAL 7
/* dispatch types */
#define DISPATCH_TYPE_IPV6 0x41
#define DISPATCH_TYPE_LOWPAN_HC1 0x42
/* compression types */
#define COMPRESSION_TYPE_NONE
/* buffer */
extern uint8_t buffer[BUFFER_SIZE];
/* ipv6 extension header length */
typedef union __attribute__((packed)) {
uint8_t uint8[16];
uint16_t uint16[8];
uint32_t uint32[4];
} ipv6_addr_t;
struct __attribute__((packed)) icmpv6_hdr_t {
uint8_t type;
uint8_t code;
uint16_t checksum;
};
typedef struct __attribute__((packed)) {
uint8_t version_trafficclass;
uint8_t trafficclass_flowlabel;
uint16_t flowlabel;
uint16_t length;
uint8_t nextheader;
uint8_t hoplimit;
ipv6_addr_t srcaddr;
ipv6_addr_t destaddr;
} ipv6_hdr_t;
/* link layer addressing */
typedef union __attribute__((packed)) {
uint8_t uint8[8];
uint16_t uint16[4];
} ieee_802154_long_t;
typedef union __attribute__((packed)) {
uint8_t uint8[2];
uint16_t uint16[1];
} ieee_802154_short_t;
typedef struct __attribute__((packed)) {
uint8_t state;
timex_t val_ltime;
timex_t pref_ltime;
uint8_t type;
ipv6_addr_t addr;
} addr_list_t;
typedef struct __attribute__((packed)) {
ieee_802154_short_t saddr;
ieee_802154_long_t laddr;
addr_list_t addr_list[IFACE_ADDR_LIST_LEN];
uint8_t adv_cur_hop_limit;
uint32_t adv_reachable_time;
uint32_t adv_retrans_timer;
} iface_t;
extern iface_t iface;
/* function prototypes */
struct icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len);
ipv6_hdr_t *get_ipv6_buf(void);
uint8_t *get_payload_buf(uint8_t ext_len);
uint8_t *get_payload_buf_send(uint8_t ext_len);
int icmpv6_demultiplex(const struct icmpv6_hdr_t *hdr);
void ipv6_init_iface_as_router(void);
uint8_t ipv6_is_router(void);
void ipv6_set_ll_prefix(ipv6_addr_t *ipaddr);
void ipv6_set_all_rtrs_mcast_addr(ipv6_addr_t *ipaddr);
void ipv6_set_all_nds_mcast_addr(ipv6_addr_t *ipaddr);
void ipv6_set_loaddr(ipv6_addr_t *ipaddr);
void ipv6_set_sol_node_mcast_addr(ipv6_addr_t *addr_in, ipv6_addr_t *addr_out);
void sixlowpan_bootstrapping(void);
void sixlowpan_send(ipv6_addr_t *addr, uint8_t *payload, uint16_t p_len, uint8_t next_header);
void ipv6_print_addr(ipv6_addr_t *ipaddr);
void ipv6_process(void);
void ipv6_get_saddr(ipv6_addr_t *src, ipv6_addr_t *dst);
uint8_t ipv6_get_addr_match(ipv6_addr_t *src, ipv6_addr_t *dst);
uint8_t ipv6_prefix_mcast_match(ipv6_addr_t *addr);
uint8_t ipv6_prefix_ll_match(ipv6_addr_t *addr);
void ipv6_iface_add_addr(ipv6_addr_t *addr, uint8_t state, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t type);
addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr);
addr_list_t *ipv6_iface_addr_match(ipv6_addr_t *addr);
void ipv6_iface_print_addrs(void);
void ipv6_init_addr_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix);
void ipv6_init_address(ipv6_addr_t *addr, uint16_t addr0, uint16_t addr1,
uint16_t addr2, uint16_t addr3, uint16_t addr4,
uint16_t addr5, uint16_t addr6, uint16_t addr7);
uint32_t get_remaining_time(timex_t *t);
void set_remaining_time(timex_t *t, uint32_t time);
void ipv6_set_prefix(ipv6_addr_t *inout, ipv6_addr_t *prefix);
uint8_t ipv6_addr_unspec_match(ipv6_addr_t *addr);
uint8_t ipv6_addr_sol_node_mcast_match(ipv6_addr_t *addr);
uint8_t ipv6_next_hdr_unrec(uint8_t next_hdr);
void set_tcp_packet_handler_pid(int pid);
void set_udp_packet_handler_pid(int pid);
void set_rpl_process_pid(int pid);
#endif /* SIXLOWIP_H*/

View File

@ -1,45 +0,0 @@
/*
* 6LoWPAN MAC - layer 2 prototypes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowmac.h
* @brief 6lowpan link layer functions
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
#ifndef SIXLOWMAC_H
#define SIXLOWMAC_H
#include <stdio.h>
#include <stdint.h>
#include "sixlowip.h"
#include "radio/radio.h"
#include <transceiver.h>
#define RADIO_STACK_SIZE (MINIMUM_STACK_SIZE + 256)
#define RADIO_RCV_BUF_SIZE (64)
#define RADIO_SENDING_DELAY (1000)
extern uint16_t fragmentcounter;
uint8_t get_radio_address(void);
void set_radio_address(uint8_t addr);
void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload,
uint8_t length, uint8_t mcast);
void init_802154_long_addr(ieee_802154_long_t *laddr);
void init_802154_short_addr(ieee_802154_short_t *saddr);
void sixlowmac_init(transceiver_type_t type);
ieee_802154_long_t *mac_get_eui(ipv6_addr_t *ipaddr);
#endif /* SIXLOWMAC_H*/

View File

@ -1,267 +0,0 @@
/*
* 6lowpan neighbor discovery
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlownd.h
* @brief 6lowpan neighbor discovery constants, data structs, and prototypes
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @}
*/
#ifndef SIXLOWND_H
#define SIXLOWND_H
#include <stdint.h>
#include "vtimer.h"
#include "sixlowpan.h"
#include "sixlowip.h"
/* parameter problem [rfc4443] */
#define PARA_PROB_LEN (8)
#define PARA_PROB_CODE_ERR (0) /* Erroneous header field encountered */
#define PARA_PROB_NXT_HDR_UNREC (1) /* Unrecognized Next Header type encountered */
#define PARA_PROB_IPV6_OPT_UNREC (2) /* Unrecognized IPv6 option encountered */
/* router solicitation */
#define RTR_SOL_LEN (4)
#define RTR_SOL_INTERVAL (4)
#define RTR_SOL_MAX (3)
/* router advertisment */
#define RTR_ADV_M_FLAG (0)
#define RTR_ADV_O_FLAG (0)
#define RTR_ADV_MAX (3)
#define RTR_ADV_MAX_INTERVAL (600)
#define RTR_ADV_LEN (12)
/* neighbour solicitation */
#define NBR_SOL_LEN (20)
/* neighbour advertisement */
#define NBR_ADV_LEN (20)
#define NBR_ADV_FLAG_R (0x80)
#define NBR_ADV_FLAG_S (0x40)
#define NBR_ADV_FLAG_O (0x20)
/* stllao option rfc4861 4.6.1 */
#define OPT_STLLAO_MIN_LEN (8)
#define OPT_STLLAO_MAX_LEN (16)
#define OPT_SLLAO_TYPE (1)
#define OPT_TLLAO_TYPE (2)
/* prefix info option rfc 4.6.2 */
#define OPT_PI_LIST_LEN (5) //TODO: initalwert suchen
#define OPT_PI_TYPE (3)
#define OPT_PI_LEN (4)
#define OPT_PI_HDR_LEN (32)
#define OPT_PI_FLAG_A (0x40)
#define OPT_PI_FLAG_L (0x80)
#define OPT_PI_VLIFETIME_INFINITE (0xffffffff)
/* mtu option rfc4861 4.6.4 */
#define OPT_MTU_TYPE (5)
#define OPT_MTU_LEN (1)
#define OPT_MTU_HDR_LEN (8)
/* aro - address registration option draft-ietf-6lowpan-nd-14 4.2 */
#define OPT_ARO_TYPE (31) /* TBD1 */
#define OPT_ARO_LEN (2)
#define OPT_ARO_HDR_LEN (16)
#define OPT_ARO_LTIME (300) /* geeigneten wert finden */
#define OPT_ARO_STATE_SUCCESS (0)
#define OPT_ARO_STATE_DUP_ADDR (1)
#define OPT_ARO_STATE_NBR_CACHE_FULL (2)
/* 6lowpan context option */
#define OPT_6CO_TYPE (32)
#define OPT_6CO_MIN_LEN (2)
#define OPT_6CO_MAX_LEN (3)
#define OPT_6CO_HDR_LEN (8)
#define OPT_6CO_LTIME (5) /* geeigneten Wert finden */
#define OPT_6CO_FLAG_C (0x10)
#define OPT_6CO_FLAG_CID (0x0F)
#define OPT_6CO_FLAG_C_VALUE_SET (1)
#define OPT_6CO_FLAG_C_VALUE_UNSET (0)
/* authoritative border router option */
#define OPT_ABRO_TYPE (33)
#define OPT_ABRO_LEN (3)
#define OPT_ABRO_HDR_LEN (24)
/* authoritive border router cache size */
#define ABR_CACHE_SIZE (2)
/* neighbor cache size */
#define NBR_CACHE_SIZE (8)
#define NBR_CACHE_TYPE_GC (1)
#define NBR_CACHE_TYPE_REG (2)
#define NBR_CACHE_TYPE_TEN (3)
#define NBR_CACHE_LTIME_TEN (20)
/* neighbor status values */
#define NBR_STATUS_INCOMPLETE (0)
#define NBR_STATUS_REACHABLE (1)
#define NBR_STATUS_STALE (2)
#define NBR_STATUS_DELAY (3)
#define NBR_STATUS_PROBE (4)
/* default router list size */
#define DEF_RTR_LST_SIZE (3) /* geeigneten wert finden */
extern unsigned int nd_nbr_cache_rem_pid;
enum option_types_t {
OPT_SLLAO = 1,
OPT_TLLAO,
OPT_PI,
OPT_MTU,
OPT_ARO,
OPT_6CO,
OPT_ABRO,
OPT_DAR,
OPT_DAC,
};
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
} opt_buf_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
} opt_stllao_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
uint16_t reserved;
uint32_t mtu;
} opt_mtu_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
uint8_t prefix_length;
uint8_t l_a_reserved1;
uint32_t val_ltime;
uint32_t pref_ltime;
uint32_t reserved2;
ipv6_addr_t addr;
} opt_pi_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
uint8_t status;
uint8_t reserved1;
uint16_t reserved2;
uint16_t reg_ltime;
ieee_802154_long_t eui64;
} opt_aro_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
uint8_t c_length;
uint8_t c_flags;
uint16_t reserved;
uint16_t val_ltime;
} opt_6co_hdr_t;
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t length;
uint16_t version;
uint32_t reserved;
ipv6_addr_t addr;
} opt_abro_t;
typedef struct __attribute__((packed)) {
uint8_t inuse;
uint8_t adv;
ipv6_addr_t addr;
uint8_t length;
uint8_t l_a_reserved1;
uint32_t val_ltime;
uint32_t pref_ltime;
uint8_t infinite;
} plist_t;
struct __attribute__((packed)) rtr_adv_t {
uint8_t hoplimit;
uint8_t autoconfig_flags;
uint16_t router_lifetime;
uint32_t reachable_time;
uint32_t retrans_timer;
};
struct __attribute__((packed)) nbr_sol_t {
uint32_t reserved;
ipv6_addr_t tgtaddr;
};
struct __attribute__((packed)) nbr_adv_t {
uint8_t rso;
uint8_t reserved[3];
ipv6_addr_t tgtaddr;
};
struct __attribute__((packed)) para_prob_t {
uint8_t pointer;
};
/* authoritive border router cache - draft-draft-ietf-6lowpan-nd-17 */
typedef struct __attribute__((packed)) abr_cache_t {
uint16_t version;
ipv6_addr_t abr_addr;
uint8_t cids[LOWPAN_CONTEXT_MAX];
} abr_cache_t;
/* neighbor cache - rfc4861 5.1. */
typedef struct __attribute__((packed)) {
uint8_t type;
uint8_t state;
uint8_t isrouter;
ipv6_addr_t addr;
ieee_802154_long_t laddr;
ieee_802154_short_t saddr;
timex_t ltime;
} nbr_cache_t;
/* default router list - rfc4861 5.1. */
typedef struct __attribute__((packed)) {
ipv6_addr_t addr;
timex_t inval_time;
} def_rtr_lst_t;
void init_rtr_sol(uint8_t sllao);
void recv_rtr_sol(void);
void recv_rtr_adv(void);
void init_rtr_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi,
uint8_t sixco, uint8_t abro);
uint8_t plist_search(ipv6_addr_t *addr);
uint8_t plist_cmp(ipv6_addr_t *addr1, ipv6_addr_t *addr2);
int8_t plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime,
uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1);
void set_llao(opt_stllao_t *sllao, uint8_t type, uint8_t length);
abr_cache_t *abr_get_version(uint16_t version, ipv6_addr_t *abr_addr);
abr_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr,
uint8_t cid);
void abr_remove_context(uint8_t cid);
nbr_cache_t *nbr_cache_search(ipv6_addr_t *ipaddr);
uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr,
uint8_t isrouter, uint8_t state, uint8_t type,
uint16_t ltime, ieee_802154_short_t *saddr);
void nbr_cache_auto_rem(void);
void nbr_cache_rem(ipv6_addr_t *addr);
uint16_t icmpv6_csum(uint8_t proto);
def_rtr_lst_t *def_rtr_lst_search(ipv6_addr_t *ipaddr);
void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime);
void def_rtr_lst_rem(def_rtr_lst_t *entry);
void init_para_prob(ipv6_addr_t *src, ipv6_addr_t *dest, uint8_t code,
uint32_t pointer, uint8_t *packet, uint8_t packet_len);
void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ,
uint8_t slloa, uint8_t aro);
void init_nbr_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt,
uint8_t rso, uint8_t sllao, uint8_t aro, uint8_t aro_state);
void recv_nbr_adv(void);
void recv_nbr_sol(void);
#endif /* SIXLOWND_H*/

View File

@ -1,144 +0,0 @@
/*
* 6lowpan constants, data structs, and prototypes
*
* Copyright (C) 2013 INRIA.
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License. See the file LICENSE in the top level directory for more
* details.
*
* @ingroup sixlowpan
* @{
* @file sixlowpan.h
* @brief 6lowpan header
* @author Stephan Zeisberg <zeisberg@mi.fu-berlin.de>
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
* @author Oliver Gesch <oliver.gesch@googlemail.com>
* @author Eric Engel <eric.engel@fu-berlin.de>
* @}
*/
#ifndef SIXLOWPAN_H
#define SIXLOWPAN_H
#define IP_PROCESS_STACKSIZE (3072)
#define NC_STACKSIZE (512)
#define CON_STACKSIZE (512)
#define LOWPAN_TRANSFER_BUF_STACKSIZE (512)
/* fragment size in bytes*/
#define FRAG_PART_ONE_HDR_LEN (4)
#define FRAG_PART_N_HDR_LEN (5)
#define LOWPAN_IPHC_DISPATCH (0x60)
#define LOWPAN_IPHC_FL_C (0x10)
#define LOWPAN_IPHC_TC_C (0x08)
#define LOWPAN_IPHC_CID (0x80)
#define LOWPAN_IPHC_SAC (0x40)
#define LOWPAN_IPHC_SAM (0x30)
#define LOWPAN_IPHC_DAC (0x04)
#define LOWPAN_IPHC_DAM (0x03)
#define LOWPAN_IPHC_M (0x08)
#define LOWPAN_IPHC_NH (0x04)
#define LOWPAN_IPV6_DISPATCH (0x41)
#define LOWPAN_CONTEXT_MAX (16)
#define LOWPAN_REAS_BUF_TIMEOUT (15 * 1000 * 1000) /* TODO: Set back to 3 * 1000 * (1000) */
/* icmp message types rfc4443 */
#define ICMP_PARA_PROB (4)
/* icmp message types rfc4861 4.*/
#define ICMP_RTR_ADV (134)
#define ICMP_RTR_SOL (133)
#define ICMP_NBR_ADV (136)
#define ICMP_NBR_SOL (135)
#define ICMP_REDIRECT (137) /* will be filtered out by the border router */
#define ICMP_RPL_CONTROL (155)
#include "transceiver.h"
#include "sixlowip.h"
#include "vtimer.h"
#include "mutex.h"
extern mutex_t lowpan_context_mutex;
extern uint16_t local_address;
typedef struct {
uint8_t num;
ipv6_addr_t prefix;
uint8_t length;
uint8_t comp;
uint16_t lifetime;
} lowpan_context_t;
typedef struct lowpan_interval_list_t {
uint8_t start;
uint8_t end;
struct lowpan_interval_list_t *next;
} lowpan_interval_list_t;
typedef struct lowpan_reas_buf_t {
/* Source Address */
ieee_802154_long_t s_laddr;
/* Destination Address */
ieee_802154_long_t d_laddr;
/* Identification Number */
uint16_t ident_no;
/* Timestamp of last packet fragment */
long timestamp;
/* Size of reassembled packet with possible IPHC header */
uint16_t packet_size;
/* Additive size of currently already received fragments */
uint16_t current_packet_size;
/* Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte */
uint8_t *packet;
/* Pointer to list of intervals of received packet fragments (if any) */
lowpan_interval_list_t *interval_list_head;
/* Pointer to next reassembly buffer (if any) */
struct lowpan_reas_buf_t *next;
} lowpan_reas_buf_t;
extern lowpan_reas_buf_t *head;
/**
* @brief Initializes 6lowpan
*
* @param[in] trans transceiver to use with 6lowpan
* @param[in] r_addr phy layer address
* @param[in] as_border 1 if node shoud act as border router, 0 otherwise
*/
void sixlowpan_init(transceiver_type_t trans, uint8_t r_addr, int as_border);
/**
* @brief Initializes a 6lowpan router with address prefix
*
* @param[in] trans transceiver to use with 6lowpan
* @param[in] prefix the address prefix to advertise
* @param[in] r_addr phy layer address
*/
void sixlowpan_adhoc_init(transceiver_type_t trans, ipv6_addr_t *prefix,
uint8_t r_addr);
void lowpan_init(ieee_802154_long_t *addr, uint8_t *data);
void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr);
void lowpan_iphc_decoding(uint8_t *data, uint8_t length,
ieee_802154_long_t *s_laddr,
ieee_802154_long_t *d_laddr);
uint8_t lowpan_context_len(void);
void add_fifo_packet(lowpan_reas_buf_t *current_packet);
lowpan_context_t *lowpan_context_update(
uint8_t num, const ipv6_addr_t *prefix,
uint8_t length, uint8_t comp,
uint16_t lifetime);
lowpan_context_t *lowpan_context_get(void);
lowpan_context_t *lowpan_context_lookup(ipv6_addr_t *addr);
lowpan_context_t *lowpan_context_num_lookup(uint8_t num);
lowpan_reas_buf_t *collect_garbage_fifo(lowpan_reas_buf_t *current_buf);
lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf);
void check_timeout(void);
void lowpan_ipv6_set_dispatch(uint8_t *data);
void init_reas_bufs(lowpan_reas_buf_t *buf);
void printReasBuffers(void);
void printFIFOBuffers(void);
#endif