use dynamic sleep for loop

ico
Harald Pichler 2016-01-06 21:57:29 +01:00
commit 428131e8a8
945 changed files with 110944 additions and 45586 deletions

14
.gitattributes vendored Normal file
View File

@ -0,0 +1,14 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto whitespace=trailing-space
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
*.java text
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.ihex binary
*.s37 binary

37
.gitignore vendored
View File

@ -4,6 +4,7 @@
*.png
*.log
*.elf
*.zip
*.d
*.ihex
*.pyc
@ -24,12 +25,15 @@
*.c128
*.c64
*.cc2538dk
*.remote
*.zoul
*.jn516x
*.srf06-cc26xx
*.ev-aducrf101mkxz
*.report
summary
*.summary
*.runerr
*.runlog
*.faillog
*.orig
*~
@ -38,6 +42,7 @@ obj_*
symbols.*
Makefile.target
doc/html
doc/latex
patches-*
tools/tunslip
tools/tunslip6
@ -86,9 +91,39 @@ contiki-cc2530dk.lib
*.d71
*.d81
# Cooja Build Artifacts
*.cooja
#regression tests artifacts
*.testlog
*.log.prog
regression-tests/[0-9][0-9]-*/report
regression-tests/[0-9][0-9]-*/org/
# rl78 build artifacts
*.eval-adf7xxxmb4z
*.eval-adf7xxxmb4z.srec
# cscope files
cscope.*
# vim swap files
*.swp
*.swo
# x86 UEFI files
cpu/x86/uefi/Makefile.uefi
cpu/x86/uefi/edk2
# galileo bsp files
platform/galileo/bsp/libc/Makefile.libc
platform/galileo/bsp/libc/i586-elf/
platform/galileo/bsp/libc/newlib-2.2.0-1*
platform/galileo/bsp/grub/src/
platform/galileo/bsp/grub/bin/
# galileo build and debug artefacts
*.galileo
*.galileo.dll
*.galileo.efi
LOG_OPENOCD

5
.gitmodules vendored
View File

@ -11,6 +11,9 @@
path = cpu/cc26xx-cc13xx/lib/cc26xxware
url = https://github.com/g-oikonomou/cc26xxware.git
[submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"]
path = cpu/cc26xx-cc13xx/lib/cc13xxware
path = cpu/cc26xx-c../.gitmodulesc13xx/lib/cc13xxware
url = https://github.com/g-oikonomou/cc13xxware.git
[submodule "platform/stm32nucleo-spirit1/stm32cube-lib"]
path = platform/stm32nucleo-spirit1/stm32cube-lib
url = https://github.com/STclab/stm32nucleo-spirit1-lib

View File

@ -17,7 +17,7 @@ before_script:
## Install msp430 toolchain
- sudo apt-get -qq install lib32z1
- $WGET http://adamdunkels.github.io/contiki-fork/mspgcc-4.7.0-compiled.tar.bz2 &&
- $WGET http://simonduq.github.io/resources/mspgcc-4.7.2-compiled.tar.bz2 &&
tar xjf mspgcc*.tar.bz2 -C /tmp/ &&
sudo cp -f -r /tmp/msp430/* /usr/local/ &&
rm -rf /tmp/msp430 mspgcc*.tar.bz2 &&
@ -36,6 +36,7 @@ before_script:
tar xjf arm-2008q3*.tar.bz2 -C /tmp/ &&
sudo cp -f -r /tmp/arm-2008q3/* /usr/ &&
rm -rf /tmp/arm-2008q3 arm-2008q3*.tar.bz2 &&
sudo apt-get -qq install libconfig-dev uuid-dev libqrencode-dev &&
arm-none-eabi-gcc --version ;
fi
@ -73,6 +74,22 @@ before_script:
cc65 --version ;
fi
## Install NXP toolchain
- if [ ${BUILD_ARCH:-0} = jn516x ] ; then
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 &&
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 &&
$WGET http://simonduq.github.io/resources/jn516x-sdk-4163.tar.bz2 &&
mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc &&
tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk &&
tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc &&
tar xjf ba-elf-gcc-*part2.tar.bz2 -C /tmp/ba-elf-gcc &&
sudo cp -f -r /tmp/jn516x-sdk /usr/ &&
sudo cp -f -r /tmp/ba-elf-gcc /usr/ &&
export PATH=/usr/ba-elf-gcc/bin:$PATH &&
rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* &&
ba-elf-gcc --version ;
fi
## Compile cooja.jar only when it's going to be needed
- if [ ${BUILD_CATEGORY:-sim} = sim ] ; then
java -version &&
@ -103,6 +120,7 @@ env:
- BUILD_TYPE='collect'
- BUILD_TYPE='collect-lossy'
- BUILD_TYPE='rpl'
- BUILD_TYPE='large-rpl'
- BUILD_TYPE='rime'
- BUILD_TYPE='ipv6'
- BUILD_TYPE='ip64' MAKE_TARGETS='cooja'
@ -119,5 +137,6 @@ env:
- BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs'
- BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502'
- BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs'
- BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x'
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja'

View File

@ -24,7 +24,7 @@ static char send_udp = 0;
static const char *prompt = "contiki> ";
/*---------------------------------------------------------------------------*/
static char * CC_FASTCALL
static char *
n(uint16_t num, char *ptr)
{
uint16_t d;

View File

@ -0,0 +1,10 @@
codeprop-tmp_src = codeprop-tmp.c
# Enable LARGE MEMORY MODEL supports for WISMOTE and EXP5438 platform
ifeq ($(TARGET),wismote)
TARGET_MEMORY_MODEL = large
endif
ifeq ($(TARGET),exp5438)
TARGET_MEMORY_MODEL = large
endif

View File

@ -58,9 +58,9 @@ LIST(observers_list);
/*---------------------------------------------------------------------------*/
/*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
coap_observer_t *
coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
size_t token_len, const char *uri)
static coap_observer_t *
add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
size_t token_len, const char *uri, int uri_len)
{
/* Remove existing observe relationship, if any. */
coap_remove_observer_by_uri(addr, port, uri);
@ -68,7 +68,12 @@ coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token,
coap_observer_t *o = memb_alloc(&observers_memb);
if(o) {
o->url = uri;
int max = sizeof(o->url) - 1;
if(max > uri_len) {
max = uri_len;
}
memcpy(o->url, uri, max);
o->url[max] = 0;
uip_ipaddr_copy(&o->addr, addr);
o->port = port;
o->token_len = token_len;
@ -177,18 +182,47 @@ coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port, uint16_t mid)
/*---------------------------------------------------------------------------*/
void
coap_notify_observers(resource_t *resource)
{
coap_notify_observers_sub(resource, NULL);
}
void
coap_notify_observers_sub(resource_t *resource, const char *subpath)
{
/* build notification */
coap_packet_t notification[1]; /* this way the packet can be treated as pointer as usual */
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
coap_packet_t request[1]; /* this way the packet can be treated as pointer as usual */
coap_observer_t *obs = NULL;
int url_len, obs_url_len;
char url[COAP_OBSERVER_URL_LEN];
PRINTF("Observe: Notification from %s\n", resource->url);
url_len = strlen(resource->url);
strncpy(url, resource->url, COAP_OBSERVER_URL_LEN - 1);
if(url_len < COAP_OBSERVER_URL_LEN - 1 && subpath != NULL) {
strncpy(&url[url_len], subpath, COAP_OBSERVER_URL_LEN - url_len - 1);
}
/* Ensure url is null terminated because strncpy does not guarantee this */
url[COAP_OBSERVER_URL_LEN - 1] = '\0';
/* url now contains the notify URL that needs to match the observer */
PRINTF("Observe: Notification from %s\n", url);
coap_init_message(notification, COAP_TYPE_NON, CONTENT_2_05, 0);
/* create a "fake" request for the URI */
coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0);
coap_set_header_uri_path(request, url);
/* iterate over observers */
url_len = strlen(url);
for(obs = (coap_observer_t *)list_head(observers_list); obs;
obs = obs->next) {
if(obs->url == resource->url) { /* using RESOURCE url pointer as handle */
obs_url_len = strlen(obs->url);
/* Do a match based on the parent/sub-resource match so that it is
possible to do parent-node observe */
if((obs_url_len == url_len
|| (obs_url_len > url_len
&& (resource->flags & HAS_SUB_RESOURCES)
&& obs->url[url_len] == '/'))
&& strncmp(url, obs->url, url_len) == 0) {
coap_transaction_t *transaction = NULL;
/*TODO implement special transaction for CON, sharing the same buffer to allow for more observers */
@ -209,7 +243,7 @@ coap_notify_observers(resource_t *resource)
/* prepare response */
notification->mid = transaction->mid;
resource->get_handler(NULL, notification,
resource->get_handler(request, notification,
transaction->packet + COAP_MAX_HEADER_SIZE,
REST_MAX_CHUNK_SIZE, NULL);
@ -234,14 +268,12 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
coap_packet_t *const coap_res = (coap_packet_t *)response;
coap_observer_t * obs;
static char content[16];
if(coap_req->code == COAP_GET && coap_res->code < 128) { /* GET request and response without error code */
if(IS_OPTION(coap_req, COAP_OPTION_OBSERVE)) {
if(coap_req->observe == 0) {
obs = coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
coap_req->token, coap_req->token_len,
resource->url);
obs = add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport,
coap_req->token, coap_req->token_len,
coap_req->uri_path, coap_req->uri_path_len);
if(obs) {
coap_set_header_observe(coap_res, (obs->obs_counter)++);
/*
@ -249,13 +281,14 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
* A subscription should return the same representation as a normal GET.
* Uncomment if you want an information about the avaiable observers.
*/
/*
* coap_set_payload(coap_res,
* content,
* snprintf(content, sizeof(content), "Added %u/%u",
* list_length(observers_list),
* COAP_MAX_OBSERVERS));
*/
#if 0
static char content[16];
coap_set_payload(coap_res,
content,
snprintf(content, sizeof(content), "Added %u/%u",
list_length(observers_list),
COAP_MAX_OBSERVERS));
#endif
} else {
coap_res->code = SERVICE_UNAVAILABLE_5_03;
coap_set_payload(coap_res, "TooManyObservers", 16);

View File

@ -43,6 +43,8 @@
#include "er-coap-transactions.h"
#include "stimer.h"
#define COAP_OBSERVER_URL_LEN 20
typedef struct coap_observable {
uint32_t observe_clock;
struct stimer orphan_timer;
@ -54,7 +56,7 @@ typedef struct coap_observable {
typedef struct coap_observer {
struct coap_observer *next; /* for LIST */
const char *url;
char url[COAP_OBSERVER_URL_LEN];
uip_ipaddr_t addr;
uint16_t port;
uint8_t token_len;
@ -68,11 +70,6 @@ typedef struct coap_observer {
} coap_observer_t;
list_t coap_get_observers(void);
coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port,
const uint8_t *token, size_t token_len,
const char *url);
void coap_remove_observer(coap_observer_t *o);
int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port);
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port,
@ -83,6 +80,7 @@ int coap_remove_observer_by_mid(uip_ipaddr_t *addr, uint16_t port,
uint16_t mid);
void coap_notify_observers(resource_t *resource);
void coap_notify_observers_sub(resource_t *resource, const char *subpath);
void coap_observe_handler(resource_t *resource, void *request,
void *response);

View File

@ -124,7 +124,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
continue;
}
end = attrib + strlen(attrib);
} else {
} else if(resource->attributes != NULL) {
attrib = strstr(resource->attributes, filter);
if(attrib == NULL
|| (attrib[strlen(filter)] != '='
@ -159,8 +159,8 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
}
#endif
PRINTF("res: /%s (%p)\npos: s%d, o%ld, b%d\n", resource->url, resource,
strpos, *offset, bufpos);
PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource,
strpos, (long)*offset, bufpos);
if(strpos > 0) {
ADD_CHAR_IF_POSSIBLE(',');
@ -170,7 +170,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
ADD_STRING_IF_POSSIBLE(resource->url, >=);
ADD_CHAR_IF_POSSIBLE('>');
if(resource->attributes[0]) {
if(resource->attributes != NULL && resource->attributes[0]) {
ADD_CHAR_IF_POSSIBLE(';');
ADD_STRING_IF_POSSIBLE(resource->attributes, >);
}
@ -183,7 +183,7 @@ well_known_core_get_handler(void *request, void *response, uint8_t *buffer,
}
if(bufpos > 0) {
PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *)buffer);
PRINTF("BUF %zu: %.*s\n", bufpos, (int)bufpos, (char *)buffer);
coap_set_payload(response, buffer, bufpos);
coap_set_header_content_format(response, APPLICATION_LINK_FORMAT);

View File

@ -113,15 +113,9 @@ coap_send_transaction(coap_transaction_t *t)
(float)t->retrans_timer.timer.interval / CLOCK_SECOND);
}
/*FIXME
* Hack: Setting timer for responsible process.
* Maybe there is a better way, but avoid posting everything to the process.
*/
struct process *process_actual = PROCESS_CURRENT();
process_current = transaction_handler_process;
PROCESS_CONTEXT_BEGIN(transaction_handler_process);
etimer_restart(&t->retrans_timer); /* interval updated above */
process_current = process_actual;
PROCESS_CONTEXT_END(transaction_handler_process);
t = NULL;
} else {

View File

@ -113,19 +113,21 @@ coap_set_option_header(unsigned int delta, size_t length, uint8_t *buffer)
buffer[0] = coap_option_nibble(delta) << 4 | coap_option_nibble(length);
/* avoids code duplication without function overhead */
unsigned int *x = &delta;
if(delta > 268) {
buffer[++written] = ((delta - 269) >> 8) & 0xff;
buffer[++written] = (delta - 269) & 0xff;
} else if(delta > 12) {
buffer[++written] = (delta - 13);
}
do {
if(*x > 268) {
buffer[++written] = (*x - 269) >> 8;
buffer[++written] = (*x - 269);
} else if(*x > 12) {
buffer[++written] = (*x - 13);
}
} while(x != &length && (x = &length));
if(length > 268) {
buffer[++written] = ((length - 269) >> 8) & 0xff;
buffer[++written] = (length - 269) & 0xff;
} else if(length > 12) {
buffer[++written] = (length - 13);
}
PRINTF("WRITTEN %u B opt header\n", 1 + written);
PRINTF("WRITTEN %zu B opt header\n", 1 + written);
return ++written;
}
@ -148,7 +150,7 @@ coap_serialize_int_option(unsigned int number, unsigned int current_number,
if(0xFFFFFFFF & value) {
++i;
}
PRINTF("OPTION %u (delta %u, len %u)\n", number, number - current_number,
PRINTF("OPTION %u (delta %u, len %zu)\n", number, number - current_number,
i);
i = coap_set_option_header(number - current_number, i, buffer);
@ -175,8 +177,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
{
size_t i = 0;
PRINTF("ARRAY type %u, len %u, full [%.*s]\n", number, length, length,
array);
PRINTF("ARRAY type %u, len %zu, full [%.*s]\n", number, length,
(int)length, array);
if(split_char != '\0') {
int j;
@ -185,7 +187,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
size_t temp_length;
for(j = 0; j <= length + 1; ++j) {
PRINTF("STEP %u/%u (%c)\n", j, length, array[j]);
PRINTF("STEP %u/%zu (%c)\n", j, length, array[j]);
if(array[j] == split_char || j == length) {
part_end = array + j;
temp_length = part_end - part_start;
@ -195,8 +197,8 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
memcpy(&buffer[i], part_start, temp_length);
i += temp_length;
PRINTF("OPTION type %u, delta %u, len %u, part [%.*s]\n", number,
number - current_number, i, temp_length, part_start);
PRINTF("OPTION type %u, delta %u, len %zu, part [%.*s]\n", number,
number - current_number, i, (int)temp_length, part_start);
++j; /* skip the splitter */
current_number = number;
@ -208,7 +210,7 @@ coap_serialize_array_option(unsigned int number, unsigned int current_number,
memcpy(&buffer[i], array, length);
i += length;
PRINTF("OPTION type %u, delta %u, len %u\n", number,
PRINTF("OPTION type %u, delta %u, len %zu\n", number,
number - current_number, length);
}
@ -332,7 +334,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
/* empty packet, dont need to do more stuff */
if(!coap_pkt->code) {
PRINTF("-Done serializing empty message at %p-\n", option);
PRINTF("-Done serializing empty message at %p-\n", coap_pkt->buffer);
return 4;
}
@ -368,6 +370,7 @@ coap_serialize_message(void *packet, uint8_t *buffer)
"Location-Path");
COAP_SERIALIZE_STRING_OPTION(COAP_OPTION_URI_PATH, uri_path, '/',
"Uri-Path");
PRINTF("Serialize content format: %d\n", coap_pkt->content_format);
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_CONTENT_FORMAT, content_format,
"Content-Format");
COAP_SERIALIZE_INT_OPTION(COAP_OPTION_MAX_AGE, max_age, "Max-Age");
@ -403,8 +406,9 @@ coap_serialize_message(void *packet, uint8_t *buffer)
}
PRINTF("-Done %u B (header len %u, payload len %u)-\n",
coap_pkt->payload_len + option - buffer, option - buffer,
coap_pkt->payload_len);
(unsigned int)(coap_pkt->payload_len + option - buffer),
(unsigned int)(option - buffer),
(unsigned int)coap_pkt->payload_len);
PRINTF("Dump [0x%02X %02X %02X %02X %02X %02X %02X %02X]\n",
coap_pkt->buffer[0],
@ -451,10 +455,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
>> COAP_HEADER_VERSION_POSITION;
coap_pkt->type = (COAP_HEADER_TYPE_MASK & coap_pkt->buffer[0])
>> COAP_HEADER_TYPE_POSITION;
coap_pkt->token_len =
MIN(COAP_TOKEN_LEN,
(COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->
buffer[0]) >> COAP_HEADER_TOKEN_LEN_POSITION);
coap_pkt->token_len = (COAP_HEADER_TOKEN_LEN_MASK & coap_pkt->buffer[0])
>> COAP_HEADER_TOKEN_LEN_POSITION;
coap_pkt->code = coap_pkt->buffer[1];
coap_pkt->mid = coap_pkt->buffer[2] << 8 | coap_pkt->buffer[3];
@ -463,6 +465,11 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
return BAD_REQUEST_4_00;
}
if(coap_pkt->token_len > COAP_TOKEN_LEN) {
coap_error_message = "Token Length must not be more than 8";
return BAD_REQUEST_4_00;
}
uint8_t *current_option = data + COAP_HEADER_LEN;
memcpy(coap_pkt->token, current_option, coap_pkt->token_len);
@ -500,25 +507,31 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
option_length = current_option[0] & 0x0F;
++current_option;
/* avoids code duplication without function overhead */
unsigned int *x = &option_delta;
if(option_delta == 13) {
option_delta += current_option[0];
++current_option;
} else if(option_delta == 14) {
option_delta += 255;
option_delta += current_option[0] << 8;
++current_option;
option_delta += current_option[0];
++current_option;
}
do {
if(*x == 13) {
*x += current_option[0];
++current_option;
} else if(*x == 14) {
*x += 255;
*x += current_option[0] << 8;
++current_option;
*x += current_option[0];
++current_option;
}
} while(x != &option_length && (x = &option_length));
if(option_length == 13) {
option_length += current_option[0];
++current_option;
} else if(option_length == 14) {
option_length += 255;
option_length += current_option[0] << 8;
++current_option;
option_length += current_option[0];
++current_option;
}
option_number += option_delta;
PRINTF("OPTION %u (delta %u, len %u): ", option_number, option_delta,
PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta,
option_length);
SET_OPTION(coap_pkt, option_number);
@ -532,7 +545,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
case COAP_OPTION_MAX_AGE:
coap_pkt->max_age = coap_parse_int_option(current_option,
option_length);
PRINTF("Max-Age [%lu]\n", coap_pkt->max_age);
PRINTF("Max-Age [%lu]\n", (unsigned long)coap_pkt->max_age);
break;
case COAP_OPTION_ETAG:
coap_pkt->etag_len = MIN(COAP_ETAG_LEN, option_length);
@ -569,7 +582,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_pkt->proxy_uri = (char *)current_option;
coap_pkt->proxy_uri_len = option_length;
#endif
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", coap_pkt->proxy_uri_len,
PRINTF("Proxy-Uri NOT IMPLEMENTED [%.*s]\n", (int)coap_pkt->proxy_uri_len,
coap_pkt->proxy_uri);
coap_error_message = "This is a constrained server (Contiki)";
return PROXYING_NOT_SUPPORTED_5_05;
@ -580,7 +593,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_pkt->proxy_scheme_len = option_length;
#endif
PRINTF("Proxy-Scheme NOT IMPLEMENTED [%.*s]\n",
coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
(int)coap_pkt->proxy_scheme_len, coap_pkt->proxy_scheme);
coap_error_message = "This is a constrained server (Contiki)";
return PROXYING_NOT_SUPPORTED_5_05;
break;
@ -588,7 +601,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
case COAP_OPTION_URI_HOST:
coap_pkt->uri_host = (char *)current_option;
coap_pkt->uri_host_len = option_length;
PRINTF("Uri-Host [%.*s]\n", coap_pkt->uri_host_len, coap_pkt->uri_host);
PRINTF("Uri-Host [%.*s]\n", (int)coap_pkt->uri_host_len,
coap_pkt->uri_host);
break;
case COAP_OPTION_URI_PORT:
coap_pkt->uri_port = coap_parse_int_option(current_option,
@ -600,14 +614,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_merge_multi_option((char **)&(coap_pkt->uri_path),
&(coap_pkt->uri_path_len), current_option,
option_length, '/');
PRINTF("Uri-Path [%.*s]\n", coap_pkt->uri_path_len, coap_pkt->uri_path);
PRINTF("Uri-Path [%.*s]\n", (int)coap_pkt->uri_path_len, coap_pkt->uri_path);
break;
case COAP_OPTION_URI_QUERY:
/* coap_merge_multi_option() operates in-place on the IPBUF, but final packet field should be const string -> cast to string */
coap_merge_multi_option((char **)&(coap_pkt->uri_query),
&(coap_pkt->uri_query_len), current_option,
option_length, '&');
PRINTF("Uri-Query [%.*s]\n", coap_pkt->uri_query_len,
PRINTF("Uri-Query [%.*s]\n", (int)coap_pkt->uri_query_len,
coap_pkt->uri_query);
break;
@ -616,7 +630,7 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_merge_multi_option((char **)&(coap_pkt->location_path),
&(coap_pkt->location_path_len), current_option,
option_length, '/');
PRINTF("Location-Path [%.*s]\n", coap_pkt->location_path_len,
PRINTF("Location-Path [%.*s]\n", (int)coap_pkt->location_path_len,
coap_pkt->location_path);
break;
case COAP_OPTION_LOCATION_QUERY:
@ -624,14 +638,14 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_merge_multi_option((char **)&(coap_pkt->location_query),
&(coap_pkt->location_query_len), current_option,
option_length, '&');
PRINTF("Location-Query [%.*s]\n", coap_pkt->location_query_len,
PRINTF("Location-Query [%.*s]\n", (int)coap_pkt->location_query_len,
coap_pkt->location_query);
break;
case COAP_OPTION_OBSERVE:
coap_pkt->observe = coap_parse_int_option(current_option,
option_length);
PRINTF("Observe [%lu]\n", coap_pkt->observe);
PRINTF("Observe [%lu]\n", (unsigned long)coap_pkt->observe);
break;
case COAP_OPTION_BLOCK2:
coap_pkt->block2_num = coap_parse_int_option(current_option,
@ -641,7 +655,8 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_pkt->block2_offset = (coap_pkt->block2_num & ~0x0000000F)
<< (coap_pkt->block2_num & 0x07);
coap_pkt->block2_num >>= 4;
PRINTF("Block2 [%lu%s (%u B/blk)]\n", coap_pkt->block2_num,
PRINTF("Block2 [%lu%s (%u B/blk)]\n",
(unsigned long)coap_pkt->block2_num,
coap_pkt->block2_more ? "+" : "", coap_pkt->block2_size);
break;
case COAP_OPTION_BLOCK1:
@ -652,16 +667,17 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
coap_pkt->block1_offset = (coap_pkt->block1_num & ~0x0000000F)
<< (coap_pkt->block1_num & 0x07);
coap_pkt->block1_num >>= 4;
PRINTF("Block1 [%lu%s (%u B/blk)]\n", coap_pkt->block1_num,
PRINTF("Block1 [%lu%s (%u B/blk)]\n",
(unsigned long)coap_pkt->block1_num,
coap_pkt->block1_more ? "+" : "", coap_pkt->block1_size);
break;
case COAP_OPTION_SIZE2:
coap_pkt->size2 = coap_parse_int_option(current_option, option_length);
PRINTF("Size2 [%lu]\n", coap_pkt->size2);
PRINTF("Size2 [%lu]\n", (unsigned long)coap_pkt->size2);
break;
case COAP_OPTION_SIZE1:
coap_pkt->size1 = coap_parse_int_option(current_option, option_length);
PRINTF("Size1 [%lu]\n", coap_pkt->size1);
PRINTF("Size1 [%lu]\n", (unsigned long)coap_pkt->size1);
break;
default:
PRINTF("unknown (%u)\n", option_number);
@ -744,7 +760,7 @@ coap_set_header_content_format(void *packet, unsigned int format)
{
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
coap_pkt->content_format = (coap_content_format_t)format;
coap_pkt->content_format = format;
SET_OPTION(coap_pkt, COAP_OPTION_CONTENT_FORMAT);
return 1;
}
@ -765,7 +781,7 @@ coap_set_header_accept(void *packet, unsigned int accept)
{
coap_packet_t *const coap_pkt = (coap_packet_t *)packet;
coap_pkt->accept = (coap_content_format_t)accept;
coap_pkt->accept = accept;
SET_OPTION(coap_pkt, COAP_OPTION_ACCEPT);
return 1;
}

View File

@ -93,7 +93,7 @@ typedef struct {
uint8_t options[COAP_OPTION_SIZE1 / OPTION_MAP_SIZE + 1]; /* bitmap to check if option is set */
coap_content_format_t content_format; /* parse options once and store; allows setting options in random order */
uint16_t content_format; /* parse options once and store; allows setting options in random order */
uint32_t max_age;
uint8_t etag_len;
uint8_t etag[COAP_ETAG_LEN];
@ -111,7 +111,7 @@ typedef struct {
size_t uri_path_len;
const char *uri_path;
int32_t observe;
coap_content_format_t accept;
uint16_t accept;
uint8_t if_match_len;
uint8_t if_match[COAP_ETAG_LEN];
uint32_t block2_num;
@ -135,13 +135,13 @@ typedef struct {
/* option format serialization */
#define COAP_SERIALIZE_INT_OPTION(number, field, text) \
if(IS_OPTION(coap_pkt, number)) { \
PRINTF(text " [%u]\n", coap_pkt->field); \
PRINTF(text " [%u]\n", (unsigned int)coap_pkt->field); \
option += coap_serialize_int_option(number, current_number, option, coap_pkt->field); \
current_number = number; \
}
#define COAP_SERIALIZE_BYTE_OPTION(number, field, text) \
if(IS_OPTION(coap_pkt, number)) { \
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", coap_pkt->field##_len, \
PRINTF(text " %u [0x%02X%02X%02X%02X%02X%02X%02X%02X]\n", (unsigned int)coap_pkt->field##_len, \
coap_pkt->field[0], \
coap_pkt->field[1], \
coap_pkt->field[2], \
@ -156,18 +156,18 @@ typedef struct {
}
#define COAP_SERIALIZE_STRING_OPTION(number, field, splitter, text) \
if(IS_OPTION(coap_pkt, number)) { \
PRINTF(text " [%.*s]\n", coap_pkt->field##_len, coap_pkt->field); \
PRINTF(text " [%.*s]\n", (int)coap_pkt->field##_len, coap_pkt->field); \
option += coap_serialize_array_option(number, current_number, option, (uint8_t *)coap_pkt->field, coap_pkt->field##_len, splitter); \
current_number = number; \
}
#define COAP_SERIALIZE_BLOCK_OPTION(number, field, text) \
if(IS_OPTION(coap_pkt, number)) \
{ \
PRINTF(text " [%lu%s (%u B/blk)]\n", coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
PRINTF(text " [%lu%s (%u B/blk)]\n", (unsigned long)coap_pkt->field##_num, coap_pkt->field##_more ? "+" : "", coap_pkt->field##_size); \
uint32_t block = coap_pkt->field##_num << 4; \
if(coap_pkt->field##_more) { block |= 0x8; } \
block |= 0xF & coap_log_2(coap_pkt->field##_size / 16); \
PRINTF(text " encoded: 0x%lX\n", block); \
PRINTF(text " encoded: 0x%lX\n", (unsigned long)block); \
option += coap_serialize_int_option(number, current_number, option, block); \
current_number = number; \
}

View File

@ -0,0 +1 @@
orchestra_src = orchestra.c orchestra-rule-default-common.c orchestra-rule-eb-per-time-source.c orchestra-rule-unicast-per-neighbor.c

51
apps/orchestra/README.md Normal file
View File

@ -0,0 +1,51 @@
# Orchestra
## Overview
Orchestra is an autonomous scheduling solution for TSCH, where nodes maintain
their own schedule solely based on their local RPL state. There is no centralized
scheduler nor negociatoin with neighbors, i.e. no traffic overhead. The default
Orchestra rules can be used out-of-box in any RPL network, reducing contention
to a low level. Orchestra is described and evaluated in
[*Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH*](http://www.simonduquennoy.net/papers/duquennoy15orchestra.pdf), ACM SenSys'15.
## Requirements
Orchestra requires a system running TSCH and RPL.
For sender-based unicast slots (`ORCHESTRA_UNICAST_SENDER_BASED`), it requires
RPL with downwards routing enabled (relies on DAO).
## Getting Started
To use Orchestra, add a couple global definitions, e.g in your `project-conf.h` file.
Disable 6TiSCH minimal schedule:
`#define TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL 0`
Enable TSCH link selector (allows Orchestra to assign TSCH links to outgoing packets):
`#define TSCH_CONF_WITH_LINK_SELECTOR 1`
Set up the following callbacks:
```
#define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source
#define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready
#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
```
To use Orchestra, fist add it to your makefile `APPS` with `APPS += orchestra`.
Finally:
* add Orchestra to your makefile `APPS` with `APPS += orchestra`;
* start Orchestra by calling `orchestra_init()` from your application, after
including `#include "orchestra.h"`.
## Configuration
Orchestra comes with a number of pre-installed rules, `orchestra-rule-*.c`.
You can define your own by using any of these as a template.
A default Orchestra configuration is described in `orchestra-conf.h`, define your own
`ORCHESTRA_CONF_*` macros to override modify the rule set and change rules configuration.

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra configuration
*
* \author Simon Duquennoy <simonduq@sics.se>
*/
#ifndef __ORCHESTRA_CONF_H__
#define __ORCHESTRA_CONF_H__
#ifdef ORCHESTRA_CONF_RULES
#define ORCHESTRA_RULES ORCHESTRA_CONF_RULES
#else /* ORCHESTRA_CONF_RULES */
/* A default configuration with:
* - a sender-based slotframe for EB transmission
* - a sender-based or receiver-based slotframe for unicast to RPL parents and children
* - a common shared slotframe for any other traffic (mostly broadcast)
* */
#define ORCHESTRA_RULES { &eb_per_time_source, \
&unicast_per_neighbor, \
&default_common, \
}
#endif /* ORCHESTRA_CONF_RULES */
/* Length of the various slotframes. Tune to balance network capacity,
* contention, energy, latency. */
#ifdef ORCHESTRA_CONF_EBSF_PERIOD
#define ORCHESTRA_EBSF_PERIOD ORCHESTRA_CONF_EBSF_PERIOD
#else /* ORCHESTRA_CONF_EBSF_PERIOD */
#define ORCHESTRA_EBSF_PERIOD 397
#endif /* ORCHESTRA_CONF_EBSF_PERIOD */
#ifdef ORCHESTRA_CONF_COMMON_SHARED_PERIOD
#define ORCHESTRA_COMMON_SHARED_PERIOD ORCHESTRA_CONF_COMMON_SHARED_PERIOD
#else /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
#define ORCHESTRA_COMMON_SHARED_PERIOD 31
#endif /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
#ifdef ORCHESTRA_CONF_UNICAST_PERIOD
#define ORCHESTRA_UNICAST_PERIOD ORCHESTRA_CONF_UNICAST_PERIOD
#else /* ORCHESTRA_CONF_UNICAST_PERIOD */
#define ORCHESTRA_UNICAST_PERIOD 17
#endif /* ORCHESTRA_CONF_UNICAST_PERIOD */
/* Is the per-neighbor unicast slotframe sender-based (if not, it is receiver-based).
* Note: sender-based works only with RPL storing mode as it relies on DAO and
* routing entries to keep track of children and parents. */
#ifdef ORCHESTRA_CONF_UNICAST_SENDER_BASED
#define ORCHESTRA_UNICAST_SENDER_BASED ORCHESTRA_CONF_UNICAST_SENDER_BASED
#else /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
#define ORCHESTRA_UNICAST_SENDER_BASED 0
#endif /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
/* The hash function used to assign timeslot to a given node (based on its link-layer address) */
#ifdef ORCHESTRA_CONF_LINKADDR_HASH
#define ORCHESTRA_LINKADDR_HASH ORCHESTRA_CONF_LINKADDR_HASH
#else /* ORCHESTRA_CONF_LINKADDR_HASH */
#define ORCHESTRA_LINKADDR_HASH(addr) ((addr != NULL) ? (addr)->u8[LINKADDR_SIZE - 1] : -1)
#endif /* ORCHESTRA_CONF_LINKADDR_HASH */
/* The maximum hash */
#ifdef ORCHESTRA_CONF_MAX_HASH
#define ORCHESTRA_MAX_HASH ORCHESTRA_CONF_MAX_HASH
#else /* ORCHESTRA_CONF_MAX_HASH */
#define ORCHESTRA_MAX_HASH 0x7fff
#endif /* ORCHESTRA_CONF_MAX_HASH */
/* Is the "hash" function collision-free? (e.g. it maps to unique node-ids) */
#ifdef ORCHESTRA_CONF_COLLISION_FREE_HASH
#define ORCHESTRA_COLLISION_FREE_HASH ORCHESTRA_CONF_COLLISION_FREE_HASH
#else /* ORCHESTRA_CONF_COLLISION_FREE_HASH */
#define ORCHESTRA_COLLISION_FREE_HASH 0 /* Set to 1 if ORCHESTRA_LINKADDR_HASH returns unique hashes */
#endif /* ORCHESTRA_CONF_COLLISION_FREE_HASH */
#endif /* __ORCHESTRA_CONF_H__ */

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra: a slotframe with a single shared link, common to all nodes
* in the network, used for unicast and broadcast.
*
* \author Simon Duquennoy <simonduq@sics.se>
*/
#include "contiki.h"
#include "orchestra.h"
static uint16_t slotframe_handle = 0;
static uint16_t channel_offset = 0;
#if ORCHESTRA_EBSF_PERIOD > 0
/* There is a slotframe for EBs, use this slotframe for non-EB traffic only */
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_NORMAL
#else
/* There is no slotframe for EBs, use this slotframe both EB and non-EB traffic */
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_ADVERTISING
#endif
/*---------------------------------------------------------------------------*/
static int
select_packet(uint16_t *slotframe, uint16_t *timeslot)
{
/* We are the default slotframe, select anything */
if(slotframe != NULL) {
*slotframe = slotframe_handle;
}
if(timeslot != NULL) {
*timeslot = 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static void
init(uint16_t sf_handle)
{
slotframe_handle = sf_handle;
channel_offset = slotframe_handle;
/* Default slotframe: for broadcast or unicast to neighbors we
* do not have a link to */
struct tsch_slotframe *sf_common = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_COMMON_SHARED_PERIOD);
tsch_schedule_add_link(sf_common,
LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED,
ORCHESTRA_COMMON_SHARED_TYPE, &tsch_broadcast_address,
0, channel_offset);
}
/*---------------------------------------------------------------------------*/
struct orchestra_rule default_common = {
init,
NULL,
select_packet,
NULL,
NULL,
};

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra: a slotframe dedicated to transmission of EBs.
* Nodes transmit at a timeslot defined as hash(MAC) % ORCHESTRA_EBSF_PERIOD
* Nodes listen at a timeslot defined as hash(time_source.MAC) % ORCHESTRA_EBSF_PERIOD
* \author Simon Duquennoy <simonduq@sics.se>
*/
#include "contiki.h"
#include "orchestra.h"
#include "net/packetbuf.h"
static uint16_t slotframe_handle = 0;
static uint16_t channel_offset = 0;
static struct tsch_slotframe *sf_eb;
/*---------------------------------------------------------------------------*/
static uint16_t
get_node_timeslot(const linkaddr_t *addr)
{
#if ORCHESTRA_EBSF_PERIOD > 0
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_EBSF_PERIOD;
#else
return 0xffff;
#endif
}
/*---------------------------------------------------------------------------*/
static int
select_packet(uint16_t *slotframe, uint16_t *timeslot)
{
/* Select EBs only */
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_BEACONFRAME) {
if(slotframe != NULL) {
*slotframe = slotframe_handle;
}
if(timeslot != NULL) {
*timeslot = get_node_timeslot(&linkaddr_node_addr);
}
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
{
uint16_t old_ts = get_node_timeslot(&old->addr);
uint16_t new_ts = get_node_timeslot(&new->addr);
if(new_ts == old_ts) {
return;
}
if(old_ts != 0xffff) {
/* Stop listening to the old time source's EBs */
tsch_schedule_remove_link_by_timeslot(sf_eb, old_ts);
}
if(new_ts != 0xffff) {
/* Listen to the time source's EBs */
tsch_schedule_add_link(sf_eb,
LINK_OPTION_RX,
LINK_TYPE_ADVERTISING_ONLY, NULL,
new_ts, 0);
}
}
/*---------------------------------------------------------------------------*/
static void
init(uint16_t sf_handle)
{
slotframe_handle = sf_handle;
channel_offset = sf_handle;
sf_eb = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_EBSF_PERIOD);
/* EB link: every neighbor uses its own to avoid contention */
tsch_schedule_add_link(sf_eb,
LINK_OPTION_TX,
LINK_TYPE_ADVERTISING_ONLY, &tsch_broadcast_address,
get_node_timeslot(&linkaddr_node_addr), 0);
}
/*---------------------------------------------------------------------------*/
struct orchestra_rule eb_per_time_source = {
init,
new_time_source,
select_packet,
NULL,
NULL,
};

View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra: a slotframe dedicated to unicast data transmission.
* If sender-based:
* Nodes listen at a timeslot defined as hash(MAC) % ORCHESTRA_SB_UNICAST_PERIOD
* Nodes transmit at: for each nbr in RPL children and RPL preferred parent,
* hash(nbr.MAC) % ORCHESTRA_SB_UNICAST_PERIOD
* If receiver-based: the opposite
*
* \author Simon Duquennoy <simonduq@sics.se>
*/
#include "contiki.h"
#include "orchestra.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/packetbuf.h"
#if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0)
#else
#define UNICAST_SLOT_SHARED_FLAG LINK_OPTION_SHARED
#endif
static uint16_t slotframe_handle = 0;
static uint16_t channel_offset = 0;
static struct tsch_slotframe *sf_unicast;
/*---------------------------------------------------------------------------*/
static uint16_t
get_node_timeslot(const linkaddr_t *addr)
{
if(addr != NULL && ORCHESTRA_UNICAST_PERIOD > 0) {
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_UNICAST_PERIOD;
} else {
return 0xffff;
}
}
/*---------------------------------------------------------------------------*/
static int
neighbor_has_uc_link(const linkaddr_t *linkaddr)
{
if(linkaddr != NULL && !linkaddr_cmp(linkaddr, &linkaddr_null)) {
if((orchestra_parent_knows_us || !ORCHESTRA_UNICAST_SENDER_BASED)
&& linkaddr_cmp(&orchestra_parent_linkaddr, linkaddr)) {
return 1;
}
if(nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)linkaddr) != NULL) {
return 1;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
add_uc_link(const linkaddr_t *linkaddr)
{
if(linkaddr != NULL) {
uint16_t timeslot = get_node_timeslot(linkaddr);
tsch_schedule_add_link(sf_unicast,
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_RX : LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG,
LINK_TYPE_NORMAL, &tsch_broadcast_address,
timeslot, channel_offset);
}
}
/*---------------------------------------------------------------------------*/
static void
remove_uc_link(const linkaddr_t *linkaddr)
{
uint16_t timeslot;
struct tsch_link *l;
if(linkaddr == NULL) {
return;
}
timeslot = get_node_timeslot(linkaddr);
l = tsch_schedule_get_link_by_timeslot(sf_unicast, timeslot);
if(l == NULL) {
return;
}
/* Does our current parent need this timeslot? */
if(timeslot == get_node_timeslot(&orchestra_parent_linkaddr)) {
/* Yes, this timeslot is being used, return */
return;
}
/* Does any other child need this timeslot?
* (lookup all route next hops) */
nbr_table_item_t *item = nbr_table_head(nbr_routes);
while(item != NULL) {
linkaddr_t *addr = nbr_table_get_lladdr(nbr_routes, item);
if(timeslot == get_node_timeslot(addr)) {
/* Yes, this timeslot is being used, return */
return;
}
item = nbr_table_next(nbr_routes, item);
}
tsch_schedule_remove_link(sf_unicast, l);
}
/*---------------------------------------------------------------------------*/
static void
child_added(const linkaddr_t *linkaddr)
{
add_uc_link(linkaddr);
}
/*---------------------------------------------------------------------------*/
static void
child_removed(const linkaddr_t *linkaddr)
{
remove_uc_link(linkaddr);
}
/*---------------------------------------------------------------------------*/
static int
select_packet(uint16_t *slotframe, uint16_t *timeslot)
{
/* Select data packets we have a unicast link to */
const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_DATAFRAME
&& neighbor_has_uc_link(dest)) {
if(slotframe != NULL) {
*slotframe = slotframe_handle;
}
if(timeslot != NULL) {
*timeslot = ORCHESTRA_UNICAST_SENDER_BASED ? get_node_timeslot(&linkaddr_node_addr) : get_node_timeslot(dest);
}
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
{
if(new != old) {
const linkaddr_t *new_addr = new != NULL ? &new->addr : NULL;
if(new_addr != NULL) {
linkaddr_copy(&orchestra_parent_linkaddr, new_addr);
} else {
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
}
remove_uc_link(new_addr);
add_uc_link(new_addr);
}
}
/*---------------------------------------------------------------------------*/
static void
init(uint16_t sf_handle)
{
slotframe_handle = sf_handle;
channel_offset = sf_handle;
/* Slotframe for unicast transmissions */
sf_unicast = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_UNICAST_PERIOD);
uint16_t timeslot = get_node_timeslot(&linkaddr_node_addr);
tsch_schedule_add_link(sf_unicast,
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG: LINK_OPTION_RX,
LINK_TYPE_NORMAL, &tsch_broadcast_address,
timeslot, channel_offset);
}
/*---------------------------------------------------------------------------*/
struct orchestra_rule unicast_per_neighbor = {
init,
new_time_source,
select_packet,
child_added,
child_removed,
};

166
apps/orchestra/orchestra.c Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra: an autonomous scheduler for TSCH exploiting RPL state.
* See "Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH", ACM SenSys'15
*
* \author Simon Duquennoy <simonduq@sics.se>
*/
#include "contiki.h"
#include "orchestra.h"
#include "net/packetbuf.h"
#include "net/ipv6/uip-icmp6.h"
#include "net/rpl/rpl-private.h"
#include "net/rime/rime.h" /* Needed for so-called rime-sniffer */
#define DEBUG DEBUG_PRINT
#include "net/ip/uip-debug.h"
/* A net-layer sniffer for packets sent and received */
static void orchestra_packet_received(void);
static void orchestra_packet_sent(int mac_status);
RIME_SNIFFER(orchestra_sniffer, orchestra_packet_received, orchestra_packet_sent);
/* The current RPL preferred parent's link-layer address */
linkaddr_t orchestra_parent_linkaddr;
/* Set to one only after getting an ACK for a DAO sent to our preferred parent */
int orchestra_parent_knows_us = 0;
/* The set of Orchestra rules in use */
const struct orchestra_rule *all_rules[] = ORCHESTRA_RULES;
#define NUM_RULES (sizeof(all_rules) / sizeof(struct orchestra_rule *))
/*---------------------------------------------------------------------------*/
static void
orchestra_packet_received(void)
{
}
/*---------------------------------------------------------------------------*/
static void
orchestra_packet_sent(int mac_status)
{
/* Check if our parent just ACKed a DAO */
if(orchestra_parent_knows_us == 0
&& mac_status == MAC_TX_OK
&& packetbuf_attr(PACKETBUF_ATTR_NETWORK_ID) == UIP_PROTO_ICMP6
&& packetbuf_attr(PACKETBUF_ATTR_CHANNEL) == (ICMP6_RPL << 8 | RPL_CODE_DAO)) {
if(!linkaddr_cmp(&orchestra_parent_linkaddr, &linkaddr_null)
&& linkaddr_cmp(&orchestra_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
orchestra_parent_knows_us = 1;
}
}
}
/*---------------------------------------------------------------------------*/
void
orchestra_callback_child_added(const linkaddr_t *addr)
{
/* Notify all Orchestra rules that a child was added */
int i;
for(i = 0; i < NUM_RULES; i++) {
if(all_rules[i]->child_added != NULL) {
all_rules[i]->child_added(addr);
}
}
}
/*---------------------------------------------------------------------------*/
void
orchestra_callback_child_removed(const linkaddr_t *addr)
{
/* Notify all Orchestra rules that a child was removed */
int i;
for(i = 0; i < NUM_RULES; i++) {
if(all_rules[i]->child_removed != NULL) {
all_rules[i]->child_removed(addr);
}
}
}
/*---------------------------------------------------------------------------*/
void
orchestra_callback_packet_ready(void)
{
int i;
/* By default, use any slotframe, any timeslot */
uint16_t slotframe = 9;
uint16_t timeslot = 0xffff;
/* Loop over all rules until finding one able to handle the packet */
for(i = 0; i < NUM_RULES; i++) {
if(all_rules[i]->select_packet != NULL) {
if(all_rules[i]->select_packet(&slotframe, &timeslot)) {
break;
}
}
}
#if TSCH_WITH_LINK_SELECTOR
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_SLOTFRAME, slotframe);
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_TIMESLOT, timeslot);
#endif
}
/*---------------------------------------------------------------------------*/
void
orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
{
/* Orchestra assumes that the time source is also the RPL parent.
* This is the case if the following is set:
* #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch
* */
int i;
if(new != old) {
orchestra_parent_knows_us = 0;
}
for(i = 0; i < NUM_RULES; i++) {
if(all_rules[i]->new_time_source != NULL) {
all_rules[i]->new_time_source(old, new);
}
}
}
/*---------------------------------------------------------------------------*/
void
orchestra_init(void)
{
int i;
/* Snoop on packet transmission to know if our parent knows about us
* (i.e. has ACKed at one of our DAOs since we decided to use it as a parent) */
rime_sniffer_add(&orchestra_sniffer);
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
/* Initialize all Orchestra rules */
for(i = 0; i < NUM_RULES; i++) {
if(all_rules[i]->init != NULL) {
PRINTF("Orchestra: initializing rule %u\n", i);
all_rules[i]->init(i);
}
}
PRINTF("Orchestra: initialization done\n");
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2015, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \file
* Orchestra header file
*
* \author Simon Duquennoy <simonduq@sics.se>
*/
#ifndef __ORCHESTRA_H__
#define __ORCHESTRA_H__
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-conf.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "orchestra-conf.h"
/* The structure of an Orchestra rule */
struct orchestra_rule {
void (* init)(uint16_t slotframe_handle);
void (* new_time_source)(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
int (* select_packet)(uint16_t *slotframe, uint16_t *timeslot);
void (* child_added)(const linkaddr_t *addr);
void (* child_removed)(const linkaddr_t *addr);
};
struct orchestra_rule eb_per_time_source;
struct orchestra_rule unicast_per_neighbor;
struct orchestra_rule default_common;
extern linkaddr_t orchestra_parent_linkaddr;
extern int orchestra_parent_knows_us;
/* Call from application to start Orchestra */
void orchestra_init(void);
/* Callbacks requied for Orchestra to operate */
/* Set with #define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready */
void orchestra_callback_packet_ready(void);
/* Set with #define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source */
void orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added */
void orchestra_callback_child_added(const linkaddr_t *addr);
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed */
void orchestra_callback_child_removed(const linkaddr_t *addr);
#endif /* __ORCHESTRA_H__ */

View File

@ -48,15 +48,15 @@
struct powertrace_sniff_stats {
struct powertrace_sniff_stats *next;
uint32_t num_input, num_output;
uint32_t input_txtime, input_rxtime;
uint32_t output_txtime, output_rxtime;
unsigned long num_input, num_output;
unsigned long input_txtime, input_rxtime;
unsigned long output_txtime, output_rxtime;
#if NETSTACK_CONF_WITH_IPV6
uint16_t proto; /* includes proto + possibly flags */
#endif
uint16_t channel;
uint32_t last_input_txtime, last_input_rxtime;
uint32_t last_output_txtime, last_output_rxtime;
unsigned long last_input_txtime, last_input_rxtime;
unsigned long last_output_txtime, last_output_rxtime;
};
#define INPUT 1
@ -72,17 +72,17 @@ PROCESS(powertrace_process, "Periodic power output");
void
powertrace_print(char *str)
{
static uint32_t last_cpu, last_lpm, last_transmit, last_listen;
static uint32_t last_idle_transmit, last_idle_listen;
static unsigned long last_cpu, last_lpm, last_transmit, last_listen;
static unsigned long last_idle_transmit, last_idle_listen;
uint32_t cpu, lpm, transmit, listen;
uint32_t all_cpu, all_lpm, all_transmit, all_listen;
uint32_t idle_transmit, idle_listen;
uint32_t all_idle_transmit, all_idle_listen;
unsigned long cpu, lpm, transmit, listen;
unsigned long all_cpu, all_lpm, all_transmit, all_listen;
unsigned long idle_transmit, idle_listen;
unsigned long all_idle_transmit, all_idle_listen;
static uint32_t seqno;
static unsigned long seqno;
uint32_t time, all_time, radio, all_radio;
unsigned long time, all_time, radio, all_radio;
struct powertrace_sniff_stats *s;
@ -287,13 +287,8 @@ output_sniffer(int mac_status)
static void
sniffprint(char *prefix, int seqno)
{
const linkaddr_t *sender, *receiver, *esender, *ereceiver;
sender = packetbuf_addr(PACKETBUF_ADDR_SENDER);
receiver = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
const linkaddr_t *esender;
esender = packetbuf_addr(PACKETBUF_ADDR_ESENDER);
ereceiver = packetbuf_addr(PACKETBUF_ADDR_ERECEIVER);
printf("%lu %s %d %u %d %d %d.%d %u %u\n",
clock_time(),

View File

@ -1,19 +1,19 @@
/*
* Copyright (c) 2003, Adam Dunkels.
* All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -25,7 +25,7 @@
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This file is part of the Contiki desktop OS
*
@ -35,7 +35,7 @@
/**
* \file
* The program handler, used for loading programs and starting the
* screensaver.
* screensaver.
* \author Adam Dunkels <adam@dunkels.com>
*
* The Contiki program handler is responsible for the Contiki menu and
@ -45,7 +45,7 @@
* The program handler also is responsible for starting the
* screensaver when the CTK detects that it should be started.
*/
#include <string.h>
#include <stdlib.h>
@ -161,7 +161,7 @@ char program_handler_screensaver[20];
/*-----------------------------------------------------------------------------------*/
void
program_handler_add(struct dsc *dsc, char *menuname,
unsigned char desktop)
unsigned char desktop)
{
contikidsc[contikidsclast++] = dsc;
ctk_menuitem_add(&contikimenu, menuname);
@ -228,7 +228,7 @@ program_handler_load(char *name, char *arg)
{
#ifdef WITH_LOADER_ARCH
struct pnarg *pnarg;
pnarg = pnarg_copy(name, arg);
if(pnarg != NULL) {
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, pnarg);
@ -246,6 +246,7 @@ program_handler_load(char *name, char *arg)
#else /* WITH_LOADER_ARCH */
#define RUN(prg, process, arg) process_start(process, arg)
#endif /* WITH_LOADER_ARCH */
#if CTK_CONF_SCREENSAVER
/*-----------------------------------------------------------------------------------*/
/**
* Configures the name of the screensaver to be loaded when
@ -255,7 +256,6 @@ program_handler_load(char *name, char *arg)
* should be used.
*/
/*-----------------------------------------------------------------------------------*/
#if CTK_CONF_SCREENSAVER
void
program_handler_setscreensaver(char *name)
{
@ -272,17 +272,17 @@ static void
make_windows(void)
{
ctk_window_new(&runwindow, 16, 3, "Run");
CTK_WIDGET_ADD(&runwindow, &namelabel);
CTK_WIDGET_ADD(&runwindow, &nameentry);
CTK_WIDGET_ADD(&runwindow, &loadbutton);
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
ctk_dialog_new(&loadingdialog, 25, 1);
CTK_WIDGET_ADD(&loadingdialog, &loadingmsg);
CTK_WIDGET_ADD(&loadingdialog, &loadingname);
ctk_dialog_new(&errordialog, 22, 8);
CTK_WIDGET_ADD(&errordialog, &errormsg);
CTK_WIDGET_ADD(&errordialog, &errorfilelabel);
@ -302,20 +302,20 @@ PROCESS_THREAD(program_handler_process, ev, data)
struct dsc **dscp;
PROCESS_BEGIN();
/* Create the menus */
ctk_menu_add(&contikimenu);
#if WITH_LOADER_ARCH
runmenuitem = ctk_menuitem_add(&contikimenu, "Run program...");
make_windows();
#endif /* WITH_LOADER_ARCH */
#if QUIT_MENU
quitmenuitem = ctk_menuitem_add(&contikimenu, "Quit");
#endif /* QUIT_MENU */
displayname = NULL;
#if CTK_CONF_SCREENSAVER
program_handler_screensaver[0] = 0;
#endif /* CTK_CONF_SCREENSAVER */
@ -325,106 +325,106 @@ PROCESS_THREAD(program_handler_process, ev, data)
if(ev == ctk_signal_button_activate) {
#ifdef WITH_LOADER_ARCH
if(data == (process_data_t)&loadbutton) {
ctk_window_close(&runwindow);
program_handler_load(name, NULL);
ctk_window_close(&runwindow);
program_handler_load(name, NULL);
} else if(data == (process_data_t)&errorokbutton) {
ctk_dialog_close();
ctk_dialog_close();
}
#endif /* WITH_LOADER_ARCH */
#if QUIT_MENU
if(data == (process_data_t)&quityesbutton) {
ctk_draw_init();
exit(EXIT_SUCCESS);
ctk_draw_init();
exit(EXIT_SUCCESS);
} else if(data == (process_data_t)&quitnobutton) {
ctk_dialog_close();
ctk_dialog_close();
}
#endif /* QUIT_MENU */
dscp = &contikidsc[0];
for(i = 0; i < CTK_MAXMENUITEMS; ++i) {
if(*dscp != NULL
for(i = 0; i < CTK_MAXMENUITEMS; ++i) {
if(*dscp != NULL
#if CTK_CONF_ICONS
&& data == (process_data_t)(*dscp)->icon
&& data == (process_data_t)(*dscp)->icon
#endif /* CTK_CONF_ICONS */
) {
RUN((*dscp)->prgname, (*dscp)->process, NULL);
break;
}
++dscp;
) {
RUN((*dscp)->prgname, (*dscp)->process, NULL);
break;
}
++dscp;
}
} else if(ev == ctk_signal_menu_activate) {
if((struct ctk_menu *)data == &contikimenu) {
#if WITH_LOADER_ARCH
dsc = contikidsc[contikimenu.active];
if(dsc != NULL) {
RUN(dsc->prgname, dsc->process, NULL);
} else if(contikimenu.active == runmenuitem) {
make_windows();
ctk_window_close(&runwindow);
ctk_window_open(&runwindow);
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
}
dsc = contikidsc[contikimenu.active];
if(dsc != NULL) {
RUN(dsc->prgname, dsc->process, NULL);
} else if(contikimenu.active == runmenuitem) {
make_windows();
ctk_window_close(&runwindow);
ctk_window_open(&runwindow);
CTK_WIDGET_FOCUS(&runwindow, &nameentry);
}
#else /* WITH_LOADER_ARCH */
if(contikidsc[contikimenu.active] != NULL) {
RUN(contikidsc[contikimenu.active]->prgname,
contikidsc[contikimenu.active]->process,
NULL);
}
if(contikidsc[contikimenu.active] != NULL) {
RUN(contikidsc[contikimenu.active]->prgname,
contikidsc[contikimenu.active]->process,
NULL);
}
#endif /* WITH_LOADER_ARCH */
#if QUIT_MENU
if(contikimenu.active == quitmenuitem) {
ctk_dialog_new(&quitdialog, 24, 5);
CTK_WIDGET_ADD(&quitdialog, &quitdialoglabel);
CTK_WIDGET_ADD(&quitdialog, &quityesbutton);
CTK_WIDGET_ADD(&quitdialog, &quitnobutton);
CTK_WIDGET_FOCUS(&quitdialog, &quitnobutton);
ctk_dialog_open(&quitdialog);
}
if(contikimenu.active == quitmenuitem) {
ctk_dialog_new(&quitdialog, 24, 5);
CTK_WIDGET_ADD(&quitdialog, &quitdialoglabel);
CTK_WIDGET_ADD(&quitdialog, &quityesbutton);
CTK_WIDGET_ADD(&quitdialog, &quitnobutton);
CTK_WIDGET_FOCUS(&quitdialog, &quitnobutton);
ctk_dialog_open(&quitdialog);
}
#endif /* QUIT_MENU */
}
#if CTK_CONF_SCREENSAVER
} else if(ev == ctk_signal_screensaver_start) {
#if WITH_LOADER_ARCH
if(program_handler_screensaver[0] != 0) {
program_handler_load(program_handler_screensaver, NULL);
program_handler_load(program_handler_screensaver, NULL);
}
#endif /* WITH_LOADER_ARCH */
#endif /* CTK_CONF_SCREENSAVER */
} else if(ev == LOADER_EVENT_DISPLAY_NAME) {
#if WITH_LOADER_ARCH
if(displayname == NULL) {
make_windows();
ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name);
ctk_dialog_open(&loadingdialog);
process_post(&program_handler_process, LOADER_EVENT_LOAD, data);
displayname = data;
make_windows();
ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name);
ctk_dialog_open(&loadingdialog);
process_post(&program_handler_process, LOADER_EVENT_LOAD, data);
displayname = data;
} else {
/* Try again. */
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
/* Try again. */
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
}
#endif /* WITH_LOADER_ARCH */
} else if(ev == LOADER_EVENT_LOAD) {
#if WITH_LOADER_ARCH
if(displayname == data) {
ctk_dialog_close();
displayname = NULL;
log_message("Loading ", ((struct pnarg *)data)->name);
err = LOADER_LOAD(((struct pnarg *)data)->name,
((struct pnarg *)data)->arg);
if(err != LOADER_OK) {
make_windows();
errorfilename[0] = '"';
strncpy(errorfilename + 1, ((struct pnarg *)data)->name,
sizeof(errorfilename) - 2);
errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"';
ctk_label_set_text(&errortype, (char *)errormsgs[err]);
ctk_dialog_open(&errordialog);
log_message((char *)errormsgs[err], errorfilename);
}
pnarg_free(data);
ctk_dialog_close();
displayname = NULL;
log_message("Loading ", ((struct pnarg *)data)->name);
err = LOADER_LOAD(((struct pnarg *)data)->name,
((struct pnarg *)data)->arg);
if(err != LOADER_OK) {
make_windows();
errorfilename[0] = '"';
strncpy(errorfilename + 1, ((struct pnarg *)data)->name,
sizeof(errorfilename) - 2);
errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"';
ctk_label_set_text(&errortype, (char *)errormsgs[err]);
ctk_dialog_open(&errordialog);
log_message((char *)errormsgs[err], errorfilename);
}
pnarg_free(data);
} else {
/* Try again. */
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
/* Try again. */
process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
}
#endif /* WITH_LOADEER_ARCH */
}

View File

@ -70,6 +70,15 @@ LIST(restful_periodic_services);
void
rest_init_engine(void)
{
/* avoid initializing twice */
static uint8_t initialized = 0;
if(initialized) {
PRINTF("REST engine process already running - double initialization?\n");
return;
}
initialized = 1;
list_init(restful_services);
REST.set_service_callback(rest_invoke_restful_service);
@ -124,15 +133,19 @@ rest_invoke_restful_service(void *request, void *response, uint8_t *buffer,
resource_t *resource = NULL;
const char *url = NULL;
int url_len, res_url_len;
url_len = REST.get_url(request, &url);
for(resource = (resource_t *)list_head(restful_services);
resource; resource = resource->next) {
/* if the web service handles that kind of requests and urls matches */
if((REST.get_url(request, &url) == strlen(resource->url)
|| (REST.get_url(request, &url) > strlen(resource->url)
&& (resource->flags & HAS_SUB_RESOURCES)))
&& strncmp(resource->url, url, strlen(resource->url)) == 0) {
res_url_len = strlen(resource->url);
if((url_len == res_url_len
|| (url_len > res_url_len
&& (resource->flags & HAS_SUB_RESOURCES)
&& url[res_url_len] == '/'))
&& strncmp(resource->url, url, res_url_len) == 0) {
found = 1;
rest_resource_flags_t method = REST.get_method_type(request);

View File

@ -332,14 +332,10 @@ static void
parse_incoming_packet(const uint8_t *buf, int len)
{
int numregs;
int flags;
int i;
int bufptr;
numregs = buf[MSG_NUMREGS_OFFSET];
flags = buf[MSG_FLAGS_OFFSET];
/* printf("parse_incoming_packet Numregs %d flags %d\n", numregs, flags);*/
bufptr = MSG_ADDRS_OFFSET;
for(i = 0; i < numregs; ++i) {

View File

@ -50,6 +50,7 @@
#define HAVE_ALLOCA 0
#else
#define HAVE_ALLOCA 1
#include <alloca.h>
#endif
#define DEBUG 0

View File

@ -71,7 +71,7 @@ PROCESS_THREAD(shell_poke_process, ev, data)
PROCESS_EXIT();
}
address = (uint8_t *)(int)shell_strtolong(args, &next);
address = (uint8_t *)(uintptr_t)shell_strtolong(args, &next);
if(next == args) {
shell_output_str(&poke_command, "usage 1", "");
PROCESS_EXIT();
@ -106,7 +106,7 @@ PROCESS_THREAD(shell_peek_process, ev, data)
PROCESS_EXIT();
}
address = (uint8_t *)(int)shell_strtolong(args, &next);
address = (uint8_t *)(uintptr_t)shell_strtolong(args, &next);
if(next == args) {
shell_output_str(&peek_command, "usage 1", "");
PROCESS_EXIT();

View File

@ -128,8 +128,8 @@ memcpy_misaligned(void *dest, const void *source, int len)
int i;
uint8_t *destptr;
const uint8_t *sourceptr;
if(((int)dest & 1) == 1 ||
((int)source & 1) == 1) {
if(((uintptr_t)dest & 1) == 1 ||
((uintptr_t)source & 1) == 1) {
destptr = dest;
sourceptr = source;
for(i = 0; i < len; ++i) {

View File

@ -129,7 +129,7 @@ PROCESS_THREAD(shell_netcmd_process, ev, data)
/* Terminate the string with a NUL character. */
msg->netcmd[len] = 0;
msg->crc = crc16_data(msg->netcmd, len, 0);
msg->crc = crc16_data((unsigned char *)msg->netcmd, len, 0);
printf("netcmd sending '%s'\n", msg->netcmd);
trickle_send(&trickle);
}
@ -157,7 +157,7 @@ recv_trickle(struct trickle_conn *c)
msg->netcmd[len] = 0;
memcpy(&crc, &msg->crc, sizeof(crc));
if(crc == crc16_data(msg->netcmd, len, 0)) {
if(crc == crc16_data((unsigned char *)msg->netcmd, len, 0)) {
/* Start the server process with the incoming command. */
process_start(&shell_netcmd_server_process, (void *)msg->netcmd);
}

View File

@ -133,7 +133,7 @@ PROCESS_THREAD(shell_sendcmd_process, ev, data)
/* Terminate the string with a NUL character. */
msg->sendcmd[len] = 0;
msg->crc = crc16_data(msg->sendcmd, len, 0);
msg->crc = crc16_data((unsigned char *)msg->sendcmd, len, 0);
/* printf("sendcmd sending '%s'\n", msg->sendcmd);*/
unicast_send(&uc, &addr);
@ -160,7 +160,7 @@ recv_uc(struct unicast_conn *c, const linkaddr_t *from)
msg->sendcmd[len] = 0;
memcpy(&crc, &msg->crc, sizeof(crc));
if(crc == crc16_data(msg->sendcmd, len, 0)) {
if(crc == crc16_data((unsigned char *)msg->sendcmd, len, 0)) {
/* Start the server process with the incoming command. */
process_start(&shell_sendcmd_server_process, (void *)msg->sendcmd);
}

View File

@ -301,7 +301,7 @@ recv_collect(const linkaddr_t *originator, uint8_t seqno, uint8_t hops)
/* Copy the collect message header. */
memcpy(&collect_msg, packetbuf_dataptr(), sizeof(collect_msg));
dataptr = ((struct collect_msg *)packetbuf_dataptr())->data;
dataptr = (char *)((struct collect_msg *)packetbuf_dataptr())->data;
#if TIMESYNCH_CONF_ENABLED
latency = timesynch_time() - collect_msg.timestamp;
@ -321,7 +321,7 @@ recv_collect(const linkaddr_t *originator, uint8_t seqno, uint8_t hops)
if(packetbuf_datalen() >= COLLECT_MSG_HDRSIZE) {
len = packetbuf_datalen() - COLLECT_MSG_HDRSIZE;
if(collect_msg.crc == crc16_data(dataptr, len, 0)) {
if(collect_msg.crc == crc16_data((unsigned char *)dataptr, len, 0)) {
msg.len = 5 + (packetbuf_datalen() - COLLECT_MSG_HDRSIZE) / 2;
linkaddr_copy((linkaddr_t *)&msg.originator, originator);
msg.seqno = seqno;

View File

@ -158,7 +158,6 @@ PROCESS_THREAD(shell_repeat_server_process, ev, data)
static char *command;
static struct process *started_process;
char command_copy[MAX_COMMANDLENGTH];
int ret;
if(ev == shell_event_input) {
goto exit;
@ -172,7 +171,7 @@ PROCESS_THREAD(shell_repeat_server_process, ev, data)
data == &shell_repeat_process);
{
strncpy(command_copy, command, MAX_COMMANDLENGTH);
ret = shell_start_command(command_copy, (int)strlen(command_copy),
shell_start_command(command_copy, (int)strlen(command_copy),
&repeat_command, &started_process);
if(started_process != NULL &&
@ -202,11 +201,10 @@ repeat_print_usage(void)
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_repeat_process, ev, data)
{
static int reps, period, period_left;
static int reps, period;
static char command[MAX_COMMANDLENGTH];
static struct etimer etimer;
static int i;
static clock_time_t start_time;
const char *args, *next;
if(ev == shell_event_input) {
@ -258,7 +256,6 @@ PROCESS_THREAD(shell_repeat_process, ev, data)
/* printf("repeats %d period %d command '%s'\n",
reps, period, command);*/
start_time = clock_time();
etimer_set(&etimer, CLOCK_SECOND * period);
for(i = 0; reps == 0 || i < reps; ++i) {
@ -291,7 +288,6 @@ PROCESS_THREAD(shell_randwait_process, ev, data)
static struct etimer etimer;
static struct process *started_process;
const char *args, *next;
int ret;
/* if(ev == shell_event_input) {
struct shell_input *input;
@ -339,7 +335,7 @@ PROCESS_THREAD(shell_randwait_process, ev, data)
/* printf("Starting '%s' child %p (%s)\n", command, randwait_command.child, */
/* randwait_command.child == NULL? "null": randwait_command.child->command); */
ret = shell_start_command(command, (int)strlen(command),
shell_start_command(command, (int)strlen(command),
randwait_command.child, &started_process);
if(started_process != NULL &&

View File

@ -51,7 +51,7 @@
#define SHELL_VARS_RAM_END SHELL_VARS_CONF_RAM_END
#else /* SHELL_VARS_CONF_RAM_BEGIN */
#define SHELL_VARS_RAM_BEGIN 0
#define SHELL_VARS_RAM_END (unsigned int)-1
#define SHELL_VARS_RAM_END (uintptr_t)-1
#endif /* SHELL_VARS_CONF_RAM_BEGIN */
/*---------------------------------------------------------------------------*/
@ -77,8 +77,8 @@ PROCESS_THREAD(shell_vars_process, ev, data)
for(i = 0; i < symbols_nelts; ++i) {
if(symbols[i].name != NULL &&
(unsigned int)symbols[i].value >= SHELL_VARS_RAM_BEGIN &&
(unsigned int)symbols[i].value <= SHELL_VARS_RAM_END) {
(uintptr_t)symbols[i].value >= SHELL_VARS_RAM_BEGIN &&
(uintptr_t)symbols[i].value <= SHELL_VARS_RAM_END) {
shell_output_str(&vars_command, (char *)symbols[i].name, "");
}
}

View File

@ -222,7 +222,7 @@ static const char *tags[] = {
};
/*-----------------------------------------------------------------------------------*/
static unsigned char CC_FASTCALL
static unsigned char
iswhitespace(char c)
{
return (c == ISO_space ||
@ -255,7 +255,7 @@ htmlparser_init(void)
#endif /* WWW_CONF_FORMS */
}
/*-----------------------------------------------------------------------------------*/
static char CC_FASTCALL
static char
lowercase(char c)
{
/* XXX: This is a *brute force* approach to lower-case
@ -276,7 +276,7 @@ endtagfound(void)
s.tagattrparam[s.tagattrparamptr] = 0;
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
switch_majorstate(unsigned char newstate)
{
if(s.majorstate != newstate) {
@ -286,7 +286,7 @@ switch_majorstate(unsigned char newstate)
}
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
add_char(unsigned char c)
{
if(s.wordlen < WWW_CONF_WEBPAGE_WIDTH - 1 && c < 0x80) {
@ -320,7 +320,7 @@ newline(void)
htmlparser_newline();
}
/*-----------------------------------------------------------------------------------*/
static unsigned char CC_FASTCALL
static unsigned char
find_tag(char *tag)
{
static unsigned char first, last, i, tabi;
@ -521,7 +521,7 @@ parse_tag(void)
}
}
/*-----------------------------------------------------------------------------------*/
static uint16_t CC_FASTCALL
static uint16_t
parse_word(char *data, uint8_t dlen)
{
static uint8_t i;

View File

@ -200,7 +200,7 @@ window_copy(int curptr, const char *data, unsigned char datalen)
len = windowend - windowstart;
}
strncpy(windowptr + windowstart, data, len);
strncpy((char *)(windowptr + windowstart), data, len);
windowstart += len;
return curptr + datalen;
@ -217,7 +217,7 @@ senddata(void)
windowstart = s.getrequestptr;
curptr = 0;
windowend = windowstart + uip_mss();
windowptr = (char *)uip_appdata - windowstart;
windowptr = (unsigned char *)uip_appdata - windowstart;
curptr = window_copy(curptr, http_get, sizeof(http_get) - 1);
curptr = window_copy(curptr, s.file, (unsigned char)strlen(s.file));
@ -479,6 +479,11 @@ webclient_appcall(void *state)
if(uip_closed()) {
tcp_markconn(uip_conn, NULL);
/* Client requested close takes precedence over server initiated close. */
if(s.state == WEBCLIENT_STATE_CLOSE) {
webclient_closed();
return;
}
switch(s.httpflag) {
case HTTPFLAG_HTTPS:
/* Send some info to the user. */

View File

@ -34,12 +34,14 @@
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include "ctk/ctk.h"
#include "ctk/ctk-textentry-cmdline.h"
#include "contiki-net.h"
#include "lib/petsciiconv.h"
#include "sys/arg.h"
#include "sys/log.h"
#if WWW_CONF_WITH_WGET
#include "program-handler.h"
#endif /* WWW_CONF_WITH_WGET */
@ -50,13 +52,8 @@
#include "www.h"
#if 1
#define PRINTF(x)
#else
#include <stdio.h>
#define PRINTF(x) printf x
#endif
/* Explicitly declare itoa as it is non-standard and not necessarily in stdlib.h */
char *itoa(int value, char *str, int base);
/* The array that holds the current URL. */
static char url[WWW_CONF_MAX_URLLEN + 1];
@ -196,7 +193,7 @@ PROCESS(www_process, "Web browser");
AUTOSTART_PROCESSES(&www_process);
static void CC_FASTCALL formsubmit(struct inputattrib *trigger);
static void formsubmit(struct inputattrib *trigger);
/*-----------------------------------------------------------------------------------*/
/* make_window()
@ -232,7 +229,7 @@ redraw_window(void)
ctk_window_redraw(&mainwindow);
}
/*-----------------------------------------------------------------------------------*/
static char * CC_FASTCALL
static char *
add_pageattrib(unsigned size)
{
char *ptr;
@ -246,7 +243,7 @@ add_pageattrib(unsigned size)
}
/*-----------------------------------------------------------------------------------*/
#if WWW_CONF_FORMS
static void CC_FASTCALL
static void
add_forminput(struct inputattrib *inputptr)
{
inputptr->nextptr = NULL;
@ -285,13 +282,24 @@ start_loading(void)
clear_page();
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
show_statustext(char *text)
{
ctk_label_set_text(&statustext, text);
CTK_WIDGET_REDRAW(&statustext);
}
/*-----------------------------------------------------------------------------------*/
static void
end_page(char *status, void *focus)
{
show_statustext(status);
petsciiconv_topetscii(webpageptr - x, x);
CTK_WIDGET_FOCUS(&mainwindow, focus);
redraw_window();
log_message("Page attribs free: ", itoa(pageattribs + sizeof(pageattribs) - pageattribptr,
pageattribs + sizeof(pageattribs) - 5, 10));
}
/*-----------------------------------------------------------------------------------*/
/* open_url():
*
* Called when the URL present in the global "url" variable should be
@ -389,7 +397,7 @@ open_url(void)
* Will format a link from the current web pages so that it suits the
* open_url() function.
*/
static void CC_FASTCALL
static void
set_link(char *link)
{
register char *urlptr;
@ -609,7 +617,7 @@ PROCESS_THREAD(www_process, ev, data)
* "url" variable and the visible "editurl" (which is shown in the URL
* text entry widget in the browser window).
*/
static void CC_FASTCALL
static void
set_url(char *host, uint16_t port, char *file)
{
char *urlptr;
@ -660,10 +668,7 @@ webclient_timedout(void)
void
webclient_closed(void)
{
show_statustext("Stopped");
petsciiconv_topetscii(webpageptr - x, x);
CTK_WIDGET_FOCUS(&mainwindow, &downbutton);
redraw_window();
end_page("Stopped", &downbutton);
}
/*-----------------------------------------------------------------------------------*/
/* webclient_connected():
@ -710,6 +715,7 @@ webclient_datahandler(char *data, uint16_t len)
" Would you like to download instead?");
CTK_WIDGET_ADD(&mainwindow, &wgetnobutton);
CTK_WIDGET_ADD(&mainwindow, &wgetyesbutton);
CTK_WIDGET_FOCUS(&mainwindow, &wgetyesbutton);
redraw_window();
#endif /* CTK_CONF_WINDOWS */
#endif /* WWW_CONF_WITH_WGET || WWW_CONF_WGET_EXEC */
@ -721,14 +727,11 @@ webclient_datahandler(char *data, uint16_t len)
if(data == NULL) {
loading = 0;
show_statustext("Done");
petsciiconv_topetscii(webpageptr - x, x);
CTK_WIDGET_FOCUS(&mainwindow, &urlentry);
redraw_window();
end_page("Done", &urlentry);
}
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
unsigned char border)
{
@ -842,7 +845,9 @@ add_pagewidget(char *text, unsigned char size, char *attrib, unsigned char type,
void
htmlparser_newline(void)
{
#ifdef WITH_PETSCII
char *wptr;
#endif /* WITH_PETSCII */
if(++newlines > 2) {
return;
@ -862,8 +867,10 @@ htmlparser_newline(void)
++y;
x = 0;
#ifdef WITH_PETSCII
wptr = webpageptr - WWW_CONF_WEBPAGE_WIDTH;
petsciiconv_topetscii(wptr, WWW_CONF_WEBPAGE_WIDTH);
#endif /* WITH_PETSCII */
if(y == WWW_CONF_WEBPAGE_HEIGHT) {
loading = 0;
@ -935,7 +942,7 @@ htmlparser_inputfield(unsigned char type, unsigned char size, char *text, char *
}
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
add_query(char delimiter, char *string)
{
static char *query;
@ -963,7 +970,7 @@ add_query(char delimiter, char *string)
query += length;
}
/*-----------------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
formsubmit(struct inputattrib *trigger)
{
struct inputattrib *input;

View File

@ -1,3 +1,3 @@
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
%! tictac
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
%! tictac
</center></body></html>

View File

@ -1,3 +1,3 @@
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
%! tictac
<html><head><link rel="stylesheet" type="text/css" href="s.css"></head><body><center>
%! tictac
</center></body></html>

View File

@ -80,7 +80,7 @@ urlconv_tofilename(char *dest, char *source, unsigned char maxlen)
*dest = ISO_slash;
strncpy(dest + 1, wwwroot, wwwrootlen);
len = 0;
from = source; to = dest + wwwrootlen;
from = (unsigned char *)source; to = (unsigned char *)dest + wwwrootlen;
maxlen -= 2 + wwwrootlen;
do {
c = *(from++);
@ -139,7 +139,7 @@ urlconv_tofilename(char *dest, char *source, unsigned char maxlen)
}
} while(c);
if(*to == ISO_slash && (len + sizeof(http_index_htm) - 3) < maxlen) {
strcpy(to, http_index_htm); // add index.htm
strcpy((char *)to, http_index_htm); // add index.htm
} else {
++to;
*to = 0;

View File

@ -192,10 +192,24 @@
#define NBR_TABLE_CONF_MAX_NEIGHBORS 8
#endif /* NBR_TABLE_CONF_MAX_NEIGHBORS */
/* UIP_CONF_ND6_SEND_RA enables standard IPv6 Router Advertisement.
* We enable it by default when IPv6 is used without RPL. */
#ifndef UIP_CONF_ND6_SEND_RA
#define UIP_CONF_ND6_SEND_RA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
#endif /* UIP_CONF_ND6_SEND_RA */
/* UIP_CONF_ND6_SEND_NA enables standard IPv6 Neighbor Discovery Protocol.
This is unneeded when RPL is used. Disable to save ROM and a little RAM. */
We enable it by default when IPv6 is used without RPL.
With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping)
is fed whenever receiving DIO and DAO messages. This is always sufficient
for RPL routing, i.e. to send to the preferred parent or any child.
Link-local unicast to other neighbors may, however, not be possible if
we never receive any DIO from them. This may happen if the link from the
neighbor to us is weak, if DIO transmissions are suppressed (Trickle
timer) or if the neighbor chooses not to transmit DIOs because it is
a leaf node or for any reason. */
#ifndef UIP_CONF_ND6_SEND_NA
#define UIP_CONF_ND6_SEND_NA 1
#define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
#endif /* UIP_CONF_ND6_SEND_NA */
/*---------------------------------------------------------------------------*/

View File

@ -155,14 +155,14 @@ ctk_filedialog_eventhandler(struct ctk_filedialog_state *s,
}
return 1;
} else if(ev == ctk_signal_keypress) {
if((ctk_arch_key_t)data == CH_CURS_UP) {
if((char)(size_t)data == CH_CURS_UP) {
clearptr();
if(fileptr > 0) {
--fileptr;
}
showptr();
return 1;
} else if((ctk_arch_key_t)data == CH_CURS_DOWN) {
} else if((char)(size_t)data == CH_CURS_DOWN) {
clearptr();
if(fileptr < FILES_HEIGHT - 1) {
++fileptr;

View File

@ -185,7 +185,7 @@ unsigned short ctk_screensaver_timeout = (5*60);
static struct timer timer;
#endif /* CTK_CONF_SCREENSAVER */
static void CC_FASTCALL
static void
textentry_input(ctk_arch_key_t c,
CC_REGISTER_ARG struct ctk_textentry *t);
@ -555,7 +555,7 @@ ctk_menu_remove(struct ctk_menu *menu)
* \param clipy2 The lower bound of the clip interval
*/
/*---------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
do_redraw_all(unsigned char clipy1, unsigned char clipy2)
{
#if CTK_CONF_WINDOWS
@ -818,7 +818,7 @@ ctk_menuitem_add(CC_REGISTER_ARG struct ctk_menu *menu, char *name)
* \param w The widget that should be redrawn.
*/
/*---------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
add_redrawwidget(struct ctk_widget *w)
{
static unsigned char i;
@ -852,7 +852,9 @@ add_redrawwidget(struct ctk_widget *w)
static void
widget_redraw(struct ctk_widget *widget)
{
#if CTK_CONF_WINDOWS
struct ctk_window *window;
#endif /* CTK_CONF_WINDOWS */
if(mode != CTK_MODE_NORMAL || widget == NULL) {
return;
@ -870,8 +872,8 @@ widget_redraw(struct ctk_widget *widget)
if(menus.open == NULL)
#endif /* CTK_CONF_MENUS */
{
window = widget->window;
#if CTK_CONF_WINDOWS
window = widget->window;
if(window == dialog) {
ctk_draw_widget(widget, CTK_FOCUS_DIALOG, 0, height);
} else if(dialog == NULL &&
@ -921,7 +923,7 @@ ctk_widget_redraw(struct ctk_widget *widget)
* \param widget The widget to be added.
*/
/*---------------------------------------------------------------------------*/
void CC_FASTCALL
void
ctk_widget_add(CC_REGISTER_ARG struct ctk_window *window,
CC_REGISTER_ARG struct ctk_widget *widget)
{
@ -973,7 +975,7 @@ ctk_desktop_height(struct ctk_desktop *d)
* \param focus The widget to be focused.
*/
/*---------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
select_widget(struct ctk_widget *focus)
{
struct ctk_window *window;
@ -1001,7 +1003,7 @@ select_widget(struct ctk_widget *focus)
#define DOWN 1
#define LEFT 2
#define RIGHT 3
static void CC_FASTCALL
static void
switch_focus_widget(unsigned char direction)
{
#if CTK_CONF_WINDOWS
@ -1126,7 +1128,7 @@ switch_menu_item(unsigned char updown)
}
#endif /* CTK_CONF_MENUS */
/*---------------------------------------------------------------------------*/
static unsigned char CC_FASTCALL
static unsigned char
activate(CC_REGISTER_ARG struct ctk_widget *w)
{
if(w->type == CTK_WIDGET_BUTTON) {
@ -1183,7 +1185,7 @@ ctk_textentry_input_null(ctk_arch_key_t c, struct ctk_textentry *t)
}
#endif /* SDCC */
/*---------------------------------------------------------------------------*/
static void CC_FASTCALL
static void
textentry_input(ctk_arch_key_t c, CC_REGISTER_ARG struct ctk_textentry *t)
{
register char *cptr, *cptr2;

View File

@ -743,8 +743,8 @@ void ctk_icon_add(struct ctk_widget *icon, struct process *p);
*/
#define CTK_WIDGET_ADD(win, widg) \
ctk_widget_add(win, (struct ctk_widget *)widg)
CCIF void CC_FASTCALL ctk_widget_add(struct ctk_window *window,
struct ctk_widget *widget);
CCIF void ctk_widget_add(struct ctk_window *window,
struct ctk_widget *widget);
/**
* Set focus to a widget.

View File

@ -150,6 +150,12 @@ enum {
/* Received signal strength indicator in dBm. */
RADIO_PARAM_RSSI,
/* RSSI of the last received packet */
RADIO_PARAM_LAST_RSSI,
/* Link quality of the last received packet */
RADIO_PARAM_LAST_LINK_QUALITY,
/*
* Long (64 bits) address for the radio, which is used by the address filter.
* The address is specified in network byte order.
@ -159,6 +165,11 @@ enum {
*/
RADIO_PARAM_64BIT_ADDR,
/* Last packet timestamp, of type rtimer_clock_t.
* Because this parameter value mat be larger than what fits in radio_value_t,
* it needs to be used with radio.get_object()/set_object(). */
RADIO_PARAM_LAST_PACKET_TIMESTAMP,
/* Constants (read only) */
/* The lowest radio channel. */
@ -192,6 +203,7 @@ enum {
*/
#define RADIO_RX_MODE_ADDRESS_FILTER (1 << 0)
#define RADIO_RX_MODE_AUTOACK (1 << 1)
#define RADIO_RX_MODE_POLL_MODE (1 << 2)
/**
* The radio transmission mode controls whether transmissions should

View File

@ -293,7 +293,7 @@ PROCESS_THREAD(slip_process, ev, data)
tcpip_input();
#endif
} else {
uip_len = 0;
uip_clear_buf();
SLIP_STATISTICS(slip_ip_drop++);
}
#else /* NETSTACK_CONF_WITH_IPV6 */

View File

@ -71,12 +71,8 @@ static uint8_t round_keys[11][AES_128_KEY_LENGTH];
static uint8_t
galois_mul2(uint8_t value)
{
if(value >> 7) {
value = value << 1;
return value ^ 0x1b;
} else {
return value << 1;
}
uint8_t xor_val = (value >> 7) * 0x1b;
return ((value << 1) ^ xor_val);
}
/*---------------------------------------------------------------------------*/
static void
@ -171,17 +167,6 @@ encrypt(uint8_t *state)
}
/*---------------------------------------------------------------------------*/
void
aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len)
{
uint8_t block[AES_128_BLOCK_SIZE];
memset(block, 0, AES_128_BLOCK_SIZE);
memcpy(block, plaintext_and_result, plaintext_len);
AES_128.encrypt(block);
memcpy(plaintext_and_result, block, plaintext_len);
}
/*---------------------------------------------------------------------------*/
void
aes_128_set_padded_key(uint8_t *key, uint8_t key_len)
{
uint8_t block[AES_128_BLOCK_SIZE];

View File

@ -37,8 +37,8 @@
* Konrad Krentz <konrad.krentz@gmail.com>
*/
#ifndef AES_H_
#define AES_H_
#ifndef AES_128_H_
#define AES_128_H_
#include "contiki.h"
@ -67,11 +67,6 @@ struct aes_128_driver {
void (* encrypt)(uint8_t *plaintext_and_result);
};
/**
* \brief Pads the plaintext with zeroes before calling AES_128.encrypt
*/
void aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len);
/**
* \brief Pads the key with zeroes before calling AES_128.set_key
*/
@ -79,4 +74,4 @@ void aes_128_set_padded_key(uint8_t *key, uint8_t key_len);
extern const struct aes_128_driver AES_128;
#endif /* AES_H_ */
#endif /* AES_128_H_ */

View File

@ -48,14 +48,11 @@
/*---------------------------------------------------------------------------*/
static void
set_nonce(uint8_t *iv,
set_iv(uint8_t *iv,
uint8_t flags,
const uint8_t *nonce,
uint8_t counter)
{
/* 1 byte|| 8 bytes || 4 bytes || 1 byte || 2 bytes */
/* flags || extended_source_address || frame_counter || sec_lvl || counter */
iv[0] = flags;
memcpy(iv + 1, nonce, CCM_STAR_NONCE_LENGTH);
iv[14] = 0;
@ -73,7 +70,7 @@ ctr_step(const uint8_t *nonce,
uint8_t a[AES_128_BLOCK_SIZE];
uint8_t i;
set_nonce(a, CCM_STAR_ENCRYPTION_FLAGS, nonce, counter);
set_iv(a, CCM_STAR_ENCRYPTION_FLAGS, nonce, counter);
AES_128.encrypt(a);
for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) {
@ -82,9 +79,9 @@ ctr_step(const uint8_t *nonce,
}
/*---------------------------------------------------------------------------*/
static void
mic(const uint8_t *m, uint8_t m_len,
const uint8_t *nonce,
const uint8_t *a, uint8_t a_len,
mic(const uint8_t *nonce,
const uint8_t *m, uint8_t m_len,
const uint8_t *a, uint8_t a_len,
uint8_t *result,
uint8_t mic_len)
{
@ -92,10 +89,10 @@ mic(const uint8_t *m, uint8_t m_len,
uint8_t pos;
uint8_t i;
set_nonce(x, CCM_STAR_AUTH_FLAGS(a_len, mic_len), nonce, m_len);
set_iv(x, CCM_STAR_AUTH_FLAGS(a_len, mic_len), nonce, m_len);
AES_128.encrypt(x);
if(a_len > 0) {
if(a_len) {
x[1] = x[1] ^ a_len;
for(i = 2; (i - 2 < a_len) && (i < AES_128_BLOCK_SIZE); i++) {
x[i] ^= a[i - 2];
@ -113,8 +110,7 @@ mic(const uint8_t *m, uint8_t m_len,
}
}
if(m_len > 0) {
m = a + a_len;
if(m_len) {
pos = 0;
while(pos < m_len) {
for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) {
@ -131,7 +127,7 @@ mic(const uint8_t *m, uint8_t m_len,
}
/*---------------------------------------------------------------------------*/
static void
ctr(uint8_t *m, uint8_t m_len, const uint8_t* nonce)
ctr(const uint8_t *nonce, uint8_t *m, uint8_t m_len)
{
uint8_t pos;
uint8_t counter;
@ -144,13 +140,38 @@ ctr(uint8_t *m, uint8_t m_len, const uint8_t* nonce)
}
}
/*---------------------------------------------------------------------------*/
static void set_key(const uint8_t *key) {
AES_128.set_key((uint8_t*)key);
static void
set_key(const uint8_t *key)
{
AES_128.set_key(key);
}
/*---------------------------------------------------------------------------*/
static void
aead(const uint8_t* nonce,
uint8_t* m, uint8_t m_len,
const uint8_t* a, uint8_t a_len,
uint8_t *result, uint8_t mic_len,
int forward)
{
if(!forward) {
/* decrypt */
ctr(nonce, m, m_len);
}
mic(nonce,
m, m_len,
a, a_len,
result,
mic_len);
if(forward) {
/* encrypt */
ctr(nonce, m, m_len);
}
}
/*---------------------------------------------------------------------------*/
const struct ccm_star_driver ccm_star_driver = {
mic,
ctr,
set_key
set_key,
aead
};
/*---------------------------------------------------------------------------*/

View File

@ -55,34 +55,26 @@
*/
struct ccm_star_driver {
/**
* \brief Generates a MIC over the data supplied.
* \param data The data buffer to read.
* \param data_length The data buffer length.
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
* \param result The generated MIC will be put here
* \param mic_len The size of the MIC to be generated. <= 16.
*/
void (* mic)(const uint8_t* data, uint8_t data_length,
const uint8_t* nonce,
const uint8_t* add, uint8_t add_len,
uint8_t *result,
uint8_t mic_len);
/**
* \brief XORs the frame in the packetbuf with the key stream.
* \param data The data buffer to read.
* \param data_length The data buffer length.
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
*/
void (* ctr)( uint8_t* data, uint8_t data_length,
const uint8_t* nonce);
/**
* \brief Sets the key in use. Default implementation calls AES_128.set_key()
* \param key The key to use.
* \brief Sets the key in use. Default implementation calls AES_128.set_key().
* \param key The key to use.
*/
void (* set_key)(const uint8_t* key);
/**
* \brief Combines authentication and encryption.
* \param nonce The nonce to use. CCM_STAR_NONCE_LENGTH bytes long.
* \param m message to encrypt or decrypt
* \param a Additional authenticated data
* \param result The generated MIC will be put here
* \param mic_len The size of the MIC to be generated. <= 16.
* \param forward != 0 if used in forward direction.
*/
void (* aead)(const uint8_t* nonce,
uint8_t* m, uint8_t m_len,
const uint8_t* a, uint8_t a_len,
uint8_t *result, uint8_t mic_len,
int forward);
};
extern const struct ccm_star_driver CCM_STAR;

View File

@ -38,6 +38,7 @@
*/
#include "lib/ringbuf.h"
#include <sys/cc.h>
/*---------------------------------------------------------------------------*/
void
ringbuf_init(struct ringbuf *r, uint8_t *dataptr, uint8_t size)
@ -63,8 +64,15 @@ ringbuf_put(struct ringbuf *r, uint8_t c)
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
return 0;
}
r->data[r->put_ptr] = c;
r->put_ptr = (r->put_ptr + 1) & r->mask;
/*
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
* the access to non-volatile variables.
* In this case a reader might read from the moved index/ptr before
* its value (c) is written. Reordering makes little sense, but
* better safe than sorry.
*/
CC_ACCESS_NOW(uint8_t, r->data[r->put_ptr]) = c;
CC_ACCESS_NOW(uint8_t, r->put_ptr) = (r->put_ptr + 1) & r->mask;
return 1;
}
/*---------------------------------------------------------------------------*/
@ -84,8 +92,17 @@ ringbuf_get(struct ringbuf *r)
most platforms, but C does not guarantee this.
*/
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
c = r->data[r->get_ptr];
r->get_ptr = (r->get_ptr + 1) & r->mask;
/*
* CC_ACCESS_NOW is used because the compiler is allowed to reorder
* the access to non-volatile variables.
* In this case the memory might be freed and overwritten by
* increasing get_ptr before the value was copied to c.
* Opposed to the put-operation this would even make sense,
* because the register used for mask can be reused to save c
* (on some architectures).
*/
c = CC_ACCESS_NOW(uint8_t, r->data[r->get_ptr]);
CC_ACCESS_NOW(uint8_t, r->get_ptr) = (r->get_ptr + 1) & r->mask;
return c;
} else {
return -1;

149
core/lib/ringbufindex.c Normal file
View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* ringbufindex library. Implements basic support for ring buffers
* of any type, as opposed to the core/lib/ringbuf module which
* is only for byte arrays. Simply returns index in the ringbuf
* rather than actual elements. The ringbuf size must be power of two.
* Like the original ringbuf, this module implements atomic put and get.
* \author
* Simon Duquennoy <simonduq@sics.se>
* based on Contiki's core/lib/ringbuf library by Adam Dunkels
*/
#include <string.h>
#include "lib/ringbufindex.h"
/* Initialize a ring buffer. The size must be a power of two */
void
ringbufindex_init(struct ringbufindex *r, uint8_t size)
{
r->mask = size - 1;
r->put_ptr = 0;
r->get_ptr = 0;
}
/* Put one element to the ring buffer */
int
ringbufindex_put(struct ringbufindex *r)
{
/* Check if buffer is full. If it is full, return 0 to indicate that
the element was not inserted.
XXX: there is a potential risk for a race condition here, because
the ->get_ptr field may be written concurrently by the
ringbufindex_get() function. To avoid this, access to ->get_ptr must
be atomic. We use an uint8_t type, which makes access atomic on
most platforms, but C does not guarantee this.
*/
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
return 0;
}
r->put_ptr = (r->put_ptr + 1) & r->mask;
return 1;
}
/* Check if there is space to put an element.
* Return the index where the next element is to be added */
int
ringbufindex_peek_put(const struct ringbufindex *r)
{
/* Check if there are bytes in the buffer. If so, we return the
first one. If there are no bytes left, we return -1.
*/
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
return -1;
}
return (r->put_ptr + 1) & r->mask;
}
/* Remove the first element and return its index */
int
ringbufindex_get(struct ringbufindex *r)
{
int get_ptr;
/* Check if there are bytes in the buffer. If so, we return the
first one and increase the pointer. If there are no bytes left, we
return -1.
XXX: there is a potential risk for a race condition here, because
the ->put_ptr field may be written concurrently by the
ringbufindex_put() function. To avoid this, access to ->get_ptr must
be atomic. We use an uint8_t type, which makes access atomic on
most platforms, but C does not guarantee this.
*/
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
get_ptr = r->get_ptr;
r->get_ptr = (r->get_ptr + 1) & r->mask;
return get_ptr;
} else {
return -1;
}
}
/* Return the index of the first element
* (which will be removed if calling ringbufindex_peek) */
int
ringbufindex_peek_get(const struct ringbufindex *r)
{
/* Check if there are bytes in the buffer. If so, we return the
first one. If there are no bytes left, we return -1.
*/
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
return (r->get_ptr + 1) & r->mask;
} else {
return -1;
}
}
/* Return the ring buffer size */
int
ringbufindex_size(const struct ringbufindex *r)
{
return r->mask + 1;
}
/* Return the number of elements currently in the ring buffer */
int
ringbufindex_elements(const struct ringbufindex *r)
{
return (r->put_ptr - r->get_ptr) & r->mask;
}
/* Is the ring buffer full? */
int
ringbufindex_full(const struct ringbufindex *r)
{
return ((r->put_ptr - r->get_ptr) & r->mask) == r->mask;
}
/* Is the ring buffer empty? */
int
ringbufindex_empty(const struct ringbufindex *r)
{
return ringbufindex_elements(r) == 0;
}

72
core/lib/ringbufindex.h Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Header file for the ringbufindex library
* \author
* Simon Duquennoy <simonduq@sics.se>
*/
#ifndef __RINGBUFINDEX_H__
#define __RINGBUFINDEX_H__
#include "contiki-conf.h"
struct ringbufindex {
uint8_t mask;
/* These must be 8-bit quantities to avoid race conditions. */
uint8_t put_ptr, get_ptr;
};
/* Initialize a ring buffer. The size must be a power of two */
void ringbufindex_init(struct ringbufindex *r, uint8_t size);
/* Put one element to the ring buffer */
int ringbufindex_put(struct ringbufindex *r);
/* Check if there is space to put an element.
* Return the index where the next element is to be added */
int ringbufindex_peek_put(const struct ringbufindex *r);
/* Remove the first element and return its index */
int ringbufindex_get(struct ringbufindex *r);
/* Return the index of the first element
* (which will be removed if calling ringbufindex_peek) */
int ringbufindex_peek_get(const struct ringbufindex *r);
/* Return the ring buffer size */
int ringbufindex_size(const struct ringbufindex *r);
/* Return the number of elements currently in the ring buffer */
int ringbufindex_elements(const struct ringbufindex *r);
/* Is the ring buffer full? */
int ringbufindex_full(const struct ringbufindex *r);
/* Is the ring buffer empty? */
int ringbufindex_empty(const struct ringbufindex *r);
#endif /* __RINGBUFINDEX_H__ */

View File

@ -0,0 +1,810 @@
/*
* Copyright (c) 2015, Indian Institute of Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* MSP430x elfloader.
* \author
* Sumankumar Panchal <suman@ece.iisc.ernet.in>
*
*/
#include "contiki.h"
#include "loader/elfloader.h"
#include "loader/elfloader-arch.h"
#include "cfs/cfs.h"
#include "loader/symtab.h"
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "dev/flash.h"
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...) do {} while(0)
#endif
#define EI_NIDENT 16
struct elf32_ehdr {
unsigned char e_ident[EI_NIDENT]; /* ident bytes */
elf32_half e_type; /* file type */
elf32_half e_machine; /* target machine */
elf32_word e_version; /* file version */
elf32_addr e_entry; /* start address */
elf32_off e_phoff; /* phdr file offset */
elf32_off e_shoff; /* shdr file offset */
elf32_word e_flags; /* file flags */
elf32_half e_ehsize; /* sizeof ehdr */
elf32_half e_phentsize; /* sizeof phdr */
elf32_half e_phnum; /* number phdrs */
elf32_half e_shentsize; /* sizeof shdr */
elf32_half e_shnum; /* number shdrs */
elf32_half e_shstrndx; /* shdr string index */
};
/* Values for e_type. */
#define ET_NONE 0 /* Unknown type. */
#define ET_REL 1 /* Relocatable. */
#define ET_EXEC 2 /* Executable. */
#define ET_DYN 3 /* Shared object. */
#define ET_CORE 4 /* Core file. */
struct elf32_shdr {
elf32_word sh_name; /* section name */
elf32_word sh_type; /* SHT_... */
elf32_word sh_flags; /* SHF_... */
elf32_addr sh_addr; /* virtual address */
elf32_off sh_offset; /* file offset */
elf32_word sh_size; /* section size */
elf32_word sh_link; /* misc info */
elf32_word sh_info; /* misc info */
elf32_word sh_addralign; /* memory alignment */
elf32_word sh_entsize; /* entry size if table */
};
/* sh_type */
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program defined information */
#define SHT_SYMTAB 2 /* symbol table section */
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends*/
#define SHT_HASH 5 /* symbol hash table section */
#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relation section without addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
struct elf32_rel {
elf32_addr r_offset; /* Location to be relocated. */
elf32_word r_info; /* Relocation type and symbol index. */
};
struct elf32_sym {
elf32_word st_name; /* String table index of name. */
elf32_addr st_value; /* Symbol value. */
elf32_word st_size; /* Size of associated object. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
elf32_half st_shndx; /* Section index of symbol. */
};
#define ELF32_R_SYM(info) ((info) >> 8)
struct relevant_section {
unsigned char number;
unsigned int offset;
char *address;
};
char elfloader_unknown[30]; /* Name that caused link error. */
struct process *const *elfloader_autostart_processes;
static struct relevant_section bss, data, rodata, rodatafar, text, textfar;
static const unsigned char elf_magic_header[] =
{ 0x7f, 0x45, 0x4c, 0x46, /* 0x7f, 'E', 'L', 'F' */
0x01, /* Only 32-bit objects. */
0x01, /* Only LSB data. */
0x01, /* Only ELF version 1. */
};
/* relocation type */
#define R_MSP430_NONE 0
#define R_MSP430_32 1
#define R_MSP430_10_PCREL 2
#define R_MSP430_16 3
#define R_MSP430_16_PCREL 4
#define R_MSP430_16_BYTE 5
#define R_MSP430_16_PCREL_BYTE 6
#define R_MSP430_2X_PCREL 7
#define R_MSP430_RL_PCREL 8
#define R_MSP430X_SRC_BYTE 9
#define R_MSP430X_SRC 10
#define R_MSP430X_DST_BYTE 11
#define R_MSP430X_DST 12
#define R_MSP430X_DST_2ND_BYTE 13
#define R_MSP430X_DST_2ND 14
#define R_MSP430X_PCREL_SRC_BYTE 15
#define R_MSP430X_PCREL_SRC 16
#define R_MSP430X_PCREL_DST_BYTE 17
#define R_MSP430X_PCREL_DST 18
#define R_MSP430X_PCREL_DST_2ND 19
#define R_MSP430X_PCREL_DST_2ND_BYTE 20
#define R_MSP430X_S_BYTE 21
#define R_MSP430X_S 22
#define R_MSP430X_D_BYTE 23
#define R_MSP430X_D 24
#define R_MSP430X_PCREL_D 25
#define R_MSP430X_INDXD 26
#define R_MSP430X_PCREL_INDXD 27
#define R_MSP430_10 28
#define ELF32_R_TYPE(info) ((unsigned char)(info))
static uint16_t datamemory_aligned[ELFLOADER_DATAMEMORY_SIZE / 2 + 1];
static uint8_t *datamemory = (uint8_t *)datamemory_aligned;
#if ELFLOADER_CONF_TEXT_IN_ROM
static const char textmemory[ELFLOADER_TEXTMEMORY_SIZE] = { 0 };
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
static char textmemory[ELFLOADER_TEXTMEMORY_SIZE];
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
/*---------------------------------------------------------------------------*/
static void
seek_read(int fd, unsigned int offset, char *buf, int len)
{
cfs_seek(fd, offset, CFS_SEEK_SET);
cfs_read(fd, buf, len);
#if DEBUG
{
int i;
PRINTF("seek_read: Read len %d from offset %d\n",
len, offset);
for(i = 0; i < len; ++i) {
PRINTF("%02x ", buf[i]);
}
printf("\n");
}
#endif /* DEBUG */
}
/*---------------------------------------------------------------------------*/
static void *
find_local_symbol(int fd, const char *symbol,
unsigned int symtab, unsigned short symtabsize,
unsigned int strtab)
{
struct elf32_sym s;
unsigned int a;
char name[30];
struct relevant_section *sect;
for(a = symtab; a < symtab + symtabsize; a += sizeof(s)) {
seek_read(fd, a, (char *)&s, sizeof(s));
if(s.st_name != 0) {
seek_read(fd, strtab + s.st_name, name, sizeof(name));
if(strcmp(name, symbol) == 0) {
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == rodatafar.number) {
sect = &rodatafar;
} else if(s.st_shndx == textfar.number) {
sect = &textfar;
} else {
return NULL;
}
return &(sect->address[s.st_value]);
}
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
static int
relocate_section(int fd,
unsigned int section, unsigned short size,
unsigned int sectionaddr,
char *sectionbase,
unsigned int strs,
unsigned int strtab,
unsigned int symtab, unsigned short symtabsize,
unsigned char using_relas)
{
/*
* sectionbase added; runtime start address of current section
*/
struct elf32_rela rela; /* Now used both for rel and rela data! */
int rel_size = 0;
struct elf32_sym s;
unsigned int a;
char name[30];
char *addr;
struct relevant_section *sect;
/* determine correct relocation entry sizes */
if(using_relas) {
rel_size = sizeof(struct elf32_rela);
} else {
rel_size = sizeof(struct elf32_rel);
}
for(a = section; a < section + size; a += rel_size) {
seek_read(fd, a, (char *)&rela, rel_size);
seek_read(fd,
symtab + sizeof(struct elf32_sym) * ELF32_R_SYM(rela.r_info),
(char *)&s, sizeof(s));
if(s.st_name != 0) {
seek_read(fd, strtab + s.st_name, name, sizeof(name));
PRINTF("name: %s\n", name);
addr = (char *)symtab_lookup(name);
if(addr == NULL) {
PRINTF("name not found in global: %s\n", name);
addr = find_local_symbol(fd, name, symtab, symtabsize, strtab);
PRINTF("found address %p\n", addr);
}
if(addr == NULL) {
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == rodatafar.number) {
sect = &rodatafar;
} else if(s.st_shndx == textfar.number) {
sect = &textfar;
} else {
PRINTF("elfloader unknown name: '%30s'\n", name);
memcpy(elfloader_unknown, name, sizeof(elfloader_unknown));
elfloader_unknown[sizeof(elfloader_unknown) - 1] = 0;
return ELFLOADER_SYMBOL_NOT_FOUND;
}
addr = sect->address;
}
} else {
if(s.st_shndx == bss.number) {
sect = &bss;
} else if(s.st_shndx == data.number) {
sect = &data;
} else if(s.st_shndx == rodatafar.number) {
sect = &rodatafar;
} else if(s.st_shndx == textfar.number) {
sect = &textfar;
} else {
return ELFLOADER_SEGMENT_NOT_FOUND;
}
addr = sect->address;
}
if(!using_relas) {
/* copy addend to rela structure */
seek_read(fd, sectionaddr + rela.r_offset, (char *)&rela.r_addend, 4);
}
elfloader_arch_relocate(fd, sectionaddr, sectionbase, &rela, addr);
}
return ELFLOADER_OK;
}
/*---------------------------------------------------------------------------*/
static void *
find_program_processes(int fd,
unsigned int symtab, unsigned short size,
unsigned int strtab)
{
struct elf32_sym s;
unsigned int a;
char name[30];
for(a = symtab; a < symtab + size; a += sizeof(s)) {
seek_read(fd, a, (char *)&s, sizeof(s));
if(s.st_name != 0) {
seek_read(fd, strtab + s.st_name, name, sizeof(name));
if(strcmp(name, "autostart_processes") == 0) {
return &data.address[s.st_value];
}
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
void
elfloader_init(void)
{
elfloader_autostart_processes = NULL;
}
/*---------------------------------------------------------------------------*/
int
elfloader_load(int fd)
{
struct elf32_ehdr ehdr;
struct elf32_shdr shdr;
struct elf32_shdr strtable;
unsigned int strs;
unsigned int shdrptr;
unsigned int nameptr;
char name[17];
int i;
unsigned short shdrnum, shdrsize;
unsigned char using_relas = -1;
unsigned short textoff = 0, textfaroff = 0, textsize, textfarsize,
textrelaoff = 0, textrelasize, textfarrelaoff = 0, textfarrelasize;
unsigned short dataoff = 0, datasize, datarelaoff = 0, datarelasize;
unsigned short rodataoff = 0, rodatafaroff = 0, rodatasize, rodatafarsize,
rodatarelaoff = 0, rodatarelasize, rodatafarrelaoff = 0,
rodatafarrelasize;
unsigned short symtaboff = 0, symtabsize;
unsigned short strtaboff = 0, strtabsize;
unsigned short bsssize = 0;
struct process **process;
int ret;
elfloader_unknown[0] = 0;
/* The ELF header is located at the start of the buffer. */
seek_read(fd, 0, (char *)&ehdr, sizeof(ehdr));
/* Make sure that we have a correct and compatible ELF header. */
if(memcmp(ehdr.e_ident, elf_magic_header, sizeof(elf_magic_header)) != 0) {
PRINTF("ELF header problems\n");
return ELFLOADER_BAD_ELF_HEADER;
}
/* Grab the section header. */
shdrptr = ehdr.e_shoff;
seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
/* Get the size and number of entries of the section header. */
shdrsize = ehdr.e_shentsize;
shdrnum = ehdr.e_shnum;
PRINTF("Section header: size %d num %d\n", shdrsize, shdrnum);
/* The string table section: holds the names of the sections. */
seek_read(fd, ehdr.e_shoff + shdrsize * ehdr.e_shstrndx,
(char *)&strtable, sizeof(strtable));
/*
* Get a pointer to the actual table of strings. This table holds
* the names of the sections, not the names of other symbols in the
* file (these are in the sybtam section).
*/
strs = strtable.sh_offset;
PRINTF("Strtable offset %d\n", strs);
/*
* Go through all sections and pick out the relevant ones. The
* ".text" and ".far.text" segments holds the actual code from
* the ELF file. The ".data" segment contains initialized data.
* The ".bss" segment holds the size of the unitialized data segment.
* The ".rodata" and ".far.rodata" segments contains constant data.
* The ".rela[a].text" and ".rela[a].far.text" segments contains
* relocation information for the contents of the ".text" and
* ".far.text" segments, respectively. The ".rela[a].rodata" and
* ".rela[a].far.rodata" segments contains relocation information
* for the contents of the ".rodata" and ".far.rodata" segments,
* respectively. The ".rela[a].data" segment contains relocation
* information for the contents of the ".data" segment. The ".symtab"
* segment contains the symbol table for this file. The ".strtab"
* segment points to the actual string names used by the symbol table.
*
* In addition to grabbing pointers to the relevant sections, we
* also save the section number for resolving addresses in the
* relocator code.
*/
/*
* Initialize the segment sizes to zero so that we can check if
* their sections was found in the file or not.
*/
textsize = textfarsize = textrelasize = textfarrelasize =
datasize = datarelasize = rodatasize = rodatafarsize =
rodatarelasize = rodatafarrelasize = symtabsize = strtabsize = 0;
bss.number = data.number = rodata.number = rodatafar.number =
text.number = textfar.number = -1;
shdrptr = ehdr.e_shoff;
for(i = 0; i < shdrnum; ++i) {
seek_read(fd, shdrptr, (char *)&shdr, sizeof(shdr));
/* The name of the section is contained in the strings table. */
nameptr = strs + shdr.sh_name;
seek_read(fd, nameptr, name, sizeof(name));
PRINTF("Section shdrptr 0x%x, %d + %d type %d\n",
shdrptr,
strs, shdr.sh_name,
(int)shdr.sh_type);
/*
* Match the name of the section with a predefined set of names
* (.text, .far.text, .data, .bss, .rodata, .far.rodata, .rela.text, .rela.far.text,
* .rela.data, .rela.rodata, .rela.far.rodata, .symtab, and .strtab).
*/
if(shdr.sh_type == SHT_SYMTAB) {
PRINTF("symtab\n");
symtaboff = shdr.sh_offset;
symtabsize = shdr.sh_size;
} else if(shdr.sh_type == SHT_STRTAB) {
PRINTF("strtab\n");
strtaboff = shdr.sh_offset;
strtabsize = shdr.sh_size;
} else if(strncmp(name, ".text", 5) == 0) {
textoff = shdr.sh_offset;
textsize = shdr.sh_size;
text.number = i;
text.offset = textoff;
} else if(strncmp(name, ".far.text", 9) == 0) {
textfaroff = shdr.sh_offset;
textfarsize = shdr.sh_size;
textfar.number = i;
textfar.offset = textfaroff;
} else if(strncmp(name, ".rel.text", 9) == 0) {
using_relas = 0;
textrelaoff = shdr.sh_offset;
textrelasize = shdr.sh_size;
} else if(strncmp(name, ".rela.text", 10) == 0) {
using_relas = 1;
textrelaoff = shdr.sh_offset;
textrelasize = shdr.sh_size;
} else if(strncmp(name, ".rela.far.text", 14) == 0) {
using_relas = 1;
textfarrelaoff = shdr.sh_offset;
textfarrelasize = shdr.sh_size;
} else if(strncmp(name, ".data", 5) == 0) {
dataoff = shdr.sh_offset;
datasize = shdr.sh_size;
data.number = i;
data.offset = dataoff;
} else if(strncmp(name, ".rodata", 7) == 0) {
/* read-only data handled the same way as regular text section */
rodataoff = shdr.sh_offset;
rodatasize = shdr.sh_size;
rodata.number = i;
rodata.offset = rodataoff;
} else if(strncmp(name, ".far.rodata", 11) == 0) {
rodatafaroff = shdr.sh_offset;
rodatafarsize = shdr.sh_size;
rodatafar.number = i;
rodatafar.offset = rodataoff;
} else if(strncmp(name, ".rel.rodata", 11) == 0) {
/* using elf32_rel instead of rela */
using_relas = 0;
rodatarelaoff = shdr.sh_offset;
rodatarelasize = shdr.sh_size;
} else if(strncmp(name, ".rela.rodata", 12) == 0) {
using_relas = 1;
rodatarelaoff = shdr.sh_offset;
rodatarelasize = shdr.sh_size;
} else if(strncmp(name, ".rela.far.rodata", 16) == 0) {
using_relas = 1;
rodatafarrelaoff = shdr.sh_offset;
rodatafarrelasize = shdr.sh_size;
} else if(strncmp(name, ".rel.data", 9) == 0) {
/* using elf32_rel instead of rela */
using_relas = 0;
datarelaoff = shdr.sh_offset;
datarelasize = shdr.sh_size;
} else if(strncmp(name, ".rela.data", 10) == 0) {
using_relas = 1;
datarelaoff = shdr.sh_offset;
datarelasize = shdr.sh_size;
} else if(strncmp(name, ".bss", 4) == 0) {
bsssize = shdr.sh_size;
bss.number = i;
bss.offset = 0;
}
/* Move on to the next section header. */
shdrptr += shdrsize;
}
if(symtabsize == 0) {
return ELFLOADER_NO_SYMTAB;
}
if(strtabsize == 0) {
return ELFLOADER_NO_STRTAB;
}
if(textfarsize == 0) {
return ELFLOADER_NO_TEXT;
}
PRINTF("before allocate ram\n");
bss.address = (char *)elfloader_arch_allocate_ram(bsssize + datasize);
data.address = (char *)bss.address + bsssize;
PRINTF("before allocate rom\n");
textfar.address = (char *)elfloader_arch_allocate_rom(textfarsize + rodatafarsize);
rodatafar.address = (char *)textfar.address + textfarsize;
PRINTF("bss base address: bss.address = 0x%08x\n", bss.address);
PRINTF("data base address: data.address = 0x%08x\n", data.address);
PRINTF("textfar base address: textfar.address = 0x%08x\n", textfar.address);
PRINTF("rodatafar base address: rodatafar.address = 0x%08x\n", rodatafar.address);
/* If we have text segment relocations, we process them. */
PRINTF("elfloader: relocate textfar\n");
if(textfarrelasize > 0) {
ret = relocate_section(fd,
textfarrelaoff, textfarrelasize,
textfaroff,
textfar.address,
strs,
strtaboff,
symtaboff, symtabsize, using_relas);
if(ret != ELFLOADER_OK) {
return ret;
}
}
/* If we have any rodata segment relocations, we process them too. */
PRINTF("elfloader: relocate rodata\n");
if(rodatafarrelasize > 0) {
ret = relocate_section(fd,
rodatafarrelaoff, rodatafarrelasize,
rodatafaroff,
rodatafar.address,
strs,
strtaboff,
symtaboff, symtabsize, using_relas);
if(ret != ELFLOADER_OK) {
PRINTF("elfloader: data failed\n");
return ret;
}
}
/* If we have any data segment relocations, we process them too. */
PRINTF("elfloader: relocate data\n");
if(datarelasize > 0) {
ret = relocate_section(fd,
datarelaoff, datarelasize,
dataoff,
data.address,
strs,
strtaboff,
symtaboff, symtabsize, using_relas);
if(ret != ELFLOADER_OK) {
PRINTF("elfloader: data failed\n");
return ret;
}
}
/* Write text and rodata segment into flash and data segment into RAM. */
elfloader_arch_write_rom(fd, textfaroff, textfarsize, textfar.address);
elfloader_arch_write_rom(fd, rodatafaroff, rodatafarsize, rodatafar.address);
memset(bss.address, 0, bsssize);
seek_read(fd, dataoff, data.address, datasize);
PRINTF("elfloader: autostart search\n");
process = (struct process **)find_local_symbol(fd, "autostart_processes",
symtaboff, symtabsize, strtaboff);
if(process != NULL) {
PRINTF("elfloader: autostart found\n");
elfloader_autostart_processes = process;
return ELFLOADER_OK;
} else {
PRINTF("elfloader: no autostart\n");
process = (struct process **)find_program_processes(fd, symtaboff,
symtabsize, strtaboff);
if(process != NULL) {
PRINTF("elfloader: FOUND PRG\n");
}
return ELFLOADER_NO_STARTPOINT;
}
}
/*---------------------------------------------------------------------------*/
void *
elfloader_arch_allocate_ram(int size)
{
return datamemory;
}
/*---------------------------------------------------------------------------*/
void *
elfloader_arch_allocate_rom(int size)
{
#if ELFLOADER_CONF_TEXT_IN_ROM
/* Return an 512-byte aligned pointer. */
return (char *)
((unsigned long)&textmemory[0] & 0xfffffe00) +
(((unsigned long)&textmemory[0] & 0x1ff) == 0 ? 0 : 0x200);
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
return textmemory;
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
}
/*---------------------------------------------------------------------------*/
#define READSIZE 32
void
elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem)
{
#if ELFLOADER_CONF_TEXT_IN_ROM
int i;
unsigned int ptr;
unsigned short *flashptr;
flash_setup();
flashptr = (unsigned short *)mem;
cfs_seek(fd, textoff, CFS_SEEK_SET);
for(ptr = 0; ptr < size; ptr += READSIZE) {
/* Read data from file into RAM. */
cfs_read(fd, (unsigned char *)datamemory, READSIZE);
/* Clear flash page on 512 byte boundary. */
if((((unsigned short)flashptr) & 0x01ff) == 0) {
flash_clear(flashptr);
}
/*
* Burn data from RAM into flash ROM. Flash is burned one 16-bit
* word at a time, so we need to be careful when incrementing
* pointers. The flashptr is already a short pointer, so
* incrementing it by one will actually increment the address by
* two.
*/
for(i = 0; i < READSIZE / 2; ++i) {
flash_write(flashptr, ((unsigned short *)datamemory)[i]);
++flashptr;
}
}
flash_done();
#else /* ELFLOADER_CONF_TEXT_IN_ROM */
cfs_seek(fd, textoff, CFS_SEEK_SET);
cfs_read(fd, (unsigned char *)mem, size);
#endif /* ELFLOADER_CONF_TEXT_IN_ROM */
}
/*---------------------------------------------------------------------------*/
/* Relocate an MSP430X ELF section. */
void
elfloader_arch_relocate(int fd, unsigned int sectionoffset,
char *sectionaddr,
struct elf32_rela *rela, char *addr)
{
unsigned int type;
unsigned char instr[2];
type = ELF32_R_TYPE(rela->r_info);
addr += rela->r_addend;
switch(type) {
case R_MSP430_16:
case R_MSP430_16_PCREL:
case R_MSP430_16_BYTE:
case R_MSP430_16_PCREL_BYTE:
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430_32:
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_S:
case R_MSP430X_S_BYTE:
/* src(19:16) located at positions 11:8 of opcode */
/* src(15:0) located just after opcode */
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_read(fd, instr, 2);
instr[1] = (int)(instr[1]) & 0xf0 | (((long int)addr >> 8) & 0x0f00);
instr[0] = (int)(instr[0]) & 0xff;
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, instr, 2);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_D:
case R_MSP430X_PCREL_D:
case R_MSP430X_D_BYTE:
/* dst(19:16) located at positions 3:0 of opcode */
/* dst(15:0) located just after opcode */
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_read(fd, instr, 2);
instr[1] = (int)(instr[1]) & 0xff;
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, instr, 2);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_PCREL_SRC_BYTE:
case R_MSP430X_SRC_BYTE:
case R_MSP430X_PCREL_SRC:
case R_MSP430X_SRC:
/* src(19:16) located at positions 10:7 of extension word */
/* src(15:0) located just after opcode */
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_read(fd, instr, 2);
/* 4 most-significant bits */
instr[1] = (int)(instr[1]) & 0xf8 | (((long int)addr >> 9) & 0x0780);
instr[0] = (int)(instr[0]) & 0x7f | (((long int)addr >> 9) & 0x0780);
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, instr, 2);
/* 16 least-significant bits */
cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_DST_BYTE:
case R_MSP430X_PCREL_DST_BYTE:
case R_MSP430X_DST:
case R_MSP430X_PCREL_DST:
/* dst(19:16) located at positions 3:0 of extension word */
/* dst(15:0) located just after opcode */
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_read(fd, instr, 2);
instr[1] = (int)(instr[1]) & 0xff;
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, instr, 2);
cfs_seek(fd, sectionoffset + rela->r_offset + 0x04, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_DST_2ND:
case R_MSP430X_PCREL_DST_2ND:
case R_MSP430X_DST_2ND_BYTE:
case R_MSP430X_PCREL_DST_2ND_BYTE:
/* dst(19:16) located at positions 3:0 of extension word */
/* dst(15:0) located after src(15:0) */
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_read(fd, instr, 2);
instr[1] = (int)(instr[1]) & 0xff;
instr[0] = (int)(instr[0]) & 0xf0 | (((long int)addr >> 16) & 0x000f);
cfs_seek(fd, sectionoffset + rela->r_offset, CFS_SEEK_SET);
cfs_write(fd, instr, 2);
cfs_seek(fd, sectionoffset + rela->r_offset + 0x06, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
case R_MSP430X_INDXD:
case R_MSP430X_PCREL_INDXD:
cfs_seek(fd, sectionoffset + rela->r_offset + 0x02, CFS_SEEK_SET);
cfs_write(fd, (char *)&addr, 2);
break;
default:
PRINTF("Unknown relocation type!\n");
break;
}
}
/*---------------------------------------------------------------------------*/

View File

@ -34,6 +34,20 @@
#include "net/ip/uip.h"
/**
* \brief Is IPv4-mapped Address
*
* See https://tools.ietf.org/html/rfc6890#page-14
*/
#define ip64_addr_is_ipv4_mapped_addr(a) \
((((a)->u16[0]) == 0) && \
(((a)->u16[1]) == 0) && \
(((a)->u16[2]) == 0) && \
(((a)->u16[3]) == 0) && \
(((a)->u16[4]) == 0) && \
(((a)->u16[5]) == 0xFFFF))
void ip64_addr_copy4(uip_ip4addr_t *dest, const uip_ip4addr_t *src);
void ip64_addr_copy6(uip_ip6addr_t *dest, const uip_ip6addr_t *src);

View File

@ -501,7 +501,7 @@ mdns_write_announce_records(unsigned char *queryptr, uint8_t *count)
for(i = 0; i < UIP_DS6_ADDR_NB; ++i) {
if(uip_ds6_if.addr_list[i].isused
#if !RESOLV_CONF_MDNS_INCLUDE_GLOBAL_V6_ADDRS
&& uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)
&& uip_is_addr_linklocal(&uip_ds6_if.addr_list[i].ipaddr)
#endif
) {
if(!*count) {

View File

@ -155,6 +155,7 @@ unsigned char tcpip_is_forwarding; /* Forwarding right now? */
PROCESS(tcpip_process, "TCP/IP stack");
/*---------------------------------------------------------------------------*/
#if UIP_TCP || UIP_CONF_IP_FORWARD
static void
start_periodic_tcp_timer(void)
{
@ -162,6 +163,7 @@ start_periodic_tcp_timer(void)
etimer_restart(&periodic);
}
}
#endif /* UIP_TCP || UIP_CONF_IP_FORWARD */
/*---------------------------------------------------------------------------*/
static void
check_for_tcp_syn(void)
@ -183,30 +185,17 @@ check_for_tcp_syn(void)
static void
packet_input(void)
{
#if UIP_CONF_IP_FORWARD
if(uip_len > 0) {
#if UIP_CONF_IP_FORWARD
tcpip_is_forwarding = 1;
if(uip_fw_forward() == UIP_FW_LOCAL) {
if(uip_fw_forward() != UIP_FW_LOCAL) {
tcpip_is_forwarding = 0;
check_for_tcp_syn();
uip_input();
if(uip_len > 0) {
#if UIP_CONF_TCP_SPLIT
uip_split_output();
#else /* UIP_CONF_TCP_SPLIT */
#if NETSTACK_CONF_WITH_IPV6
tcpip_ipv6_output();
#else
PRINTF("tcpip packet_input forward output len %d\n", uip_len);
tcpip_output();
#endif
#endif /* UIP_CONF_TCP_SPLIT */
}
return;
}
tcpip_is_forwarding = 0;
}
#else /* UIP_CONF_IP_FORWARD */
if(uip_len > 0) {
#endif /* UIP_CONF_IP_FORWARD */
check_for_tcp_syn();
uip_input();
if(uip_len > 0) {
@ -215,14 +204,13 @@ packet_input(void)
#else /* UIP_CONF_TCP_SPLIT */
#if NETSTACK_CONF_WITH_IPV6
tcpip_ipv6_output();
#else
#else /* NETSTACK_CONF_WITH_IPV6 */
PRINTF("tcpip packet_input output len %d\n", uip_len);
tcpip_output();
#endif
#endif /* NETSTACK_CONF_WITH_IPV6 */
#endif /* UIP_CONF_TCP_SPLIT */
}
}
#endif /* UIP_CONF_IP_FORWARD */
}
/*---------------------------------------------------------------------------*/
#if UIP_TCP
@ -529,10 +517,7 @@ void
tcpip_input(void)
{
process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
uip_len = 0;
#if NETSTACK_CONF_WITH_IPV6
uip_ext_len = 0;
#endif /*NETSTACK_CONF_WITH_IPV6*/
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
#if NETSTACK_CONF_WITH_IPV6
@ -548,13 +533,13 @@ tcpip_ipv6_output(void)
if(uip_len > UIP_LINK_MTU) {
UIP_LOG("tcpip_ipv6_output: Packet to big");
uip_len = 0;
uip_clear_buf();
return;
}
if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
uip_len = 0;
uip_clear_buf();
return;
}
@ -587,11 +572,20 @@ tcpip_ipv6_output(void)
/* This should be copied from the ext header... */
UIP_IP_BUF->proto = proto;
}
UIP_FALLBACK_INTERFACE.output();
/* Inform the other end that the destination is not reachable. If it's
* not informed routes might get lost unexpectedly until there's a need
* to send a new packet to the peer */
if(UIP_FALLBACK_INTERFACE.output() < 0) {
PRINTF("FALLBACK: output error. Reporting DST UNREACH\n");
uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0);
uip_flags = 0;
tcpip_ipv6_output();
return;
}
#else
PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif /* !UIP_FALLBACK_INTERFACE */
uip_len = 0;
uip_clear_buf();
return;
}
@ -643,7 +637,7 @@ tcpip_ipv6_output(void)
#if UIP_CONF_IPV6_RPL
if(rpl_update_header_final(nexthop)) {
uip_len = 0;
uip_clear_buf();
return;
}
#endif /* UIP_CONF_IPV6_RPL */
@ -651,7 +645,7 @@ tcpip_ipv6_output(void)
if(nbr == NULL) {
#if UIP_ND6_SEND_NA
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
uip_len = 0;
uip_clear_buf();
return;
} else {
#if UIP_CONF_IPV6_QUEUE_PKT
@ -675,7 +669,11 @@ tcpip_ipv6_output(void)
stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
nbr->nscount = 1;
/* Send the first NS try from here (multicast destination IP address). */
}
#else /* UIP_ND6_SEND_NA */
uip_len = 0;
return;
#endif /* UIP_ND6_SEND_NA */
} else {
#if UIP_ND6_SEND_NA
@ -689,7 +687,7 @@ tcpip_ipv6_output(void)
uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
}
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
uip_len = 0;
uip_clear_buf();
return;
}
/* Send in parallel if we are running NUD (nbc state is either STALE,
@ -719,15 +717,13 @@ tcpip_ipv6_output(void)
}
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
uip_len = 0;
uip_clear_buf();
return;
}
return;
}
/* Multicast IP destination address. */
tcpip_output(NULL);
uip_len = 0;
uip_ext_len = 0;
uip_clear_buf();
}
#endif /* NETSTACK_CONF_WITH_IPV6 */
/*---------------------------------------------------------------------------*/

View File

@ -38,6 +38,7 @@
*/
#include "net/ip/uip-debug.h"
#include "net/ip/ip64-addr.h"
/*---------------------------------------------------------------------------*/
void
@ -53,20 +54,38 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr)
return;
}
#if NETSTACK_CONF_WITH_IPV6
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (addr->u8[i] << 8) + addr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) {
PRINTA("::");
if(ip64_addr_is_ipv4_mapped_addr(addr)) {
/*
* Printing IPv4-mapped addresses is done according to RFC 3513 [1]
*
* "An alternative form that is sometimes more
* convenient when dealing with a mixed environment
* of IPv4 and IPv6 nodes is x:x:x:x:x:x:d.d.d.d,
* where the 'x's are the hexadecimal values of the
* six high-order 16-bit pieces of the address, and
* the 'd's are the decimal values of the four
* low-order 8-bit pieces of the address (standard
* IPv4 representation)."
*
* [1] https://tools.ietf.org/html/rfc3513#page-5
*/
PRINTA("::FFFF:%u.%u.%u.%u", addr->u8[12], addr->u8[13], addr->u8[14], addr->u8[15]);
} else {
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (addr->u8[i] << 8) + addr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) {
PRINTA("::");
}
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
PRINTA(":");
}
PRINTA("%x", a);
}
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
PRINTA(":");
}
PRINTA("%x", a);
}
}
}
#else /* NETSTACK_CONF_WITH_IPV6 */
PRINTA("%u.%u.%u.%u", addr->u8[0], addr->u8[1], addr->u8[2], addr->u8[3]);

View File

@ -54,9 +54,9 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
if(data != NULL) {
uip_udp_conn = c;
uip_slen = len;
memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
memmove(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
uip_process(UIP_UDP_SEND_CONN);
#if UIP_CONF_IPV6_MULTICAST

View File

@ -64,17 +64,11 @@
#define UIP_TCPH_LEN 20 /* Size of TCP header */
#define UIP_ICMPH_LEN 4 /* Size of ICMP header */
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
* UDP
* header */
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
* TCP
* header */
#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */
#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */
#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* size of ICMP
+ IP header */
#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* size of L2
+ IP header */
#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* Size of ICMP + IP header */
#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* Size of L2 + IP header */
#if NETSTACK_CONF_WITH_IPV6
/**
* The sums below are quite used in ND. When used for uip_buf, we
@ -99,12 +93,12 @@
*
*/
typedef union uip_ip4addr_t {
uint8_t u8[4]; /* Initializer, must come first. */
uint8_t u8[4]; /* Initializer, must come first. */
uint16_t u16[2];
} uip_ip4addr_t;
typedef union uip_ip6addr_t {
uint8_t u8[16]; /* Initializer, must come first. */
uint8_t u8[16]; /* Initializer, must come first. */
uint16_t u16[8];
} uip_ip6addr_t;
@ -142,15 +136,18 @@ typedef struct uip_eth_addr {
typedef uip_802154_longaddr uip_lladdr_t;
#define UIP_802154_SHORTADDR_LEN 2
#define UIP_802154_LONGADDR_LEN 8
/** \brief Link layer address length */
#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
#else /*UIP_CONF_LL_802154*/
#if UIP_CONF_LL_80211
/** \brief 802.11 address */
typedef uip_80211_addr uip_lladdr_t;
/** \brief Link layer address length */
#define UIP_LLADDR_LEN 6
#else /*UIP_CONF_LL_80211*/
/** \brief Ethernet address */
typedef uip_eth_addr uip_lladdr_t;
/** \brief Link layer address length */
#define UIP_LLADDR_LEN 6
#endif /*UIP_CONF_LL_80211*/
#endif /*UIP_CONF_LL_802154*/
@ -1057,7 +1054,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport);
* \hideinitializer
*/
#define uip_ip4addr_cmp(addr1, addr2) ((addr1)->u16[0] == (addr2)->u16[0] && \
(addr1)->u16[1] == (addr2)->u16[1])
(addr1)->u16[1] == (addr2)->u16[1])
#define uip_ip6addr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
#if NETSTACK_CONF_WITH_IPV6
@ -1326,6 +1323,22 @@ extern uint8_t uip_ext_len;
extern uint16_t uip_urglen, uip_surglen;
#endif /* UIP_URGDATA > 0 */
/*
* Clear uIP buffer
*
* This function clears the uIP buffer by reseting the uip_len and
* uip_ext_len pointers.
*/
#if NETSTACK_CONF_WITH_IPV6
#define uip_clear_buf() { \
uip_len = 0; \
uip_ext_len = 0; \
}
#else /*NETSTACK_CONF_WITH_IPV6*/
#define uip_clear_buf() { \
uip_len = 0; \
}
#endif /*NETSTACK_CONF_WITH_IPV6*/
/**
* Representation of a uIP TCP connection.
@ -1342,29 +1355,23 @@ struct uip_conn {
uint16_t lport; /**< The local TCP port, in network byte order. */
uint16_t rport; /**< The local remote TCP port, in network byte
order. */
order. */
uint8_t rcv_nxt[4]; /**< The sequence number that we expect to
receive next. */
uint8_t snd_nxt[4]; /**< The sequence number that was last sent by
us. */
receive next. */
uint8_t snd_nxt[4]; /**< The sequence number that was last sent by us. */
uint16_t len; /**< Length of the data that was previously sent. */
uint16_t mss; /**< Current maximum segment size for the
connection. */
uint16_t initialmss; /**< Initial maximum segment size for the
connection. */
uint8_t sa; /**< Retransmission time-out calculation state
variable. */
uint8_t sv; /**< Retransmission time-out calculation state
variable. */
uint16_t mss; /**< Current maximum segment size for the connection. */
uint16_t initialmss; /**< Initial maximum segment size for the connection. */
uint8_t sa; /**< Retransmission time-out calculation state variable. */
uint8_t sv; /**< Retransmission time-out calculation state variable. */
uint8_t rto; /**< Retransmission time-out. */
uint8_t tcpstateflags; /**< TCP state and flags. */
uint8_t timer; /**< The retransmission timer. */
uint8_t nrtx; /**< The number of retransmissions for the last
segment sent. */
segment sent. */
/** The application state. */
uip_tcp_appstate_t appstate;
uip_tcp_appstate_t appstate; /** The application state. */
};
@ -1413,7 +1420,13 @@ extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
struct uip_fallback_interface {
void (*init)(void);
void (*output)(void);
/**
* \retval >=0
* in case of success
* \retval <0
* in case of failure
*/
int (*output)(void);
};
#if UIP_CONF_ICMP6
@ -1442,51 +1455,43 @@ extern struct uip_stats uip_stat;
*/
struct uip_stats {
struct {
uip_stats_t recv; /**< Number of received packets at the IP
layer. */
uip_stats_t sent; /**< Number of sent packets at the IP
layer. */
uip_stats_t forwarded;/**< Number of forwarded packets at the IP
layer. */
uip_stats_t drop; /**< Number of dropped packets at the IP
layer. */
uip_stats_t recv; /**< Number of received packets at the IP layer. */
uip_stats_t sent; /**< Number of sent packets at the IP layer. */
uip_stats_t forwarded;/**< Number of forwarded packets at the IP layer. */
uip_stats_t drop; /**< Number of dropped packets at the IP layer. */
uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
IP version or header length. */
IP version or header length. */
uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
IP length, high byte. */
IP length, high byte. */
uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
IP length, low byte. */
IP length, low byte. */
uip_stats_t fragerr; /**< Number of packets dropped because they
were IP fragments. */
were IP fragments. */
uip_stats_t chkerr; /**< Number of packets dropped due to IP
checksum errors. */
checksum errors. */
uip_stats_t protoerr; /**< Number of packets dropped because they
were neither ICMP, UDP nor TCP. */
were neither ICMP, UDP nor TCP. */
} ip; /**< IP statistics. */
struct {
uip_stats_t recv; /**< Number of received ICMP packets. */
uip_stats_t sent; /**< Number of sent ICMP packets. */
uip_stats_t drop; /**< Number of dropped ICMP packets. */
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
type. */
uip_stats_t chkerr; /**< Number of ICMP packets with a bad
checksum. */
uip_stats_t typeerr; /**< Number of ICMP packets with a wrong type. */
uip_stats_t chkerr; /**< Number of ICMP packets with a bad checksum. */
} icmp; /**< ICMP statistics. */
#if UIP_TCP
struct {
uip_stats_t recv; /**< Number of recived TCP segments. */
uip_stats_t sent; /**< Number of sent TCP segments. */
uip_stats_t drop; /**< Number of dropped TCP segments. */
uip_stats_t chkerr; /**< Number of TCP segments with a bad
checksum. */
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
number. */
uip_stats_t chkerr; /**< Number of TCP segments with a bad checksum. */
uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK number. */
uip_stats_t rst; /**< Number of received TCP RST (reset) segments. */
uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
uip_stats_t syndrop; /**< Number of dropped SYNs because too few
connections were available. */
connections were available. */
uip_stats_t synrst; /**< Number of SYNs for closed ports,
triggering a RST. */
triggering a RST. */
} tcp; /**< TCP statistics. */
#endif
#if UIP_UDP
@ -1495,7 +1500,7 @@ struct uip_stats {
uip_stats_t recv; /**< Number of recived UDP segments. */
uip_stats_t sent; /**< Number of sent UDP segments. */
uip_stats_t chkerr; /**< Number of UDP segments with a bad
checksum. */
checksum. */
} udp; /**< UDP statistics. */
#endif /* UIP_UDP */
#if NETSTACK_CONF_WITH_IPV6
@ -1532,33 +1537,33 @@ CCIF extern uint8_t uip_flags;
functions/macros. */
#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
acked and the application should send
out new data instead of retransmitting
the last data. */
acked and the application should send
out new data instead of retransmitting
the last data. */
#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
us new data. */
us new data. */
#define UIP_REXMIT 4 /* Tells the application to retransmit the
data that was last sent. */
data that was last sent. */
#define UIP_POLL 8 /* Used for polling the application, to
check if the application has data that
it wants to send. */
check if the application has data that
it wants to send. */
#define UIP_CLOSE 16 /* The remote host has closed the
connection, thus the connection has
gone away. Or the application signals
that it wants to close the
connection. */
connection, thus the connection has
gone away. Or the application signals
that it wants to close the
connection. */
#define UIP_ABORT 32 /* The remote host has aborted the
connection, thus the connection has
gone away. Or the application signals
that it wants to abort the
connection. */
connection, thus the connection has
gone away. Or the application signals
that it wants to abort the
connection. */
#define UIP_CONNECTED 64 /* We have got a connection from a remote
host and have set up a new connection
for it, or an active connection has
been successfully established. */
#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
too many retransmissions. */
too many retransmissions. */
/**
@ -1584,16 +1589,16 @@ void uip_process(uint8_t flag);
the macros defined in this file. */
#define UIP_DATA 1 /* Tells uIP that there is incoming
data in the uip_buf buffer. The
length of the data is stored in the
global variable uip_len. */
data in the uip_buf buffer. The
length of the data is stored in the
global variable uip_len. */
#define UIP_TIMER 2 /* Tells uIP that the periodic timer
has fired. */
has fired. */
#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
be polled. */
be polled. */
#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
should be constructed in the
uip_buf buffer. */
should be constructed in the
uip_buf buffer. */
#if UIP_UDP
#define UIP_UDP_TIMER 5
#endif /* UIP_UDP */
@ -2000,8 +2005,9 @@ CCIF extern uip_lladdr_t uip_lladdr;
(((a)->u8[15]) == 0x02))
/**
* \brief Checks whether the address a is link local.
* a is of type uip_ipaddr_t
* \brief is addr (a) a link local unicast address, see RFC3513
* i.e. is (a) on prefix FE80::/10
* a is of type uip_ipaddr_t*
*/
#define uip_is_addr_linklocal(a) \
((a)->u8[0] == 0xfe && \
@ -2054,15 +2060,6 @@ CCIF extern uip_lladdr_t uip_lladdr;
(((b)->u8[13]) = ((a)->u8[13])); \
(((b)->u16[7]) = ((a)->u16[7]))
/**
* \brief is addr (a) a link local unicast address, see RFC3513
* i.e. is (a) on prefix FE80::/10
* a is of type uip_ipaddr_t*
*/
#define uip_is_addr_link_local(a) \
((((a)->u8[0]) == 0xFE) && \
(((a)->u8[1]) == 0x80))
/**
* \brief was addr (a) forged based on the mac address m
* a type is uip_ipaddr_t

View File

@ -35,9 +35,14 @@
#include "ip64-tap-driver.h"
#include "ip64-eth-interface.h"
#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
#define IP64_CONF_INPUT ip64_eth_interface_input
#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
#define IP64_CONF_INPUT ip64_eth_interface_input
#define IP64_CONF_ETH_DRIVER ip64_tap_driver
#define IP64_CONF_ETH_DRIVER ip64_tap_driver
/*
* In contrast to the mandatory parameters above, IP64_CONF_DHCP is an
* optional configuration parameter. The default value is set in ip64.h
*/
/* #define IP64_CONF_DHCP 1 */
#endif /* IP64_CONF_H */

View File

@ -84,7 +84,7 @@ init(void)
printf("ip64-eth-interface: init\n");
}
/*---------------------------------------------------------------------------*/
static void
static int
output(void)
{
int len, ret;
@ -114,7 +114,7 @@ output(void)
printf("Create request\n");
len = ip64_arp_create_arp_request(ip64_packet_buffer,
&ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
return IP64_ETH_DRIVER.output(ip64_packet_buffer, len);
}
}
}

View File

@ -59,7 +59,7 @@ input_callback(void)
/*PRINTF("SIN: %u\n", uip_len);*/
if(uip_buf[0] == '!') {
PRINTF("Got configuration message of type %c\n", uip_buf[1]);
uip_len = 0;
uip_clear_buf();
#if 0
if(uip_buf[1] == 'P') {
uip_ipaddr_t prefix;
@ -87,7 +87,7 @@ input_callback(void)
slip_send();
}
uip_len = 0;
uip_clear_buf();
} else {
/* Save the last sender received over SLIP to avoid bouncing the
@ -101,7 +101,7 @@ input_callback(void)
uip_len = len;
/* PRINTF("send len %d\n", len); */
} else {
uip_len = 0;
uip_clear_buf();
}
}
}
@ -115,7 +115,7 @@ init(void)
slip_set_input_callback(input_callback);
}
/*---------------------------------------------------------------------------*/
static void
static int
output(void)
{
int len;
@ -138,8 +138,10 @@ output(void)
memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
uip_len = len;
slip_send();
return len;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
const struct uip_fallback_interface ip64_slip_interface = {

View File

@ -188,7 +188,7 @@ ip64_init(void)
PRINTF("ip64_init\n");
IP64_ETH_DRIVER.init();
#if IP64_CONF_DHCP
#if IP64_DHCP
ip64_ipv4_dhcp_init();
#endif /* IP64_CONF_DHCP */
@ -894,14 +894,14 @@ ip64_hostaddr_is_configured(void)
static void
interface_init(void)
{
IP64_CONF_UIP_FALLBACK_INTERFACE.init();
IP64_UIP_FALLBACK_INTERFACE.init();
}
/*---------------------------------------------------------------------------*/
static void
interface_output(void)
{
PRINTF("ip64: interface_output len %d\n", uip_len);
IP64_CONF_UIP_FALLBACK_INTERFACE.output();
IP64_UIP_FALLBACK_INTERFACE.output();
}
/*---------------------------------------------------------------------------*/
const struct uip_fallback_interface ip64_uip_fallback_interface = {

View File

@ -36,12 +36,12 @@
void ip64_init(void);
int ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6len,
uint8_t *resultpacket);
uint8_t *resultpacket);
int ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4len,
uint8_t *resultpacket);
uint8_t *resultpacket);
void ip64_set_ipv4_address(const uip_ip4addr_t *ipv4addr,
const uip_ip4addr_t *netmask);
const uip_ip4addr_t *netmask);
void ip64_set_ipv6_address(const uip_ip6addr_t *ipv6addr);
const uip_ip4addr_t *ip64_get_hostaddr(void);
@ -71,7 +71,18 @@ extern uint16_t ip64_packet_buffer_maxlen;
#define IP64_INPUT IP64_CONF_INPUT
#endif /* IP64_CONF_INPUT */
#ifndef IP64_CONF_UIP_FALLBACK_INTERFACE
#error IP64_CONF_UIP_FALLBACK_INTERFACE must be #defined in ip64-conf.h
#else /* IP64_CONF_UIP_FALLBACK_INTERFACE */
#define IP64_UIP_FALLBACK_INTERFACE IP64_CONF_UIP_FALLBACK_INTERFACE
#endif /* IP64_CONF_UIP_FALLBACK_INTERFACE */
#ifdef IP64_CONF_DHCP
#define IP64_DHCP IP64_CONF_DHCP
#else /* IP64_CONF_DHCP */
/* Enable DHCP per default */
#define IP64_DHCP 1
#endif /* IP64_CONF_DHCP */
#endif /* IP64_H */

View File

@ -229,7 +229,7 @@ time_exceeded(void)
/* We don't send out ICMP errors for ICMP messages (unless they are pings). */
if(ICMPBUF->proto == UIP_PROTO_ICMP &&
ICMPBUF->type != ICMP_ECHO) {
uip_len = 0;
uip_clear_buf();
return;
}
/* Copy fields from packet header into payload of this ICMP packet. */

View File

@ -436,6 +436,11 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
conn->snd_nxt[2] = iss[2];
conn->snd_nxt[3] = iss[3];
conn->rcv_nxt[0] = 0;
conn->rcv_nxt[1] = 0;
conn->rcv_nxt[2] = 0;
conn->rcv_nxt[3] = 0;
conn->initialmss = conn->mss = UIP_TCP_MSS;
conn->len = 1; /* TCP length of the SYN is one. */
@ -709,7 +714,7 @@ uip_process(uint8_t flag)
}
/* Reset the length variables. */
uip_len = 0;
uip_clear_buf();
uip_slen = 0;
#if UIP_TCP
@ -1367,10 +1372,10 @@ uip_process(uint8_t flag)
uip_connr->len = 1;
/* rcv_nxt should be the seqno from the incoming packet + 1. */
uip_connr->rcv_nxt[3] = BUF->seqno[3];
uip_connr->rcv_nxt[2] = BUF->seqno[2];
uip_connr->rcv_nxt[1] = BUF->seqno[1];
uip_connr->rcv_nxt[0] = BUF->seqno[0];
uip_connr->rcv_nxt[1] = BUF->seqno[1];
uip_connr->rcv_nxt[2] = BUF->seqno[2];
uip_connr->rcv_nxt[3] = BUF->seqno[3];
uip_add_rcv_nxt(1);
/* Parse the TCP MSS option, if present. */
@ -1589,7 +1594,7 @@ uip_process(uint8_t flag)
uip_add_rcv_nxt(1);
uip_flags = UIP_CONNECTED | UIP_NEWDATA;
uip_connr->len = 0;
uip_len = 0;
uip_clear_buf();
uip_slen = 0;
UIP_APPCALL();
goto appsend;
@ -1934,7 +1939,7 @@ uip_process(uint8_t flag)
return;
drop:
uip_len = 0;
uip_clear_buf();
uip_flags = 0;
return;
}

View File

@ -284,10 +284,10 @@ uip_arp_arpin(void)
{
if(uip_len < sizeof(struct arp_hdr)) {
uip_len = 0;
uip_clear_buf();
return;
}
uip_len = 0;
uip_clear_buf();
switch(BUF->opcode) {
case UIP_HTONS(ARP_REQUEST):

View File

@ -1100,7 +1100,7 @@ icmp_input()
uint16_t val;
#if UIP_CONF_IPV6_CHECKS
if(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) {
if(!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) {
PRINTF("ROLL TM: ICMPv6 In, bad source ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" to ");
@ -1383,8 +1383,7 @@ out()
drop:
uip_slen = 0;
uip_len = 0;
uip_ext_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
static uint8_t

View File

@ -81,7 +81,7 @@ mcast_fwd(void *p)
uip_len = mcast_len;
UIP_IP_BUF->ttl--;
tcpip_output(NULL);
uip_len = 0;
uip_clear_buf();
}
/*---------------------------------------------------------------------------*/
static uint8_t

View File

@ -52,9 +52,9 @@
* FOR HC-06 COMPLIANCE TODO:
* -Add compression options to UDP, currently only supports
* both ports compressed or both ports elided
*
*
* -Verify TC/FL compression works
*
*
* -Add stateless multicast option
*/
@ -317,7 +317,7 @@ set_packet_attrs()
/** Addresses contexts for IPHC. */
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
static struct sicslowpan_addr_context
static struct sicslowpan_addr_context
addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
#endif
@ -381,7 +381,7 @@ addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
static struct sicslowpan_addr_context*
addr_context_lookup_by_number(uint8_t number)
{
/* Remove code to avoid warnings and save flash if no context is used */
/* Remove code to avoid warnings and save flash if no context is used */
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
int i;
for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
@ -540,11 +540,11 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
* We have to process both in the same time as the offset of traffic class
* depends on the presence of version and flow label
*/
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
(UIP_IP_BUF->flow == 0)) {
/* flow label can be compressed */
@ -585,7 +585,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
iphc0 |= SICSLOWPAN_IPHC_NH_C;
}
#endif /*UIP_CONF_UDP*/
#ifdef SICSLOWPAN_NH_COMPRESSOR
#ifdef SICSLOWPAN_NH_COMPRESSOR
if(SICSLOWPAN_NH_COMPRESSOR.is_compressable(UIP_IP_BUF->proto)) {
iphc0 |= SICSLOWPAN_IPHC_NH_C;
}
@ -627,7 +627,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
!= NULL) {
/* elide the prefix - indicate by CID and set context + SAC */
PRINTF("IPHC: compressing src with context - setting CID & SAC ctx: %d\n",
context->number);
context->number);
iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
PACKETBUF_IPHC_BUF[2] |= context->number << 4;
/* compession compare with this nodes address (source) */
@ -635,10 +635,10 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
/* No context found for this address */
} else if(uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
UIP_IP_BUF->destipaddr.u16[3] == 0) {
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
UIP_IP_BUF->destipaddr.u16[3] == 0) {
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
} else {
@ -684,12 +684,13 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
/* compession compare with link adress (destination) */
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
&UIP_IP_BUF->destipaddr,
(uip_lladdr_t *)link_destaddr);
/* No context found for this address */
} else if(uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
UIP_IP_BUF->destipaddr.u16[3] == 0) {
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
UIP_IP_BUF->destipaddr.u16[3] == 0) {
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
} else {
@ -706,7 +707,7 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
/* UDP header compression */
if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
PRINTF("IPHC: Uncompressed UDP ports on send side: %x, %x\n",
UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
/* Mask out the last 4 bits can be used as a mask */
if(((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
((UIP_HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
@ -714,10 +715,10 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_11;
PRINTF("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
*(hc06_ptr + 1) =
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
hc06_ptr += 2;
} else if((UIP_HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
/* we can compress 8 bits of dest, leave source. */
@ -725,16 +726,16 @@ compress_hdr_hc06(linkaddr_t *link_destaddr)
PRINTF("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 2);
*(hc06_ptr + 3) =
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
hc06_ptr += 4;
} else if((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
/* we can compress 8 bits of src, leave dest. Copy compressed port */
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_10;
PRINTF("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *hc06_ptr);
*(hc06_ptr + 1) =
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
memcpy(hc06_ptr + 2, &UIP_UDP_BUF->destport, 2);
hc06_ptr += 4;
} else {
@ -811,13 +812,13 @@ uncompress_hdr_hc06(uint16_t ip_len)
SICSLOWPAN_IP_BUF->vtc = 0x60 | ((tmp >> 2) & 0x0f);
/* ECN rolled down two steps + lowest DSCP bits at top two bits */
SICSLOWPAN_IP_BUF->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
(SICSLOWPAN_IP_BUF->tcflow & 0x0f);
(SICSLOWPAN_IP_BUF->tcflow & 0x0f);
} else {
/* Traffic class is compressed (set version and no TC)*/
SICSLOWPAN_IP_BUF->vtc = 0x60;
/* highest flow label bits + ECN bits */
SICSLOWPAN_IP_BUF->tcflow = (*hc06_ptr & 0x0F) |
((*hc06_ptr >> 2) & 0x30);
((*hc06_ptr >> 2) & 0x30);
memcpy(&SICSLOWPAN_IP_BUF->flow, hc06_ptr + 1, 2);
hc06_ptr += 3;
}
@ -908,14 +909,13 @@ uncompress_hdr_hc06(uint16_t ip_len)
/* no multicast */
/* Context based */
if(iphc1 & SICSLOWPAN_IPHC_DAC) {
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
context = addr_context_lookup_by_number(dci);
/* all valid cases below need the context! */
if(context == NULL) {
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
return;
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
return;
}
uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix,
unc_ctxconf[tmp],
@ -939,56 +939,56 @@ uncompress_hdr_hc06(uint16_t ip_len)
PRINTF("IPHC: Incoming header value: %i\n", *hc06_ptr);
switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
case SICSLOWPAN_NHC_UDP_CS_P_00:
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 5;
break;
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 5;
break;
case SICSLOWPAN_NHC_UDP_CS_P_01:
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
PRINTF("IPHC: Decompressing destination\n");
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 4;
break;
PRINTF("IPHC: Decompressing destination\n");
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 4;
break;
case SICSLOWPAN_NHC_UDP_CS_P_10:
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
PRINTF("IPHC: Decompressing source\n");
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
(*(hc06_ptr + 1)));
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 4;
break;
PRINTF("IPHC: Decompressing source\n");
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
(*(hc06_ptr + 1)));
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 4;
break;
case SICSLOWPAN_NHC_UDP_CS_P_11:
/* 1 byte for NHC, 1 byte for ports */
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
(*(hc06_ptr + 1) >> 4));
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
((*(hc06_ptr + 1)) & 0x0F));
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 2;
break;
/* 1 byte for NHC, 1 byte for ports */
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
(*(hc06_ptr + 1) >> 4));
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
((*(hc06_ptr + 1)) & 0x0F));
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
hc06_ptr += 2;
break;
default:
PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
return;
PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
return;
}
if(!checksum_compressed) { /* has_checksum, default */
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
hc06_ptr += 2;
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
hc06_ptr += 2;
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
} else {
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
}
uncomp_hdr_len += UIP_UDPH_LEN;
}
@ -1000,7 +1000,7 @@ uncompress_hdr_hc06(uint16_t ip_len)
}
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
/* IP length field. */
if(ip_len == 0) {
int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
@ -1012,7 +1012,7 @@ uncompress_hdr_hc06(uint16_t ip_len)
SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
}
/* length field in UDP header */
if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
@ -1046,12 +1046,14 @@ uncompress_hdr_hc06(uint16_t ip_len)
* - Both src and dest interface ID are recoverable from lower layer
* header
* - Next header is either ICMP, UDP or TCP
*
* Moreover, if next header is UDP, we try to compress it using HC_UDP.
* This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
* This is feasible is both ports are between F0B0 and F0B0 + 15.
*
*
* Resulting header structure:
* - For ICMP, TCP, non compressed UDP\n
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
* - For ICMP, TCP, non compressed UDP\n
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
* \verbatim
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -1062,8 +1064,8 @@ uncompress_hdr_hc06(uint16_t ip_len)
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* \endverbatim
*
* - For compressed UDP
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
* - For compressed UDP\n
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
* \verbatim
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -1087,9 +1089,9 @@ compress_hdr_hc1(linkaddr_t *link_destaddr)
if(UIP_IP_BUF->vtc != 0x60 ||
UIP_IP_BUF->tcflow != 0 ||
UIP_IP_BUF->flow != 0 ||
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) ||
!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) ||
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->srcipaddr, &uip_lladdr) ||
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) ||
!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) ||
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->destipaddr,
(uip_lladdr_t *)link_destaddr) ||
(UIP_IP_BUF->proto != UIP_PROTO_ICMP6 &&
@ -1144,7 +1146,7 @@ compress_hdr_hc1(linkaddr_t *link_destaddr)
UIP_HTONS(UIP_UDP_BUF->destport) < SICSLOWPAN_UDP_PORT_MAX) {
/* HC1 encoding */
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_HC1_ENCODING] = 0xFB;
/* HC_UDP encoding, ttl, src and dest ports, checksum */
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_UDP_ENCODING] = 0xE0;
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_TTL] = UIP_IP_BUF->ttl;
@ -1192,17 +1194,17 @@ uncompress_hdr_hc1(uint16_t ip_len)
SICSLOWPAN_IP_BUF->vtc = 0x60;
SICSLOWPAN_IP_BUF->tcflow = 0;
SICSLOWPAN_IP_BUF->flow = 0;
/* src and dest ip addresses */
uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
uncomp_hdr_len += UIP_IPH_LEN;
/* Next header field */
switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] & 0x06) {
case SICSLOWPAN_HC1_NH_ICMP6:
@ -1248,7 +1250,7 @@ uncompress_hdr_hc1(uint16_t ip_len)
/* this shouldn't happen, drop */
return;
}
/* IP length field. */
if(ip_len == 0) {
int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
@ -1363,8 +1365,10 @@ output(const uip_lladdr_t *localdest)
/* The MAC address of the destination of the packet */
linkaddr_t dest;
#if SICSLOWPAN_CONF_FRAG
/* Number of bytes processed. */
uint16_t processed_ip_out_len;
#endif /* SICSLOWPAN_CONF_FRAG */
/* init */
uncomp_hdr_len = 0;
@ -1410,7 +1414,7 @@ output(const uip_lladdr_t *localdest)
} else {
linkaddr_copy(&dest, (const linkaddr_t *)localdest);
}
PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
if(uip_len >= COMPRESSION_THRESHOLD) {
@ -1443,7 +1447,7 @@ output(const uip_lladdr_t *localdest)
#else /* USE_FRAMER_HDRLEN */
framer_hdrlen = 21;
#endif /* USE_FRAMER_HDRLEN */
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead();
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
#if SICSLOWPAN_CONF_FRAG
@ -1455,7 +1459,7 @@ output(const uip_lladdr_t *localdest)
* IPv6/HC1/HC06/HC_UDP dispatchs/headers.
* The following fragments contain only the fragn dispatch.
*/
int estimated_fragments = ((int)uip_len) / ((int)MAC_MAX_PAYLOAD - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
int freebuf = queuebuf_numfree() - 1;
PRINTFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
if(freebuf < estimated_fragments) {
@ -1510,7 +1514,7 @@ output(const uip_lladdr_t *localdest)
/* set processed_ip_out_len to what we already sent from the IP payload*/
processed_ip_out_len = packetbuf_payload_len + uncomp_hdr_len;
/*
* Create following fragments
* Datagram tag is already in the buffer, we need to set the
@ -1525,7 +1529,7 @@ output(const uip_lladdr_t *localdest)
while(processed_ip_out_len < uip_len) {
PRINTFO("sicslowpan output: fragment ");
PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
/* Copy payload and send */
if(uip_len - processed_ip_out_len < packetbuf_payload_len) {
/* last fragment */
@ -1575,7 +1579,6 @@ output(const uip_lladdr_t *localdest)
/*--------------------------------------------------------------------*/
/** \brief Process a received 6lowpan packet.
* \param r The MAC layer
*
* The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
* a non-fragmented packet we first uncompress the IP header. The
@ -1593,8 +1596,8 @@ input(void)
uint16_t frag_size = 0;
/* offset of the fragment in the IP packet */
uint8_t frag_offset = 0;
uint8_t is_fragment = 0;
#if SICSLOWPAN_CONF_FRAG
uint8_t is_fragment = 0;
/* tag of the fragment */
uint16_t frag_tag = 0;
uint8_t first_fragment = 0, last_fragment = 0;
@ -1757,8 +1760,8 @@ input(void)
PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]);
return;
}
#if SICSLOWPAN_CONF_FRAG
copypayload:
#endif /*SICSLOWPAN_CONF_FRAG*/
@ -1789,7 +1792,7 @@ input(void)
}
memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
/* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
#if SICSLOWPAN_CONF_FRAG
@ -1871,13 +1874,13 @@ sicslowpan_init(void)
* The platform contiki-conf.h file can override this using e.g.
* #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
*/
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
addr_contexts[0].used = 1;
addr_contexts[0].number = 0;
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
#else
addr_contexts[0].prefix[0] = 0xaa;
addr_contexts[0].prefix[0] = 0xaa;
addr_contexts[0].prefix[1] = 0xaa;
#endif
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
@ -1887,23 +1890,22 @@ sicslowpan_init(void)
int i;
for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
if (i==1) {
addr_contexts[1].used = 1;
addr_contexts[1].number = 1;
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
if (i==1) {
addr_contexts[1].used = 1;
addr_contexts[1].number = 1;
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
} else if (i==2) {
addr_contexts[2].used = 1;
addr_contexts[2].number = 2;
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
addr_contexts[2].used = 1;
addr_contexts[2].number = 2;
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
#endif
} else {
addr_contexts[i].used = 0;
}
}
#else
addr_contexts[i].used = 0;
#endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
}
}
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */

View File

@ -203,18 +203,18 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
#if UIP_DS6_LL_NUD
/* From RFC4861, page 72, last paragraph of section 7.3.3:
*
* "In some cases, link-specific information may indicate that a path to
* a neighbor has failed (e.g., the resetting of a virtual circuit). In
* such cases, link-specific information may be used to purge Neighbor
* Cache entries before the Neighbor Unreachability Detection would do
* so. However, link-specific information MUST NOT be used to confirm
* the reachability of a neighbor; such information does not provide
* end-to-end confirmation between neighboring IP layers."
* "In some cases, link-specific information may indicate that a path to
* a neighbor has failed (e.g., the resetting of a virtual circuit). In
* such cases, link-specific information may be used to purge Neighbor
* Cache entries before the Neighbor Unreachability Detection would do
* so. However, link-specific information MUST NOT be used to confirm
* the reachability of a neighbor; such information does not provide
* end-to-end confirmation between neighboring IP layers."
*
* However, we assume that receiving a link layer ack ensures the delivery
* of the transmitted packed to the IP stack of the neighbour. This is a
* fair assumption and allows battery powered nodes save some battery by
* not re-testing the state of a neighbour periodically if it
* of the transmitted packed to the IP stack of the neighbour. This is a
* fair assumption and allows battery powered nodes save some battery by
* not re-testing the state of a neighbour periodically if it
* acknowledges link packets. */
if(status == MAC_TX_OK) {
uip_ds6_nbr_t *nbr;
@ -231,10 +231,10 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
}
/*---------------------------------------------------------------------------*/
/** Periodic processing on neighbors */
void
uip_ds6_neighbor_periodic(void)
{
/* Periodic processing on neighbors */
uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
while(nbr != NULL) {
switch(nbr->state) {

View File

@ -47,12 +47,22 @@
#include <string.h>
/* A configurable function called after adding a new neighbor as next hop */
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(const linkaddr_t *addr);
#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK */
/* A configurable function called after removing a next hop neighbor */
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(const linkaddr_t *addr);
#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */
/* The nbr_routes holds a neighbor table to be able to maintain
information about what routes go through what neighbor. This
neighbor table is registered with the central nbr-table repository
so that it will be maintained along with the rest of the neighbor
tables in the system. */
NBR_TABLE(struct uip_ds6_route_neighbor_routes, nbr_routes);
NBR_TABLE_GLOBAL(struct uip_ds6_route_neighbor_routes, nbr_routes);
MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
/* Each route is repressented by a uip_ds6_route_t structure and
@ -335,6 +345,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
return NULL;
}
LIST_STRUCT_INIT(routes, route_list);
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((const linkaddr_t *)nexthop_lladdr);
#endif
}
/* Allocate a routing entry and populate it. */
@ -367,6 +380,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
num_routes++;
PRINTF("uip_ds6_route_add num %d\n", num_routes);
/* lock this entry so that nexthop is not removed */
nbr_table_lock(nbr_routes, routes);
}
uip_ipaddr_copy(&(r->ipaddr), ipaddr);
@ -423,9 +439,19 @@ uip_ds6_route_rm(uip_ds6_route_t *route)
list_remove(route->neighbor_routes->route_list, neighbor_route);
if(list_head(route->neighbor_routes->route_list) == NULL) {
/* If this was the only route using this neighbor, remove the
neibhor from the table */
neighbor from the table - this implicitly unlocks nexthop */
#if (DEBUG) & DEBUG_ANNOTATE
uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route);
if(nexthop != NULL) {
ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
}
#endif /* (DEBUG) & DEBUG_ANNOTATE */
PRINTF("uip_ds6_route_rm: removing neighbor too\n");
nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
(const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list));
#endif
}
memb_free(&routememb, route);
memb_free(&neighborroutememb, neighbor_route);
@ -437,25 +463,6 @@ uip_ds6_route_rm(uip_ds6_route_t *route)
#if UIP_DS6_NOTIFICATIONS
call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
&route->ipaddr, uip_ds6_route_nexthop(route));
#endif
#if 0 //(DEBUG & DEBUG_ANNOTATE) == DEBUG_ANNOTATE
/* we need to check if this was the last route towards "nexthop" */
/* if so - remove that link (annotation) */
uip_ds6_route_t *r;
for(r = uip_ds6_route_head();
r != NULL;
r = uip_ds6_route_next(r)) {
uip_ipaddr_t *nextr, *nextroute;
nextr = uip_ds6_route_nexthop(r);
nextroute = uip_ds6_route_nexthop(route);
if(nextr != NULL &&
nextroute != NULL &&
uip_ipaddr_cmp(nextr, nextroute)) {
/* we found another link using the specific nexthop, so keep the #L */
return;
}
}
ANNOTATE("#L %u 0\n", uip_ds6_route_nexthop(route)->u8[sizeof(uip_ipaddr_t) - 1]);
#endif
}

View File

@ -40,9 +40,13 @@
#ifndef UIP_DS6_ROUTE_H
#define UIP_DS6_ROUTE_H
#include "net/ip/uip.h"
#include "net/nbr-table.h"
#include "sys/stimer.h"
#include "lib/list.h"
NBR_TABLE_DECLARE(nbr_routes);
void uip_ds6_route_init(void);
#ifndef UIP_CONF_UIP_DS6_NOTIFICATIONS

View File

@ -53,23 +53,23 @@
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
struct etimer uip_ds6_timer_periodic; /** \brief Timer for maintenance of data structures */
struct etimer uip_ds6_timer_periodic; /**< Timer for maintenance of data structures */
#if UIP_CONF_ROUTER
struct stimer uip_ds6_timer_ra; /** \brief RA timer, to schedule RA sending */
struct stimer uip_ds6_timer_ra; /**< RA timer, to schedule RA sending */
#if UIP_ND6_SEND_RA
static uint8_t racount; /** \brief number of RA already sent */
static uint16_t rand_time; /** \brief random time value for timers */
static uint8_t racount; /**< number of RA already sent */
static uint16_t rand_time; /**< random time value for timers */
#endif
#else /* UIP_CONF_ROUTER */
struct etimer uip_ds6_timer_rs; /** \brief RS timer, to schedule RS sending */
static uint8_t rscount; /** \brief number of rs already sent */
struct etimer uip_ds6_timer_rs; /**< RS timer, to schedule RS sending */
static uint8_t rscount; /**< number of rs already sent */
#endif /* UIP_CONF_ROUTER */
/** \name "DS6" Data structures */
/** @{ */
uip_ds6_netif_t uip_ds6_if; /** \brief The single interface */
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /** \brief Prefix list */
uip_ds6_netif_t uip_ds6_if; /**< The single interface */
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]; /**< Prefix list */
/* Used by Cooja to enable extraction of addresses from memory.*/
uint8_t uip_ds6_addr_size;
@ -83,7 +83,9 @@ static uip_ipaddr_t loc_fipaddr;
/* Pointers used in this file */
static uip_ds6_addr_t *locaddr;
static uip_ds6_maddr_t *locmaddr;
#if UIP_DS6_AADDR_NB
static uip_ds6_aaddr_t *locaaddr;
#endif /* UIP_DS6_AADDR_NB */
static uip_ds6_prefix_t *locprefix;
/*---------------------------------------------------------------------------*/
@ -274,7 +276,8 @@ uip_ds6_prefix_add(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen,
}
PRINTF("Adding prefix ");
PRINT6ADDR(&locprefix->ipaddr);
PRINTF("length %u, vlifetime%lu\n", ipaddrlen, interval);
PRINTF("length %u, vlifetime %lu\n", ipaddrlen, interval);
return locprefix;
}
return NULL;
}
@ -294,9 +297,9 @@ uip_ds6_prefix_t *
uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr, uint8_t ipaddrlen)
{
if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_prefix_list,
UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
ipaddr, ipaddrlen,
(uip_ds6_element_t **)&locprefix) == FOUND) {
UIP_DS6_PREFIX_NB, sizeof(uip_ds6_prefix_t),
ipaddr, ipaddrlen,
(uip_ds6_element_t **)&locprefix) == FOUND) {
return locprefix;
}
return NULL;
@ -388,7 +391,7 @@ uip_ds6_get_link_local(int8_t state)
for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if(locaddr->isused && (state == -1 || locaddr->state == state)
&& (uip_is_addr_link_local(&locaddr->ipaddr))) {
&& (uip_is_addr_linklocal(&locaddr->ipaddr))) {
return locaddr;
}
}
@ -407,7 +410,7 @@ uip_ds6_get_global(int8_t state)
for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
if(locaddr->isused && (state == -1 || locaddr->state == state)
&& !(uip_is_addr_link_local(&locaddr->ipaddr))) {
&& !(uip_is_addr_linklocal(&locaddr->ipaddr))) {
return locaddr;
}
}
@ -457,6 +460,7 @@ uip_ds6_maddr_lookup(const uip_ipaddr_t *ipaddr)
uip_ds6_aaddr_t *
uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
{
#if UIP_DS6_AADDR_NB
if(uip_ds6_list_loop
((uip_ds6_element_t *)uip_ds6_if.aaddr_list, UIP_DS6_AADDR_NB,
sizeof(uip_ds6_aaddr_t), ipaddr, 128,
@ -465,6 +469,7 @@ uip_ds6_aaddr_add(uip_ipaddr_t *ipaddr)
uip_ipaddr_copy(&locaaddr->ipaddr, ipaddr);
return locaaddr;
}
#endif /* UIP_DS6_AADDR_NB */
return NULL;
}
@ -482,11 +487,13 @@ uip_ds6_aaddr_rm(uip_ds6_aaddr_t *aaddr)
uip_ds6_aaddr_t *
uip_ds6_aaddr_lookup(uip_ipaddr_t *ipaddr)
{
#if UIP_DS6_AADDR_NB
if(uip_ds6_list_loop((uip_ds6_element_t *)uip_ds6_if.aaddr_list,
UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
(uip_ds6_element_t **)&locaaddr) == FOUND) {
UIP_DS6_AADDR_NB, sizeof(uip_ds6_aaddr_t), ipaddr, 128,
(uip_ds6_element_t **)&locaaddr) == FOUND) {
return locaaddr;
}
#endif /* UIP_DS6_AADDR_NB */
return NULL;
}
@ -498,13 +505,13 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
uint8_t n = 0;
uip_ds6_addr_t *matchaddr = NULL;
if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
if(!uip_is_addr_linklocal(dst) && !uip_is_addr_mcast(dst)) {
/* find longest match */
for(locaddr = uip_ds6_if.addr_list;
locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
/* Only preferred global (not link-local) addresses */
if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
!uip_is_addr_link_local(&locaddr->ipaddr)) {
!uip_is_addr_linklocal(&locaddr->ipaddr)) {
n = get_match_length(dst, &locaddr->ipaddr);
if(n >= best) {
best = n;
@ -591,7 +598,7 @@ uip_ds6_dad(uip_ds6_addr_t *addr)
* If we arrive here it means DAD succeeded, otherwise the dad process
* would have been interrupted in ds6_dad_ns/na_input
*/
PRINTF("DAD succeeded, ipaddr:");
PRINTF("DAD succeeded, ipaddr: ");
PRINT6ADDR(&addr->ipaddr);
PRINTF("\n");
@ -607,7 +614,7 @@ uip_ds6_dad(uip_ds6_addr_t *addr)
int
uip_ds6_dad_failed(uip_ds6_addr_t *addr)
{
if(uip_is_addr_link_local(&addr->ipaddr)) {
if(uip_is_addr_linklocal(&addr->ipaddr)) {
PRINTF("Contiki shutdown, DAD for link local address failed\n");
return 0;
}

View File

@ -216,9 +216,15 @@ typedef struct uip_ds6_netif {
uint32_t reachable_time; /* in msec */
uint32_t retrans_timer; /* in msec */
uint8_t maxdadns;
#if UIP_DS6_ADDR_NB
uip_ds6_addr_t addr_list[UIP_DS6_ADDR_NB];
#endif /* UIP_DS6_ADDR_NB */
#if UIP_DS6_AADDR_NB
uip_ds6_aaddr_t aaddr_list[UIP_DS6_AADDR_NB];
#endif /* UIP_DS6_AADDR_NB */
#if UIP_DS6_MADDR_NB
uip_ds6_maddr_t maddr_list[UIP_DS6_MADDR_NB];
#endif /* UIP_DS6_MADDR_NB */
} uip_ds6_netif_t;
/** \brief Generic type for a DS6, to use a common loop though all DS */
@ -276,6 +282,7 @@ uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr);
/** \name Unicast address list basic routines */
/** @{ */
/** \brief Add a unicast address to the interface */
uip_ds6_addr_t *uip_ds6_addr_add(uip_ipaddr_t *ipaddr,
unsigned long vlifetime, uint8_t type);
void uip_ds6_addr_rm(uip_ds6_addr_t *addr);

View File

@ -128,9 +128,9 @@ echo_request_input(void)
* headers in the request otherwise we need to remove the extension
* headers and change a few fields
*/
PRINTF("Received Echo Request from");
PRINTF("Received Echo Request from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
@ -195,9 +195,9 @@ echo_request_input(void)
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
PRINTF("Sending Echo Reply to");
PRINTF("Sending Echo Reply to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
UIP_STAT(++uip_stat.icmp.sent);
@ -210,12 +210,12 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
/* check if originating packet is not an ICMP error*/
if (uip_ext_len) {
if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
uip_len = 0;
uip_clear_buf();
return;
}
} else {
if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){
uip_len = 0;
uip_clear_buf();
return;
}
}
@ -250,7 +250,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
/* the source should not be unspecified nor multicast, the check for
multicast is done in uip_process */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){
uip_len = 0;
uip_clear_buf();
return;
}
@ -260,7 +260,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
if(type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION){
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
} else {
uip_len = 0;
uip_clear_buf();
return;
}
} else {
@ -282,9 +282,9 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
UIP_STAT(++uip_stat.icmp.sent);
PRINTF("Sending ICMPv6 ERROR message type %d code %d to", type, code);
PRINTF("Sending ICMPv6 ERROR message type %d code %d to ", type, code);
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
return;
@ -385,7 +385,7 @@ echo_reply_input(void)
}
}
uip_len = 0;
uip_clear_buf();
return;
}
/*---------------------------------------------------------------------------*/

View File

@ -93,7 +93,7 @@ void uip_log(char *msg);
/** \name Pointers to the header structures.
* All pointers except UIP_IP_BUF depend on uip_ext_len, which at
* packet reception, is the total length of the extension headers.
*
*
* The pointer to ND6 options header also depends on nd6_opt_offset,
* which we set in each function.
*
@ -127,11 +127,23 @@ static uip_ds6_addr_t *addr; /** Pointer to an interface address */
#if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
static uip_ipaddr_t ipaddr;
#endif
#if (!UIP_CONF_ROUTER || UIP_ND6_SEND_RA)
static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
#endif
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
/*------------------------------------------------------------------*/
/* create a llao */
/* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */
static void
extract_lladdr_aligned(uip_lladdr_t *dest) {
if(dest != NULL && nd6_opt_llao != NULL) {
memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
}
}
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
/*------------------------------------------------------------------*/
/* create a llao */
static void
create_llao(uint8_t *llao, uint8_t type) {
llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
@ -153,7 +165,7 @@ ns_input(void)
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF(" with target address");
PRINTF(" with target address ");
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
@ -189,15 +201,14 @@ ns_input(void)
#endif /*UIP_CONF_IPV6_CHECKS */
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
if(nbr == NULL) {
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
0, NBR_STALE);
uip_lladdr_t lladdr_aligned;
extract_lladdr_aligned(&lladdr_aligned);
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
} else {
uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
lladdr, UIP_LLADDR_LEN) != 0) {
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
UIP_LLADDR_LEN);
lladdr, UIP_LLADDR_LEN) != 0) {
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN);
nbr->state = NBR_STALE;
} else {
if(nbr->state == NBR_INCOMPLETE) {
@ -321,7 +332,7 @@ create_na:
return;
discard:
uip_len = 0;
uip_clear_buf();
return;
}
#endif /* UIP_ND6_SEND_NA */
@ -350,7 +361,7 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
UIP_IP_BUF->len[0] = 0; /* length will not be more than 255 */
/*
* check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
* (here yes), for Address resolution , MUST
* (here yes), for Address resolution , MUST
*/
if(!(uip_ds6_is_my_addr(tgt))) {
if(src != NULL) {
@ -360,14 +371,14 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
}
if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
PRINTF("Dropping NS due to no suitable source address\n");
uip_len = 0;
uip_clear_buf();
return;
}
UIP_IP_BUF->len[1] =
UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
UIP_ND6_OPT_SLLAO);
UIP_ND6_OPT_SLLAO);
uip_len =
UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
@ -381,11 +392,11 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending NS to");
PRINTF("Sending NS to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("with target address");
PRINTF(" with target address ");
PRINT6ADDR(tgt);
PRINTF("\n");
return;
@ -417,18 +428,18 @@ na_input(void)
uint8_t is_solicited;
uint8_t is_override;
PRINTF("Received NA from");
PRINTF("Received NA from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("with target address");
PRINTF(" with target address ");
PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
/*
/*
* booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20
* but it works. Be careful though, do not use tests such as is_router == 1
* but it works. Be careful though, do not use tests such as is_router == 1
*/
is_llchange = 0;
is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
@ -494,7 +505,7 @@ na_input(void)
goto discard;
}
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
UIP_LLADDR_LEN);
UIP_LLADDR_LEN);
if(is_solicited) {
nbr->state = NBR_REACHABLE;
nbr->nscount = 0;
@ -517,7 +528,7 @@ na_input(void)
|| nd6_opt_llao == 0) {
if(nd6_opt_llao != 0) {
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
UIP_LLADDR_LEN);
UIP_LLADDR_LEN);
}
if(is_solicited) {
nbr->state = NBR_REACHABLE;
@ -553,11 +564,11 @@ na_input(void)
uip_packetqueue_free(&nbr->packethandle);
return;
}
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
discard:
uip_len = 0;
uip_clear_buf();
return;
}
#endif /* UIP_ND6_SEND_NA */
@ -569,9 +580,9 @@ static void
rs_input(void)
{
PRINTF("Received RS from");
PRINTF("Received RS from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
@ -579,7 +590,7 @@ rs_input(void)
#if UIP_CONF_IPV6_CHECKS
/*
* Check hop limit / icmp code
* Check hop limit / icmp code
* target address must not be multicast
* if the NA is solicited, dest must not be multicast
*/
@ -619,18 +630,18 @@ rs_input(void)
goto discard;
} else {
#endif /*UIP_CONF_IPV6_CHECKS */
uip_lladdr_t lladdr_aligned;
extract_lladdr_aligned(&lladdr_aligned);
if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) {
/* we need to add the neighbor */
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
} else {
/* If LL address changed, set neighbor state to stale */
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) {
uip_ds6_nbr_t nbr_data = *nbr;
uip_ds6_nbr_rm(nbr);
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE);
nbr->reachable = nbr_data.reachable;
nbr->sendns = nbr_data.sendns;
nbr->nscount = nbr_data.nscount;
@ -646,7 +657,7 @@ rs_input(void)
uip_ds6_send_ra_sollicited();
discard:
uip_len = 0;
uip_clear_buf();
return;
}
@ -687,7 +698,6 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
nd6_opt_offset = UIP_ND6_RA_LEN;
#if !UIP_CONF_ROUTER
/* Prefix list */
for(prefix = uip_ds6_prefix_list;
prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
@ -704,7 +714,6 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
}
}
#endif /* !UIP_CONF_ROUTER */
/* Source link-layer option */
create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
@ -752,9 +761,9 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sending RA to");
PRINTF("Sending RA to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
return;
@ -787,22 +796,22 @@ uip_nd6_rs_output(void)
UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
UIP_ND6_OPT_SLLAO);
UIP_ND6_OPT_SLLAO);
}
UIP_ICMP_BUF->icmpchksum = 0;
UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
UIP_STAT(++uip_stat.nd6.sent);
PRINTF("Sendin RS to");
PRINTF("Sendin RS to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINTF(" from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n");
return;
}
/*---------------------------------------------------------------------------*/
/*
/**
* Process a Router Advertisement
*
* - Possible actions when receiving a RA: add router to router list,
@ -814,16 +823,16 @@ uip_nd6_rs_output(void)
void
ra_input(void)
{
PRINTF("Received RA from");
PRINTF("Received RA from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("to");
PRINTF(" to ");
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("\n");
UIP_STAT(++uip_stat.nd6.recv);
#if UIP_CONF_IPV6_CHECKS
if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
(!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
(!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) ||
(UIP_ICMP_BUF->icode != 0)) {
PRINTF("RA received is bad");
goto discard;
@ -859,18 +868,18 @@ ra_input(void)
nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
if(nbr == NULL) {
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
(uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
1, NBR_STALE);
uip_lladdr_t lladdr_aligned;
extract_lladdr_aligned(&lladdr_aligned);
nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE);
} else {
uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr);
if(nbr->state == NBR_INCOMPLETE) {
nbr->state = NBR_STALE;
}
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
lladdr, UIP_LLADDR_LEN) != 0) {
lladdr, UIP_LLADDR_LEN) != 0) {
memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
UIP_LLADDR_LEN);
UIP_LLADDR_LEN);
nbr->state = NBR_STALE;
}
nbr->isrouter = 1;
@ -886,7 +895,7 @@ ra_input(void)
nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
uip_ntohl(nd6_opt_prefix_info->preferredlt))
&& (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) {
&& (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) {
/* on-link flag related processing */
if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
prefix =
@ -913,9 +922,9 @@ ra_input(void)
prefix->isinfinite = 1;
break;
default:
PRINTF("Updating timer of prefix");
PRINTF("Updating timer of prefix ");
PRINT6ADDR(&prefix->ipaddr);
PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
PRINTF(" new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
stimer_set(&prefix->vlifetime,
uip_ntohl(nd6_opt_prefix_info->validlt));
prefix->isinfinite = 0;
@ -928,7 +937,7 @@ ra_input(void)
if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
&& (nd6_opt_prefix_info->validlt != 0)
&& (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
addr = uip_ds6_addr_lookup(&ipaddr);
@ -938,9 +947,9 @@ ra_input(void)
if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
(uip_ntohl(nd6_opt_prefix_info->validlt) >
stimer_remaining(&addr->vlifetime))) {
PRINTF("Updating timer of address");
PRINTF("Updating timer of address ");
PRINT6ADDR(&addr->ipaddr);
PRINTF("new value %lu\n",
PRINTF(" new value %lu\n",
uip_ntohl(nd6_opt_prefix_info->validlt));
stimer_set(&addr->vlifetime,
uip_ntohl(nd6_opt_prefix_info->validlt));
@ -948,7 +957,7 @@ ra_input(void)
stimer_set(&addr->vlifetime, 2 * 60 * 60);
PRINTF("Updating timer of address ");
PRINT6ADDR(&addr->ipaddr);
PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
PRINTF(" new value %lu\n", (unsigned long)(2 * 60 * 60));
}
addr->isinfinite = 0;
} else {
@ -1029,7 +1038,7 @@ ra_input(void)
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
discard:
uip_len = 0;
uip_clear_buf();
return;
}
#endif /* !UIP_CONF_ROUTER */

View File

@ -59,9 +59,12 @@
/** \name RFC 4861 Host constant */
/** @{ */
/** \brief Maximum router solicitation delay */
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
/** \brief Router solicitation interval */
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
/** \brief Maximum router solicitations */
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3
/** @} */
/** \name RFC 4861 Router constants */
@ -128,9 +131,9 @@
#endif
#ifdef UIP_CONF_ND6_RETRANS_TIMER
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
#define UIP_ND6_RETRANS_TIMER UIP_CONF_ND6_RETRANS_TIMER
#else
#define UIP_ND6_RETRANS_TIMER 1000
#define UIP_ND6_RETRANS_TIMER 1000
#endif
#define UIP_ND6_DELAY_FIRST_PROBE_TIME 5

View File

@ -103,7 +103,7 @@ void uip_log(char *msg);
#if UIP_STATISTICS == 1
struct uip_stats uip_stat;
#endif /* UIP_STATISTICS == 1 */
/*---------------------------------------------------------------------------*/
/**
@ -288,7 +288,10 @@ struct uip_icmp6_conn uip_icmp6_conns;
/*---------------------------------------------------------------------------*/
/* Functions */
/*---------------------------------------------------------------------------*/
#if (!UIP_ARCH_ADD32 && UIP_TCP)
#if UIP_TCP
#if UIP_ARCH_ADD32
void uip_add32(uint8_t *op32, uint16_t op16);
#else /* UIP_ARCH_ADD32 */
void
uip_add32(uint8_t *op32, uint16_t op16)
{
@ -296,15 +299,15 @@ uip_add32(uint8_t *op32, uint16_t op16)
uip_acc32[2] = op32[2] + (op16 >> 8);
uip_acc32[1] = op32[1];
uip_acc32[0] = op32[0];
if(uip_acc32[2] < (op16 >> 8)) {
++uip_acc32[1];
if(uip_acc32[1] == 0) {
++uip_acc32[0];
}
}
if(uip_acc32[3] < (op16 & 0xff)) {
++uip_acc32[2];
if(uip_acc32[2] == 0) {
@ -315,8 +318,8 @@ uip_add32(uint8_t *op32, uint16_t op16)
}
}
}
#endif /* UIP_ARCH_ADD32 && UIP_TCP */
#endif /* UIP_ARCH_ADD32 */
#endif /* UIP_TCP */
#if ! UIP_ARCH_CHKSUM
/*---------------------------------------------------------------------------*/
@ -329,7 +332,7 @@ chksum(uint16_t sum, const uint8_t *data, uint16_t len)
dataptr = data;
last_byte = data + len - 1;
while(dataptr < last_byte) { /* At least two more bytes */
t = (dataptr[0] << 8) + dataptr[1];
sum += t;
@ -338,7 +341,7 @@ chksum(uint16_t sum, const uint8_t *data, uint16_t len)
}
dataptr += 2;
}
if(dataptr == last_byte) {
t = (dataptr[0] << 8) + 0;
sum += t;
@ -383,11 +386,11 @@ upper_layer_chksum(uint8_t proto)
*/
volatile uint16_t upper_layer_len;
uint16_t sum;
upper_layer_len = (((uint16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1] - uip_ext_len);
PRINTF("Upper layer checksum len: %d from: %d\n", upper_layer_len,
UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len);
UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len);
/* First sum pseudoheader. */
/* IP protocol and length fields. This addition cannot carry. */
@ -398,7 +401,7 @@ upper_layer_chksum(uint8_t proto)
/* Sum TCP header and data. */
sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len],
upper_layer_len);
return (sum == 0) ? 0xffff : uip_htons(sum);
}
/*---------------------------------------------------------------------------*/
@ -406,7 +409,7 @@ uint16_t
uip_icmp6chksum(void)
{
return upper_layer_chksum(UIP_PROTO_ICMP6);
}
/*---------------------------------------------------------------------------*/
#if UIP_TCP
@ -429,7 +432,7 @@ uip_udpchksum(void)
void
uip_init(void)
{
uip_ds6_init();
uip_icmp6_init();
uip_nd6_init();
@ -463,7 +466,7 @@ struct uip_conn *
uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
{
register struct uip_conn *conn, *cconn;
/* Find an unused local port. */
again:
++lastport;
@ -500,7 +503,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
if(conn == 0) {
return 0;
}
conn->tcpstateflags = UIP_SYN_SENT;
conn->snd_nxt[0] = iss[0];
@ -514,7 +517,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
conn->rcv_nxt[3] = 0;
conn->initialmss = conn->mss = UIP_TCP_MSS;
conn->len = 1; /* TCP length of the SYN is one. */
conn->nrtx = 0;
conn->timer = 1; /* Send the SYN next time around. */
@ -524,7 +527,7 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
conn->lport = uip_htons(lastport);
conn->rport = rport;
uip_ipaddr_copy(&conn->ripaddr, ripaddr);
return conn;
}
#endif /* UIP_TCP && UIP_ACTIVE_OPEN */
@ -535,15 +538,14 @@ remove_ext_hdr(void)
/* Remove ext header before TCP/UDP processing. */
if(uip_ext_len > 0) {
PRINTF("Cutting ext-header before processing (extlen: %d, uiplen: %d)\n",
uip_ext_len, uip_len);
uip_ext_len, uip_len);
if(uip_len < UIP_IPH_LEN + uip_ext_len) {
PRINTF("ERROR: uip_len too short compared to ext len\n");
uip_ext_len = 0;
uip_len = 0;
uip_clear_buf();
return;
}
memmove(((uint8_t *)UIP_TCP_BUF), (uint8_t *)UIP_TCP_BUF + uip_ext_len,
uip_len - UIP_IPH_LEN - uip_ext_len);
uip_len - UIP_IPH_LEN - uip_ext_len);
uip_len -= uip_ext_len;
@ -559,7 +561,7 @@ struct uip_udp_conn *
uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
{
register struct uip_udp_conn *conn;
/* Find an unused local port. */
again:
++lastport;
@ -567,7 +569,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
if(lastport >= 32000) {
lastport = 4096;
}
for(c = 0; c < UIP_UDP_CONNS; ++c) {
if(uip_udp_conns[c].lport == uip_htons(lastport)) {
goto again;
@ -585,7 +587,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
if(conn == 0) {
return 0;
}
conn->lport = UIP_HTONS(lastport);
conn->rport = rport;
if(ripaddr == NULL) {
@ -594,7 +596,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport)
uip_ipaddr_copy(&conn->ripaddr, ripaddr);
}
conn->ttl = uip_ds6_if.cur_hop_limit;
return conn;
}
#endif /* UIP_UDP */
@ -652,7 +654,7 @@ static uint8_t uip_reassflags;
*/
struct etimer uip_reass_timer; /* timer for reassembly */
struct etimer uip_reass_timer; /**< Timer for reassembly */
uint8_t uip_reass_on; /* equal to 1 if we are currently reassembling a packet */
static uint32_t uip_id; /* For every packet that is to be fragmented, the source
@ -666,7 +668,7 @@ uip_reass(void)
uint16_t offset=0;
uint16_t len;
uint16_t i;
/* If ip_reasstmr is zero, no packet is present in the buffer */
/* We first write the unfragmentable part of IP header into the reassembly
buffer. The reset the other reassembly variables. */
@ -708,9 +710,9 @@ uip_reass(void)
PRINTF("dest ");
PRINT6ADDR(&FBUF->destipaddr);
PRINTF("next %d\n", UIP_IP_BUF->proto);
}
/* If the offset or the offset + fragment length overflows the
reassembly buffer, we discard the entire packet. */
if(offset > UIP_REASS_BUFSIZE ||
@ -742,12 +744,12 @@ uip_reass(void)
return uip_len;
}
}
/* Copy the fragment into the reassembly buffer, at the right
offset. */
memcpy((uint8_t *)FBUF + UIP_IPH_LEN + uip_ext_len + offset,
(uint8_t *)UIP_FRAG_BUF + UIP_FRAGH_LEN, len);
/* Update the bitmap. */
if(offset >> 6 == (offset + len) >> 6) {
uip_reassbitmap[offset >> 6] |=
@ -758,18 +760,18 @@ uip_reass(void)
bytes in the endpoints and fill the stuff inbetween with
0xff. */
uip_reassbitmap[offset >> 6] |= bitmap_bits[(offset >> 3) & 7];
for(i = (1 + (offset >> 6)); i < ((offset + len) >> 6); ++i) {
uip_reassbitmap[i] = 0xff;
}
uip_reassbitmap[(offset + len) >> 6] |=
~bitmap_bits[((offset + len) >> 3) & 7];
}
/* Finally, we check if we have a full packet in the buffer. We do
this by checking if we have the last fragment and if all bits
in the bitmap are set. */
if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
/* Check all bytes up to and including all but the last byte in
the bitmap. */
@ -796,9 +798,9 @@ uip_reass(void)
UIP_IP_BUF->len[1] = ((uip_reasslen - UIP_IPH_LEN) & 0xff);
PRINTF("REASSEMBLED PAQUET %d (%d)\n", uip_reasslen,
(UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
return uip_reasslen;
}
} else {
PRINTF("Already reassembling another paquet\n");
@ -825,12 +827,11 @@ uip_reass_over(void)
* any RFC, we decided not to include it as it reduces the size of
* the packet.
*/
uip_len = 0;
uip_ext_len = 0;
uip_clear_buf();
memcpy(UIP_IP_BUF, FBUF, UIP_IPH_LEN); /* copy the header for src
and dest address*/
uip_icmp6_error_output(ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY, 0);
UIP_STAT(++uip_stat.ip.sent);
uip_flags = 0;
}
@ -880,14 +881,14 @@ ext_hdr_options_process(void)
uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2;
break;
case UIP_EXT_HDR_OPT_RPL:
/* Fixes situation when a node that is not using RPL
* joins a network which does. The received packages will include the
* RPL header and processed by the "default" case of the switch
* (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header
* is considered invalid.
* Using this fix, the header is ignored, and the next header (if
* present) is processed.
*/
/* Fixes situation when a node that is not using RPL
* joins a network which does. The received packages will include the
* RPL header and processed by the "default" case of the switch
* (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header
* is considered invalid.
* Using this fix, the header is ignored, and the next header (if
* present) is processed.
*/
#if UIP_CONF_IPV6_RPL
PRINTF("Processing RPL option\n");
if(rpl_verify_header(uip_ext_opt_offset)) {
@ -948,7 +949,7 @@ uip_process(uint8_t flag)
}
#endif /* UIP_UDP */
uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
/* Check if we were invoked because of a poll request for a
particular connection. */
if(flag == UIP_POLL_REQUEST) {
@ -971,9 +972,9 @@ uip_process(uint8_t flag)
} else if(flag == UIP_TIMER) {
/* Reset the length variables. */
#if UIP_TCP
uip_len = 0;
uip_clear_buf();
uip_slen = 0;
/* Increase the initial sequence number. */
if(++iss[3] == 0) {
if(++iss[2] == 0) {
@ -982,7 +983,7 @@ uip_process(uint8_t flag)
}
}
}
/*
* Check if the connection is in a state in which we simply wait
* for the connection to time out. If so, we increase the
@ -1008,7 +1009,7 @@ uip_process(uint8_t flag)
uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
uip_connr->nrtx == UIP_MAXSYNRTX)) {
uip_connr->tcpstateflags = UIP_CLOSED;
/*
* We call UIP_APPCALL() with uip_flags set to
* UIP_TIMEDOUT to inform the application that the
@ -1016,18 +1017,18 @@ uip_process(uint8_t flag)
*/
uip_flags = UIP_TIMEDOUT;
UIP_APPCALL();
/* We also send a reset packet to the remote host. */
UIP_TCP_BUF->flags = TCP_RST | TCP_ACK;
goto tcp_send_nodata;
}
/* Exponential backoff. */
uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
4:
uip_connr->nrtx);
++(uip_connr->nrtx);
/*
* Ok, so we need to retransmit. We do this differently
* depending on which state we are in. In ESTABLISHED, we
@ -1041,14 +1042,14 @@ uip_process(uint8_t flag)
case UIP_SYN_RCVD:
/* In the SYN_RCVD state, we should retransmit our SYNACK. */
goto tcp_send_synack;
#if UIP_ACTIVE_OPEN
case UIP_SYN_SENT:
/* In the SYN_SENT state, we retransmit out SYN. */
UIP_TCP_BUF->flags = 0;
goto tcp_send_syn;
#endif /* UIP_ACTIVE_OPEN */
case UIP_ESTABLISHED:
/*
* In the ESTABLISHED state, we call upon the application
@ -1059,7 +1060,7 @@ uip_process(uint8_t flag)
uip_flags = UIP_REXMIT;
UIP_APPCALL();
goto apprexmit;
case UIP_FIN_WAIT_1:
case UIP_CLOSING:
case UIP_LAST_ACK:
@ -1095,12 +1096,12 @@ uip_process(uint8_t flag)
}
#endif /* UIP_UDP */
/* This is where the input processing starts. */
UIP_STAT(++uip_stat.ip.recv);
/* Start of IP input header processing code. */
/* Check validity of the IP header. */
if((UIP_IP_BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
UIP_STAT(++uip_stat.ip.drop);
@ -1116,7 +1117,7 @@ uip_process(uint8_t flag)
* the packet has been padded and we set uip_len to the correct
* value..
*/
if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] <= uip_len) {
uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN;
/*
@ -1134,7 +1135,7 @@ uip_process(uint8_t flag)
UIP_LOG("ip: packet shorter than reported in IP header.");
goto drop;
}
PRINTF("IPv6 packet received from ");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF(" to ");
@ -1167,11 +1168,11 @@ uip_process(uint8_t flag)
uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
break;
case 1:
PRINTF("Dropping packet after extension header processing\n");
PRINTF("Dropping packet after extension header processing\n");
/* silently discard */
goto drop;
case 2:
PRINTF("Sending error message after extension header processing\n");
PRINTF("Sending error message after extension header processing\n");
/* send icmp error message (created in ext_hdr_options_process)
* and discard*/
goto send;
@ -1205,8 +1206,8 @@ uip_process(uint8_t flag)
if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) &&
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
!uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) &&
!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) {
@ -1240,7 +1241,7 @@ uip_process(uint8_t flag)
UIP_STAT(++uip_stat.ip.forwarded);
goto send;
} else {
if((uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) &&
if((uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr)) &&
(!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) &&
(!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) &&
(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) &&
@ -1416,7 +1417,7 @@ uip_process(uint8_t flag)
UIP_LOG("ip6: unrecognized header");
goto send;
/* End of headers processing */
icmp6_input:
/* This is IPv6 ICMPv6 processing code. */
PRINTF("icmp6_input: length %d type: %d \n", uip_len, UIP_ICMP_BUF->type);
@ -1456,16 +1457,16 @@ uip_process(uint8_t flag)
UIP_STAT(++uip_stat.icmp.drop);
UIP_STAT(++uip_stat.icmp.typeerr);
UIP_LOG("icmp6: unknown ICMPv6 message.");
uip_len = 0;
uip_clear_buf();
}
if(uip_len > 0) {
goto send;
} else {
goto drop;
}
/* End of IPv6 ICMP processing. */
#if UIP_UDP
/* UDP input processing. */
@ -1474,7 +1475,7 @@ uip_process(uint8_t flag)
remove_ext_hdr();
PRINTF("Receiving UDP packet\n");
/* UDP processing is really just a hack. We don't do anything to the
UDP/IP headers, but let the UDP application do all the hard
work. If the application sets uip_slen, it has a packet to
@ -1537,7 +1538,7 @@ uip_process(uint8_t flag)
udp_found:
PRINTF("In udp_found\n");
UIP_STAT(++uip_stat.udp.recv);
uip_conn = NULL;
uip_flags = UIP_NEWDATA;
uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN];
@ -1596,7 +1597,7 @@ uip_process(uint8_t flag)
UIP_STAT(++uip_stat.tcp.recv);
PRINTF("Receiving TCP packet\n");
/* Start of TCP input header processing code. */
if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
checksum. */
UIP_STAT(++uip_stat.tcp.drop);
@ -1631,7 +1632,7 @@ uip_process(uint8_t flag)
if((UIP_TCP_BUF->flags & TCP_CTL) != TCP_SYN) {
goto reset;
}
tmp16 = UIP_TCP_BUF->destport;
/* Next, check listening connections. */
for(c = 0; c < UIP_LISTENPORTS; ++c) {
@ -1639,7 +1640,7 @@ uip_process(uint8_t flag)
goto found_listen;
}
}
/* No matching connection found, so we send a RST packet. */
UIP_STAT(++uip_stat.tcp.synrst);
@ -1651,7 +1652,7 @@ uip_process(uint8_t flag)
}
UIP_STAT(++uip_stat.tcp.rst);
UIP_TCP_BUF->flags = TCP_RST | TCP_ACK;
uip_len = UIP_IPTCPH_LEN;
UIP_TCP_BUF->tcpoffset = 5 << 4;
@ -1660,15 +1661,15 @@ uip_process(uint8_t flag)
c = UIP_TCP_BUF->seqno[3];
UIP_TCP_BUF->seqno[3] = UIP_TCP_BUF->ackno[3];
UIP_TCP_BUF->ackno[3] = c;
c = UIP_TCP_BUF->seqno[2];
UIP_TCP_BUF->seqno[2] = UIP_TCP_BUF->ackno[2];
UIP_TCP_BUF->ackno[2] = c;
c = UIP_TCP_BUF->seqno[1];
UIP_TCP_BUF->seqno[1] = UIP_TCP_BUF->ackno[1];
UIP_TCP_BUF->ackno[1] = c;
c = UIP_TCP_BUF->seqno[0];
UIP_TCP_BUF->seqno[0] = UIP_TCP_BUF->ackno[0];
UIP_TCP_BUF->ackno[0] = c;
@ -1683,12 +1684,12 @@ uip_process(uint8_t flag)
}
}
}
/* Swap port numbers. */
tmp16 = UIP_TCP_BUF->srcport;
UIP_TCP_BUF->srcport = UIP_TCP_BUF->destport;
UIP_TCP_BUF->destport = tmp16;
/* Swap IP addresses. */
uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
@ -1729,7 +1730,7 @@ uip_process(uint8_t flag)
goto drop;
}
uip_conn = uip_connr;
/* Fill in the necessary fields for the new connection. */
uip_connr->rto = uip_connr->timer = UIP_RTO;
uip_connr->sa = 0;
@ -1747,10 +1748,10 @@ uip_process(uint8_t flag)
uip_connr->len = 1;
/* rcv_nxt should be the seqno from the incoming packet + 1. */
uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3];
uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2];
uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1];
uip_connr->rcv_nxt[0] = UIP_TCP_BUF->seqno[0];
uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1];
uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2];
uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3];
uip_add_rcv_nxt(1);
/* Parse the TCP MSS option, if present. */
@ -1770,7 +1771,7 @@ uip_process(uint8_t flag)
(uint16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
uip_connr->initialmss = uip_connr->mss =
tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
/* And we are done processing options. */
break;
} else {
@ -1785,19 +1786,19 @@ uip_process(uint8_t flag)
}
}
}
/* Our response will be a SYNACK. */
#if UIP_ACTIVE_OPEN
tcp_send_synack:
UIP_TCP_BUF->flags = TCP_ACK;
tcp_send_syn:
UIP_TCP_BUF->flags |= TCP_SYN;
#else /* UIP_ACTIVE_OPEN */
tcp_send_synack:
UIP_TCP_BUF->flags = TCP_SYN | TCP_ACK;
#endif /* UIP_ACTIVE_OPEN */
/* We send out the TCP Maximum Segment Size option with our
SYNACK. */
UIP_TCP_BUF->optdata[0] = TCP_OPT_MSS;
@ -1838,9 +1839,9 @@ uip_process(uint8_t flag)
receive a SYN, in which case we should retransmit our SYNACK
(which is done futher down). */
if(!((((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
((UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
((UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_RCVD) &&
((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN)))) {
((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN)))) {
if((uip_len > 0 || ((UIP_TCP_BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
(UIP_TCP_BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
UIP_TCP_BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
@ -1874,7 +1875,7 @@ uip_process(uint8_t flag)
uip_connr->snd_nxt[1] = uip_acc32[1];
uip_connr->snd_nxt[2] = uip_acc32[2];
uip_connr->snd_nxt[3] = uip_acc32[3];
/* Do RTT estimation, unless we have done retransmissions. */
if(uip_connr->nrtx == 0) {
signed char m;
@ -1898,7 +1899,7 @@ uip_process(uint8_t flag)
/* Reset length of outstanding data. */
uip_connr->len = 0;
}
}
/* Do different things depending on in what state the connection is. */
@ -1926,7 +1927,7 @@ uip_process(uint8_t flag)
}
/* We need to retransmit the SYNACK */
if((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN) {
goto tcp_send_synack;
goto tcp_send_synack;
}
goto drop;
#if UIP_ACTIVE_OPEN
@ -1978,7 +1979,7 @@ uip_process(uint8_t flag)
uip_add_rcv_nxt(1);
uip_flags = UIP_CONNECTED | UIP_NEWDATA;
uip_connr->len = 0;
uip_len = 0;
uip_clear_buf();
uip_slen = 0;
UIP_APPCALL();
goto appsend;
@ -1990,7 +1991,7 @@ uip_process(uint8_t flag)
uip_conn->tcpstateflags = UIP_CLOSED;
goto reset;
#endif /* UIP_ACTIVE_OPEN */
case UIP_ESTABLISHED:
/* In the ESTABLISHED state, we call upon the application to feed
data into the uip_buf. If the UIP_ACKDATA flag is set, the
@ -2092,7 +2093,7 @@ uip_process(uint8_t flag)
UIP_APPCALL();
appsend:
if(uip_flags & UIP_ABORT) {
uip_slen = 0;
uip_connr->tcpstateflags = UIP_CLOSED;
@ -2144,7 +2145,7 @@ uip_process(uint8_t flag)
uip_connr->nrtx = 0;
apprexmit:
uip_appdata = uip_sappdata;
/* If the application has data to be sent, or if the incoming
packet had new data in it, we must send out a packet. */
if(uip_slen > 0 && uip_connr->len > 0) {
@ -2173,7 +2174,7 @@ uip_process(uint8_t flag)
UIP_APPCALL();
}
break;
case UIP_FIN_WAIT_1:
/* The application has closed the connection, but the remote host
hasn't closed its end yet. Thus we do nothing but wait for a
@ -2202,7 +2203,7 @@ uip_process(uint8_t flag)
goto tcp_send_ack;
}
goto drop;
case UIP_FIN_WAIT_2:
if(uip_len > 0) {
uip_add_rcv_nxt(uip_len);
@ -2222,7 +2223,7 @@ uip_process(uint8_t flag)
case UIP_TIME_WAIT:
goto tcp_send_ack;
case UIP_CLOSING:
if(uip_flags & UIP_ACKDATA) {
uip_connr->tcpstateflags = UIP_TIME_WAIT;
@ -2230,7 +2231,7 @@ uip_process(uint8_t flag)
}
}
goto drop;
/* We jump here when we are ready to send the packet, and just want
to set the appropriate TCP sequence numbers in the TCP header. */
tcp_send_ack:
@ -2248,12 +2249,12 @@ uip_process(uint8_t flag)
packet. */
tcp_send:
PRINTF("In tcp_send\n");
UIP_TCP_BUF->ackno[0] = uip_connr->rcv_nxt[0];
UIP_TCP_BUF->ackno[1] = uip_connr->rcv_nxt[1];
UIP_TCP_BUF->ackno[2] = uip_connr->rcv_nxt[2];
UIP_TCP_BUF->ackno[3] = uip_connr->rcv_nxt[3];
UIP_TCP_BUF->seqno[0] = uip_connr->snd_nxt[0];
UIP_TCP_BUF->seqno[1] = uip_connr->snd_nxt[1];
UIP_TCP_BUF->seqno[2] = uip_connr->snd_nxt[2];
@ -2287,7 +2288,7 @@ uip_process(uint8_t flag)
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
UIP_TCP_BUF->urgp[0] = UIP_TCP_BUF->urgp[1] = 0;
/* Calculate TCP checksum. */
UIP_TCP_BUF->tcpchksum = 0;
UIP_TCP_BUF->tcpchksum = ~(uip_tcpchksum());
@ -2303,15 +2304,14 @@ uip_process(uint8_t flag)
send:
PRINTF("Sending packet with length %d (%d)\n", uip_len,
(UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
UIP_STAT(++uip_stat.ip.sent);
/* Return and let the caller do the actual transmission. */
uip_flags = 0;
return;
drop:
uip_len = 0;
uip_ext_len = 0;
uip_clear_buf();
uip_ext_bitmap = 0;
uip_flags = 0;
return;

View File

@ -55,7 +55,8 @@ anti_replay_set_counter(void)
{
frame802154_frame_counter_t reordered_counter;
reordered_counter.u32 = LLSEC802154_HTONL(++counter);
++counter;
reordered_counter.u32 = LLSEC802154_HTONL(counter);
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, reordered_counter.u16[0]);
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, reordered_counter.u16[1]);

View File

@ -1,52 +1,78 @@
/*
* Copyright (c) 2013, Hasso-Plattner-Institut.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* CCM* convenience functions for LLSEC use
* \author
* Justin King-Lacroix <justin.kinglacroix@gmail.com>
* Konrad Krentz <konrad.krentz@gmail.com>
*/
#include "lib/ccm-star.h"
#include "llsec/ccm-star-packetbuf.h"
#include "net/linkaddr.h"
#include "net/packetbuf.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
void ccm_star_mic_packetbuf(const uint8_t *extended_source_address,
uint8_t *result,
uint8_t mic_len)
static const uint8_t *
get_extended_address(const linkaddr_t *addr)
#if LINKADDR_SIZE == 2
{
uint8_t *dataptr = packetbuf_dataptr();
uint8_t data_len = packetbuf_datalen();
uint8_t *headerptr = packetbuf_hdrptr();
uint8_t header_len = packetbuf_hdrlen();
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
/* workaround for short addresses: derive EUI64 as in RFC 6282 */
static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 ,
0xFF , 0xFE , 0x00 , 0x00 , 0x00 } };
memcpy(nonce, extended_source_address, 8);
template.u16[3] = LLSEC802154_HTONS(addr->u16);
return template.u8;
}
#else /* LINKADDR_SIZE == 2 */
{
return addr->u8;
}
#endif /* LINKADDR_SIZE == 2 */
/*---------------------------------------------------------------------------*/
void
ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward)
{
const linkaddr_t *source_addr;
source_addr = forward ? &linkaddr_node_addr : packetbuf_addr(PACKETBUF_ADDR_SENDER);
memcpy(nonce, get_extended_address(source_addr), 8);
nonce[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8;
nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff;
nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8;
nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff;
nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) {
CCM_STAR.mic(dataptr, data_len, nonce, headerptr, header_len, result, mic_len);
} else {
CCM_STAR.mic(dataptr, 0, nonce, headerptr, packetbuf_totlen(), result, mic_len);
}
}
/*---------------------------------------------------------------------------*/
void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address)
{
uint8_t *dataptr = packetbuf_dataptr();
uint8_t data_len = packetbuf_datalen();
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
memcpy(nonce, extended_source_address, 8);
nonce[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8;
nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff;
nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8;
nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff;
nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
CCM_STAR.ctr(dataptr, data_len, nonce);
}
/*---------------------------------------------------------------------------*/

View File

@ -1,24 +1,48 @@
/*
* Copyright (c) 2013, Hasso-Plattner-Institut.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* CCM* convenience functions for MAC security
* \author
* Justin King-Lacroix <justin.kinglacroix@gmail.com>
* Konrad Krentz <konrad.krentz@gmail.com>
*/
#ifndef CCM_STAR_PACKETBUF_H_
#define CCM_STAR_PACKETBUF_H_
/**
* \brief Calls CCM_STAR.mic with parameters appropriate for LLSEC.
*/
void ccm_star_mic_packetbuf(const uint8_t *extended_source_address,
uint8_t *result,
uint8_t mic_len);
#include "lib/ccm-star.h"
/**
* \brief Calls CCM_STAR.ctr with parameters appropriate for LLSEC.
*/
void ccm_star_ctr_packetbuf(const uint8_t *extended_source_address);
void ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward);
#endif /* CCM_STAR_PACKETBUF_H_ */

View File

@ -48,10 +48,6 @@
* for incoming packets. Likewise, all NETSTACK_NETWORK protocols
* invoke NETSTACK_LLSEC.send(...) for outgoing packets.
*
* The bootstrap function of llsec_drivers can be used to defer the start
* of upper layers so as to bootstrap pairwise keys. Only contiki-sky-main.c
* supports this at the moment.
*
* @{
*/
@ -60,35 +56,23 @@
#include "net/mac/mac.h"
typedef void (* llsec_on_bootstrapped_t)(void);
/**
* The structure of a link layer security driver.
*/
struct llsec_driver {
char *name;
/** Bootstraps link layer security and thereafter starts upper layers. */
void (* bootstrap)(llsec_on_bootstrapped_t on_bootstrapped);
/** Inits link layer security. */
void (* init)(void);
/** Secures outgoing frames before passing them to NETSTACK_MAC. */
void (* send)(mac_callback_t sent_callback, void *ptr);
/**
* Once the NETSTACK_FRAMER wrote the headers, the LLSEC driver
* can generate a MIC over the entire frame.
* \return Returns != 0 <-> success
*/
int (* on_frame_created)(void);
/**
* Decrypts incoming frames;
* filters out injected or replayed frames.
*/
void (* input)(void);
/** Returns the security-related overhead per frame in bytes */
uint8_t (* get_overhead)(void);
};
#endif /* LLSEC_H_ */

View File

@ -85,6 +85,12 @@
#define LLSEC802154_USES_EXPLICIT_KEYS 0
#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */
#ifdef LLSEC802154_CONF_USES_FRAME_COUNTER
#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER
#else /* LLSEC802154_CONF_USES_FRAME_COUNTER */
#define LLSEC802154_USES_FRAME_COUNTER (LLSEC802154_SECURITY_LEVEL != FRAME802154_SECURITY_LEVEL_NONE)
#endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */
#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
#define LLSEC802154_HTONS(n) (n)
#define LLSEC802154_HTONL(n) (n)

View File

@ -47,6 +47,7 @@
#include "net/llsec/llsec802154.h"
#include "net/llsec/ccm-star-packetbuf.h"
#include "net/mac/frame802154.h"
#include "net/mac/framer-802154.h"
#include "net/netstack.h"
#include "net/packetbuf.h"
#include "net/nbr-table.h"
@ -80,81 +81,109 @@ static uint8_t key[16] = NONCORESEC_KEY;
NBR_TABLE(struct anti_replay_info, anti_replay_table);
/*---------------------------------------------------------------------------*/
static const uint8_t *
get_extended_address(const linkaddr_t *addr)
#if LINKADDR_SIZE == 2
static int
aead(uint8_t hdrlen, int forward)
{
/* workaround for short addresses: derive EUI64 as in RFC 6282 */
static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 ,
0xFF , 0xFE , 0x00 , 0x00 , 0x00 } };
uint8_t totlen;
uint8_t nonce[CCM_STAR_NONCE_LENGTH];
uint8_t *m;
uint8_t m_len;
uint8_t *a;
uint8_t a_len;
uint8_t *result;
uint8_t generated_mic[LLSEC802154_MIC_LENGTH];
uint8_t *mic;
template.u16[3] = LLSEC802154_HTONS(addr->u16);
ccm_star_packetbuf_set_nonce(nonce, forward);
totlen = packetbuf_totlen();
a = packetbuf_hdrptr();
#if WITH_ENCRYPTION
a_len = hdrlen;
m = a + a_len;
m_len = totlen - hdrlen;
#else /* WITH_ENCRYPTION */
a_len = totlen;
m = NULL;
m_len = 0;
#endif /* WITH_ENCRYPTION */
return template.u8;
mic = a + totlen;
result = forward ? mic : generated_mic;
CCM_STAR.aead(nonce,
m, m_len,
a, a_len,
result, LLSEC802154_MIC_LENGTH,
forward);
if(forward) {
packetbuf_set_datalen(packetbuf_datalen() + LLSEC802154_MIC_LENGTH);
return 1;
} else {
return (memcmp(generated_mic, mic, LLSEC802154_MIC_LENGTH) == 0);
}
}
#else /* LINKADDR_SIZE == 2 */
/*---------------------------------------------------------------------------*/
static void
add_security_header(void)
{
return addr->u8;
if(!packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL);
anti_replay_set_counter();
}
}
#endif /* LINKADDR_SIZE == 2 */
/*---------------------------------------------------------------------------*/
static void
send(mac_callback_t sent, void *ptr)
{
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL);
anti_replay_set_counter();
NETSTACK_MAC.send(sent, ptr);
}
/*---------------------------------------------------------------------------*/
static int
on_frame_created(void)
create(void)
{
uint8_t *dataptr = packetbuf_dataptr();
uint8_t data_len = packetbuf_datalen();
ccm_star_mic_packetbuf(get_extended_address(&linkaddr_node_addr), dataptr + data_len, LLSEC802154_MIC_LENGTH);
#if WITH_ENCRYPTION
ccm_star_ctr_packetbuf(get_extended_address(&linkaddr_node_addr));
#endif /* WITH_ENCRYPTION */
packetbuf_set_datalen(data_len + LLSEC802154_MIC_LENGTH);
int result;
return 1;
add_security_header();
result = framer_802154.create();
if(result == FRAMER_FAILED) {
return result;
}
aead(result, 1);
return result;
}
/*---------------------------------------------------------------------------*/
static void
input(void)
static int
parse(void)
{
uint8_t generated_mic[LLSEC802154_MIC_LENGTH];
uint8_t *received_mic;
int result;
const linkaddr_t *sender;
struct anti_replay_info* info;
uint8_t *dataptr = packetbuf_dataptr();
uint8_t data_len = packetbuf_datalen();
result = framer_802154.parse();
if(result == FRAMER_FAILED) {
return result;
}
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != LLSEC802154_SECURITY_LEVEL) {
PRINTF("noncoresec: received frame with wrong security level\n");
return;
return FRAMER_FAILED;
}
sender = packetbuf_addr(PACKETBUF_ADDR_SENDER);
if(linkaddr_cmp(sender, &linkaddr_node_addr)) {
PRINTF("noncoresec: frame from ourselves\n");
return;
return FRAMER_FAILED;
}
data_len -= LLSEC802154_MIC_LENGTH;
packetbuf_set_datalen(data_len);
packetbuf_set_datalen(packetbuf_datalen() - LLSEC802154_MIC_LENGTH);
#if WITH_ENCRYPTION
ccm_star_ctr_packetbuf(get_extended_address(sender));
#endif /* WITH_ENCRYPTION */
ccm_star_mic_packetbuf(get_extended_address(sender), generated_mic, LLSEC802154_MIC_LENGTH);
received_mic = dataptr + data_len;
if(memcmp(generated_mic, received_mic, LLSEC802154_MIC_LENGTH) != 0) {
PRINTF("noncoresec: received nonauthentic frame %"PRIu32"\n",
if(!aead(result, 0)) {
PRINTF("noncoresec: received unauthentic frame %"PRIu32"\n",
anti_replay_get_counter());
return;
return FRAMER_FAILED;
}
info = nbr_table_get_from_lladdr(anti_replay_table, sender);
@ -162,7 +191,7 @@ input(void)
info = nbr_table_add_lladdr(anti_replay_table, sender);
if(!info) {
PRINTF("noncoresec: could not get nbr_table_item\n");
return;
return FRAMER_FAILED;
}
/*
@ -179,7 +208,7 @@ input(void)
if(!nbr_table_lock(anti_replay_table, info)) {
nbr_table_remove(anti_replay_table, info);
PRINTF("noncoresec: could not lock\n");
return;
return FRAMER_FAILED;
}
anti_replay_init_info(info);
@ -187,34 +216,44 @@ input(void)
if(anti_replay_was_replayed(info)) {
PRINTF("noncoresec: received replayed frame %"PRIu32"\n",
anti_replay_get_counter());
return;
return FRAMER_FAILED;
}
}
NETSTACK_NETWORK.input();
}
/*---------------------------------------------------------------------------*/
static uint8_t
get_overhead(void)
{
return SECURITY_HEADER_LENGTH + LLSEC802154_MIC_LENGTH;
return result;
}
/*---------------------------------------------------------------------------*/
static void
bootstrap(llsec_on_bootstrapped_t on_bootstrapped)
input(void)
{
NETSTACK_NETWORK.input();
}
/*---------------------------------------------------------------------------*/
static int
length(void)
{
add_security_header();
return framer_802154.length() + LLSEC802154_MIC_LENGTH;
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
CCM_STAR.set_key(key);
nbr_table_register(anti_replay_table, NULL);
on_bootstrapped();
}
/*---------------------------------------------------------------------------*/
const struct llsec_driver noncoresec_driver = {
"noncoresec",
bootstrap,
init,
send,
on_frame_created,
input,
get_overhead
input
};
/*---------------------------------------------------------------------------*/
const struct framer noncoresec_framer = {
length,
create,
parse
};
/*---------------------------------------------------------------------------*/

View File

@ -56,6 +56,7 @@
#include "net/llsec/llsec.h"
extern const struct llsec_driver noncoresec_driver;
extern const struct framer noncoresec_framer;
#endif /* NONCORESEC_H_ */

View File

@ -49,9 +49,9 @@
/*---------------------------------------------------------------------------*/
static void
bootstrap(llsec_on_bootstrapped_t on_bootstrapped)
init(void)
{
on_bootstrapped();
}
/*---------------------------------------------------------------------------*/
static void
@ -61,31 +61,17 @@ send(mac_callback_t sent, void *ptr)
NETSTACK_MAC.send(sent, ptr);
}
/*---------------------------------------------------------------------------*/
static int
on_frame_created(void)
{
return 1;
}
/*---------------------------------------------------------------------------*/
static void
input(void)
{
NETSTACK_NETWORK.input();
}
/*---------------------------------------------------------------------------*/
static uint8_t
get_overhead(void)
{
return 0;
}
/*---------------------------------------------------------------------------*/
const struct llsec_driver nullsec_driver = {
"nullsec",
bootstrap,
init,
send,
on_frame_created,
input,
get_overhead
input
};
/*---------------------------------------------------------------------------*/

View File

@ -73,6 +73,8 @@ extern const struct framer DECORATED_FRAMER;
#define PRINTF(...)
#endif
static void pad(void);
/* 2-byte header for recovering padded packets.
Wireshark will not understand such packets at present. */
struct hdr {
@ -99,7 +101,8 @@ create(void)
}
chdr = packetbuf_hdrptr();
chdr->id = CONTIKIMAC_ID;
chdr->len = 0;
chdr->len = packetbuf_datalen();
pad();
hdr_len = DECORATED_FRAMER.create();
if(hdr_len < 0) {
@ -107,6 +110,8 @@ create(void)
return FRAMER_FAILED;
}
packetbuf_compact();
return hdr_len + sizeof(struct hdr);
}
/*---------------------------------------------------------------------------*/
@ -117,7 +122,7 @@ pad(void)
uint8_t *ptr;
uint8_t zeroes_count;
transmit_len = packetbuf_totlen();
transmit_len = packetbuf_totlen() + hdr_length();
if(transmit_len < SHORTEST_PACKET_SIZE) {
/* Padding required */
zeroes_count = SHORTEST_PACKET_SIZE - transmit_len;
@ -128,30 +133,6 @@ pad(void)
}
/*---------------------------------------------------------------------------*/
static int
create_and_secure(void)
{
struct hdr *chdr;
int hdr_len;
hdr_len = create();
if(hdr_len < 0) {
return FRAMER_FAILED;
}
packetbuf_compact();
if(!NETSTACK_LLSEC.on_frame_created()) {
PRINTF("contikimac-framer: securing failed\n");
return FRAMER_FAILED;
}
chdr = (struct hdr *)(((uint8_t *) packetbuf_dataptr()) - sizeof(struct hdr));
chdr->len = packetbuf_datalen();
pad();
return hdr_len;
}
/*---------------------------------------------------------------------------*/
static int
parse(void)
{
int hdr_len;
@ -174,7 +155,6 @@ parse(void)
}
packetbuf_set_datalen(chdr->len);
chdr->len = 0;
return hdr_len + sizeof(struct hdr);
}
@ -182,7 +162,6 @@ parse(void)
const struct framer contikimac_framer = {
hdr_length,
create,
create_and_secure,
parse
};
/*---------------------------------------------------------------------------*/

View File

@ -106,7 +106,11 @@ static int we_are_receiving_burst = 0;
/* INTER_PACKET_DEADLINE is the maximum time a receiver waits for the
next packet of a burst when FRAME_PENDING is set. */
#ifdef CONTIKIMAC_CONF_INTER_PACKET_DEADLINE
#define INTER_PACKET_DEADLINE CONTIKIMAC_CONF_INTER_PACKET_DEADLINE
#else
#define INTER_PACKET_DEADLINE CLOCK_SECOND / 32
#endif
/* ContikiMAC performs periodic channel checks. Each channel check
consists of two or more CCA checks. CCA_COUNT_MAX is the number of
@ -166,12 +170,21 @@ static int we_are_receiving_burst = 0;
/* MAX_SILENCE_PERIODS is the maximum amount of periods (a period is
CCA_CHECK_TIME + CCA_SLEEP_TIME) that we allow to be silent before
we turn of the radio. */
#ifdef CONTIKIMAC_CONF_MAX_SILENCE_PERIODS
#define MAX_SILENCE_PERIODS CONTIKIMAC_CONF_MAX_SILENCE_PERIODS
#else
#define MAX_SILENCE_PERIODS 5
#endif
/* MAX_NONACTIVITY_PERIODS is the maximum number of periods we allow
the radio to be turned on without any packet being received, when
WITH_FAST_SLEEP is enabled. */
#ifdef CONTIKIMAC_CONF_MAX_NONACTIVITY_PERIODS
#define MAX_NONACTIVITY_PERIODS CONTIKIMAC_CONF_MAX_NONACTIVITY_PERIODS
#else
#define MAX_NONACTIVITY_PERIODS 10
#endif
@ -181,7 +194,11 @@ static int we_are_receiving_burst = 0;
/* GUARD_TIME is the time before the expected phase of a neighbor that
a transmitted should begin transmitting packets. */
#ifdef CONTIKIMAC_CONF_GUARD_TIME
#define GUARD_TIME CONTIKIMAC_CONF_GUARD_TIME
#else
#define GUARD_TIME 10 * CHECK_TIME + CHECK_TIME_TX
#endif
/* INTER_PACKET_INTERVAL is the interval between two successive packet transmissions */
#ifdef CONTIKIMAC_CONF_INTER_PACKET_INTERVAL
@ -201,7 +218,11 @@ static int we_are_receiving_burst = 0;
/* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
to a neighbor for which we have a phase lock. */
#ifdef CONTIKIMAC_CONF_MAX_PHASE_STROBE_TIME
#define MAX_PHASE_STROBE_TIME CONTIKIMAC_CONF_MAX_PHASE_STROBE_TIME
#else
#define MAX_PHASE_STROBE_TIME RTIMER_ARCH_SECOND / 60
#endif
#ifdef CONTIKIMAC_CONF_SEND_SW_ACK
#define CONTIKIMAC_SEND_SW_ACK CONTIKIMAC_CONF_SEND_SW_ACK
@ -269,20 +290,24 @@ off(void)
}
/*---------------------------------------------------------------------------*/
static volatile rtimer_clock_t cycle_start;
static void powercycle_wrapper(struct rtimer *t, void *ptr);
static char powercycle(struct rtimer *t, void *ptr);
static void
schedule_powercycle(struct rtimer *t, rtimer_clock_t time)
{
int r;
rtimer_clock_t now;
if(contikimac_is_on) {
if(RTIMER_CLOCK_LT(RTIMER_TIME(t) + time, RTIMER_NOW() + 2)) {
time = RTIMER_NOW() - RTIMER_TIME(t) + 2;
time += RTIMER_TIME(t);
now = RTIMER_NOW();
if(RTIMER_CLOCK_LT(time, now + RTIMER_GUARD_TIME)) {
time = now + RTIMER_GUARD_TIME;
}
r = rtimer_set(t, RTIMER_TIME(t) + time, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL);
r = rtimer_set(t, time, 1, powercycle_wrapper, NULL);
if(r != RTIMER_OK) {
PRINTF("schedule_powercycle: could not set rtimer\n");
}
@ -293,15 +318,16 @@ static void
schedule_powercycle_fixed(struct rtimer *t, rtimer_clock_t fixed_time)
{
int r;
rtimer_clock_t now;
if(contikimac_is_on) {
if(RTIMER_CLOCK_LT(fixed_time, RTIMER_NOW() + 1)) {
fixed_time = RTIMER_NOW() + 1;
now = RTIMER_NOW();
if(RTIMER_CLOCK_LT(fixed_time, now + RTIMER_GUARD_TIME)) {
fixed_time = now + RTIMER_GUARD_TIME;
}
r = rtimer_set(t, fixed_time, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL);
r = rtimer_set(t, fixed_time, 1, powercycle_wrapper, NULL);
if(r != RTIMER_OK) {
PRINTF("schedule_powercycle: could not set rtimer\n");
}
@ -335,6 +361,12 @@ powercycle_turn_radio_on(void)
/*---------------------------------------------------------------------------*/
volatile uint8_t mcusleepcycle=16;
static void
powercycle_wrapper(struct rtimer *t, void *ptr)
{
powercycle(t, ptr);
}
/*---------------------------------------------------------------------------*/
static char
powercycle(struct rtimer *t, void *ptr)
{
@ -511,14 +543,16 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
#endif
int strobes;
uint8_t got_strobe_ack = 0;
int len;
uint8_t is_broadcast = 0;
uint8_t is_known_receiver = 0;
uint8_t collisions;
int transmit_len;
int ret;
uint8_t contikimac_was_on;
#if !RDC_CONF_HARDWARE_ACK
int len;
uint8_t seqno;
#endif
/* Exit if RDC and radio were explicitly turned off */
if(!contikimac_is_on && !contikimac_keep_radio_on) {
@ -562,7 +596,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
if(NETSTACK_FRAMER.create_and_secure() < 0) {
if(NETSTACK_FRAMER.create() < 0) {
PRINTF("contikimac: framer failed\n");
return MAC_TX_ERR_FATAL;
}
@ -659,11 +693,11 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
or rx cycle */
on();
}
seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
#endif
watchdog_periodic();
t0 = RTIMER_NOW();
seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
for(strobes = 0, collisions = 0;
got_strobe_ack == 0 && collisions == 0 &&
RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {
@ -678,7 +712,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
}
#endif /* WITH_PHASE_OPTIMIZATION */
#if !RDC_CONF_HARDWARE_ACK
len = 0;
#endif
{
rtimer_clock_t wt;
@ -807,6 +843,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
struct rdc_buf_list *next;
int ret;
int is_receiver_awake;
int pending;
if(buf_list == NULL) {
return;
@ -831,7 +868,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
}
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
if(NETSTACK_FRAMER.create_and_secure() < 0) {
if(NETSTACK_FRAMER.create() < 0) {
PRINTF("contikimac: framer failed\n");
mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
return;
@ -851,7 +888,9 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
/* Prepare the packetbuf */
queuebuf_to_packetbuf(curr->buf);
pending = packetbuf_attr(PACKETBUF_ATTR_PENDING);
/* Send the current packet */
ret = send_packet(sent, ptr, curr, is_receiver_awake);
if(ret != MAC_TX_DEFERRED) {
@ -868,7 +907,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
/* The transmission failed, we stop the burst */
next = NULL;
}
} while((next != NULL) && packetbuf_attr(PACKETBUF_ATTR_PENDING));
} while((next != NULL) && pending);
}
/*---------------------------------------------------------------------------*/
/* Timer callback triggered when receiving a burst, after having
@ -917,8 +956,6 @@ input_packet(void)
broadcast address. */
/* If FRAME_PENDING is set, we are receiving a packets in a burst */
/* TODO To prevent denial-of-sleep attacks, the transceiver should
be disabled upon receipt of an unauthentic frame. */
we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
if(we_are_receiving_burst) {
on();
@ -995,8 +1032,7 @@ init(void)
radio_is_on = 0;
PT_INIT(&pt);
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL);
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1, powercycle_wrapper, NULL);
contikimac_is_on = 1;
@ -1012,8 +1048,7 @@ turn_on(void)
if(contikimac_is_on == 0) {
contikimac_is_on = 1;
contikimac_keep_radio_on = 0;
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1,
(void (*)(struct rtimer *, void *))powercycle, NULL);
rtimer_set(&rt, RTIMER_NOW() + CYCLE_TIME, 1, powercycle_wrapper, NULL);
}
return 1;
}

View File

@ -171,8 +171,10 @@ transmit_packet_list(void *ptr)
}
/*---------------------------------------------------------------------------*/
static void
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status)
{
clock_time_t tx_delay;
if(p != NULL) {
/* Remove packet from list and deallocate */
list_remove(n->queued_packet_list, p);
@ -188,8 +190,8 @@ free_packet(struct neighbor_queue *n, struct rdc_buf_list *p)
n->collisions = 0;
n->deferrals = 0;
/* Set a timer for next transmissions */
ctimer_set(&n->transmit_timer, default_timebase(),
transmit_packet_list, n);
tx_delay = (status == MAC_TX_OK) ? 0 : default_timebase();
ctimer_set(&n->transmit_timer, tx_delay, transmit_packet_list, n);
} else {
/* This was the last packet in the queue, we free the neighbor */
ctimer_stop(&n->transmit_timer);
@ -293,7 +295,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
} else {
PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
status, n->transmissions, n->collisions);
free_packet(n, q);
free_packet(n, q, status);
mac_call_sent_callback(sent, cptr, status, num_tx);
}
} else {
@ -302,7 +304,7 @@ packet_sent(void *ptr, int status, int num_transmissions)
} else {
PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
}
free_packet(n, q);
free_packet(n, q, status);
mac_call_sent_callback(sent, cptr, status, num_tx);
}
} else {

View File

@ -44,11 +44,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
*/
/*
* \brief This file is where the main functions that relate to frame
* manipulation will reside.
*/
*/
/**
* \file
@ -61,7 +61,7 @@
/**
* \addtogroup frame802154
* @{
*/
*/
#include "sys/cc.h"
#include "net/mac/frame802154.h"
@ -69,11 +69,18 @@
#include "net/linkaddr.h"
#include <string.h>
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated.
*/
static uint16_t mac_pan_id = IEEE802154_PANID;
/**
* \brief Structure that contains the lengths of the various addressing and security fields
* in the 802.15.4 header. This structure is used in \ref frame802154_create()
*/
typedef struct {
uint8_t seqno_len; /**< Length (in bytes) of sequence number field */
uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */
uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */
uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */
@ -111,30 +118,199 @@ get_key_id_len(uint8_t key_id_mode)
}
}
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
/*---------------------------------------------------------------------------*/
/* Get current PAN ID */
uint16_t
frame802154_get_pan_id(void)
{
return mac_pan_id;
}
/*---------------------------------------------------------------------------*/
/* Set current PAN ID */
void
frame802154_set_pan_id(uint16_t pan_id)
{
mac_pan_id = pan_id;
}
/*----------------------------------------------------------------------------*/
/* Tells whether a given Frame Control Field indicates a frame with
* source PANID and/or destination PANID */
void
frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id)
{
int src_pan_id = 0;
int dest_pan_id = 0;
if(fcf == NULL) {
return;
}
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
if(!fcf->panid_compression) {
/* Compressed PAN ID == no PAN ID at all */
if(fcf->dest_addr_mode == fcf->dest_addr_mode) {
/* No address or both addresses: include destination PAN ID */
dest_pan_id = 1;
} else if(fcf->dest_addr_mode) {
/* Only dest address, include dest PAN ID */
dest_pan_id = 1;
} else if(fcf->src_addr_mode) {
/* Only src address, include src PAN ID */
src_pan_id = 1;
}
}
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 1) {
/* No address included, include dest PAN ID conditionally */
if(!fcf->panid_compression) {
dest_pan_id = 1;
}
}
/* Remove the following rule the day rows 2 and 3 from table 2a are fixed: */
if(fcf->dest_addr_mode == 0 && fcf->dest_addr_mode == 0) {
/* Not meaningful, we include a PAN ID iff the compress flag is set, but
* this is what the standard currently stipulates */
dest_pan_id = fcf->panid_compression;
}
} else {
/* No PAN ID in ACK */
if(fcf->frame_type != FRAME802154_ACKFRAME) {
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
/* If compressed, don't inclue source PAN ID */
src_pan_id = 1;
}
if(fcf->dest_addr_mode & 3) {
dest_pan_id = 1;
}
}
}
if(has_src_pan_id != NULL) {
*has_src_pan_id = src_pan_id;
}
if(has_dest_pan_id != NULL) {
*has_dest_pan_id = dest_pan_id;
}
}
/*---------------------------------------------------------------------------*/
/* Check if the destination PAN ID, if any, matches ours */
int
frame802154_check_dest_panid(frame802154_t *frame)
{
int has_dest_panid;
if(frame == NULL) {
return 0;
}
frame802154_has_panid(&frame->fcf, NULL, &has_dest_panid);
if(has_dest_panid
&& frame->dest_pid != frame802154_get_pan_id()
&& frame->dest_pid != FRAME802154_BROADCASTPANDID) {
/* Packet to another PAN */
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
/* Check is the address is a broadcast address, whatever its size */
int
frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr)
{
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
while(i-- > 0) {
if(addr[i] != 0xff) {
return 0;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
/* Check and extract source and destination linkaddr from frame */
int
frame802154_extract_linkaddr(frame802154_t *frame,
linkaddr_t *source_address, linkaddr_t *dest_address)
{
int src_addr_len;
int dest_addr_len;
if(frame == NULL) {
return 0;
}
/* Check and extract source address */
src_addr_len = frame->fcf.src_addr_mode ?
((frame->fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
if(src_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.src_addr_mode, frame->src_addr)) {
/* Broadcast address */
if(source_address != NULL) {
linkaddr_copy(source_address, &linkaddr_null);
}
} else {
/* Unicast address */
if(src_addr_len != LINKADDR_SIZE) {
/* Destination address has a size we can not handle */
return 0;
}
if(source_address != NULL) {
linkaddr_copy(source_address, (linkaddr_t *)frame->src_addr);
}
}
/* Check and extract destination address */
dest_addr_len = frame->fcf.dest_addr_mode ?
((frame->fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) ? 2 : 8) : 0;
if(dest_addr_len == 0 || frame802154_is_broadcast_addr(frame->fcf.dest_addr_mode, frame->dest_addr)) {
/* Broadcast address */
if(dest_address != NULL) {
linkaddr_copy(dest_address, &linkaddr_null);
}
} else {
/* Unicast address */
if(dest_addr_len != LINKADDR_SIZE) {
/* Destination address has a size we can not handle */
return 0;
}
if(dest_address != NULL) {
linkaddr_copy(dest_address, (linkaddr_t *)frame->dest_addr);
}
}
return 1;
}
/*----------------------------------------------------------------------------*/
static void
field_len(frame802154_t *p, field_length_t *flen)
{
int has_src_panid;
int has_dest_panid;
/* init flen to zeros */
memset(flen, 0, sizeof(field_length_t));
/* Determine lengths of each field based on fcf and other args */
if(p->fcf.dest_addr_mode & 3) {
flen->dest_pid_len = 2;
if((p->fcf.sequence_number_suppression & 1) == 0) {
flen->seqno_len = 1;
}
if(p->fcf.src_addr_mode & 3) {
/* IEEE802.15.4e changes the meaning of PAN ID Compression (see Table 2a).
* In this case, we leave the decision whether to compress PAN ID or not
* up to the caller. */
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
/* Set PAN ID compression bit if src pan id matches dest pan id. */
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1;
} else {
p->fcf.panid_compression = 0;
}
}
frame802154_has_panid(&p->fcf, &has_src_panid, &has_dest_panid);
if(has_src_panid) {
flen->src_pid_len = 2;
}
/* Set PAN ID compression bit if src pan id matches dest pan id. */
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1;
/* compressed header, only do dest pid */
flen->src_pid_len = 0;
} else {
p->fcf.panid_compression = 0;
if(has_dest_panid) {
flen->dest_pid_len = 2;
}
/* determine address lengths */
@ -144,9 +320,16 @@ field_len(frame802154_t *p, field_length_t *flen)
#if LLSEC802154_SECURITY_LEVEL
/* Aux security header */
if(p->fcf.security_enabled & 1) {
flen->aux_sec_len = 5
flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
if(p->aux_hdr.security_control.frame_counter_size == 1) {
flen->aux_sec_len += 5;
} else {
flen->aux_sec_len += 4;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS
+ get_key_id_len(p->aux_hdr.security_control.key_id_mode);
flen->aux_sec_len += get_key_id_len(p->aux_hdr.security_control.key_id_mode);
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
;
}
@ -161,14 +344,14 @@ field_len(frame802154_t *p, field_length_t *flen)
* frame to send.
*
* \return The length of the frame header.
*/
*/
int
frame802154_hdrlen(frame802154_t *p)
{
field_length_t flen;
field_len(p, &flen);
return 3 + flen.dest_pid_len + flen.dest_addr_len +
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
}
/*----------------------------------------------------------------------------*/
/**
@ -181,7 +364,7 @@ frame802154_hdrlen(frame802154_t *p)
* \param buf Pointer to the buffer to use for the frame.
*
* \return The length of the frame header
*/
*/
int
frame802154_create(frame802154_t *p, uint8_t *buf)
{
@ -193,7 +376,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
field_len(p, &flen);
/* OK, now we have field lengths. Time to actually construct */
/* the outgoing frame, and store it in buf */
buf[0] = (p->fcf.frame_type & 7) |
@ -201,13 +384,18 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
((p->fcf.frame_pending & 1) << 4) |
((p->fcf.ack_required & 1) << 5) |
((p->fcf.panid_compression & 1) << 6);
buf[1] = ((p->fcf.dest_addr_mode & 3) << 2) |
buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
((p->fcf.ie_list_present & 1)) << 1 |
((p->fcf.dest_addr_mode & 3) << 2) |
((p->fcf.frame_version & 3) << 4) |
((p->fcf.src_addr_mode & 3) << 6);
/* sequence number */
buf[2] = p->seq;
pos = 3;
pos = 2;
/* Sequence number */
if(flen.seqno_len == 1) {
buf[pos++] = p->seq;
}
/* Destination PAN ID */
if(flen.dest_pid_len == 2) {
@ -230,17 +418,24 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
for(c = flen.src_addr_len; c > 0; c--) {
buf[pos++] = p->src_addr[c - 1];
}
#if LLSEC802154_SECURITY_LEVEL
/* Aux header */
if(flen.aux_sec_len) {
buf[pos++] = p->aux_hdr.security_control.security_level
#if LLSEC802154_USES_EXPLICIT_KEYS
| (p->aux_hdr.security_control.key_id_mode << 3)
| (p->aux_hdr.security_control.key_id_mode << 3)
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
| (p->aux_hdr.security_control.frame_counter_suppression << 5)
| (p->aux_hdr.security_control.frame_counter_size << 6)
;
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
pos += 4;
if(p->aux_hdr.security_control.frame_counter_suppression == 0) {
/* We support only 4-byte counters */
memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
pos += 4;
if(p->aux_hdr.security_control.frame_counter_size == 1) {
pos++;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS
key_id_mode = p->aux_hdr.security_control.key_id_mode;
@ -272,11 +467,13 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
uint8_t *p;
frame802154_fcf_t fcf;
int c;
int has_src_panid;
int has_dest_panid;
#if LLSEC802154_USES_EXPLICIT_KEYS
uint8_t key_id_mode;
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
if(len < 3) {
if(len < 2) {
return 0;
}
@ -289,20 +486,32 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
fcf.ack_required = (p[0] >> 5) & 1;
fcf.panid_compression = (p[0] >> 6) & 1;
fcf.sequence_number_suppression = p[1] & 1;
fcf.ie_list_present = (p[1] >> 1) & 1;
fcf.dest_addr_mode = (p[1] >> 2) & 3;
fcf.frame_version = (p[1] >> 4) & 3;
fcf.src_addr_mode = (p[1] >> 6) & 3;
/* copy fcf and seqNum */
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
pf->seq = p[2];
p += 3; /* Skip first three bytes */
p += 2; /* Skip first two bytes */
if(fcf.sequence_number_suppression == 0) {
pf->seq = p[0];
p++;
}
frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
/* Destination address, if any */
if(fcf.dest_addr_mode) {
/* Destination PAN */
pf->dest_pid = p[0] + (p[1] << 8);
p += 2;
if(has_dest_panid) {
/* Destination PAN */
pf->dest_pid = p[0] + (p[1] << 8);
p += 2;
} else {
pf->dest_pid = 0;
}
/* Destination address */
/* l = addr_len(fcf.dest_addr_mode); */
@ -329,9 +538,12 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
/* Source address, if any */
if(fcf.src_addr_mode) {
/* Source PAN */
if(!fcf.panid_compression) {
if(has_src_panid) {
pf->src_pid = p[0] + (p[1] << 8);
p += 2;
if(!has_dest_panid) {
pf->dest_pid = pf->src_pid;
}
} else {
pf->src_pid = pf->dest_pid;
}
@ -357,18 +569,25 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null);
pf->src_pid = 0;
}
#if LLSEC802154_SECURITY_LEVEL
if(fcf.security_enabled) {
pf->aux_hdr.security_control.security_level = p[0] & 7;
#if LLSEC802154_USES_EXPLICIT_KEYS
pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
pf->aux_hdr.security_control.frame_counter_suppression = p[0] >> 5;
pf->aux_hdr.security_control.frame_counter_size = p[0] >> 6;
p += 1;
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
p += 4;
if(pf->aux_hdr.security_control.frame_counter_suppression == 0) {
memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
p += 4;
if(pf->aux_hdr.security_control.frame_counter_size == 1) {
p ++;
}
}
#if LLSEC802154_USES_EXPLICIT_KEYS
key_id_mode = pf->aux_hdr.security_control.key_id_mode;
if(key_id_mode) {

View File

@ -41,7 +41,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
/**
* \addtogroup net
@ -59,14 +59,14 @@
* This file converts to and from a structure to a packed 802.15.4
* frame.
*
*/
*/
/* Includes */
#ifndef FRAME_802154_H
#define FRAME_802154_H
#include "contiki-conf.h"
#include "net/linkaddr.h"
#ifdef IEEE802154_CONF_PANID
#define IEEE802154_PANID IEEE802154_CONF_PANID
@ -74,6 +74,18 @@
#define IEEE802154_PANID 0xABCD
#endif /* IEEE802154_CONF_PANID */
#ifdef FRAME802154_CONF_VERSION
#define FRAME802154_VERSION FRAME802154_CONF_VERSION
#else /* FRAME802154_CONF_VERSION */
#define FRAME802154_VERSION FRAME802154_IEEE802154_2006
#endif /* FRAME802154_CONF_VERSION */
#ifdef FRAME802154_CONF_SUPPR_SEQNO
#define FRAME802154_SUPPR_SEQNO FRAME802154_CONF_SUPPR_SEQNO
#else /* FRAME802154_CONF_SUPPR_SEQNO */
#define FRAME802154_SUPPR_SEQNO 0
#endif /* FRAME802154_CONF_SUPPR_SEQNO */
/* Macros & Defines */
/** \brief These are some definitions of values used in the FCF. See the 802.15.4 spec for details.
@ -97,8 +109,9 @@
#define FRAME802154_BROADCASTADDR (0xFFFF)
#define FRAME802154_BROADCASTPANDID (0xFFFF)
#define FRAME802154_IEEE802154_2003 (0x00)
#define FRAME802154_IEEE802154_2006 (0x01)
#define FRAME802154_IEEE802154_2003 (0x00)
#define FRAME802154_IEEE802154_2006 (0x01)
#define FRAME802154_IEEE802154E_2012 (0x02)
#define FRAME802154_SECURITY_LEVEL_NONE (0)
#define FRAME802154_SECURITY_LEVEL_MIC_32 (1)
@ -125,7 +138,7 @@
* 3. Addressing fields - 4 - 20 bytes - Variable
* 4. Aux security header - 0 - 14 bytes - Variable
* 5. CRC - 2 bytes - Fixed
*/
*/
/**
* \brief Defines the bitfields of the frame control field (FCF).
@ -136,7 +149,9 @@ typedef struct {
uint8_t frame_pending; /**< 1 bit. True if sender has more data to send */
uint8_t ack_required; /**< 1 bit. Is an ack frame required? */
uint8_t panid_compression; /**< 1 bit. Is this a compressed header? */
/* uint8_t reserved; */ /**< 3 bit. Unused bits */
/* uint8_t reserved; */ /**< 1 bit. Unused bit */
uint8_t sequence_number_suppression; /**< 1 bit. Does the header omit sequence number?, see 802.15.4e */
uint8_t ie_list_present; /**< 1 bit. Does the header contain Information Elements?, see 802.15.4e */
uint8_t dest_addr_mode; /**< 2 bit. Destination address mode, see 802.15.4 */
uint8_t frame_version; /**< 2 bit. 802.15.4 frame version */
uint8_t src_addr_mode; /**< 2 bit. Source address mode, see 802.15.4 */
@ -146,6 +161,8 @@ typedef struct {
typedef struct {
uint8_t security_level; /**< 3 bit. security level */
uint8_t key_id_mode; /**< 2 bit. Key identifier mode */
uint8_t frame_counter_suppression; /**< 1 bit. Frame counter suppression */
uint8_t frame_counter_size; /**< 1 bit. Frame counter size (0: 4 bytes, 1: 5 bytes) */
uint8_t reserved; /**< 3 bit. Reserved bits */
} frame802154_scf_t;
@ -193,6 +210,20 @@ int frame802154_hdrlen(frame802154_t *p);
int frame802154_create(frame802154_t *p, uint8_t *buf);
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
/* Get current PAN ID */
uint16_t frame802154_get_pan_id(void);
/* Set current PAN ID */
void frame802154_set_pan_id(uint16_t pan_id);
/* Tells whether a given Frame Control Field indicates a frame with
* source PANID and/or destination PANID */
void frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest_pan_id);
/* Check if the destination PAN ID, if any, matches ours */
int frame802154_check_dest_panid(frame802154_t *frame);
/* Check is the address is a broadcast address, whatever its size */
int frame802154_is_broadcast_addr(uint8_t mode, uint8_t *addr);
/* Check and extract source and destination linkaddr from frame */
int frame802154_extract_linkaddr(frame802154_t *frame, linkaddr_t *source_address, linkaddr_t *dest_address);
/** @} */
#endif /* FRAME_802154_H */
/** @} */

View File

@ -0,0 +1,585 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* IEEE 802.15.4e Information Element (IE) creation and parsing.
* \author
* Simon Duquennoy <simonduq@sics.se>
*/
#include <string.h>
#include "net/mac/frame802154e-ie.h"
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
/* c.f. IEEE 802.15.4e Table 4b */
enum ieee802154e_header_ie_id {
HEADER_IE_LE_CSL = 0x1a,
HEADER_IE_LE_RIT,
HEADER_IE_DSME_PAN_DESCRIPTOR,
HEADER_IE_RZ_TIME,
HEADER_IE_ACK_NACK_TIME_CORRECTION,
HEADER_IE_GACK,
HEADER_IE_LOW_LATENCY_NETWORK_INFO,
HEADER_IE_LIST_TERMINATION_1 = 0x7e,
HEADER_IE_LIST_TERMINATION_2 = 0x7f,
};
/* c.f. IEEE 802.15.4e Table 4c */
enum ieee802154e_payload_ie_id {
PAYLOAD_IE_ESDU = 0,
PAYLOAD_IE_MLME,
PAYLOAD_IE_LIST_TERMINATION = 0xf,
};
/* c.f. IEEE 802.15.4e Table 4d */
enum ieee802154e_mlme_short_subie_id {
MLME_SHORT_IE_TSCH_SYNCHRONIZATION = 0x1a,
MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK,
MLME_SHORT_IE_TSCH_TIMESLOT,
MLME_SHORT_IE_TSCH_HOPPING_TIMING,
MLME_SHORT_IE_TSCH_EB_FILTER,
MLME_SHORT_IE_TSCH_MAC_METRICS_1,
MLME_SHORT_IE_TSCH_MAC_METRICS_2,
};
/* c.f. IEEE 802.15.4e Table 4e */
enum ieee802154e_mlme_long_subie_id {
MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE = 0x9,
};
#define WRITE16(buf, val) \
do { ((uint8_t *)(buf))[0] = (val) & 0xff; \
((uint8_t *)(buf))[1] = ((val) >> 8) & 0xff; } while(0);
#define READ16(buf, var) \
(var) = ((uint8_t *)(buf))[0] | ((uint8_t *)(buf))[1] << 8
/* Create a header IE 2-byte descriptor */
static void
create_header_ie_descriptor(uint8_t *buf, uint8_t element_id, int ie_len)
{
uint16_t ie_desc;
/* Header IE descriptor: b0-6: len, b7-14: element id:, b15: type: 0 */
ie_desc = (ie_len & 0x7f) + ((element_id & 0xff) << 7);
WRITE16(buf, ie_desc);
}
/* Create a payload IE 2-byte descriptor */
static void
create_payload_ie_descriptor(uint8_t *buf, uint8_t group_id, int ie_len)
{
uint16_t ie_desc;
/* MLME Long IE descriptor: b0-10: len, b11-14: group id:, b15: type: 1 */
ie_desc = (ie_len & 0x07ff) + ((group_id & 0x0f) << 11) + (1 << 15);
WRITE16(buf, ie_desc);
}
/* Create a MLME short IE 2-byte descriptor */
static void
create_mlme_short_ie_descriptor(uint8_t *buf, uint8_t sub_id, int ie_len)
{
uint16_t ie_desc;
/* MLME Short IE descriptor: b0-7: len, b8-14: sub id:, b15: type: 0 */
ie_desc = (ie_len & 0xff) + ((sub_id & 0x7f) << 8);
WRITE16(buf, ie_desc);
}
/* Create a MLME long IE 2-byte descriptor */
static void
create_mlme_long_ie_descriptor(uint8_t *buf, uint8_t sub_id, int ie_len)
{
uint16_t ie_desc;
/* MLME Long IE descriptor: b0-10: len, b11-14: sub id:, b15: type: 1 */
ie_desc = (ie_len & 0x07ff) + ((sub_id & 0x0f) << 11) + (1 << 15);
WRITE16(buf, ie_desc);
}
/* Header IE. ACK/NACK time correction. Used in enhanced ACKs */
int
frame80215e_create_ie_header_ack_nack_time_correction(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 2;
if(len >= 2 + ie_len && ies != NULL) {
int16_t drift_us;
uint16_t time_sync_field;
drift_us = ies->ie_time_correction;
time_sync_field = drift_us & 0x0fff;
if(ies->ie_is_nack) {
time_sync_field |= 0x8000;
}
WRITE16(buf+2, time_sync_field);
create_header_ie_descriptor(buf, HEADER_IE_ACK_NACK_TIME_CORRECTION, ie_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* Header IE. List termination 1 (Signals the end of the Header IEs when
* followed by payload IEs) */
int
frame80215e_create_ie_header_list_termination_1(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 0;
if(len >= 2 + ie_len && ies != NULL) {
create_header_ie_descriptor(buf, HEADER_IE_LIST_TERMINATION_1, 0);
return 2 + ie_len;
} else {
return -1;
}
}
/* Header IE. List termination 2 (Signals the end of the Header IEs when
* followed by an unformatted payload) */
int
frame80215e_create_ie_header_list_termination_2(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 0;
if(len >= 2 + ie_len && ies != NULL) {
create_header_ie_descriptor(buf, HEADER_IE_LIST_TERMINATION_2, 0);
return 2 + ie_len;
} else {
return -1;
}
}
/* Payload IE. List termination */
int
frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 0;
if(len >= 2 + ie_len && ies != NULL) {
create_payload_ie_descriptor(buf, PAYLOAD_IE_LIST_TERMINATION, 0);
return 2 + ie_len;
} else {
return -1;
}
}
/* Payload IE. MLME. Used to nest sub-IEs */
int
frame80215e_create_ie_mlme(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 0;
if(len >= 2 + ie_len && ies != NULL) {
/* The length of the outer MLME IE is the total length of sub-IEs */
create_payload_ie_descriptor(buf, PAYLOAD_IE_MLME, ies->ie_mlme_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* MLME sub-IE. TSCH synchronization. Used in EBs: ASN and join priority */
int
frame80215e_create_ie_tsch_synchronization(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len = 6;
if(len >= 2 + ie_len && ies != NULL) {
buf[2] = ies->ie_asn.ls4b;
buf[3] = ies->ie_asn.ls4b >> 8;
buf[4] = ies->ie_asn.ls4b >> 16;
buf[5] = ies->ie_asn.ls4b >> 24;
buf[6] = ies->ie_asn.ms1b;
buf[7] = ies->ie_join_priority;
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_SYNCHRONIZATION, ie_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* MLME sub-IE. TSCH slotframe and link. Used in EBs: initial schedule */
int
frame80215e_create_ie_tsch_slotframe_and_link(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
if(ies != NULL) {
int i;
int num_slotframes = ies->ie_tsch_slotframe_and_link.num_slotframes;
int num_links = ies->ie_tsch_slotframe_and_link.num_links;
int ie_len = 1 + num_slotframes * (4 + 5 * num_links);
if(num_slotframes > 1 || num_links > FRAME802154E_IE_MAX_LINKS
|| len < 2 + ie_len) {
/* We support only 0 or 1 slotframe in this IE and a predefined maximum number of links */
return -1;
}
/* Insert IE */
buf[2] = num_slotframes;
/* Insert slotframe */
if(num_slotframes == 1) {
buf[2 + 1] = ies->ie_tsch_slotframe_and_link.slotframe_handle;
WRITE16(buf + 2 + 2, ies->ie_tsch_slotframe_and_link.slotframe_size);
buf[2 + 4] = num_links;
/* Loop over links */
for(i = 0; i < num_links; i++) {
/* Insert links */
WRITE16(buf + 2 + 5 + i * 5, ies->ie_tsch_slotframe_and_link.links[i].timeslot);
WRITE16(buf + 2 + 5 + i * 5 + 2, ies->ie_tsch_slotframe_and_link.links[i].channel_offset);
buf[2 + 5 + i * 5 + 4] = ies->ie_tsch_slotframe_and_link.links[i].link_options;
}
}
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK, ie_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* MLME sub-IE. TSCH timeslot. Used in EBs: timeslot template (timing) */
int
frame80215e_create_ie_tsch_timeslot(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len;
if(ies == NULL) {
return -1;
}
/* Only ID if ID == 0, else full timing description */
ie_len = ies->ie_tsch_timeslot_id == 0 ? 1 : 25;
if(len >= 2 + ie_len) {
buf[2] = ies->ie_tsch_timeslot_id;
if(ies->ie_tsch_timeslot_id != 0) {
int i;
for(i = 0; i < tsch_ts_elements_count; i++) {
WRITE16(buf + 3 + 2 * i, ies->ie_tsch_timeslot[i]);
}
}
create_mlme_short_ie_descriptor(buf, MLME_SHORT_IE_TSCH_TIMESLOT, ie_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* MLME sub-IE. TSCH channel hopping sequence. Used in EBs: hopping sequence */
int
frame80215e_create_ie_tsch_channel_hopping_sequence(uint8_t *buf, int len,
struct ieee802154_ies *ies)
{
int ie_len;
if(ies == NULL || ies->ie_hopping_sequence_len > sizeof(ies->ie_hopping_sequence_list)) {
return -1;
}
ie_len = ies->ie_channel_hopping_sequence_id == 0 ? 1 : 12 + ies->ie_hopping_sequence_len;
if(len >= 2 + ie_len && ies != NULL) {
buf[2] = ies->ie_channel_hopping_sequence_id;
buf[3] = 0; /* channel page */
WRITE16(buf + 4, 0); /* number of channels */
WRITE16(buf + 6, 0); /* phy configuration */
WRITE16(buf + 8, 0);
/* Extended bitmap. Size: 0 */
WRITE16(buf + 10, ies->ie_hopping_sequence_len); /* sequence len */
memcpy(buf + 12, ies->ie_hopping_sequence_list, ies->ie_hopping_sequence_len); /* sequence list */
WRITE16(buf + 12 + ies->ie_hopping_sequence_len, 0); /* current hop */
create_mlme_long_ie_descriptor(buf, MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE, ie_len);
return 2 + ie_len;
} else {
return -1;
}
}
/* Parse a header IE */
static int
frame802154e_parse_header_ie(const uint8_t *buf, int len,
uint8_t element_id, struct ieee802154_ies *ies)
{
switch(element_id) {
case HEADER_IE_ACK_NACK_TIME_CORRECTION:
if(len == 2) {
if(ies != NULL) {
/* If the originator was a time source neighbor, the receiver adjust
* its own clock by incorporating the received drift correction */
uint16_t time_sync_field = 0;
int16_t drift_us = 0;
/* Extract drift correction from Sync-IE, cast from 12 to 16-bit,
* and convert it to RTIMER ticks.
* See page 88 in IEEE Std 802.15.4e-2012. */
READ16(buf, time_sync_field);
/* First extract NACK */
ies->ie_is_nack = (time_sync_field & (uint16_t)0x8000) ? 1 : 0;
/* Then cast from 12 to 16 bit signed */
if(time_sync_field & 0x0800) { /* Negative integer */
drift_us = time_sync_field | 0xf000;
} else { /* Positive integer */
drift_us = time_sync_field & 0x0fff;
}
/* Convert to RTIMER ticks */
ies->ie_time_correction = drift_us;
}
return len;
}
break;
}
return -1;
}
/* Parse a MLME short IE */
static int
frame802154e_parse_mlme_short_ie(const uint8_t *buf, int len,
uint8_t sub_id, struct ieee802154_ies *ies)
{
switch(sub_id) {
case MLME_SHORT_IE_TSCH_SLOFTRAME_AND_LINK:
if(len >= 1) {
int i;
int num_slotframes = buf[0];
int num_links = buf[4];
if(num_slotframes == 0) {
return len;
}
if(num_slotframes <= 1 && num_links <= FRAME802154E_IE_MAX_LINKS
&& len == 1 + num_slotframes * (4 + 5 * num_links)) {
if(ies != NULL) {
/* We support only 0 or 1 slotframe in this IE and a predefined maximum number of links */
ies->ie_tsch_slotframe_and_link.num_slotframes = buf[0];
ies->ie_tsch_slotframe_and_link.slotframe_handle = buf[1];
READ16(buf + 2, ies->ie_tsch_slotframe_and_link.slotframe_size);
ies->ie_tsch_slotframe_and_link.num_links = buf[4];
for(i = 0; i < num_links; i++) {
READ16(buf + 5 + i * 5, ies->ie_tsch_slotframe_and_link.links[i].timeslot);
READ16(buf + 5 + i * 5 + 2, ies->ie_tsch_slotframe_and_link.links[i].channel_offset);
ies->ie_tsch_slotframe_and_link.links[i].link_options = buf[5 + i * 5 + 4];
}
}
return len;
}
}
break;
case MLME_SHORT_IE_TSCH_SYNCHRONIZATION:
if(len == 6) {
if(ies != NULL) {
ies->ie_asn.ls4b = (uint32_t)buf[0];
ies->ie_asn.ls4b |= (uint32_t)buf[1] << 8;
ies->ie_asn.ls4b |= (uint32_t)buf[2] << 16;
ies->ie_asn.ls4b |= (uint32_t)buf[3] << 24;
ies->ie_asn.ms1b = (uint8_t)buf[4];
ies->ie_join_priority = (uint8_t)buf[5];
}
return len;
}
break;
case MLME_SHORT_IE_TSCH_TIMESLOT:
if(len == 1 || len == 25) {
if(ies != NULL) {
ies->ie_tsch_timeslot_id = buf[0];
if(len == 25) {
int i;
for(i = 0; i < tsch_ts_elements_count; i++) {
READ16(buf+1+2*i, ies->ie_tsch_timeslot[i]);
}
}
}
return len;
}
break;
}
return -1;
}
/* Parse a MLME long IE */
static int
frame802154e_parse_mlme_long_ie(const uint8_t *buf, int len,
uint8_t sub_id, struct ieee802154_ies *ies)
{
switch(sub_id) {
case MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE:
if(len > 0) {
if(ies != NULL) {
ies->ie_channel_hopping_sequence_id = buf[0];
if(len > 1) {
READ16(buf+8, ies->ie_hopping_sequence_len); /* sequence len */
if(ies->ie_hopping_sequence_len <= sizeof(ies->ie_hopping_sequence_list)
&& len == 12 + ies->ie_hopping_sequence_len) {
memcpy(ies->ie_hopping_sequence_list, buf+10, ies->ie_hopping_sequence_len); /* sequence list */
}
}
}
return len;
}
break;
}
return -1;
}
/* Parse all IEEE 802.15.4e Information Elements (IE) from a frame */
int
frame802154e_parse_information_elements(const uint8_t *buf, uint8_t buf_size,
struct ieee802154_ies *ies)
{
const uint8_t *start = buf;
uint16_t ie_desc;
uint8_t type;
uint8_t id;
uint16_t len = 0;
int nested_mlme_len = 0;
enum {PARSING_HEADER_IE, PARSING_PAYLOAD_IE, PARSING_MLME_SUBIE} parsing_state;
if(ies == NULL) {
return -1;
}
/* Always look for a header IE first (at least "list termination 1") */
parsing_state = PARSING_HEADER_IE;
ies->ie_payload_ie_offset = 0;
/* Loop over all IEs */
while(buf_size > 0) {
if(buf_size < 2) { /* Not enough space for IE descriptor */
return -1;
}
READ16(buf, ie_desc);
buf_size -= 2;
buf += 2;
type = ie_desc & 0x8000 ? 1 : 0; /* b15 */
PRINTF("frame802154e: ie type %u, current state %u\n", type, parsing_state);
switch(parsing_state) {
case PARSING_HEADER_IE:
if(type != 0) {
PRINTF("frame802154e: wrong type %04x\n", ie_desc);
return -1;
}
/* Header IE: 2 bytes descriptor, c.f. fig 48n in IEEE 802.15.4e */
len = ie_desc & 0x007f; /* b0-b6 */
id = (ie_desc & 0x7f80) >> 7; /* b7-b14 */
PRINTF("frame802154e: header ie len %u id %x\n", len, id);
switch(id) {
case HEADER_IE_LIST_TERMINATION_1:
if(len == 0) {
/* End of payload IE list, now expect payload IEs */
parsing_state = PARSING_PAYLOAD_IE;
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
PRINTF("frame802154e: list termination 1, look for payload IEs\n");
} else {
PRINTF("frame802154e: list termination 1, wrong len %u\n", len);
return -1;
}
break;
case HEADER_IE_LIST_TERMINATION_2:
/* End of IE parsing */
if(len == 0) {
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
PRINTF("frame802154e: list termination 2\n");
return buf + len - start;
} else {
PRINTF("frame802154e: list termination 2, wrong len %u\n", len);
return -1;
}
default:
if(len > buf_size || frame802154e_parse_header_ie(buf, len, id, ies) == -1) {
PRINTF("frame802154e: failed to parse\n");
return -1;
}
break;
}
break;
case PARSING_PAYLOAD_IE:
if(type != 1) {
PRINTF("frame802154e: wrong type %04x\n", ie_desc);
return -1;
}
/* Payload IE: 2 bytes descriptor, c.f. fig 48o in IEEE 802.15.4e */
len = ie_desc & 0x7ff; /* b0-b10 */
id = (ie_desc & 0x7800) >> 11; /* b11-b14 */
PRINTF("frame802154e: payload ie len %u id %x\n", len, id);
switch(id) {
case PAYLOAD_IE_MLME:
/* Now expect 'len' bytes of MLME sub-IEs */
parsing_state = PARSING_MLME_SUBIE;
nested_mlme_len = len;
len = 0; /* Reset len as we want to read subIEs and not jump over them */
PRINTF("frame802154e: entering MLME ie with len %u\n", nested_mlme_len);
break;
case PAYLOAD_IE_LIST_TERMINATION:
PRINTF("frame802154e: payload ie list termination %u\n", len);
return (len == 0) ? buf + len - start : -1;
default:
PRINTF("frame802154e: non-supported payload ie\n");
return -1;
}
break;
case PARSING_MLME_SUBIE:
/* MLME sub-IE: 2 bytes descriptor, c.f. fig 48q in IEEE 802.15.4e */
/* type == 0 means short sub-IE, type == 1 means long sub-IE */
if(type == 0) {
/* Short sub-IE, c.f. fig 48r in IEEE 802.15.4e */
len = ie_desc & 0x00ff; /* b0-b7 */
id = (ie_desc & 0x7f00) >> 8; /* b8-b14 */
PRINTF("frame802154e: short mlme ie len %u id %x\n", len, id);
if(len > buf_size || frame802154e_parse_mlme_short_ie(buf, len, id, ies) == -1) {
PRINTF("frame802154e: failed to parse ie\n");
return -1;
}
} else {
/* Long sub-IE, c.f. fig 48s in IEEE 802.15.4e */
len = ie_desc & 0x7ff; /* b0-b10 */
id = (ie_desc & 0x7800) >> 11; /* b11-b14 */
PRINTF("frame802154e: long mlme ie len %u id %x\n", len, id);
if(len > buf_size || frame802154e_parse_mlme_long_ie(buf, len, id, ies) == -1) {
PRINTF("frame802154e: failed to parse ie\n");
return -1;
}
}
/* Update remaining nested MLME len */
nested_mlme_len -= 2 + len;
if(nested_mlme_len < 0) {
PRINTF("frame802154e: found more sub-IEs than initially advertised\n");
/* We found more sub-IEs than initially advertised */
return -1;
}
if(nested_mlme_len == 0) {
PRINTF("frame802154e: end of MLME IE parsing\n");
/* End of IE parsing, look for another payload IE */
parsing_state = PARSING_PAYLOAD_IE;
}
break;
}
buf += len;
buf_size -= len;
}
if(parsing_state == PARSING_HEADER_IE) {
ies->ie_payload_ie_offset = buf - start; /* Save IE header len */
}
return buf - start;
}

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* IEEE 802.15.4e Information Element (IE) creation and parsing.
* \author
* Simon Duquennoy <simonduq@sics.se>
*/
#ifndef FRAME_802154E_H
#define FRAME_802154E_H
#include "contiki.h"
/* We need definitions from tsch-private.h for TSCH-specific information elements */
#include "net/mac/tsch/tsch-private.h"
#define FRAME802154E_IE_MAX_LINKS 4
/* Structures used for the Slotframe and Links information element */
struct tsch_slotframe_and_links_link {
uint16_t timeslot;
uint16_t channel_offset;
uint8_t link_options;
};
struct tsch_slotframe_and_links {
uint8_t num_slotframes; /* We support only 0 or 1 slotframe in this IE */
uint8_t slotframe_handle;
uint16_t slotframe_size;
uint8_t num_links;
struct tsch_slotframe_and_links_link links[FRAME802154E_IE_MAX_LINKS];
};
/* The information elements that we currently support */
struct ieee802154_ies {
/* Header IEs */
int16_t ie_time_correction;
uint8_t ie_is_nack;
/* Payload MLME */
uint8_t ie_payload_ie_offset;
uint16_t ie_mlme_len;
/* Payload Short MLME IEs */
uint8_t ie_tsch_synchronization_offset;
struct asn_t ie_asn;
uint8_t ie_join_priority;
uint8_t ie_tsch_timeslot_id;
uint16_t ie_tsch_timeslot[tsch_ts_elements_count];
struct tsch_slotframe_and_links ie_tsch_slotframe_and_link;
/* Payload Long MLME IEs */
uint8_t ie_channel_hopping_sequence_id;
/* We include and parse only the sequence len and list and omit unused fields */
uint16_t ie_hopping_sequence_len;
uint8_t ie_hopping_sequence_list[TSCH_HOPPING_SEQUENCE_MAX_LEN];
};
/** Insert various Information Elements **/
/* Header IE. ACK/NACK time correction. Used in enhanced ACKs */
int frame80215e_create_ie_header_ack_nack_time_correction(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* Header IE. List termination 1 (Signals the end of the Header IEs when
* followed by payload IEs) */
int frame80215e_create_ie_header_list_termination_1(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* Header IE. List termination 2 (Signals the end of the Header IEs when
* followed by an unformatted payload) */
int frame80215e_create_ie_header_list_termination_2(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* Payload IE. List termination */
int frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* Payload IE. MLME. Used to nest sub-IEs */
int frame80215e_create_ie_mlme(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* MLME sub-IE. TSCH synchronization. Used in EBs: ASN and join priority */
int frame80215e_create_ie_tsch_synchronization(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* MLME sub-IE. TSCH slotframe and link. Used in EBs: initial schedule */
int frame80215e_create_ie_tsch_slotframe_and_link(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* MLME sub-IE. TSCH timeslot. Used in EBs: timeslot template (timing) */
int frame80215e_create_ie_tsch_timeslot(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* MLME sub-IE. TSCH channel hopping sequence. Used in EBs: hopping sequence */
int frame80215e_create_ie_tsch_channel_hopping_sequence(uint8_t *buf, int len,
struct ieee802154_ies *ies);
/* Parse all Information Elements of a frame */
int frame802154e_parse_information_elements(const uint8_t *buf, uint8_t buf_size,
struct ieee802154_ies *ies);
#endif /* FRAME_802154E_H */

View File

@ -62,30 +62,6 @@ static uint8_t mac_dsn;
static uint8_t initialized = 0;
/** \brief The 16-bit identifier of the PAN on which the device is
* sending to. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_dst_pan_id = IEEE802154_PANID;
/** \brief The 16-bit identifier of the PAN on which the device is
* operating. If this value is 0xffff, the device is not
* associated.
*/
static const uint16_t mac_src_pan_id = IEEE802154_PANID;
/*---------------------------------------------------------------------------*/
static int
is_broadcast_addr(uint8_t mode, uint8_t *addr)
{
int i = mode == FRAME802154_SHORTADDRMODE ? 2 : 8;
while(i-- > 0) {
if(addr[i] != 0xff) {
return 0;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int
create_frame(int type, int do_create)
@ -93,6 +69,10 @@ create_frame(int type, int do_create)
frame802154_t params;
int hdr_len;
if(frame802154_get_pan_id() == 0xffff) {
return -1;
}
/* init to zeros */
memset(&params, 0, sizeof(params));
@ -109,10 +89,14 @@ create_frame(int type, int do_create)
} else {
params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK);
}
/* We do not compress PAN ID in outgoing frames, i.e. include one PAN ID (dest by default)
* There is one exception, seemingly a typo in Table 2a: rows 2 and 3: when there is no
* source nor destination address, we have dest PAN ID iff compression is *set*. */
params.fcf.panid_compression = 0;
params.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
/* Insert IEEE 802.15.4 (2006) version bits. */
params.fcf.frame_version = FRAME802154_IEEE802154_2006;
/* Insert IEEE 802.15.4 version bits. */
params.fcf.frame_version = FRAME802154_VERSION;
#if LLSEC802154_SECURITY_LEVEL
if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) {
@ -120,8 +104,13 @@ create_frame(int type, int do_create)
}
/* Setting security-related attributes */
params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
#if LLSEC802154_USES_FRAME_COUNTER
params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
#else /* LLSEC802154_USES_FRAME_COUNTER */
params.aux_hdr.security_control.frame_counter_suppression = 1;
params.aux_hdr.security_control.frame_counter_size = 1;
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS
params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE);
params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
@ -150,21 +139,20 @@ create_frame(int type, int do_create)
/**
\todo For phase 1 the addresses are all long. We'll need a mechanism
in the rime attributes to tell the mac to use long or short for phase 2.
*/
*/
if(LINKADDR_SIZE == 2) {
/* Use short address mode if linkaddr size is short. */
params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE;
} else {
params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
}
params.dest_pid = mac_dst_pan_id;
params.dest_pid = frame802154_get_pan_id();
if(packetbuf_holds_broadcast()) {
/* Broadcast requires short address mode. */
params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE;
params.dest_addr[0] = 0xFF;
params.dest_addr[1] = 0xFF;
} else {
linkaddr_copy((linkaddr_t *)&params.dest_addr,
packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
@ -177,7 +165,7 @@ create_frame(int type, int do_create)
}
/* Set the source PAN ID to the global variable. */
params.src_pid = mac_src_pan_id;
params.src_pid = frame802154_get_pan_id();
/*
* Set up the source address using only the long address mode for
@ -191,7 +179,6 @@ create_frame(int type, int do_create)
if(!do_create) {
/* Only calculate header length */
return hdr_len;
} else if(packetbuf_hdralloc(hdr_len)) {
frame802154_create(&params, packetbuf_hdrptr());
@ -223,35 +210,41 @@ parse(void)
{
frame802154_t frame;
int hdr_len;
hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame);
if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
if(frame.fcf.dest_addr_mode) {
if(frame.dest_pid != mac_src_pan_id &&
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
if(frame.dest_pid != frame802154_get_pan_id() &&
frame.dest_pid != FRAME802154_BROADCASTPANDID) {
/* Packet to another PAN */
PRINTF("15.4: for another pan %u\n", frame.dest_pid);
return FRAMER_FAILED;
}
if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
if(!frame802154_is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, (linkaddr_t *)&frame.dest_addr);
}
}
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending);
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
if(frame.fcf.sequence_number_suppression == 0) {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
} else {
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, 0xffff);
}
#if NETSTACK_CONF_WITH_RIME
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq);
#endif
#if LLSEC802154_SECURITY_LEVEL
if(frame.fcf.security_enabled) {
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level);
#if LLSEC802154_USES_FRAME_COUNTER
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]);
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]);
#endif /* LLSEC802154_USES_FRAME_COUNTER */
#if LLSEC802154_USES_EXPLICIT_KEYS
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode);
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index);
@ -264,7 +257,7 @@ parse(void)
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen());
return hdr_len;
}
return FRAMER_FAILED;
@ -273,7 +266,6 @@ parse(void)
const struct framer framer_802154 = {
hdr_length,
create,
framer_canonical_create_and_secure,
parse
};
/*---------------------------------------------------------------------------*/

View File

@ -99,6 +99,5 @@ parse(void)
const struct framer framer_nullmac = {
hdr_length,
create,
framer_canonical_create_and_secure,
parse
};

View File

@ -47,13 +47,8 @@ struct framer {
int (* length)(void);
int (* create)(void);
/** Creates the frame and calls LLSEC.on_frame_created() */
int (* create_and_secure)(void);
int (* parse)(void);
};
int framer_canonical_create_and_secure(void);
#endif /* FRAMER_H_ */

94
core/net/mac/nordc.c Normal file
View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2014, SICS Swedish ICT.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* This RDC layer does nothing. It is meant for use with MAC
* layers that do not use a RDC at all, such as TSCH.
* \author
* Simon Duquennoy <simonduq@sics.se>
*
*/
#include "net/mac/rdc.h"
#include "net/netstack.h"
/*---------------------------------------------------------------------------*/
static void
send_packet(mac_callback_t sent, void *ptr)
{
}
/*---------------------------------------------------------------------------*/
static void
send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
{
}
/*---------------------------------------------------------------------------*/
static void
packet_input(void)
{
}
/*---------------------------------------------------------------------------*/
static int
on(void)
{
return 0;
}
/*---------------------------------------------------------------------------*/
static int
off(int keep_radio_on)
{
return 0;
}
/*---------------------------------------------------------------------------*/
static unsigned short
channel_check_interval(void)
{
return 0;
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
}
/*---------------------------------------------------------------------------*/
const struct rdc_driver nordc_driver = {
"nordc",
init,
send_packet,
send_list,
packet_input,
on,
off,
channel_check_interval,
};
/*---------------------------------------------------------------------------*/

View File

@ -48,6 +48,7 @@
#if CONTIKI_TARGET_COOJA
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */
#define DEBUG 0
@ -120,7 +121,7 @@ send_one_packet(mac_callback_t sent, void *ptr)
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */
if(NETSTACK_FRAMER.create_and_secure() < 0) {
if(NETSTACK_FRAMER.create() < 0) {
/* Failed to allocate space for headers */
PRINTF("nullrdc: send failed, too large header\n");
ret = MAC_TX_ERR_FATAL;
@ -302,8 +303,7 @@ packet_input(void)
}
#endif /* RDC_WITH_DUPLICATE_DETECTION */
#endif /* NULLRDC_802154_AUTOACK */
/* TODO We may want to acknowledge only authentic frames */
#if NULLRDC_SEND_802154_ACK
{
frame802154_t info154;

View File

@ -219,6 +219,11 @@ phase_wait(const linkaddr_t *neighbor, rtimer_clock_t cycle_time,
if(buf_list == NULL) {
packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
p->q = queuebuf_new_from_packetbuf();
if(p->q == NULL) {
/* memory allocation failed */
memb_free(&queued_packets_memb, p);
return PHASE_UNKNOWN;
}
}
p->mac_callback = mac_callback;
p->mac_callback_ptr = mac_callback_ptr;

View File

@ -0,0 +1 @@
CONTIKI_SOURCEFILES += tsch.c tsch-slot-operation.c tsch-queue.c tsch-packet.c tsch-schedule.c tsch-log.c tsch-rpl.c tsch-adaptive-timesync.c

Some files were not shown because too many files have changed in this diff Show More