1635 lines
60 KiB
C
1635 lines
60 KiB
C
#include "pico_addressing.h"
|
|
#include "pico_ipv6_nd.h"
|
|
#include "pico_stack.h"
|
|
#include "pico_frame.h"
|
|
#include "pico_ipv6.h"
|
|
#include "pico_dev_radiotest.c"
|
|
#include "modules/pico_6lowpan_ll.c"
|
|
#include "modules/pico_6lowpan.c"
|
|
#include "pico_6lowpan_ll.h"
|
|
#include "check.h"
|
|
|
|
#include "pico_config.h"
|
|
#include "pico_frame.h"
|
|
#include "pico_device.h"
|
|
#include "pico_protocol.h"
|
|
#include "pico_stack.h"
|
|
#include "pico_addressing.h"
|
|
#include "pico_dns_client.h"
|
|
|
|
#include "pico_ethernet.h"
|
|
#include "pico_6lowpan.h"
|
|
#include "pico_802154.h"
|
|
#include "pico_olsr.h"
|
|
#include "pico_aodv.h"
|
|
#include "pico_eth.h"
|
|
#include "pico_arp.h"
|
|
#include "pico_ipv4.h"
|
|
#include "pico_ipv6.h"
|
|
#include "pico_icmp4.h"
|
|
#include "pico_icmp6.h"
|
|
#include "pico_igmp.h"
|
|
#include "pico_udp.h"
|
|
#include "pico_tcp.h"
|
|
#include "pico_socket.h"
|
|
#include "heap.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
/*******************************************************************************
|
|
* MACROS
|
|
******************************************************************************/
|
|
|
|
#define STARTING() \
|
|
printf("*********************** STARTING %s ***\n", __func__); \
|
|
fflush(stdout)
|
|
#define TRYING(s, ...) \
|
|
printf("\n=== TRYING %s: " s, __func__, ##__VA_ARGS__); \
|
|
fflush(stdout)
|
|
#define OUTPUT() \
|
|
do { \
|
|
printf("\n> OUTPUT:\n"); \
|
|
} while (0)
|
|
#define RESULTS() \
|
|
do { \
|
|
printf("\n> RESULTS:\n"); \
|
|
} while (0)
|
|
#define FAIL_UNLESS(cond, i, s, ...) \
|
|
do { \
|
|
char str[80] = { 0 }; \
|
|
snprintf(str, 80, "TEST %2d: "s"...", (i)++, ##__VA_ARGS__); \
|
|
printf("%s",str); \
|
|
if (cond) { \
|
|
printf("%-*s %s\n", (int)(80 - strlen(str) - 12), "", "[SUCCESS]"); \
|
|
} else { \
|
|
printf("%-*s %s\n", (int)(80 - strlen(str) - 12), "", "[FAILED]"); \
|
|
} \
|
|
fflush(stdout); \
|
|
fail_unless((int)(intptr_t)cond, s, ##__VA_ARGS__); \
|
|
}while(0)
|
|
#define FAIL_IF(cond, i, s, ...) }\
|
|
do { \
|
|
char str[80] = { 0 }; \
|
|
snprintf(str, 80, "TEST %2d: "s"...", (i)++, ##__VA_ARGS__); \
|
|
printf(str); \
|
|
if (!cond) { \
|
|
printf("%-*s %s\n", (int)(80 - strlen(str) - 12), "", "[SUCCESS]"); \
|
|
} else { \
|
|
printf("%-*s %s\n", (int)(80 - strlen(str) - 12), "", "[FAILED]"); \
|
|
} \
|
|
fflush(stdout); \
|
|
fail_if((int)(intptr_t)(cond), s, ##__VA_ARGS__); \
|
|
}while(0)
|
|
#define ENDING(i) \
|
|
printf("*********************** ENDING %s *** NUMBER OF TESTS: %d\n",\
|
|
__func__, ((i)-1)); \
|
|
fflush(stdout)
|
|
#define DBG(s, ...) \
|
|
printf(s, ##__VA_ARGS__); \
|
|
fflush(stdout)
|
|
static void
|
|
dbg_buffer(uint8_t *buf, size_t len)
|
|
{
|
|
int i = 0;
|
|
printf("Buffer:");
|
|
for (i = 0; i < (int)len; i++) {
|
|
if (i % 8 != 0)
|
|
printf("0x%02x, ", buf[i]);
|
|
else {
|
|
printf("\n0x%02x, ", buf[i]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* CTX
|
|
******************************************************************************/
|
|
|
|
START_TEST(tc_compare_prefix)
|
|
{
|
|
int test = 1, ret = 0;
|
|
struct pico_ip6 a, b, c;
|
|
pico_string_to_ipv6("2aaa:1234:5678:9123:0:0ff:fe00:0105", a.addr);
|
|
pico_string_to_ipv6("2aaa:1234:5678:9143:0102:0304:0506:0708", b.addr);
|
|
pico_string_to_ipv6("2aaa:1234:5678:9156:0102:0304:0506:0708", c.addr);
|
|
|
|
STARTING();
|
|
|
|
TRYING("With 2 equal prexixes\n");
|
|
ret = compare_prefix(a.addr, b.addr, 54);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Prefixes are equal, should've returned 0, ret = %d",ret);
|
|
|
|
TRYING("With b > a\n");
|
|
ret = compare_prefix(a.addr, b.addr, 60);
|
|
RESULTS();
|
|
FAIL_UNLESS(ret, test, "Prefixes are not equal, shouldn't have returned 0, ret = %d",ret);
|
|
|
|
TRYING("With c > b\n");
|
|
ret = compare_prefix(b.addr, c.addr, 64);
|
|
RESULTS();
|
|
FAIL_UNLESS(ret, test, "Prefixes are not equal, shouldn't have returned 0, ret = %d",ret);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compare_ctx)
|
|
{
|
|
int test = 1, ret = 0;
|
|
struct pico_ip6 a, b, c;
|
|
struct iphc_ctx ca, cb, cc;
|
|
pico_string_to_ipv6("2aaa:1234:5678:9123:0:0ff:fe00:0105", a.addr);
|
|
pico_string_to_ipv6("2aaa:1234:5678:9145:0102:0304:0506:0708", b.addr);
|
|
pico_string_to_ipv6("2aaa:1234:5678:9156:0102:0304:0506:0708", c.addr);
|
|
ca.prefix = a;
|
|
ca.size = 54;
|
|
cb.prefix = b;
|
|
cc.prefix = c;
|
|
|
|
STARTING();
|
|
|
|
TRYING("With 2 equal ctx's\n");
|
|
ret = compare_ctx(&ca, &cb);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Prefixes are equal, should've returned 0, ret = %d", ret);
|
|
|
|
ca.size = 60;
|
|
TRYING("With b > a\n");
|
|
ret = compare_ctx(&ca, &cb);
|
|
RESULTS();
|
|
FAIL_UNLESS(ret, test, "Prefixes are not equal, shouln'r return 0, ret = %d", ret);
|
|
|
|
cb.size = 64;
|
|
TRYING("With b > c\n");
|
|
ret = compare_ctx(&cb, &cc);
|
|
RESULTS();
|
|
FAIL_UNLESS(ret, test, "Prefixes are not equal, shouldn't return 0, ret = %d", ret);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_ctx_lookup)
|
|
{
|
|
int test = 1, ret = 0;
|
|
struct pico_ip6 a, b;
|
|
struct iphc_ctx *found = NULL;
|
|
pico_string_to_ipv6("2aaa:1234:5678:9123:0:0ff:fe00:0105", a.addr);
|
|
pico_string_to_ipv6("2aaa:1234:5678:9145:0102:0304:0506:0708", b.addr);
|
|
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("To find a prefix in the context tree\n");
|
|
ret = ctx_insert(a, 13, 54, 0, PICO_IPHC_CTX_COMPRESS, NULL);
|
|
found = ctx_lookup(b);
|
|
RESULTS();
|
|
FAIL_UNLESS(!ret, test, "Inserting should've succeeded, return 0. ret = %d", ret);
|
|
FAIL_UNLESS(found, test, "Should've found the context");
|
|
FAIL_UNLESS(found->id == 13, test, "Should've found the correct ctx, ID = %d", ret);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
/*******************************************************************************
|
|
* IPHC
|
|
******************************************************************************/
|
|
|
|
#ifdef PICO_6LOWPAN_IPHC_ENABLED
|
|
|
|
START_TEST(tc_compressor_vtf)
|
|
{
|
|
int test = 1, ret = 0;
|
|
uint8_t ori_fl[] = {0x64,0x00,0x00,0x00};
|
|
uint8_t ori_dscp[] = {0x62,0x00,0x00,0x00};
|
|
uint8_t ori_notc[] = {0x60,0x0f,0xed,0xcb};
|
|
uint8_t ori_inline[] = {0x6f,0xaf,0xed,0xcb};
|
|
uint8_t comp_fl[] = {0x40};
|
|
uint8_t comp_dscp[] = {0x20};
|
|
uint8_t comp_notc[] = {0x0f,0xed,0xcb};
|
|
uint8_t comp_inline[] = {0xfa,0x0f,0xed,0xcb};
|
|
uint8_t comp[4] = {0, 0, 0, 0};
|
|
uint8_t iphc[3] = {0, 0, 0};
|
|
|
|
STARTING();
|
|
|
|
TRYING("With ECN set. No matter DSCP, should elide flow label and reformat tc\n");
|
|
ret = compressor_vtf(ori_fl, comp, iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(comp, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS((iphc[0] & TF_ELIDED) == TF_ELIDED_FL, test, "Should've set the IPHC-bits correctly, %02X", iphc[0]);
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned size of 1, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(comp_fl, comp, (size_t)ret), test, "inline formatting not correct");
|
|
memset(comp, 0, 4);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With DSCP set. No matter ECN, should elide flow label and reformat tc\n");
|
|
ret = compressor_vtf(ori_dscp, comp, iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(comp, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS((iphc[0] & TF_ELIDED) == TF_ELIDED_FL, test, "Should've set the IPHC-bits correctly, %02X", iphc[0]);
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned size of 1, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(comp_dscp, comp, (size_t)ret), test, "inline formatting not correct");
|
|
memset(comp, 0, 4);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With FL set. If DSCP is not set, can be compressed to 3 bytes\n");
|
|
ret = compressor_vtf(ori_notc, comp, iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(comp, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS((iphc[0] & TF_ELIDED) == TF_ELIDED_DSCP, test, "Should've set the IPHC-bits correctly, %02X", iphc[0]);
|
|
FAIL_UNLESS(3 == ret, test, "Should've returned size of 3, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(comp_notc, comp, (size_t)ret), test, "inline formatting not correct");
|
|
memset(comp, 0, 4);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With evt. set. Should elide nothing and reformat traffic class\n");
|
|
ret = compressor_vtf(ori_inline, comp, iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(comp, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS((iphc[0] & TF_ELIDED) == TF_INLINE, test, "Should've set the IPHC-bits correctly, %02X", iphc[0]);
|
|
FAIL_UNLESS(4 == ret, test, "Should've returned size of 4, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(comp_inline, comp, (size_t)ret), test, "inline formatting not correct");
|
|
memset(comp, 0, 4);
|
|
memset(iphc, 0, 3);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_vtf)
|
|
{
|
|
int test = 1, ret = 0;
|
|
uint8_t ori_fl[] = {0x64,0x00,0x00,0x00};
|
|
uint8_t ori_dscp[] = {0x62,0x00,0x00,0x00};
|
|
uint8_t ori_notc[] = {0x60,0x0f,0xed,0xcb};
|
|
uint8_t ori_inline[] = {0x6f,0xaf,0xed,0xcb};
|
|
uint8_t comp_fl[] = {0x40};
|
|
uint8_t comp_dscp[] = {0x20};
|
|
uint8_t comp_notc[] = {0x0f,0xed,0xcb};
|
|
uint8_t comp_inline[] = {0xfa,0x0f,0xed,0xcb};
|
|
uint8_t ori[4] = {0};
|
|
uint8_t iphc_fl[3] = {TF_ELIDED_FL, 0,0};
|
|
uint8_t iphc_dscp[3] = {TF_ELIDED_FL, 0,0};
|
|
uint8_t iphc_notc[3] = {TF_ELIDED_DSCP, 0,0};
|
|
uint8_t iphc_inline[3] = {TF_INLINE, 0,0};
|
|
|
|
STARTING();
|
|
|
|
TRYING("With flow label compressed\n");
|
|
ret = decompressor_vtf(ori, comp_fl, iphc_fl, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(ori, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned length of 1, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(ori_fl, ori, (size_t)4), test, "Should've formatted IPv6 VTF-field correctly");
|
|
memset(ori, 0, 4);
|
|
|
|
TRYING("With flow label compression but with IPHC inline\n");
|
|
ret = decompressor_vtf(ori, comp_dscp, iphc_dscp, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(ori, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned length of 1, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(ori_dscp, ori, (size_t)4), test, "Should've formatted IPv6 VTF-field correctly");
|
|
memset(ori, 0, 4);
|
|
|
|
TRYING("With flow label inline and DSCP compressed\n");
|
|
ret = decompressor_vtf(ori, comp_notc, iphc_notc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(ori, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS(3 == ret, test, "Should've returned length of 3, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(ori_notc, ori, (size_t)4), test, "Should've formatted IPv6 VTF-field correctly");
|
|
memset(ori, 0, 4);
|
|
|
|
TRYING("With evt. inline\n");
|
|
ret = decompressor_vtf(ori, comp_inline, iphc_inline, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
dbg_buffer(ori, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == ret, test, "Should've returned length of 4, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(ori_inline, ori, (size_t)4), test, "Should've formatted IPv6 VTF-field correctly");
|
|
memset(ori, 0, 4);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_nh)
|
|
{
|
|
int test = 1;
|
|
uint8_t nxthdr = PICO_PROTO_UDP;
|
|
uint8_t iphc = 0;
|
|
uint8_t comp = 0;
|
|
int ret = 0;
|
|
|
|
STARTING();
|
|
|
|
TRYING("With next header = UDP\n");
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == NH_COMPRESSED, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(0 == comp, test, "Shouldn't have changed compressed");
|
|
|
|
TRYING("With next header = EXT_HOPBYHOP\n");
|
|
nxthdr = PICO_IPV6_EXTHDR_HOPBYHOP;
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == NH_COMPRESSED, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(0 == comp, test, "Shouldn't have changed compressed");
|
|
|
|
TRYING("With next header = EXT_ROUTING\n");
|
|
nxthdr = PICO_IPV6_EXTHDR_ROUTING;
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == NH_COMPRESSED, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(0 == comp, test, "Shouldn't have changed compressed");
|
|
|
|
TRYING("With next header = EXT_FRAG\n");
|
|
nxthdr = PICO_IPV6_EXTHDR_FRAG;
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == NH_COMPRESSED, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(0 == comp, test, "Shouldn't have changed compressed");
|
|
|
|
TRYING("With next header = EXT_DSTOPT\n");
|
|
nxthdr = PICO_IPV6_EXTHDR_DESTOPT;
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == NH_COMPRESSED, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(0 == comp, test, "Shouldn't have changed compressed");
|
|
|
|
TRYING("With next header = TCP\n");
|
|
nxthdr = PICO_PROTO_TCP;
|
|
ret = compressor_nh(&nxthdr, &comp, &iphc, NULL, NULL, NULL);
|
|
OUTPUT();
|
|
printf("IPHC: %02X", iphc);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc == 0, test, "Should've set the IPHC bits correctly");
|
|
FAIL_UNLESS(PICO_PROTO_TCP == comp, test, "Shouldn't have changed compressed");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_nh)
|
|
{
|
|
int test = 1;
|
|
uint8_t iphc = NH_COMPRESSED;
|
|
uint8_t ori = 0;
|
|
int8_t ret = 0;
|
|
uint8_t comp = PICO_PROTO_TCP;
|
|
|
|
STARTING();
|
|
|
|
TRYING("With NH bit set\n");
|
|
ret = decompressor_nh(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(0 == ori, test, "Should've filled ori with NH_COMPRESSED");
|
|
|
|
TRYING("With NH bit cleared\n");
|
|
iphc = 0;
|
|
ret = decompressor_nh(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned 1, ret = %d", ret);
|
|
FAIL_UNLESS(PICO_PROTO_TCP == ori, test, "Should've filled ori with PICO_PROTO_TCP");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_hl)
|
|
{
|
|
int test = 1;
|
|
uint8_t iphc = 0;
|
|
uint8_t ori = 1;
|
|
uint8_t comp;
|
|
int ret = 0;
|
|
|
|
STARTING();
|
|
|
|
TRYING("With HL set to 1\n");
|
|
ret = compressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(HL_COMPRESSED_1 == iphc, test, "Should've set IPHC bits correctly");
|
|
|
|
TRYING("With HL set to 64\n");
|
|
ori = 64;
|
|
ret = compressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(HL_COMPRESSED_64 == iphc, test, "Should've set IPHC bits correctly");
|
|
|
|
TRYING("With HL set to 255\n");
|
|
ori = 255;
|
|
ret = compressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(HL_COMPRESSED_255 == iphc, test, "Should've set IPHC bits correctly");
|
|
|
|
TRYING("With random HL\n");
|
|
ori = 153;
|
|
ret = compressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned 1, ret = %d",ret);
|
|
FAIL_UNLESS(0 == iphc, test, "Should've set IPHC bits correctly");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_hl)
|
|
{
|
|
int test = 1;
|
|
uint8_t iphc = HL_COMPRESSED_1;
|
|
uint8_t ori = 0;
|
|
uint8_t comp = 0;
|
|
int ret = 0;
|
|
|
|
STARTING();
|
|
|
|
TRYING("HL 1 compressed\n");
|
|
ret = decompressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d",ret );
|
|
FAIL_UNLESS(1 == ori, test, "Should filled in correct hop limit");
|
|
|
|
TRYING("HL 64 compressed\n");
|
|
iphc = HL_COMPRESSED_64;
|
|
ret = decompressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d",ret );
|
|
FAIL_UNLESS(64 == ori, test, "Should filled in correct hop limit");
|
|
|
|
TRYING("HL 255 compressed\n");
|
|
iphc = HL_COMPRESSED_255;
|
|
ret = decompressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d",ret );
|
|
FAIL_UNLESS(255 == ori, test, "Should filled in correct hop limit");
|
|
|
|
TRYING("HL not compressed\n");
|
|
iphc = 0;
|
|
comp = 125;
|
|
ret = decompressor_hl(&ori, &comp, &iphc, NULL, NULL, NULL);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned 0, ret = %d",ret );
|
|
FAIL_UNLESS(125 == ori, test, "Should filled in correct hop limit");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_addr_comp_mode)
|
|
{
|
|
uint8_t iphc[3] = { 0 };
|
|
int test = 1, ret = 0;
|
|
struct pico_ip6 ip;
|
|
struct pico_ip6 local;
|
|
struct pico_ip6 local2;
|
|
struct pico_ip6 local3;
|
|
union pico_ll_addr addr = { .pan = { .addr.data = {1,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_SHORT }};
|
|
struct pico_device dev = { .mode = LL_MODE_IEEE802154 };
|
|
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", ip.addr);
|
|
pico_string_to_ipv6("fe80:0:0:0:0102:0304:0506:0708", local.addr);
|
|
pico_string_to_ipv6("fe80:0:0:0:0:0ff:fe00:0105", local3.addr);
|
|
pico_string_to_ipv6("fe80:0:0:0:0:0ff:fe00:0102", local2.addr);
|
|
|
|
STARTING();
|
|
|
|
pico_stack_init();
|
|
|
|
TRYING("With MAC derived address\n");
|
|
ret = addr_comp_mode(iphc, &local2, addr, &dev, SRC_SHIFT);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned 0, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & SRC_COMPRESSED, test, "Should've set IPHC bits correctly, %02X", iphc[1]);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With wrong device link layer mode\n");
|
|
dev.mode = LL_MODE_ETHERNET;
|
|
ret = addr_comp_mode(iphc, &local2, addr, &dev, SRC_SHIFT);
|
|
RESULTS();
|
|
FAIL_UNLESS(-1 == ret, test, "Shoudl've returned error (-1), ret = %d", ret);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With non MAC derived extended address\n");
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
ret = addr_comp_mode(iphc, &local, addr, &dev, SRC_SHIFT);
|
|
FAIL_UNLESS(8 == ret, test, "Should've return 8, ret = %d", ret);
|
|
FAIL_UNLESS(SRC_COMPRESSED_64 == iphc[1], test, "Should've set the IPHC bits correctly, iphc = %02X", iphc[1]);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With non MAC derived short address\n");
|
|
ret = addr_comp_mode(iphc, &local3, addr, &dev, SRC_SHIFT);
|
|
FAIL_UNLESS(2 == ret, test, "should've returned 2, ret = %d", ret);
|
|
FAIL_UNLESS(SRC_COMPRESSED_16 == iphc[1], test, "Should've set the IPHC bits correctly, iphc = %02X", iphc[1]);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_addr_comp_prefix)
|
|
{
|
|
int test = 1, ret = 0;
|
|
uint8_t iphc[3] = { 0 };
|
|
struct pico_ip6 ip;
|
|
struct pico_ip6 local;
|
|
struct pico_ip6 local3;
|
|
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", ip.addr);
|
|
pico_string_to_ipv6("fe80:0:0:0:0102:0304:0506:0708", local.addr);
|
|
pico_string_to_ipv6("2aaa:0:0:0:0:0ff:fe00:0105", local3.addr);
|
|
|
|
STARTING();
|
|
|
|
pico_stack_init();
|
|
|
|
TRYING("With MCAST address\n");
|
|
ret = addr_comp_prefix(iphc, &ip, 1);
|
|
RESULTS();
|
|
FAIL_UNLESS(COMP_MULTICAST == ret, test, "Should've returned COMP_MULTICAST, ret = %d", ret);
|
|
FAIL_UNLESS(!iphc[1], test, "Shouldn't have set any IPHC bytes, iphc = %02X", iphc[1]);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With link local destination address\n");
|
|
ret = addr_comp_prefix(iphc, &local, 0);
|
|
RESULTS();
|
|
FAIL_UNLESS(COMP_LINKLOCAL == ret, test, "Should've returned COMP_LINKLOCAL, ret = %d", ret);
|
|
FAIL_UNLESS(!iphc[1], test, "Shouldn't have set any IPHC bytes, iphc = %02X", iphc[1]);
|
|
memset(iphc, 0, 3);
|
|
|
|
TRYING("With a unicast address where there's no context available for\n");
|
|
ret = addr_comp_prefix(iphc, &local3, 0);
|
|
RESULTS();
|
|
FAIL_UNLESS(COMP_STATELESS == ret, test, "Should've return COMP_STATELESS, ret = %d", ret);
|
|
FAIL_UNLESS(!iphc[1], test, "Shouldn't have set any IPHC bytes, iphc = %02X", iphc[1]);
|
|
memset(iphc, 0,3);
|
|
|
|
TRYING("With a unicast address where there's context available for\n");
|
|
ctx_insert(local3, 13, 64, 0, PICO_IPHC_CTX_COMPRESS, NULL);
|
|
ret = addr_comp_prefix(iphc, &local3, 0);
|
|
FAIL_UNLESS(13 == ret, test, "Should've returned CTX ID of 13, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & DST_STATEFUL, test, "Should've set DAC correctly, iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(iphc[1] & CTX_EXTENSION, test, "Should've set CTX extension bit correctly, iphc = %02X", iphc[1]);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_src)
|
|
{
|
|
int test = 1;
|
|
struct pico_ip6 unspec = {{ 0 }};
|
|
struct pico_ip6 ll_mac = {{0xfe,0x80,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
struct pico_ip6 ll_nmac_16 = {{0xfe,0x80,0,0,0,0,0,0 ,0,0,0,0xff,0xfe,0,0x12,0x34}};
|
|
struct pico_ip6 ll_nmac_64 = {{0xfe,0x80,0,0,0,0,0,0 ,8,7,6,5,4,3,2,1}};
|
|
struct pico_ip6 ip_ctx = {{0x2a,0xaa,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
struct pico_ip6 ip_stateless = {{0x2a,0xbb,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
union pico_ll_addr mac = { .pan = {.addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT } };
|
|
struct pico_device dev = { 0 };
|
|
int ret = 0;
|
|
|
|
uint8_t iphc[3] = { 0, 0, 0 };
|
|
uint8_t buf[PICO_SIZE_IP6] = { 0 };
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("With unspecified source address, should: set SAC, clear SAM\n");
|
|
ret = compressor_src(unspec.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(16 == ret, test, "Shouldn't elide unspecified address, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & SRC_STATEFUL, test, "Should've set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == 0, test, "Should've cleared SAM");
|
|
|
|
TRYING("With invalid device, should indicate error\n");
|
|
dev.mode = LL_MODE_ETHERNET;
|
|
ret = compressor_src(ll_mac.addr, buf, iphc, &mac, NULL, &dev);
|
|
RESULTS();
|
|
FAIL_UNLESS(-1 == ret, test, "Should've indicated error, invalid device, ret = %d",ret);
|
|
|
|
TRYING("With mac derived address, should elide fully\n");
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
ret = compressor_src(ll_mac.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc,3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned compressed size of 0, ret = %d", ret);
|
|
FAIL_UNLESS(!(iphc[1] & SRC_STATEFUL), test, "Shoudln't have set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == SRC_COMPRESSED, test, "Should set SAM to '11', iphc = %02X", iphc[1]);
|
|
|
|
TRYING("With non mac derived 16-bit derivable address\n");
|
|
ret = compressor_src(ll_nmac_16.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc,3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(2 == ret, test, "Should've returned compressed size of 2, ret = %d", ret);
|
|
FAIL_UNLESS(!(iphc[1] & SRC_STATEFUL), test, "Shouldn't have set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == SRC_COMPRESSED_16, test, "Should've set SAM to '10', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(0 == memcmp(buf, ll_nmac_16.addr + 14, 2), test, "Should've copied 16 bit of source address inline");
|
|
|
|
TRYING("With non mac derived 64-bit derivable address\n");
|
|
ret = compressor_src(ll_nmac_64.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc,3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(8 == ret, test, "Should've returned compressed size of 8, ret = %d", ret);
|
|
FAIL_UNLESS(!(iphc[1] & SRC_STATEFUL), test, "Shoudln't have set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == SRC_COMPRESSED_64, test, "Should've set SAM to '01', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(0 == memcmp(buf, ll_nmac_64.addr + 8, 8), test, "Should've copied IID of source address inline");
|
|
|
|
TRYING("With context derived address\n");
|
|
pico_stack_init();
|
|
ctx_insert(ip_ctx, 13, 64, 0, PICO_IPHC_CTX_COMPRESS, NULL);
|
|
ret = compressor_src(ip_ctx.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned compressed size of 0, ret = %d", ret);
|
|
FAIL_UNLESS((iphc[1] & SRC_STATEFUL), test, "Shoudl've set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == SRC_COMPRESSED, test, "Shoudl've set SAM to '11', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS((iphc[2] >> SRC_SHIFT) == 13, test, "Should've filled in the context extension correctly, ctx = %02X", iphc[2]);
|
|
|
|
TRYING("With stateless compression\n");
|
|
ret = compressor_src(ip_stateless.addr, buf, iphc, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(PICO_SIZE_IP6 == ret, test, "Should've returned compressed size of 16, ret = %d",ret);
|
|
FAIL_UNLESS((iphc[1] & SRC_STATEFUL) == 0, test, "Shoudln't have set SAC");
|
|
FAIL_UNLESS((iphc[1] & SRC_COMPRESSED) == 0, test, "Should've set SAM to '00', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip_stateless.addr, PICO_SIZE_IP6), test, "Should've copied the source address inline");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_src)
|
|
{
|
|
int test = 1;
|
|
int ret = 0;
|
|
|
|
union pico_ll_addr mac = { .pan = {.addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT } };
|
|
struct pico_device dev;
|
|
|
|
/* Stateless compression */
|
|
uint8_t iphc1[] = {0x00, 0x00, 0x00};
|
|
uint8_t buf1[] = {0x2a, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
|
struct pico_ip6 ip1 = {{0x2a,0xbb,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
|
|
/* With context */
|
|
uint8_t iphc2[] = {0x00, 0xf0, 0xd0};
|
|
uint8_t buf2[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
struct pico_ip6 ip2 = {{0x2a,0xaa,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
|
|
/* Link-local non-mac 64-bit derivable address */
|
|
uint8_t iphc4[] = {0x00, 0x10, 0x00};
|
|
uint8_t buf4[] = {0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
struct pico_ip6 ip4 = {{0xfe,0x80,0,0,0,0,0,0 ,8,7,6,5,4,3,2,1}};
|
|
|
|
/* Link-local non-mac 16-bit derivable address */
|
|
uint8_t iphc3[] = {0x00, 0x20, 0x00};
|
|
uint8_t buf3[] = {0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
struct pico_ip6 ip3 = {{0xfe,0x80,0,0,0,0,0,0 ,0,0,0,0xff,0xfe,0,0x12,0x34}};
|
|
|
|
/* Link-local mac derivable address */
|
|
uint8_t iphc5[] = {0x00, 0x30, 0x00};
|
|
uint8_t buf5[] = {0};
|
|
struct pico_ip6 ip5 = {{0xfe,0x80,0,0,0,0,0,0 ,1,2,3,4,5,6,7,8}};
|
|
|
|
/* Context non-mac 16-bit derivable address */
|
|
uint8_t iphc6[] = {0x00, 0xE0, 0xd0};
|
|
uint8_t buf6[] = {0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
struct pico_ip6 ip6 = {{0x2a,0xaa,0,0,0,0,0,0 ,0,0,0,0xff,0xfe,0,0x12,0x34}};
|
|
|
|
uint8_t buf[PICO_SIZE_IP6] = { 0 };
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
|
|
pico_stack_init();
|
|
STARTING();
|
|
|
|
TRYING("With statelessly compressed address\n");
|
|
ret = decompressor_src(buf, buf1, iphc1, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(16 == ret, test, "Should've returned compressed size of 16, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip1.addr, PICO_SIZE_IP6), test, "Should've correctly decompressed address");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
TRYING("With context\n");
|
|
pico_stack_init();
|
|
ctx_insert(ip2, 13, 64, 0, PICO_IPHC_CTX_COMPRESS, NULL);
|
|
ret = decompressor_src(buf, buf2, iphc2, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned compressed size of 0, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip2.addr, PICO_SIZE_IP6), test, "Shoudld've correctly decompressed addresss");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
TRYING("With link-local non-mac 16-bit derivable address\n");
|
|
ret = decompressor_src(buf, buf3, iphc3, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(2 == ret, test, "Shoudl've returned compressed size of 2, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip3.addr, PICO_SIZE_IP6), test, "Shoudld've correctly decompressed addresss");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
TRYING("With link-local non-mac 64-bit derivable address\n");
|
|
ret = decompressor_src(buf, buf4, iphc4, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(8 == ret, test, "Should've returned compressed size of 8, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip4.addr, PICO_SIZE_IP6), test, "Should've correctly decompressed address");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
TRYING("With link-local mac based address\n");
|
|
ret = decompressor_src(buf, buf5, iphc5, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(0 == ret, test, "Should've returned compressed size of 0, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip5.addr, PICO_SIZE_IP6), test, "Should've correctly decompressed address");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
TRYING("Context based non-mac 16-bit derivable address\n");
|
|
ret = decompressor_src(buf, buf6, iphc6, &mac, NULL, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(2 == ret, test, "Should've returned compressed size of 2, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(buf, ip6.addr, PICO_SIZE_IP6), test, "Should've correctly decompressed addresss");
|
|
memset(buf, 0, PICO_SIZE_IP6);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_dst)
|
|
{
|
|
int test = 1;
|
|
int ret = 0;
|
|
|
|
union pico_ll_addr mac = { .pan = {.addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT } };
|
|
struct pico_device dev;
|
|
|
|
/* Multicast 48-bit */
|
|
struct pico_ip6 mcast1 = {{0xff,0x12,0,0,0,0,0,0 ,0,0,0,5,4,3,2,1}};
|
|
uint8_t buf1[] = {0x12,5,4,3,2,1};
|
|
|
|
/* Multicast 32-bit */
|
|
struct pico_ip6 mcast2 = {{0xFF,0x34,0,0,0,0,0,0 ,0,0,0,0,0,1,2,3}};
|
|
uint8_t buf2[] = {0x34,1,2,3};
|
|
|
|
/* Multicast 8-bit */
|
|
struct pico_ip6 mcast3 = {{0xFF,0x02,0,0,0,0,0,0 ,0,0,0,0,0,0,0,5}};
|
|
uint8_t buf3 = 5;
|
|
|
|
uint8_t iphc[3] = { 0 };
|
|
uint8_t buf[PICO_SIZE_IP6] = { 0 };
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("48-bit derivable mcast address\n");
|
|
ret = compressor_dst(mcast1.addr, buf, iphc, NULL, &mac, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == ret, test, "Should've returned compressed length of 6, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & DST_MULTICAST, test, "Should've set IPHC mcast-flag");
|
|
FAIL_UNLESS(!(iphc[1] & DST_STATEFUL), test, "Shouldn't have set stateful flag, iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS((iphc[1] & DST_COMPRESSED) == DST_MCAST_48, test, "Should've set DAM to '01', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(0 == memcmp(buf1, buf, 6), test, "Shoudl've correctly compressed MCAST 48 address");
|
|
|
|
TRYING("32-bit derivable mcast address\n");
|
|
ret = compressor_dst(mcast2.addr, buf, iphc, NULL, &mac, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == ret, test, "Should've returned compressed length of 4, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & DST_MULTICAST, test, "Should've set IPHC mcast-flag");
|
|
FAIL_UNLESS(!(iphc[1] & DST_STATEFUL), test, "Shouldn't have set stateful flag, iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS((iphc[1] & DST_COMPRESSED) == DST_MCAST_32, test, "Should've set DAM to '10', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(0 == memcmp(buf2, buf, 4), test, "Shoudl've correctly compressed MCAST 32 address");
|
|
|
|
TRYING("8-bit derivable mcast address\n");
|
|
ret = compressor_dst(mcast3.addr, buf, iphc, NULL, &mac, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(iphc, 3);
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned compressed length of 1, ret = %d", ret);
|
|
FAIL_UNLESS(iphc[1] & DST_MULTICAST, test, "Should've set IPHC mcast-flag");
|
|
FAIL_UNLESS(!(iphc[1] & DST_STATEFUL), test, "Shouldn't have set stateful flag, iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS((iphc[1] & DST_COMPRESSED) == DST_MCAST_8, test, "Should've set DAM to '11', iphc = %02X", iphc[1]);
|
|
FAIL_UNLESS(buf[0] == buf3, test, "Shoudl've correctly compressed MCAST 32 address");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_dst)
|
|
{
|
|
int test = 1;
|
|
int ret = 0;
|
|
|
|
union pico_ll_addr mac = { .pan = {.addr.data = {3,2,3,4,5,6,7,8}, .mode = AM_6LOWPAN_EXT } };
|
|
struct pico_device dev;
|
|
|
|
/* Multicast 48-bit */
|
|
uint8_t iphc1[3] = {0x00, 0x09, 0x00};
|
|
struct pico_ip6 mcast1 = {{0xff,0x12,0,0,0,0,0,0 ,0,0,0,5,4,3,2,1}};
|
|
uint8_t buf1[] = {0x12,5,4,3,2,1};
|
|
|
|
/* Multicast 32-bit */
|
|
uint8_t iphc2[3] = {0x00, 0x0a, 0x00};
|
|
struct pico_ip6 mcast2 = {{0xFF,0x34,0,0,0,0,0,0 ,0,0,0,0,0,1,2,3}};
|
|
uint8_t buf2[] = {0x34,1,2,3};
|
|
|
|
/* Multicast 8-bit */
|
|
uint8_t iphc3[3] = {0x00, 0x0b, 0x00};
|
|
struct pico_ip6 mcast3 = {{0xFF,0x02,0,0,0,0,0,0 ,0,0,0,0,0,0,0,5}};
|
|
uint8_t buf3[] = {5};
|
|
|
|
uint8_t buf[PICO_SIZE_IP6] = { 0 };
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("48-bit compressed address\n");
|
|
ret = decompressor_dst(buf,buf1,iphc1,NULL, &mac,&dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == ret, test, "Should've returned compressed length of 6, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(mcast1.addr, buf, PICO_SIZE_IP6), test, "Should've correctly decompressed the mcast address");
|
|
|
|
TRYING("32-bit compressed address\n");
|
|
ret = decompressor_dst(buf,buf2,iphc2,NULL, &mac,&dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == ret, test, "Should've returned compressed length of 4, ret = %d",ret);
|
|
FAIL_UNLESS(0 == memcmp(mcast2.addr, buf, PICO_SIZE_IP6), test, "Should've correctly decompressed 32-bit mcast address");
|
|
|
|
TRYING("8-bit compressed address\n");
|
|
ret = decompressor_dst(buf,buf3, iphc3, NULL, &mac, &dev);
|
|
OUTPUT();
|
|
dbg_buffer(buf, PICO_SIZE_IP6);
|
|
RESULTS();
|
|
FAIL_UNLESS(1 == ret, test, "Should've returned compressed length of 1, ret = %d", ret);
|
|
FAIL_UNLESS(0 == memcmp(mcast3.addr, buf, PICO_SIZE_IP6), test, "Should've correctly decompressed 8-bit mcast address");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
static const unsigned char ipv6_frame[61] = {
|
|
0x60, 0x00, 0x00, 0x00, 0x00, 0x15, 0x3c, 0xff, /* `.....<. */
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
|
|
0x02, 0x80, 0xe1, 0x03, 0x00, 0x00, 0x9d, 0x00, /* ........ */
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
|
|
0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x65, 0x63, /* ......ec */
|
|
0x11, 0x00, 0x1e, 0x00, 0x01, 0x02, 0x00, 0x00, /* ........ */
|
|
0x4d, 0x4c, 0x4d, 0x4c, 0x00, 0x0d, 0x7b, 0x50, /* MLML..{P */
|
|
0xff, 0x00, 0x01, 0x01, 0x08 /* ..... */
|
|
};
|
|
|
|
static const unsigned char lowpan_frame[18] = {
|
|
0x7f, 0x33, 0xe7, 0x02, 0x1e, 0x00, 0xf0,
|
|
0x4d, 0x4c, 0x4d, 0x4c, 0x7b, 0x50, 0xff, 0x00,
|
|
0x01, 0x01, 0x08
|
|
};
|
|
|
|
static const unsigned char comp_frame[22] = {
|
|
0x7f, 0x33, 0xe7, 0x06, 0x1e, 0x00, 0x01, 0x02,
|
|
0x00, 0x00, 0xf0, 0x4d, 0x4c, 0x4d, 0x4c, 0x7b,
|
|
0x50, 0xff, 0x00, 0x01, 0x01, 0x08
|
|
};
|
|
|
|
START_TEST(tc_compressor_iphc)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(61);
|
|
union pico_ll_addr src = { .pan = {.addr.data = {0x00,0x80,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_EXT } };
|
|
union pico_ll_addr dst = { .pan = {.addr.data = {0x65,0x63,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_SHORT } };
|
|
int compressed_len = 0;
|
|
struct pico_device dev;
|
|
uint8_t *buf = NULL;
|
|
uint8_t nh;
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
memcpy(f->buffer, ipv6_frame, 61);
|
|
f->net_hdr = f->buffer;
|
|
f->transport_hdr = f->buffer + 48;
|
|
f->dev = &dev;
|
|
f->src = src;
|
|
f->dst = dst;
|
|
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("To compress a IPv6 frame from a sample capture\n");
|
|
buf = compressor_iphc(f, &compressed_len, &nh);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 42);
|
|
RESULTS();
|
|
FAIL_UNLESS(2 == compressed_len, test, "Should have returned compressed_len of 2, compressed_len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, lowpan_frame, (size_t)compressed_len), test, "Should've compressed frame correctly");
|
|
pico_frame_discard(f);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_iphc)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(2);
|
|
union pico_ll_addr src = { .pan = {.addr.data = {0x00,0x80,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_EXT } };
|
|
union pico_ll_addr dst = { .pan = {.addr.data = {0x65,0x63,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_SHORT } };
|
|
struct pico_device dev;
|
|
int compressed_len = 0;
|
|
uint8_t *buf = NULL;
|
|
uint8_t hdr[40] = {
|
|
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* `.....<. */
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
|
|
0x02, 0x80, 0xe1, 0x03, 0x00, 0x00, 0x9d, 0x00, /* ........ */
|
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
|
|
0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x65, 0x63 };
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
memcpy(f->buffer, lowpan_frame, 2);
|
|
f->net_hdr = f->buffer;
|
|
f->dev = &dev;
|
|
f->src = src;
|
|
f->dst = dst;
|
|
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("To decompress a 6LoWPAN frame from a sampel capture\n");
|
|
buf = decompressor_iphc(f, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 40);
|
|
RESULTS();
|
|
FAIL_UNLESS(2 == compressed_len, test, "Should've returned compressed_len of 2, compressed_len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, hdr, 40), test, "Should've correctly decompressed the 6LoWPAN frame");
|
|
pico_frame_discard(f);
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_nhc_udp)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(8);
|
|
int compressed_len = 0;
|
|
uint8_t *buf = NULL;
|
|
|
|
uint8_t udp1[8] = {0x4d, 0x4c, 0x4d, 0x4c, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp1[] = {0xf0, 0x4d, 0x4c, 0x4d, 0x4c, 0x7b, 0x50};
|
|
|
|
uint8_t udp2[8] = {0xF0, 0xb1, 0xF0, 0xb2, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp2[] = {0xf3, 0x12, 0x7b, 0x50};
|
|
|
|
uint8_t udp3[8] = {0xF0, 0xb1, 0x4d, 0x4c, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp3[] = {0xf2, 0xb1, 0x4d, 0x4c, 0x7b, 0x50};
|
|
|
|
uint8_t udp4[8] = {0x4d, 0x4c, 0xF0, 0xb2, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp4[] = {0xf1, 0x4d, 0x4c, 0xb2, 0x7b, 0x50};
|
|
|
|
f->transport_hdr = f->buffer;
|
|
|
|
STARTING();
|
|
|
|
TRYING("To compress a UDP header from a sample capture\n");
|
|
memcpy(f->buffer, udp1, 8);
|
|
buf = compressor_nhc_udp(f, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 7);
|
|
RESULTS();
|
|
FAIL_UNLESS(7 == compressed_len, test, "Should've returned compressed_len of 7, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, comp1, 7), test, "Should've correctly compressed UDP header");
|
|
|
|
TRYING("To compress a UDP header from a sample capture with both compressible addresses\n");
|
|
memcpy(f->buffer, udp2, 8);
|
|
buf = compressor_nhc_udp(f, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 4);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == compressed_len, test, "Should've returned compressed_len of 4, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, comp2, 4), test, "should've correctly compressed UDP header");
|
|
|
|
TRYING("To compress a UDP header from a sample capture with compressible source\n");
|
|
memcpy(f->buffer, udp3, 8);
|
|
buf = compressor_nhc_udp(f, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 6);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == compressed_len, test, "Should've returned compressed_len of 6, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, comp3, 6), test, "should've correctly compressed UDP header");
|
|
|
|
TRYING("To compress a UDP header from a sample capture with compressible destination\n");
|
|
memcpy(f->buffer, udp4, 8);
|
|
buf = compressor_nhc_udp(f, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 6);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == compressed_len, test, "Should've returned compressed_len of 6, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, comp4, 6), test, "should've correctly compressed UDP header");
|
|
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_nhc_udp)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(9);
|
|
int compressed_len = 0;
|
|
uint8_t *buf = NULL;
|
|
|
|
uint8_t udp1[8] = {0x4d, 0x4c, 0x4d, 0x4c, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp1[] = {0xf0, 0x4d, 0x4c, 0x4d, 0x4c, 0x7b, 0x50};
|
|
|
|
uint8_t udp2[8] = {0xF0, 0xb1, 0xF0, 0xb2, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp2[] = {0xf3, 0x12, 0x7b, 0x50};
|
|
|
|
uint8_t udp3[8] = {0xF0, 0xb1, 0x4d, 0x4c, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp3[] = {0xf2, 0xb1, 0x4d, 0x4c, 0x7b, 0x50};
|
|
|
|
uint8_t udp4[8] = {0x4d, 0x4c, 0xF0, 0xb2, 0x00, 0x0d, 0x7b, 0x50};
|
|
uint8_t comp4[] = {0xf1, 0x4d, 0x4c, 0xb2, 0x7b, 0x50};
|
|
|
|
f->transport_hdr = f->buffer;
|
|
f->net_len = PICO_SIZE_IP6HDR;
|
|
|
|
STARTING();
|
|
|
|
TRYING("To decompress NH_UDP header with inline addresses\n");
|
|
memcpy(f->buffer, comp1, 7);
|
|
f->len = 12;
|
|
buf = decompressor_nhc_udp(f, 0, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 8);
|
|
RESULTS();
|
|
FAIL_UNLESS(7 == compressed_len, test, "Should've returned compressed_len of 7, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, udp1, 8), test, "Should've correctly compressed UDP header");
|
|
|
|
TRYING("To decompress NHC_UDP header with both addresses compressed\n");
|
|
memcpy(f->buffer, comp2, 4);
|
|
f->len = 9;
|
|
buf = decompressor_nhc_udp(f, 0, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 8);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == compressed_len, test, "Should've returned compressed_len of 4, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, udp2, 8), test, "Should've correctly decompressed UDP header");
|
|
|
|
TRYING("To decompress NHC_UDP header with both addresses compressed\n");
|
|
memcpy(f->buffer, comp3, 6);
|
|
f->len = 11;
|
|
buf = decompressor_nhc_udp(f, 0, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 8);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == compressed_len, test, "Should've returned compressed_len of 6, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, udp3, 8), test, "Should've correctly decompressed UDP header");
|
|
|
|
TRYING("To decompress NHC_UDP header with both addresses compressed\n");
|
|
memcpy(f->buffer, comp4, 6);
|
|
f->len = 11;
|
|
buf = decompressor_nhc_udp(f, 0, &compressed_len);
|
|
FAIL_UNLESS(buf, test, "Should've at least returned a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 8);
|
|
RESULTS();
|
|
FAIL_UNLESS(6 == compressed_len, test, "Should've returned compressed_len of 6, len = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, udp4, 8), test, "Should've correctly decompressed UDP header");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_compressor_nhc_ext)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(9);
|
|
uint8_t nh = PICO_IPV6_EXTHDR_DESTOPT;
|
|
int compressed_len = 0;
|
|
uint8_t *buf = NULL;
|
|
|
|
uint8_t ext1[8] = {0x11, 0x00, 0x1e, 0x00, 0x01, 0x02, 0x00, 0x00};
|
|
uint8_t nhc1[8] = {0xe7, 0x06, 0x1e, 0x00, 0x01, 0x02, 0x00, 0x00};
|
|
|
|
f->net_hdr = f->buffer;
|
|
|
|
STARTING();
|
|
|
|
TRYING("With DSTOPT extension header\n");
|
|
memcpy(f->buffer, ext1, 8);
|
|
buf = compressor_nhc_ext(f, &compressed_len, &nh);
|
|
FAIL_UNLESS(buf, test, "Should've at least returend a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, (size_t)compressed_len);
|
|
RESULTS();
|
|
FAIL_UNLESS(8 == compressed_len, test, "Should've returned length of 8, ret = %d", compressed_len);
|
|
FAIL_UNLESS(PICO_PROTO_UDP == nh, test, "Should've updated next header to %02X, ret = %02X", PICO_PROTO_UDP, nh);
|
|
FAIL_UNLESS(0 == memcmp(buf, nhc1, (size_t)compressed_len), test, "Should've correctly compressed next header");
|
|
|
|
pico_frame_discard(f);
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_decompressor_nhc_ext)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(9);
|
|
int compressed_len = 0, decomp;
|
|
uint8_t *buf = NULL;
|
|
|
|
uint8_t ext1[8] = {0x11, 0x00, 0x1e, 0x00, 0x01, 0x02, 0x00, 0x00};
|
|
uint8_t nhc1[8] = {0xe7, 0x02, 0x1e, 0x00, 0xf0 /* udp dispatch */};
|
|
|
|
f->net_hdr = f->buffer;
|
|
|
|
STARTING();
|
|
|
|
TRYING("nhc_ext compressed header with dstopt extension header\n");
|
|
memcpy(f->buffer, nhc1, 5);
|
|
buf = decompressor_nhc_ext(f, &compressed_len, &decomp);
|
|
FAIL_UNLESS(buf, test, "should've at least returend a buffer");
|
|
OUTPUT();
|
|
dbg_buffer(buf, 8);
|
|
RESULTS();
|
|
FAIL_UNLESS(4 == compressed_len, test, "should've returned length of 4, ret = %d", compressed_len);
|
|
FAIL_UNLESS(0 == memcmp(buf, ext1, 8), test, "should've correctly decompressed next header");
|
|
|
|
pico_frame_discard(f);
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_pico_iphc_compress)
|
|
{
|
|
int test = 1;
|
|
struct pico_frame *f = pico_frame_alloc(61);
|
|
union pico_ll_addr src = { .pan = {.addr.data = {0x00,0x80,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_EXT } };
|
|
union pico_ll_addr dst = { .pan = {.addr.data = {0x65,0x63,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_SHORT } };
|
|
struct pico_device dev;
|
|
struct pico_frame *new = NULL;
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
memcpy(f->buffer, ipv6_frame, 61);
|
|
f->net_hdr = f->buffer;
|
|
f->net_len = 48;
|
|
f->transport_hdr = f->buffer + 48;
|
|
f->transport_len = 8;
|
|
f->len = 61;
|
|
f->dev = &dev;
|
|
f->src = src;
|
|
f->dst = dst;
|
|
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("Trying to compress an IPv6 frame from an example capture\n");
|
|
new = pico_iphc_compress(f);
|
|
FAIL_UNLESS(new, test, "Should've at least returned a frame");
|
|
OUTPUT();
|
|
dbg_buffer(new->net_hdr, new->len);
|
|
RESULTS();
|
|
FAIL_UNLESS(22 == new->len, test, "Should have returned length of 22, len = %d", new->len);
|
|
FAIL_UNLESS(0 == memcmp(new->net_hdr, comp_frame, 22), test, "Should've compressed the frame correctly");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(tc_pico_iphc_decompress)
|
|
{
|
|
int test = 0;
|
|
struct pico_frame *f = pico_frame_alloc(61);
|
|
union pico_ll_addr src = { .pan = {.addr.data = {0x00,0x80,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_EXT } };
|
|
union pico_ll_addr dst = { .pan = {.addr.data = {0x65,0x63,0xe1,0x03,0x00,0x00,0x9d,0x00}, .mode = AM_6LOWPAN_SHORT } };
|
|
struct pico_device dev;
|
|
struct pico_frame *new = NULL;
|
|
|
|
dev.mode = LL_MODE_IEEE802154;
|
|
memcpy(f->buffer, comp_frame, 22);
|
|
f->net_hdr = f->buffer;
|
|
f->net_len = 22;
|
|
f->len = 22;
|
|
f->dev = &dev;
|
|
f->src = src;
|
|
f->dst = dst;
|
|
|
|
STARTING();
|
|
pico_stack_init();
|
|
|
|
TRYING("Trying to decompress a 6LoWPAN frame from an example capture\n");
|
|
new = pico_iphc_decompress(f);
|
|
FAIL_UNLESS(new, test, "Should've at least returned a frame");
|
|
OUTPUT();
|
|
dbg_buffer(new->net_hdr, new->len);
|
|
RESULTS();
|
|
FAIL_UNLESS(61 == new->len, test, "Should've returned a length of 61, len = %d", new->len);
|
|
dbg_buffer(new->net_hdr, new->len);
|
|
FAIL_UNLESS(0 == memcmp(new->net_hdr, ipv6_frame, new->len), test, "Should've decompressed the frame correctly");
|
|
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
#endif
|
|
|
|
static struct pico_frame *rx = NULL;
|
|
static uint8_t tx[1500];
|
|
static int rx_called = 0;
|
|
static int tx_called = 0;
|
|
static uint8_t tx_len = 0;
|
|
|
|
int pico_datalink_send(struct pico_frame *f) {
|
|
dbg("Datalink_send called!\n");
|
|
if (++tx_called == 2) {
|
|
memcpy(tx, f->start, f->len);
|
|
OUTPUT();
|
|
dbg("tx: ");
|
|
dbg_buffer(tx, tx_len);
|
|
}
|
|
|
|
if (f->dev->eth) {
|
|
/* If device has stack with datalink-layer pass frame through it */
|
|
if (LL_MODE_IEEE802154 == f->dev->mode) {
|
|
return pico_enqueue(pico_proto_6lowpan.q_out, f);
|
|
} else {
|
|
return pico_enqueue(pico_proto_ethernet.q_out, f);
|
|
}
|
|
} else {
|
|
/* non-ethernet: no post-processing needed */
|
|
return pico_sendto_dev(f);
|
|
}
|
|
}
|
|
|
|
int32_t pico_network_receive(struct pico_frame *f)
|
|
{
|
|
dbg("Network_receive called!\n");
|
|
if (++rx_called == 2)
|
|
rx = pico_frame_copy(f);
|
|
|
|
printf("RCVD frame at network layer \n");
|
|
dbg_buffer(f->buffer, f->buffer_len);
|
|
return (int32_t)f->buffer_len;
|
|
}
|
|
|
|
#define NUM_PING 1
|
|
|
|
#ifdef PICO_SUPPORT_IPV6
|
|
static void cb_ping6(struct pico_icmp6_stats *s)
|
|
{
|
|
char host[50];
|
|
pico_ipv6_to_string(host, s->dst.addr);
|
|
if (s->err == 0) {
|
|
dbg("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size, host, s->seq,
|
|
s->ttl, (long unsigned int)s->time);
|
|
if (s->seq >= NUM_PING)
|
|
exit(0);
|
|
} else {
|
|
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
|
|
exit(1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void ping_abort_timer(pico_time now, void *_id)
|
|
{
|
|
int *id = (int *) _id;
|
|
IGNORE_PARAMETER(now);
|
|
printf("Ping: aborting...\n");
|
|
pico_icmp6_ping_abort(*id);
|
|
}
|
|
|
|
/* Copy a string until the separator,
|
|
terminate it and return the next index,
|
|
or NULL if it encounters a EOS */
|
|
static char *cpy_arg(char **dst, char *str)
|
|
{
|
|
char *p, *nxt = NULL;
|
|
char *start = str;
|
|
char *end = start + strlen(start);
|
|
char sep = ',';
|
|
|
|
p = str;
|
|
while (p) {
|
|
if ((*p == sep) || (*p == '\0')) {
|
|
*p = (char)0;
|
|
nxt = p + 1;
|
|
if ((*nxt == 0) || (nxt >= end))
|
|
nxt = 0;
|
|
|
|
printf("dup'ing %s\n", start);
|
|
*dst = strdup(start);
|
|
break;
|
|
}
|
|
|
|
p++;
|
|
}
|
|
return nxt;
|
|
}
|
|
|
|
static void app_ping(char *arg)
|
|
{
|
|
char *dest = NULL;
|
|
char *next = NULL;
|
|
char *abort = NULL;
|
|
char *delay = NULL;
|
|
char *asize = NULL;
|
|
static int id;
|
|
int timeout = 0;
|
|
int size = 64;
|
|
|
|
next = cpy_arg(&dest, arg);
|
|
if (!dest) {
|
|
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
|
|
exit(255);
|
|
}
|
|
if (next) {
|
|
next = cpy_arg(&asize, next);
|
|
size = atoi(asize);
|
|
if (size <= 0) {
|
|
size = 64; /* Default */
|
|
}
|
|
}
|
|
|
|
if (next) {
|
|
next = cpy_arg(&abort, next);
|
|
if (strlen(abort) > 0) {
|
|
printf("Got arg: '%s'\n", abort);
|
|
timeout = atoi(abort);
|
|
if (timeout < 0) {
|
|
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
|
|
exit(255);
|
|
}
|
|
printf("Aborting ping after %d seconds\n", timeout);
|
|
}
|
|
}
|
|
|
|
if (next) {
|
|
next = cpy_arg(&delay, next);
|
|
if (strlen(delay) > 0) {
|
|
uint32_t initial_delay = (uint32_t) atoi(delay);
|
|
if (initial_delay > 0) {
|
|
printf("Initial delay: %u seconds\n", initial_delay);
|
|
initial_delay = PICO_TIME_MS() + (initial_delay * 1000);
|
|
while (PICO_TIME_MS() < initial_delay) {
|
|
pico_stack_tick();
|
|
usleep(10000);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("Starting ping.\n");
|
|
|
|
id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, size, cb_ping6, NULL);
|
|
if (timeout > 0) {
|
|
printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
|
|
if (!pico_timer_add((pico_time)(timeout * 1000), ping_abort_timer, &id)) {
|
|
printf("Failed to set ping abort timeout, aborting ping\n");
|
|
ping_abort_timer((pico_time)0, &id);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/* free copied args */
|
|
if (dest)
|
|
free(dest);
|
|
|
|
if (abort)
|
|
free(abort);
|
|
}
|
|
|
|
START_TEST(tc_tx_rx)
|
|
{
|
|
int test = 0;
|
|
struct pico_device *dev = NULL;
|
|
uint8_t n_id, n_area0, n_area1;
|
|
struct pico_ip6 myaddr, pan, netmask;
|
|
const char pan_addr[] = "2aaa:abcd::0";
|
|
const char pan_netmask[] = "ffff:ffff:ffff:ffff::0";
|
|
|
|
const char *id = "3";
|
|
const char *area0 = "1";
|
|
const char *area1 = "0";
|
|
char *dump = (char *)strdup("build/test/unit_6lowpan.pcap");
|
|
char *arg = (char *)strdup("2aaa:abcd:0000:0000:0200:00aa:ab00:0001,1450,0,1,");
|
|
|
|
STARTING();
|
|
|
|
n_id = (uint8_t) atoi(id);
|
|
n_area0 = (uint8_t) atoi(area0);
|
|
n_area1 = (uint8_t) atoi(area1);
|
|
|
|
/* Initialize picoTCP */
|
|
pico_stack_init();
|
|
|
|
pico_string_to_ipv6(pan_addr, myaddr.addr);
|
|
pico_string_to_ipv6(pan_addr, pan.addr);
|
|
pico_string_to_ipv6(pan_netmask, netmask.addr);
|
|
myaddr.addr[8] = 0x02;
|
|
myaddr.addr[11] = 0xaa;
|
|
myaddr.addr[12] = 0xab;
|
|
myaddr.addr[15] = n_id;
|
|
|
|
printf("%d:%d:%d\n", n_id, n_area0, n_area1);
|
|
dev = pico_radiotest_create(n_id, n_area0, n_area1, 1, (char *)dump);
|
|
if (!dev) {
|
|
exit(1);
|
|
}
|
|
|
|
printf("Radiotest created.\n");
|
|
|
|
/* Add a routable link */
|
|
pico_ipv6_link_add(dev, myaddr, netmask);
|
|
|
|
/* Start ping-application */
|
|
app_ping((char *)arg);
|
|
|
|
printf("%s: launching PicoTCP loop\n", __FUNCTION__);
|
|
while(!rx) {
|
|
pico_stack_tick();
|
|
usleep(2000);
|
|
}
|
|
OUTPUT();
|
|
dbg("RX: ");
|
|
dbg_buffer(rx->start, rx->len);
|
|
RESULTS();
|
|
tx[0] |= 0x60;
|
|
FAIL_UNLESS(0 == memcmp(rx->start, tx, rx->len), test, "Should've received exactly the same frame as was transmitted");
|
|
|
|
ENDING(test);
|
|
}
|
|
END_TEST
|
|
|
|
static Suite *pico_suite(void)
|
|
{
|
|
Suite *s = suite_create("PicoTCP");
|
|
|
|
TCase *TCase_compare_prefix = tcase_create("Unit test for compare_prefix");
|
|
TCase *TCase_compare_ctx = tcase_create("Unit test for compare_ctx");
|
|
TCase *TCase_ctx_lookup = tcase_create("Unit test for ctx_lookup");
|
|
|
|
/*******************************************************************************
|
|
* IPHC
|
|
******************************************************************************/
|
|
#ifdef PICO_6LOWPAN_IPHC_ENABLED
|
|
TCase *TCase_compressor_vtf = tcase_create("Unit test for compressor_vtf");
|
|
TCase *TCase_decompressor_vtf = tcase_create("Unit test for decompressor_vtf");
|
|
TCase *TCase_compressor_nh = tcase_create("Unit test for compressor_nh");
|
|
TCase *TCase_decompressor_nh = tcase_create("Unit test for decompressor_nh");
|
|
TCase *TCase_compressor_hl = tcase_create("Unit test for compressor_hl");
|
|
TCase *TCase_decompressor_hl = tcase_create("Unit test for decompressor_hl");
|
|
TCase *TCase_addr_comp_prefix = tcase_create("Unit test for addr_comp_prefix");
|
|
TCase *TCase_addr_comp_mode = tcase_create("Unit test for addr_comp_mode");
|
|
TCase *TCase_compressor_src = tcase_create("Unit test for compressor_src");
|
|
TCase *TCase_decompressor_src = tcase_create("Unit test for decompressor_src");
|
|
TCase *TCase_compressor_dst = tcase_create("Unit test for compressor_dst");
|
|
TCase *TCase_decompressor_dst = tcase_create("Unit test for decompressor_dst");
|
|
TCase *TCase_compressor_iphc = tcase_create("Unit test for compressor_iphc");
|
|
TCase *TCase_decompressor_iphc = tcase_create("Unit test for decompressor_iphc");
|
|
TCase *TCase_compressor_nhc_udp = tcase_create("Unit test for compressor_nhc_udp");
|
|
TCase *TCase_decompressor_nhc_udp = tcase_create("Unit test for decompressor_nhc_udp");
|
|
TCase *TCase_compressor_nhc_ext = tcase_create("Unit test for compressor_nhc_ext");
|
|
TCase *TCase_decompressor_nhc_ext = tcase_create("Unit test for decompressor_nhc_ext");
|
|
TCase *TCase_pico_iphc_compress = tcase_create("Unit test for pico_iphc_compress");
|
|
TCase *TCase_pico_iphc_decompress = tcase_create("Unit test for pico_iphc_decompress");
|
|
#endif
|
|
|
|
TCase *TCase_tx_rx = tcase_create("Unit test for tx_rx");
|
|
|
|
tcase_add_test(TCase_compare_prefix, tc_compare_prefix);
|
|
suite_add_tcase(s, TCase_compare_prefix);
|
|
tcase_add_test(TCase_compare_ctx ,tc_compare_ctx);
|
|
suite_add_tcase(s, TCase_compare_ctx);
|
|
tcase_add_test(TCase_ctx_lookup ,tc_ctx_lookup);
|
|
suite_add_tcase(s, TCase_ctx_lookup);
|
|
|
|
/*******************************************************************************
|
|
* IPHC
|
|
******************************************************************************/
|
|
#ifdef PICO_6LOWPAN_IPHC_ENABLED
|
|
tcase_add_test(TCase_compressor_vtf, tc_compressor_vtf);
|
|
suite_add_tcase(s, TCase_compressor_vtf);
|
|
tcase_add_test(TCase_decompressor_vtf, tc_decompressor_vtf);
|
|
suite_add_tcase(s, TCase_decompressor_vtf);
|
|
tcase_add_test(TCase_compressor_nh, tc_compressor_nh);
|
|
suite_add_tcase(s, TCase_compressor_nh);
|
|
tcase_add_test(TCase_decompressor_nh, tc_decompressor_nh);
|
|
suite_add_tcase(s, TCase_decompressor_nh);
|
|
tcase_add_test(TCase_compressor_hl, tc_compressor_hl);
|
|
suite_add_tcase(s, TCase_compressor_hl);
|
|
tcase_add_test(TCase_decompressor_hl, tc_decompressor_hl);
|
|
suite_add_tcase(s, TCase_decompressor_hl);
|
|
tcase_add_test(TCase_addr_comp_prefix, tc_addr_comp_prefix);
|
|
suite_add_tcase(s, TCase_addr_comp_prefix);
|
|
tcase_add_test(TCase_addr_comp_mode, tc_addr_comp_mode);
|
|
suite_add_tcase(s, TCase_addr_comp_mode);
|
|
tcase_add_test(TCase_compressor_src, tc_compressor_src);
|
|
suite_add_tcase(s, TCase_compressor_src);
|
|
tcase_add_test(TCase_decompressor_src, tc_decompressor_src);
|
|
suite_add_tcase(s, TCase_decompressor_src);
|
|
tcase_add_test(TCase_compressor_dst, tc_compressor_dst);
|
|
suite_add_tcase(s, TCase_compressor_dst);
|
|
tcase_add_test(TCase_decompressor_dst, tc_decompressor_dst);
|
|
suite_add_tcase(s, TCase_decompressor_dst);
|
|
tcase_add_test(TCase_compressor_iphc, tc_compressor_iphc);
|
|
suite_add_tcase(s, TCase_compressor_iphc);
|
|
tcase_add_test(TCase_decompressor_iphc, tc_decompressor_iphc);
|
|
suite_add_tcase(s, TCase_decompressor_iphc);
|
|
tcase_add_test(TCase_compressor_nhc_udp, tc_compressor_nhc_udp);
|
|
suite_add_tcase(s, TCase_compressor_nhc_udp);
|
|
tcase_add_test(TCase_decompressor_nhc_udp, tc_decompressor_nhc_udp);
|
|
suite_add_tcase(s, TCase_decompressor_nhc_udp);
|
|
tcase_add_test(TCase_compressor_nhc_ext, tc_compressor_nhc_ext);
|
|
suite_add_tcase(s, TCase_compressor_nhc_ext);
|
|
tcase_add_test(TCase_decompressor_nhc_ext, tc_decompressor_nhc_ext);
|
|
suite_add_tcase(s, TCase_decompressor_nhc_ext);
|
|
tcase_add_test(TCase_pico_iphc_compress, tc_pico_iphc_compress);
|
|
suite_add_tcase(s, TCase_pico_iphc_compress);
|
|
tcase_add_test(TCase_pico_iphc_decompress, tc_pico_iphc_decompress);
|
|
suite_add_tcase(s, TCase_pico_iphc_decompress);
|
|
#endif
|
|
|
|
tcase_add_test(TCase_tx_rx ,tc_tx_rx);
|
|
suite_add_tcase(s, TCase_tx_rx);
|
|
|
|
return s;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int fails;
|
|
Suite *s = pico_suite();
|
|
SRunner *sr = srunner_create(s);
|
|
srunner_run_all(sr, CK_NORMAL);
|
|
fails = srunner_ntests_failed(sr);
|
|
srunner_free(sr);
|
|
return fails;
|
|
}
|