-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: provide test application for IPHC+VRB behavior
- Loading branch information
Showing
4 changed files
with
454 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
include ../Makefile.tests_common | ||
|
||
USEMODULE += embunit | ||
USEMODULE += gnrc_ipv6_nib_6ln | ||
USEMODULE += gnrc_sixlowpan_iphc | ||
USEMODULE += gnrc_sixlowpan_frag | ||
USEMODULE += gnrc_sixlowpan_frag_vrb | ||
USEMODULE += netdev_ieee802154 | ||
USEMODULE += netdev_test | ||
USEMODULE += od | ||
|
||
# we don't need all this packet buffer space so reduce it a little | ||
CFLAGS += -DTEST_SUITES -DGNRC_PKTBUF_SIZE=2048 | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
arduino-duemilanove \ | ||
arduino-leonardo \ | ||
arduino-mega2560 \ | ||
arduino-nano \ | ||
arduino-uno \ | ||
atmega328p \ | ||
chronos \ | ||
i-nucleo-lrwan1 \ | ||
msb-430 \ | ||
msb-430h \ | ||
nucleo-f030r8 \ | ||
nucleo-f031k6 \ | ||
nucleo-f042k6 \ | ||
nucleo-l031k6 \ | ||
nucleo-l053r8 \ | ||
stm32f030f4-demo \ | ||
stm32f0discovery \ | ||
stm32l0538-disco \ | ||
telosb \ | ||
waspmote-pro \ | ||
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
/* | ||
* Copyright (C) 2019 Freie Universität Berlin | ||
* | ||
* 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 6LoWPAN fragmentation handling of gnrc stack. | ||
* | ||
* @author Martine S. Lenders <m.lenders@fu-berlin.de> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include "embUnit.h" | ||
#include "net/gnrc.h" | ||
#include "net/gnrc/netif/ieee802154.h" | ||
#include "net/gnrc/sixlowpan.h" | ||
#include "net/gnrc/sixlowpan/frag/rb.h" | ||
#include "net/gnrc/sixlowpan/frag/vrb.h" | ||
#include "net/gnrc/ipv6/nib.h" | ||
#include "net/netdev_test.h" | ||
#include "thread.h" | ||
#include "xtimer.h" | ||
|
||
#define TEST_DST { 0x5a, 0x9d, 0x93, 0x86, 0x22, 0x08, 0x65, 0x79 } | ||
#define TEST_SRC { 0x2a, 0xab, 0xdc, 0x15, 0x54, 0x01, 0x64, 0x79 } | ||
#define TEST_6LO_PAYLOAD { \ | ||
/* 6LoWPAN, Src: 2001:db8::1, Dest: 2001:db8::2 | ||
* Fragmentation Header | ||
* 1100 0... = Pattern: First fragment (0x18) | ||
* Datagram size: 188 | ||
* Datagram tag: 0x000f | ||
* IPHC Header | ||
* 011. .... = Pattern: IP header compression (0x03) | ||
* ...1 1... .... .... = Version, traffic class, and flow label compressed (0x3) | ||
* .... .0.. .... .... = Next header: Inline | ||
* .... ..10 .... .... = Hop limit: 64 (0x2) | ||
* .... .... 0... .... = Context identifier extension: False | ||
* .... .... .0.. .... = Source address compression: Stateless | ||
* .... .... ..00 .... = Source address mode: Inline (0x0000) | ||
* .... .... .... 0... = Multicast address compression: False | ||
* .... .... .... .0.. = Destination address compression: Stateless | ||
* .... .... .... ..00 = Destination address mode: Inline (0x0000) | ||
* Next header: ICMPv6 (0x3a) | ||
* Source: 2001:db8::1 | ||
* Destination: 2001:db8::2 */ \ | ||
0xc0, 0xbc, 0x00, 0x0f, \ | ||
/* IPHC Header | ||
* 011. .... = Pattern: IP header compression (0x03) | ||
* ...1 1... .... .... = Version, traffic class, and flow label compressed (0x3) | ||
* .... .0.. .... .... = Next header: Inline | ||
* .... ..10 .... .... = Hop limit: 64 (0x2) | ||
* .... .... 0... .... = Context identifier extension: False | ||
* .... .... .0.. .... = Source address compression: Stateless | ||
* .... .... ..00 .... = Source address mode: Inline (0x0000) | ||
* .... .... .... 0... = Multicast address compression: False | ||
* .... .... .... .0.. = Destination address compression: Stateless | ||
* .... .... .... ..00 = Destination address mode: Inline (0x0000) | ||
* Next header: ICMPv6 (0x3a) */ \ | ||
0x7a, 0x00, 0x3a, \ | ||
/* Source: 2001:db8::1 */ \ | ||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, \ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, \ | ||
/* Destination: 2001:db8::2 */ \ | ||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, \ | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, \ | ||
/* Internet Control Message Protocol v6 | ||
* Type: Echo (ping) request (128) | ||
* Code: 0 | ||
* Checksum: 0x8ea0 | ||
* Identifier: 0x238f | ||
* Sequence: 2 | ||
* [No response seen] | ||
* Data (140 bytes) | ||
* Data: 9d4bb21c5353535353535353535353535353535353535353… | ||
*/ \ | ||
0x80, 0x00, 0x8e, 0xa0, 0x23, 0x8f, 0x00, 0x02, \ | ||
0x9d, 0x4b, 0xb2, 0x1c, 0x53, 0x53, 0x53, 0x53, \ | ||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, \ | ||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, \ | ||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, \ | ||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, \ | ||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, \ | ||
} | ||
#define TEST_TAG (0x000f) | ||
#define TEST_TGT_IPV6 { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
0x48, 0x3d, 0x1d, 0x0c, 0x98, 0x31, 0x58, 0xae } | ||
|
||
const uint8_t _test_src[] = TEST_SRC; | ||
const uint8_t _test_dst[] = TEST_DST; | ||
const uint8_t _test_6lo_payload[] = TEST_6LO_PAYLOAD; | ||
const ipv6_addr_t _test_tgt_ipv6 = { .u8 = TEST_TGT_IPV6 }; | ||
|
||
static char _mock_netif_stack[THREAD_STACKSIZE_DEFAULT]; | ||
static netdev_test_t _mock_dev; | ||
static gnrc_netif_t *_mock_netif; | ||
|
||
void _set_up(void) | ||
{ | ||
/* Add default route for the VRB entry created from */ | ||
gnrc_ipv6_nib_ft_add(NULL, 0, &_test_tgt_ipv6, _mock_netif->pid, 0); | ||
} | ||
|
||
void _tear_down(void) | ||
{ | ||
gnrc_ipv6_nib_ft_del(NULL, 0); | ||
gnrc_sixlowpan_frag_rb_reset(); | ||
gnrc_sixlowpan_frag_vrb_reset(); | ||
} | ||
|
||
gnrc_pktsnip_t *_create_fragment(void) | ||
{ | ||
gnrc_pktsnip_t *res = gnrc_netif_hdr_build(_test_src, sizeof(_test_src), | ||
_test_dst, sizeof(_test_dst)); | ||
if (res == NULL) { | ||
return NULL; | ||
} | ||
gnrc_netif_hdr_set_netif(res->data, _mock_netif); | ||
res = gnrc_pktbuf_add(res, _test_6lo_payload, sizeof(_test_6lo_payload), | ||
GNRC_NETTYPE_SIXLOWPAN); | ||
return res; | ||
} | ||
|
||
static unsigned _dispatch_to_6lowpan(gnrc_pktsnip_t *pkt) | ||
{ | ||
unsigned res = gnrc_netapi_dispatch_receive(GNRC_NETTYPE_SIXLOWPAN, | ||
GNRC_NETREG_DEMUX_CTX_ALL, | ||
pkt); | ||
thread_yield_higher(); | ||
return res; | ||
} | ||
|
||
static bool _rb_is_empty(void) | ||
{ | ||
const gnrc_sixlowpan_frag_rb_t *rb = gnrc_sixlowpan_frag_rb_array(); | ||
unsigned res = 0; | ||
|
||
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) { | ||
res += gnrc_sixlowpan_frag_rb_entry_empty(&rb[i]); | ||
} | ||
return res; | ||
} | ||
|
||
static void _test_no_vrbe_but_rbe_exists(void) | ||
{ | ||
const gnrc_sixlowpan_frag_rb_t *rb = gnrc_sixlowpan_frag_rb_array(); | ||
unsigned rbs = 0; | ||
|
||
/* VRB entry does not exist */ | ||
TEST_ASSERT_NULL(gnrc_sixlowpan_frag_vrb_get(_test_src, | ||
sizeof(_test_src), | ||
TEST_TAG)); | ||
/* and one reassembly buffer entry exists with the source and tag exists */ | ||
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_RBUF_SIZE; i++) { | ||
if (!gnrc_sixlowpan_frag_rb_entry_empty(&rb[i])) { | ||
rbs++; | ||
TEST_ASSERT_EQUAL_INT(sizeof(_test_src), rb[i].super.src_len); | ||
TEST_ASSERT_EQUAL_INT(0, memcmp(rb[i].super.src, _test_src, | ||
rb[i].super.src_len)); | ||
TEST_ASSERT_EQUAL_INT(TEST_TAG, rb[i].super.tag); | ||
/* release packet for packet buffer check */ | ||
gnrc_pktbuf_release(rb[i].pkt); | ||
|
||
} | ||
} | ||
TEST_ASSERT_EQUAL_INT(1, rbs); | ||
} | ||
|
||
static void test_recv__success(void) | ||
{ | ||
gnrc_pktsnip_t *pkt = _create_fragment(); | ||
|
||
TEST_ASSERT_NOT_NULL(pkt); | ||
TEST_ASSERT_EQUAL_INT(1, _dispatch_to_6lowpan(pkt)); | ||
/* A VRB entry exists was created but deleted due to -ENOTSUP being | ||
* returned by gnrc_sixlowpan_iphc.c:_forward_frag() | ||
* but the reassembly buffer is empty */ | ||
TEST_ASSERT(_rb_is_empty()); | ||
TEST_ASSERT(gnrc_pktbuf_is_empty()); | ||
} | ||
|
||
static void test_recv__no_route(void) | ||
{ | ||
gnrc_pktsnip_t *pkt = _create_fragment(); | ||
|
||
gnrc_ipv6_nib_ft_del(NULL, 0); | ||
TEST_ASSERT_NOT_NULL(pkt); | ||
TEST_ASSERT_EQUAL_INT(1, _dispatch_to_6lowpan(pkt)); | ||
_test_no_vrbe_but_rbe_exists(); | ||
TEST_ASSERT(gnrc_pktbuf_is_empty()); | ||
} | ||
|
||
static void test_recv__vrb_full(void) | ||
{ | ||
gnrc_pktsnip_t *pkt = _create_fragment(); | ||
gnrc_sixlowpan_frag_rb_base_t base = { | ||
.src = TEST_SRC, | ||
.src_len = sizeof(_test_src), | ||
.tag = TEST_TAG, | ||
}; | ||
|
||
TEST_ASSERT_NOT_NULL(pkt); | ||
/* Fill up VRB */ | ||
for (unsigned i = 0; i < GNRC_SIXLOWPAN_FRAG_VRB_SIZE; i++) { | ||
base.tag++; | ||
base.arrival = xtimer_now_usec(); | ||
TEST_ASSERT_NOT_NULL(gnrc_sixlowpan_frag_vrb_add(&base, _mock_netif, | ||
_test_dst, | ||
sizeof(_test_dst))); | ||
} | ||
TEST_ASSERT_EQUAL_INT(1, _dispatch_to_6lowpan(pkt)); | ||
_test_no_vrbe_but_rbe_exists(); | ||
TEST_ASSERT(gnrc_pktbuf_is_empty()); | ||
} | ||
|
||
static void test_recv__pkt_held(void) | ||
{ | ||
gnrc_pktsnip_t *pkt = _create_fragment(); | ||
|
||
TEST_ASSERT_NOT_NULL(pkt); | ||
gnrc_pktbuf_hold(pkt, 1); | ||
TEST_ASSERT_EQUAL_INT(1, _dispatch_to_6lowpan(pkt)); | ||
/* A VRB entry exists was created but deleted due to -ENOTSUP being | ||
* returned by gnrc_sixlowpan_iphc.c:_forward_frag() | ||
* but the reassembly buffer is empty */ | ||
TEST_ASSERT(_rb_is_empty()); | ||
gnrc_pktbuf_release(pkt); | ||
TEST_ASSERT(gnrc_pktbuf_is_empty()); | ||
} | ||
|
||
static void run_unittests(void) | ||
{ | ||
EMB_UNIT_TESTFIXTURES(fixtures) { | ||
new_TestFixture(test_recv__success), | ||
new_TestFixture(test_recv__no_route), | ||
new_TestFixture(test_recv__vrb_full), | ||
new_TestFixture(test_recv__pkt_held), | ||
}; | ||
|
||
EMB_UNIT_TESTCALLER(sixlo_iphc_vrb_tests, _set_up, _tear_down, fixtures); | ||
TESTS_START(); | ||
TESTS_RUN((Test *)&sixlo_iphc_vrb_tests); | ||
TESTS_END(); | ||
} | ||
|
||
static int _get_netdev_device_type(netdev_t *netdev, void *value, size_t max_len) | ||
{ | ||
assert(max_len == sizeof(uint16_t)); | ||
(void)netdev; | ||
|
||
*((uint16_t *)value) = NETDEV_TYPE_IEEE802154; | ||
return sizeof(uint16_t); | ||
} | ||
|
||
static int _get_netdev_proto(netdev_t *netdev, void *value, size_t max_len) | ||
{ | ||
assert(max_len == sizeof(gnrc_nettype_t)); | ||
(void)netdev; | ||
|
||
*((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN; | ||
return sizeof(gnrc_nettype_t); | ||
} | ||
|
||
static int _get_netdev_max_pdu_size(netdev_t *netdev, void *value, | ||
size_t max_len) | ||
{ | ||
assert(max_len == sizeof(uint16_t)); | ||
(void)netdev; | ||
|
||
*((uint16_t *)value) = sizeof(_test_6lo_payload); | ||
return sizeof(uint16_t); | ||
} | ||
|
||
static int _get_netdev_src_len(netdev_t *netdev, void *value, size_t max_len) | ||
{ | ||
(void)netdev; | ||
assert(max_len == sizeof(uint16_t)); | ||
*((uint16_t *)value) = sizeof(_test_dst); | ||
return sizeof(uint16_t); | ||
} | ||
|
||
static int _get_netdev_addr_long(netdev_t *netdev, void *value, size_t max_len) | ||
{ | ||
(void)netdev; | ||
assert(max_len >= sizeof(_test_dst)); | ||
memcpy(value, _test_dst, sizeof(_test_dst)); | ||
return sizeof(_test_dst); | ||
} | ||
|
||
static void _init_mock_netif(void) | ||
{ | ||
netdev_test_setup(&_mock_dev, NULL); | ||
netdev_test_set_get_cb(&_mock_dev, NETOPT_DEVICE_TYPE, | ||
_get_netdev_device_type); | ||
netdev_test_set_get_cb(&_mock_dev, NETOPT_PROTO, | ||
_get_netdev_proto); | ||
netdev_test_set_get_cb(&_mock_dev, NETOPT_MAX_PDU_SIZE, | ||
_get_netdev_max_pdu_size); | ||
netdev_test_set_get_cb(&_mock_dev, NETOPT_SRC_LEN, | ||
_get_netdev_src_len); | ||
netdev_test_set_get_cb(&_mock_dev, NETOPT_ADDRESS_LONG, | ||
_get_netdev_addr_long); | ||
_mock_netif = gnrc_netif_ieee802154_create( | ||
_mock_netif_stack, THREAD_STACKSIZE_DEFAULT, GNRC_NETIF_PRIO, | ||
"mock_netif", (netdev_t *)&_mock_dev); | ||
thread_yield_higher(); | ||
} | ||
|
||
int main(void) | ||
{ | ||
_init_mock_netif(); | ||
run_unittests(); | ||
return 0; | ||
} |
Oops, something went wrong.