/* * 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 */ #include #include #include "embUnit.h" #include "net/ipv6/addr.h" #include "net/ipv6/hdr.h" #include "net/gnrc/pktbuf.h" #include "net/protnum.h" #include "net/inet_csum.h" #include "unittests-constants.h" #include "tests-ipv6_hdr.h" #define OTHER_BYTE (TEST_UINT16 >> 8) #define DEFAULT_TEST_SRC { { \ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f \ } \ } #define DEFAULT_TEST_DST { { \ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f \ } \ } static void test_ipv6_hdr_set_version(void) { uint8_t val[] = { TEST_UINT8 }; ipv6_hdr_set_version((ipv6_hdr_t *)val); /* * Header format: * 1 * +----+-- * | 6 | * +----+-- */ TEST_ASSERT_EQUAL_INT(0x60, val[0] & 0xf0); TEST_ASSERT_EQUAL_INT(TEST_UINT8 & 0x0f, val[0] & 0x0f); } static void test_ipv6_hdr_get_version(void) { uint8_t val[] = { TEST_UINT8 }; /* * Header format: * 8 * +----+---- * | 6 | * +----+---- */ TEST_ASSERT_EQUAL_INT(TEST_UINT8 >> 4, ipv6_hdr_get_version((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_is_ipv6_hdr__false(void) { /* * Header format: * 8 * +----+---- * | 6 | * +----+---- */ uint8_t val[] = { 0 }; TEST_ASSERT(!ipv6_hdr_is((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_is_ipv6_hdr__true(void) { /* * Header format: * 8 * +----+---- * | 6 | * +----+---- */ uint8_t val[] = { 0x60 | (TEST_UINT8 & 0x0f) }; TEST_ASSERT(ipv6_hdr_is((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_set_tc(void) { uint8_t val[] = { TEST_UINT8, 0 }; ipv6_hdr_set_tc((ipv6_hdr_t *)val, OTHER_BYTE); /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- */ TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf0) | (OTHER_BYTE >> 4), val[0]); TEST_ASSERT_EQUAL_INT((OTHER_BYTE << 4) & 0xf0, val[1]); } static void test_ipv6_hdr_set_tc_ecn(void) { uint8_t val[] = { TEST_UINT8 }; ipv6_hdr_set_tc_ecn((ipv6_hdr_t *)val, OTHER_BYTE); /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- * / \ * 8 12 * +----+------------+ * | ecn| dscp | * +----+------------+ */ TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf3) | ((OTHER_BYTE & 0x03) << 2), val[0]); } static void test_ipv6_hdr_set_tc_dscp(void) { uint8_t val[] = { TEST_UINT8, 0 }; ipv6_hdr_set_tc_dscp((ipv6_hdr_t *)val, OTHER_BYTE); /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- * / \ * 8 12 * +----+------------+ * | ecn| dscp | * +----+------------+ */ TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xfc) | ((OTHER_BYTE & 0x30) >> 4), val[0]); TEST_ASSERT_EQUAL_INT((OTHER_BYTE & 0x0f) << 4, val[1]); } static void test_ipv6_hdr_get_tc(void) { uint8_t val[] = { TEST_UINT8, OTHER_BYTE }; /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- */ TEST_ASSERT_EQUAL_INT(((TEST_UINT8 << 4) & 0xf0) | (OTHER_BYTE >> 4), ipv6_hdr_get_tc((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_get_tc_ecn(void) { uint8_t val[] = { TEST_UINT8 }; /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- * / \ * 8 12 * +----+------------+ * | ecn| dscp | * +----+------------+ */ TEST_ASSERT_EQUAL_INT(TEST_UINT8 & 0x03, ipv6_hdr_get_tc_ecn((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_get_tc_dscp(void) { uint8_t val[] = { TEST_UINT8, OTHER_BYTE }; /* * Header format: * 8 * +----+--------+-- * | 6 | tc | * +----+--------+-- * / \ * 8 12 * +----+------------+ * | ecn| dscp | * +----+------------+ */ TEST_ASSERT_EQUAL_INT(((TEST_UINT8 & 0x03) << 4) | ((OTHER_BYTE & 0xf0) >> 4), ipv6_hdr_get_tc_dscp((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_set_fl(void) { uint8_t val[] = { 0, TEST_UINT8, 0, 0 }; ipv6_hdr_set_fl((ipv6_hdr_t *)val, TEST_UINT32); /* * Header format: * 8 16 24 32 * +----+--------+--------------------+ * | 6 | tc | flow label | * +----+--------+--------------------+ */ TEST_ASSERT_EQUAL_INT(0, val[0]); TEST_ASSERT_EQUAL_INT((TEST_UINT8 & 0xf0) | ((TEST_UINT32 & 0x000f0000) >> 16), val[1]); TEST_ASSERT_EQUAL_INT((TEST_UINT32 & 0x0000ff00) >> 8, val[2]); TEST_ASSERT_EQUAL_INT((TEST_UINT32 & 0x000000ff), val[3]); } static void test_ipv6_hdr_get_fl(void) { uint8_t val[] = { TEST_UINT8, OTHER_BYTE, 0, 0 }; /* * Header format: * 8 16 24 32 * +----+--------+--------------------+ * | 6 | tc | flow label | * +----+--------+--------------------+ */ TEST_ASSERT_EQUAL_INT((uint32_t)(OTHER_BYTE & 0x0f) << 16, ipv6_hdr_get_fl((ipv6_hdr_t *)val)); } static void test_ipv6_hdr_inet_csum__initial_sum_overflows(void) { uint16_t sum = 0xffff; uint16_t res = 0, payload_len = 0; uint8_t val[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x3a, 0x40, /* IPv6 header */ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x86, 0xcd, 0xff, 0xfe, 0x0f, 0xce, 0x49, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xaa, 0x2d, 0xff, 0xfe, 0x44, 0x43, 0xac }; /* calculate checksum of pseudo header */ res = ipv6_hdr_inet_csum(sum, (ipv6_hdr_t *)&val, PROTNUM_ICMPV6, payload_len); res = ~res; /* take 1's-complement for correct checksum */ TEST_ASSERT_EQUAL_INT(0x1749, res); } static void test_ipv6_hdr_inet_csum__initial_sum_0(void) { /* source: https://www.cloudshark.org/captures/ea72fbab241b (No. 56) */ uint16_t res = 0, payload_len; uint8_t val[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3a, 0xff, /* IPv6 header */ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x6d, 0x8f, 0xff, 0xfe, 0x56, 0x30, 0x09, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x40, 0x58, 0x07, 0x08, /* ICMPv6 payload */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* set checksum to 0 */ 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x18, 0x3d, 0xdb, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x58, 0x6d, 0x8f, 0x56, 0x30, 0x09 }; payload_len = sizeof(val) - sizeof(ipv6_hdr_t); /* calculate checksum of pseudo header */ res = ipv6_hdr_inet_csum(0, (ipv6_hdr_t *)&val, PROTNUM_ICMPV6, payload_len); /* calculate checksum of payload */ res = inet_csum(res, val + sizeof(ipv6_hdr_t), payload_len); res = ~res; /* take 1's-complement for correct checksum */ TEST_ASSERT_EQUAL_INT(0xab32, res); } Test *tests_ipv6_hdr_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_ipv6_hdr_set_version), new_TestFixture(test_ipv6_hdr_get_version), new_TestFixture(test_ipv6_hdr_is_ipv6_hdr__false), new_TestFixture(test_ipv6_hdr_is_ipv6_hdr__true), new_TestFixture(test_ipv6_hdr_set_tc), new_TestFixture(test_ipv6_hdr_set_tc_ecn), new_TestFixture(test_ipv6_hdr_set_tc_dscp), new_TestFixture(test_ipv6_hdr_get_tc), new_TestFixture(test_ipv6_hdr_get_tc_ecn), new_TestFixture(test_ipv6_hdr_get_tc_dscp), new_TestFixture(test_ipv6_hdr_set_fl), new_TestFixture(test_ipv6_hdr_get_fl), new_TestFixture(test_ipv6_hdr_inet_csum__initial_sum_overflows), new_TestFixture(test_ipv6_hdr_inet_csum__initial_sum_0), }; EMB_UNIT_TESTCALLER(ipv6_hdr_tests, NULL, NULL, fixtures); return (Test *)&ipv6_hdr_tests; } void tests_ipv6_hdr(void) { TESTS_RUN(tests_ipv6_hdr_tests()); } /** @} */