diff --git a/Makefile.dep b/Makefile.dep index b72827857066..1fdbe4752db2 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -47,6 +47,10 @@ ifneq (,$(filter sixlowpan_legacy,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter sixlowpan_iphc_cbuf,$(USEMODULE))) + USEMODULE += vtimer +endif + ifneq (,$(filter sixlowpan,$(USEMODULE))) USEMODULE += netapi USEMODULE += netdev_base diff --git a/sys/Makefile b/sys/Makefile index 54f00bbce893..8e2be8df0222 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -44,6 +44,9 @@ endif ifneq (,$(filter sixlowpan,$(USEMODULE))) DIRS += net/link_layer/sixlowpan endif +ifneq (,$(filter sixlowpan_iphc_cbuf,$(USEMODULE))) + DIRS += net/link_layer/sixlowpan/iphc_cbuf +endif ifneq (,$(filter ipv6,$(USEMODULE))) # TODO endif diff --git a/sys/Makefile.include b/sys/Makefile.include index 830f1f569b10..05f77e8116a7 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -34,6 +34,9 @@ endif ifneq (,$(filter sixlowpan_legacy,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif +ifneq (,$(filter sixlowpan_iphc_cbuf,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif ifneq (,$(filter rpl,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/routing/rpl diff --git a/sys/net/include/sixlowpan/iphc_cbuf.h b/sys/net/include/sixlowpan/iphc_cbuf.h new file mode 100644 index 000000000000..7d1a0b534f3b --- /dev/null +++ b/sys/net/include/sixlowpan/iphc_cbuf.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for + * more details. + */ + +/** + * @defgroup net_sixlowpan_iphc_cbuf Context buffer for 6LoWPAN IP header compression + * @addtogroup net_sixlowpan + * @{ + * + * @file iphc_cbuf.h + * @brief Context buffer for 6LoWPAN IP header compression + * + * @see + * RFC 6282, section 3.1.2 + * + * @see + * RFC 6775, section 4.2 + * + * + * @author Martine Lenders + */ + + +#ifndef __SIXLOWPAN_IPHC_CBUF_H_ +#define __SIXLOWPAN_IPHC_CBUF_H_ + +#include "ipv6.h" + +#define SIXLOWPAN_IPHC_CBUF_SIZE (16) + +/** + * @brief Data type to configure 6LoWPAN contexts + * @see + * RFC 6282, section 3.1 + * + */ +typedef struct { + uint8_t cid; /**< Context ID */ + uint8_t prefix_len; /**< Length of the prefix in bits, if 0 on + NETAPI_CMD_SET the context will be removed. */ + ipv6_addr_t prefix; /**< The prefix associated to this context */ + + /** + * @brief Lifetime in minutes this context is valid. + * + * @see + * 6LoWPAN Context Option + * + */ + uint32_t lifetime; +} sixlowpan_iphc_cbuf_t; + +/** + * @brief Lookup best context for an IPv6 address. + * + * @param[in] addr An IPv6 address. + * + * @return best fitting context for given IPv6 address. + * @return NULL, if no fitting context can be found. + */ +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_addr(const ipv6_addr_t *addr); + +/** + * @brief Lookup best context for a context ID. + * + * @param[in] cid A context ID, must be < 16. + * + * @return best fitting context for given context ID. + * @return NULL, if no fitting context can be found. + */ +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_cid(uint8_t cid); + +/** + * @brief Returns number of currently saved contexts. + * + * @return Number of currently saved contexts. + */ +uint8_t sixlowpan_iphc_cbuf_num(void); + +/** + * @brief Remove context by context ID. + + * @param[in] cid A context ID, must be < 16. + */ +void sixlowpan_iphc_cbuf_remove_by_cid(uint8_t cid); + +/** + * @brief Remove context by best address match. + * + * @param[in] addr An IPv6 address. + */ +static inline void sixlowpan_iphc_cbuf_remove_by_addr(const ipv6_addr_t *addr) +{ + sixlowpan_iphc_cbuf_t *context = sixlowpan_iphc_cbuf_lookup_addr(addr); + + if (context) { + sixlowpan_iphc_cbuf_remove_by_cid(context->cid); + } +} + +/** + * @brief Removes all context with expired lifetime + */ +void sixlowpan_iphc_cbuf_remove_invalid(void); + +/** + * @brief Update a context + * + * @param[in] cid A context ID, must be < 16. + * @param[in] prefix An IPv6 prefix to associate with *cid*. + * @param[in] prefix_len Length of prefix in bits. If *prefix_len* is longer + * then 128, it will be set to 128. Must be > 0. + * @param[in] lifetime Lifetime the context is valid in minutes. Must be > 0. + * + * @return The updated context on success. + * @return NULL, if cid is >= 16, prefix_len is 0, or lifetime is 0. + */ +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_update(uint8_t cid, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint16_t lifetime); + +#endif /* __SIXLOWPAN_IPHC_CBUF_H_ */ +/** + * @} + */ diff --git a/sys/net/link_layer/sixlowpan/iphc_cbuf/Makefile b/sys/net/link_layer/sixlowpan/iphc_cbuf/Makefile new file mode 100644 index 000000000000..4979f7af4f53 --- /dev/null +++ b/sys/net/link_layer/sixlowpan/iphc_cbuf/Makefile @@ -0,0 +1,3 @@ +MODULE = sixlowpan_iphc_cbuf + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/sixlowpan/iphc_cbuf/iphc_cbuf.c b/sys/net/link_layer/sixlowpan/iphc_cbuf/iphc_cbuf.c new file mode 100644 index 000000000000..7d8dd2bc022d --- /dev/null +++ b/sys/net/link_layer/sixlowpan/iphc_cbuf/iphc_cbuf.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for + * more details. + */ + +/** + * @addtogroup net_sixlowpan_iphc_cbuf + * @{ + * + * @file iphc_cbuf.c + * + * @author Martine Lenders + */ + +#include + +#include "mutex.h" +#include "vtimer.h" + +#include "ipv6.h" +#include "sixlowpan/iphc_cbuf.h" + +static sixlowpan_iphc_cbuf_t _cbuf[SIXLOWPAN_IPHC_CBUF_SIZE]; +static uint32_t _cbuf_invalid_time[SIXLOWPAN_IPHC_CBUF_SIZE]; +static mutex_t _cbuf_mutex = MUTEX_INIT; + +#ifndef MODULE_IPV6 +void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, + uint8_t bits) +{ + if (bits > 128) { + bits = 128; + } + + uint8_t bytes = bits / 8, mask; + + if (bits % 8) { + mask = 0xff << (8 - (bits - (bytes * 8))); + } + else { + mask = 0x00; + } + + memcpy(out, prefix, bytes); + out->u8[bytes] = prefix->u8[bytes] & mask; + memset(&(out[bytes + 1]), 0, 15 - bytes); +} +#endif /* MODULE_IPV6 */ + +static uint32_t _now_in_minutes(void) +{ + timex_t now; + + vtimer_now(&now); + + return now.seconds / 60; +} + +static void _cid_update_lifetime(uint8_t cid) +{ + uint32_t now = _now_in_minutes(); +#ifdef DEVELHELP + + if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { + return; + } + +#endif + + if (now >= _cbuf_invalid_time[cid]) { + _cbuf[cid].lifetime = 0; + } + else { + _cbuf[cid].lifetime = _cbuf_invalid_time[cid] - now; + } +} + +static int _cid_still_valid(uint8_t cid) +{ +#ifdef DEVELHELP + + if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { + return 0; + } + +#endif + _cid_update_lifetime(cid); + + return (_cbuf[cid].lifetime > 0); +} + +void _iphc_cbuf_internal_remove(uint8_t cid) +{ + if (cid < SIXLOWPAN_IPHC_CBUF_SIZE) { + _cbuf[cid].cid = 0; + _cbuf[cid].prefix_len = 0; + memset(&(_cbuf[cid].prefix), 0, sizeof(ipv6_addr_t)); + _cbuf[cid].lifetime = 0; + _cbuf_invalid_time[cid] = 0; + } +} + +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_addr(const ipv6_addr_t *addr) +{ + sixlowpan_iphc_cbuf_t *c = NULL; + uint8_t bytes; + + mutex_lock(&_cbuf_mutex); + + for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { + bytes = _cbuf[i].prefix_len / 8; + + if (_cbuf[i].prefix_len > 0 && memcmp(addr, &(_cbuf[i].prefix), bytes) == 0) { + if (_cbuf[i].prefix_len % 8) { + uint8_t mask = 0xff << (8 - (_cbuf[i].prefix_len - (bytes * 8))); + + if ((addr->u8[bytes] & mask) != (_cbuf[i].prefix.u8[bytes] & mask)) { + continue; + } + } + + if (_cid_still_valid(i)) { + if (c == NULL || c->prefix_len < _cbuf[i].prefix_len) { + c = &_cbuf[i]; + } + } + else { + _iphc_cbuf_internal_remove(i); + } + } + } + + mutex_unlock(&_cbuf_mutex); + + return c; +} + +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_cid(uint8_t cid) +{ + sixlowpan_iphc_cbuf_t *c = NULL; + + if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { + return NULL; + } + + mutex_lock(&_cbuf_mutex); + + if (_cid_still_valid(cid)) { + c = &(_cbuf[cid]); + } + else { + _iphc_cbuf_internal_remove(cid); + } + + mutex_unlock(&_cbuf_mutex); + + return c; +} + +uint8_t sixlowpan_iphc_cbuf_num(void) +{ + uint8_t num = 0; + + mutex_lock(&_cbuf_mutex); + + for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { + if (_cid_still_valid(i) && _cbuf[i].prefix_len > 0) { + num++; + } + else { + _iphc_cbuf_internal_remove(i); + } + } + + mutex_unlock(&_cbuf_mutex); + + return num; +} + +void sixlowpan_iphc_cbuf_remove_by_cid(uint8_t cid) +{ + mutex_lock(&_cbuf_mutex); + _iphc_cbuf_internal_remove(cid); + mutex_unlock(&_cbuf_mutex); +} + +void sixlowpan_iphc_cbuf_remove_invalid(void) +{ + mutex_lock(&_cbuf_mutex); + + for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { + if (!_cid_still_valid(i)) { + _iphc_cbuf_internal_remove(i); + } + } + + mutex_unlock(&_cbuf_mutex); +} + +sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_update(uint8_t cid, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint16_t lifetime) +{ + sixlowpan_iphc_cbuf_t *c = NULL; + + mutex_lock(&_cbuf_mutex); + + if (cid < SIXLOWPAN_IPHC_CBUF_SIZE && prefix_len > 0 && lifetime > 0) { + _cbuf[cid].cid = cid; + _cbuf[cid].prefix_len = (prefix_len < IPV6_ADDR_BIT_LEN) ? prefix_len : IPV6_ADDR_BIT_LEN; + _cbuf[cid].lifetime = lifetime; + ipv6_addr_init_prefix(&(_cbuf[cid].prefix), prefix, prefix_len); + _cbuf_invalid_time[cid] = _now_in_minutes() + lifetime; + + c = &(_cbuf[cid]); + } + + mutex_unlock(&_cbuf_mutex); + + return c; +} + +/** + * @} + */ diff --git a/tests/sixlowpan/framework.c b/tests/sixlowpan/framework.c index f67952635455..677aa5f07a61 100644 --- a/tests/sixlowpan/framework.c +++ b/tests/sixlowpan/framework.c @@ -25,6 +25,9 @@ #include "netapi.h" #include "pktbuf.h" #include "sixlowpan.h" +#ifdef MODULE_SIXLOWPAN_IPHC_CBUF +#include "sixlowpan/iphc_cbuf.h" +#endif #include "thread.h" #include "framework.h" @@ -417,6 +420,14 @@ int sixlowpan_test_run(uint32_t exp, sixlowpan_test_t test, char *name) pktbuf_reset(); sixlowpan_reset(); +#ifdef MODULE_SIXLOWPAN_IPHC_CBUF + + for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { + sixlowpan_iphc_cbuf_remove_by_cid(i); + } + +#endif + res = test(); if (res != exp) { diff --git a/tests/sixlowpan_iphc_cbuf_timeout/Makefile b/tests/sixlowpan_iphc_cbuf_timeout/Makefile new file mode 100644 index 000000000000..efce72535a2b --- /dev/null +++ b/tests/sixlowpan_iphc_cbuf_timeout/Makefile @@ -0,0 +1,17 @@ +export APPLICATION = sixlowpan_iphc_cbuf_timeout + +include ../Makefile.tests_common + +USEMODULE += sixlowpan_iphc_cbuf + +DISABLE_MODULE += auto_init + +RANDOM_STRING = "$(shell head -c "$(1)" /dev/urandom | base64 | head -c "$(1)")" +RANDOM_U8BIT = $(shell od -vAn -N1 -tu1 < /dev/urandom | xargs echo) +RANDOM_U16BIT = $(shell od -vAn -N2 -tu2 < /dev/urandom | xargs echo) + +CFLAGS += -DRAND_CID=$(shell echo "$(RANDOM_U8BIT) % 16" | bc)U +CFLAGS += -DRAND_IP="((ipv6_addr_t *)\"$(call RANDOM_STRING,16)\")" +CFLAGS += -DRAND_IP_LEN=$(shell echo "($(RANDOM_U8BIT) % 128) + 1" | bc)U + +include $(RIOTBASE)/Makefile.include diff --git a/tests/sixlowpan_iphc_cbuf_timeout/main.c b/tests/sixlowpan_iphc_cbuf_timeout/main.c new file mode 100644 index 000000000000..cf432190991c --- /dev/null +++ b/tests/sixlowpan_iphc_cbuf_timeout/main.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Tests for sixlowpan_iphc_cbuf module + * + * + * @author Martine Lenders + * + * @} + */ +#include + +#include "vtimer.h" + +#include "sixlowpan/iphc_cbuf.h" + +int main(void) +{ + sixlowpan_iphc_cbuf_t *c; + + vtimer_init(); + puts("Add context with 1 minute lifetime"); + c = sixlowpan_iphc_cbuf_update(RAND_CID, RAND_IP, RAND_IP_LEN, 1); + + if (c == NULL) { + puts("Adding the context failed"); + return 1; + } + + c = sixlowpan_iphc_cbuf_lookup_cid(RAND_CID); + + if (c == NULL) { + puts("Checking the context failed"); + return 1; + } + + puts("Now wait 1.5 minutes"); + vtimer_usleep(1500000 * 60); + c = sixlowpan_iphc_cbuf_lookup_cid(RAND_CID); + + puts("Context should not be available anymore"); + + if (c == NULL) { + puts("SUCCESS"); + } + else { + puts("Context did not time out"); + return 1; + } + + return 0; +} diff --git a/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile b/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile new file mode 100644 index 000000000000..3f3bde3a39cb --- /dev/null +++ b/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile @@ -0,0 +1,12 @@ +MODULE = tests-sixlowpan_iphc_cbuf + +CFLAGS += -DTEST_CID1=6U +CFLAGS += -DTEST_CID2=3U +CFLAGS += -DTEST_IP1="((ipv6_addr_t *)\"/bq%m6A4Go(B~0)E\")" +CFLAGS += -DTEST_IP2="((ipv6_addr_t *)\"3:{xb$$FaF;/2GgBI}\")" +CFLAGS += -DTEST_IP1_LEN=26U +CFLAGS += -DTEST_IP2_LEN=17U +CFLAGS += -DTEST_LIFETIME1=60927U +CFLAGS += -DTEST_LIFETIME2=40207U + +include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile.include b/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile.include new file mode 100644 index 000000000000..30e7fcb0f41d --- /dev/null +++ b/tests/unittests/tests-sixlowpan_iphc_cbuf/Makefile.include @@ -0,0 +1 @@ +USEMODULE += sixlowpan_iphc_cbuf diff --git a/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.c b/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.c new file mode 100644 index 000000000000..37e278939b59 --- /dev/null +++ b/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2014 Martine Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file tests-sixlowpan_iphc_cbuf.c + */ +#include +#include +#include + +#include "embUnit/embUnit.h" + +#include "ipv6.h" +#include "sixlowpan/iphc_cbuf.h" + +#include "tests-sixlowpan_iphc_cbuf.h" + +static void set_up(void) +{ + for (int cid = 0; cid < SIXLOWPAN_IPHC_CBUF_SIZE; cid++) { + sixlowpan_iphc_cbuf_remove_by_cid(cid); + } +} + +static void test_sixlowpan_iphc_cbuf_lookup_addr_empty(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_lookup_addr(TEST_IP1)); +} + +static void test_sixlowpan_iphc_cbuf_lookup_addr_no_fitting_addr(void) +{ + if (memcmp(TEST_IP1, TEST_IP2, sizeof(ipv6_addr_t)) == 0) { + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_lookup_addr(TEST_IP2)); + } +} + +static void test_sixlowpan_iphc_cbuf_lookup_addr_success(void) +{ + sixlowpan_iphc_cbuf_t *c1, *c2; + uint8_t mask = (uint8_t)(0xff << (8 - (TEST_IP1_LEN - ((TEST_IP1_LEN / 8) * 8)))); + ipv6_addr_t *prefix = TEST_IP1; + + c1 = sixlowpan_iphc_cbuf_update(TEST_CID1, prefix, TEST_IP1_LEN, + TEST_LIFETIME1); + TEST_ASSERT_NOT_NULL(c1); + c2 = sixlowpan_iphc_cbuf_lookup_addr(prefix); + TEST_ASSERT(c1 == c2); + TEST_ASSERT_EQUAL_INT(TEST_CID1, c1->cid); + TEST_ASSERT_EQUAL_INT(TEST_IP1_LEN, c1->prefix_len); + TEST_ASSERT_EQUAL_INT(TEST_LIFETIME1, c1->lifetime); + TEST_ASSERT_EQUAL_INT(0, memcmp(prefix, &(c1->prefix), TEST_IP1_LEN / 8)); + TEST_ASSERT_EQUAL_INT((prefix->u8[TEST_IP1_LEN / 8] & mask), + (c1->prefix.u8[TEST_IP1_LEN / 8] & mask)); +} + +static void test_sixlowpan_iphc_cbuf_lookup_cid_empty(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_lookup_cid(TEST_CID1)); +} + +static void test_sixlowpan_iphc_cbuf_lookup_cid_no_fitting_context(void) +{ + if (TEST_CID1 != TEST_CID2) { + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_lookup_cid(TEST_CID2)); + } +} + +static void test_sixlowpan_iphc_cbuf_lookup_cid_success(void) +{ + sixlowpan_iphc_cbuf_t *c1, *c2; + uint8_t mask = (uint8_t)(0xff << (8 - (TEST_IP1_LEN - ((TEST_IP1_LEN / 8) * 8)))); + ipv6_addr_t *prefix = TEST_IP1; + + c1 = sixlowpan_iphc_cbuf_update(TEST_CID1, prefix, TEST_IP1_LEN, + TEST_LIFETIME1); + TEST_ASSERT_NOT_NULL(c1); + c2 = sixlowpan_iphc_cbuf_lookup_cid(TEST_CID1); + TEST_ASSERT(c1 == c2); + TEST_ASSERT_EQUAL_INT(TEST_CID1, c1->cid); + TEST_ASSERT_EQUAL_INT(TEST_IP1_LEN, c1->prefix_len); + TEST_ASSERT_EQUAL_INT(TEST_LIFETIME1, c1->lifetime); + TEST_ASSERT_EQUAL_INT(0, memcmp(prefix, &(c1->prefix), TEST_IP1_LEN / 8)); + TEST_ASSERT_EQUAL_INT((prefix->u8[TEST_IP1_LEN / 8] & mask), + (c1->prefix.u8[TEST_IP1_LEN / 8] & mask)); +} + +static void test_sixlowpan_iphc_cbuf_num_empty(void) +{ + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_num_one_item(void) +{ + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_num_two_items(void) +{ + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID2, TEST_IP2, + TEST_IP2_LEN, TEST_LIFETIME2)); + + if (TEST_CID1 == TEST_CID2) { + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + } + else { + TEST_ASSERT_EQUAL_INT(2, sixlowpan_iphc_cbuf_num()); + } +} + +static void test_sixlowpan_iphc_cbuf_remove_by_cid_empty(void) +{ + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_cid(TEST_CID2); + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_remove_by_cid_no_fitting_context(void) +{ + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID2, TEST_IP2, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_cid(TEST_CID1); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_remove_by_cid_success(void) +{ + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID2, TEST_IP2, + TEST_IP2_LEN, TEST_LIFETIME2)); + TEST_ASSERT_EQUAL_INT(2, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_cid(TEST_CID1); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_cid(TEST_CID2); + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_remove_by_addr_empty(void) +{ + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_addr(TEST_IP1); + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_remove_by_addr_no_fitting_addr(void) +{ + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID2, TEST_IP2, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_addr(TEST_IP1); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_remove_by_addr_success(void) +{ + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); + TEST_ASSERT_NOT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID2, TEST_IP2, + TEST_IP2_LEN, TEST_LIFETIME2)); + TEST_ASSERT_EQUAL_INT(2, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_addr(TEST_IP2); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + sixlowpan_iphc_cbuf_remove_by_addr(TEST_IP1); + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); +} + +static void test_sixlowpan_iphc_cbuf_update_illegal_cid(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1 + 16, TEST_IP1, + TEST_IP1_LEN, TEST_LIFETIME1)); +} + +static void test_sixlowpan_iphc_cbuf_update_illegal_prefix_len(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + 0, TEST_LIFETIME1)); +} + +static void test_sixlowpan_iphc_cbuf_update_illegal_lifetime(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1, TEST_IP1, + TEST_IP1_LEN, 0)); +} + +static void test_sixlowpan_iphc_cbuf_update_just_wrong(void) +{ + TEST_ASSERT_NULL(sixlowpan_iphc_cbuf_update(TEST_CID1 + 16, TEST_IP1, 0, 0)); +} + +static void test_sixlowpan_iphc_cbuf_update_success(void) +{ + sixlowpan_iphc_cbuf_t *c1, *c2; + uint8_t mask1 = (uint8_t)(0xff << (8 - (TEST_IP1_LEN - ((TEST_IP1_LEN / 8) * 8)))); + uint8_t mask2 = (uint8_t)(0xff << (8 - (TEST_IP2_LEN - ((TEST_IP2_LEN / 8) * 8)))); + ipv6_addr_t *prefix1 = TEST_IP1, *prefix2 = TEST_IP2; + + TEST_ASSERT_EQUAL_INT(0, sixlowpan_iphc_cbuf_num()); + c1 = sixlowpan_iphc_cbuf_update(TEST_CID1, prefix1, TEST_IP1_LEN, + TEST_LIFETIME1); + TEST_ASSERT_NOT_NULL(c1); + TEST_ASSERT_EQUAL_INT(1, sixlowpan_iphc_cbuf_num()); + TEST_ASSERT_EQUAL_INT(TEST_CID1, c1->cid); + TEST_ASSERT_EQUAL_INT(TEST_IP1_LEN, c1->prefix_len); + TEST_ASSERT_EQUAL_INT(TEST_LIFETIME1, c1->lifetime); + TEST_ASSERT_EQUAL_INT(0, memcmp(prefix1, &(c1->prefix), TEST_IP1_LEN / 8)); + TEST_ASSERT_EQUAL_INT((prefix1->u8[TEST_IP1_LEN / 8] & mask1), + (c1->prefix.u8[TEST_IP1_LEN / 8] & mask1)); + + c2 = sixlowpan_iphc_cbuf_update(TEST_CID2, prefix2, TEST_IP2_LEN, + TEST_LIFETIME2); + TEST_ASSERT_NOT_NULL(c2); + TEST_ASSERT_EQUAL_INT(2, sixlowpan_iphc_cbuf_num()); + + if (TEST_CID1 == TEST_CID2) { + TEST_ASSERT(c1 == c2); + } + else { + TEST_ASSERT(c1 != c2); + } + + if (TEST_CID1 != TEST_CID2) { + TEST_ASSERT_EQUAL_INT(TEST_CID1, c1->cid); + TEST_ASSERT_EQUAL_INT(TEST_IP1_LEN, c1->prefix_len); + TEST_ASSERT_EQUAL_INT(TEST_LIFETIME1, c1->lifetime); + TEST_ASSERT_EQUAL_INT(0, memcmp(prefix1, &(c1->prefix), TEST_IP1_LEN / 8)); + TEST_ASSERT_EQUAL_INT((prefix1->u8[TEST_IP1_LEN / 8] & mask1), + (c1->prefix.u8[TEST_IP1_LEN / 8] & mask1)); + } + + TEST_ASSERT_EQUAL_INT(TEST_CID2, c2->cid); + TEST_ASSERT_EQUAL_INT(TEST_IP2_LEN, c2->prefix_len); + TEST_ASSERT_EQUAL_INT(TEST_LIFETIME2, c2->lifetime); + TEST_ASSERT_EQUAL_INT(0, memcmp(prefix2, &(c2->prefix), TEST_IP2_LEN / 8)); + TEST_ASSERT_EQUAL_INT((prefix2->u8[TEST_IP2_LEN / 8] & mask2), + (c2->prefix.u8[TEST_IP2_LEN / 8] & mask2)); +} + +Test *tests_sixlowpan_iphc_cbuf_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_addr_empty), + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_addr_no_fitting_addr), + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_addr_success), + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_cid_empty), + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_cid_no_fitting_context), + new_TestFixture(test_sixlowpan_iphc_cbuf_lookup_cid_success), + new_TestFixture(test_sixlowpan_iphc_cbuf_num_empty), + new_TestFixture(test_sixlowpan_iphc_cbuf_num_one_item), + new_TestFixture(test_sixlowpan_iphc_cbuf_num_two_items), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_cid_empty), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_cid_no_fitting_context), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_cid_success), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_addr_empty), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_addr_no_fitting_addr), + new_TestFixture(test_sixlowpan_iphc_cbuf_remove_by_addr_success), + new_TestFixture(test_sixlowpan_iphc_cbuf_update_illegal_cid), + new_TestFixture(test_sixlowpan_iphc_cbuf_update_illegal_prefix_len), + new_TestFixture(test_sixlowpan_iphc_cbuf_update_illegal_lifetime), + new_TestFixture(test_sixlowpan_iphc_cbuf_update_just_wrong), + new_TestFixture(test_sixlowpan_iphc_cbuf_update_success), + }; + + EMB_UNIT_TESTCALLER(sixlowpan_iphc_cbuf_tests, set_up, NULL, fixtures); + + return (Test *)&sixlowpan_iphc_cbuf_tests; +} + +void tests_sixlowpan_iphc_cbuf(void) +{ + TESTS_RUN(tests_sixlowpan_iphc_cbuf_tests()); +} +/** @} */ diff --git a/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.h b/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.h new file mode 100644 index 000000000000..3be12e4e23e0 --- /dev/null +++ b/tests/unittests/tests-sixlowpan_iphc_cbuf/tests-sixlowpan_iphc_cbuf.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file tests-sixlowpan_iphc_cbuf.h + * @brief Unittests for the ``sixlowpan_iphc_cbuf`` module + * + * @author Martine Lenders + */ +#ifndef __TESTS_PKTBUF_H_ +#define __TESTS_PKTBUF_H_ + +#include "../unittests.h" + +/** + * @brief The entry point of this test suite. + */ +void tests_sixlowpan_iphc_cbuf(void); + +#endif /* __TESTS_PKTBUF_H_ */ +/** @} */