/* * Copyright (C) 2016 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. */ /** * @{ * * @file * @author Martine Lenders */ #include #include "net/ipv6/addr.h" #include "net/gnrc/ipv6/nib.h" #include "net/gnrc/ipv6/nib/pl.h" #include "_nib-internal.h" #include "unittests-constants.h" #include "tests-gnrc_ipv6_nib.h" #define LINK_LOCAL_PREFIX { 0xfe, 0x08, 0, 0, 0, 0, 0, 0 } #define GLOBAL_PREFIX { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0 } #define L2ADDR { 0x90, 0xd5, 0x8e, 0x8c, 0x92, 0x43, 0x73, 0x5c } #define GLOBAL_PREFIX_LEN (30) #define IFACE (6) static void set_up(void) { evtimer_event_t *tmp; for (evtimer_event_t *ptr = _nib_evtimer.events; (ptr != NULL) && (tmp = (ptr->next), 1); ptr = tmp) { evtimer_del((evtimer_t *)(&_nib_evtimer), ptr); } _nib_init(); } /* * Tries to create a prefix list entry with the unspecified address (::) as * prefix. * Expected result: gnrc_ipv6_nib_pl_set() returns -EINVAL */ static void test_nib_pl_set__EINVAL_unspec_addr(void) { TEST_ASSERT_EQUAL_INT(-EINVAL, gnrc_ipv6_nib_pl_set(IFACE, &ipv6_addr_unspecified, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Tries to create a prefix list entry with a link-local prefix (fe80::) as * prefix. * Expected result: gnrc_ipv6_nib_pl_set() returns -EINVAL */ static void test_nib_pl_set__EINVAL_link_local(void) { TEST_ASSERT_EQUAL_INT(-EINVAL, gnrc_ipv6_nib_pl_set(IFACE, &ipv6_addr_link_local_prefix, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Tries to create a prefix list entry with the multicast address as * prefix. * Expected result: gnrc_ipv6_nib_pl_set() returns -EINVAL */ static void test_nib_pl_set__EINVAL_mc_addr(void) { TEST_ASSERT_EQUAL_INT(-EINVAL, gnrc_ipv6_nib_pl_set(IFACE, &ipv6_addr_all_nodes_link_local, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Tries to create multiple prefix list entries with prefix length 0 and > 128. * Expected result: gnrc_ipv6_nib_pl_set() always returns -EINVAL */ static void test_nib_pl_set__EINVAL_pfx_len(void) { static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX } } }; TEST_ASSERT_EQUAL_INT(-EINVAL, gnrc_ipv6_nib_pl_set(IFACE, &pfx, 0, UINT32_MAX, UINT32_MAX)); } #if GNRC_IPV6_NIB_NUMOF < GNRC_IPV6_NIB_OFFL_NUMOF #define MAX_NUMOF (GNRC_IPV6_NIB_NUMOF) #else /* GNRC_IPV6_NIB_NUMOF < GNRC_IPV6_NIB_OFFL_NUMOF */ #define MAX_NUMOF (GNRC_IPV6_NIB_OFFL_NUMOF) #endif /* * Creates MAX_NUMOF prefix list entries with different interfaces and then * tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_iface(void) { static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned iface = IFACE; for (unsigned i = 0; i < MAX_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); iface++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(iface, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Creates GNRC_IPV6_NIB_OFFL_NUMOF prefix list entries with different prefix of * the same length and then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_pfx(void) { ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; for (unsigned i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); pfx.u16[0].u16++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Creates GNRC_IPV6_NIB_OFFL_NUMOF prefix list entries with different prefix of * the same length and different interfaces and then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_iface_pfx(void) { ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned iface = IFACE; for (unsigned i = 0; i < MAX_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); iface++; pfx.u16[0].u16++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(iface, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); } /* * Creates GNRC_IPV6_NIB_OFFL_NUMOF prefix list entries with prefixes of * different length and then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_pfx_len(void) { static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned pfx_len = GLOBAL_PREFIX_LEN; for (unsigned i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); pfx_len--; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(IFACE, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } /* * Creates MAX_NUMOF prefix list entries with prefixes of different length and * different interfaces and then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_iface_pfx_len(void) { static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE; for (unsigned i = 0; i < MAX_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); pfx_len--; iface++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } /* * Creates GNRC_IPV6_NIB_OFFL_NUMOF prefix list entries with different prefixes * and then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_pfx_pfx_len(void) { ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned pfx_len = GLOBAL_PREFIX_LEN; for (unsigned i = 0; i < GNRC_IPV6_NIB_OFFL_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); pfx_len--; pfx.u16[0].u16++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(IFACE, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } /* * Creates MAX_NUMOF prefix list entries with different prefixes and different * interfaces then tries to create another one * Expected result: gnrc_ipv6_nib_pl_set() returns -ENOMEM */ static void test_nib_pl_set__ENOMEM_diff_iface_pfx_pfx_len(void) { ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE; for (unsigned i = 0; i < MAX_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); pfx_len--; pfx.u16[0].u16++; iface++; } TEST_ASSERT_EQUAL_INT(-ENOMEM, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } /* * Creates MAX_NUMOF prefix list entries with different prefixes and different * interfaces and then tries to add another equal to the last. * Expected result: should return not NULL (the last) */ static void test_nib_pl_set__success_duplicate(void) { ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE; for (unsigned i = 0; i < MAX_NUMOF; i++) { pfx_len--; pfx.u16[0].u16++; iface++; TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); } /* * Creates a prefix list entry then creates it again with a different valid and * preferred lifetime. * Expected result: should be able to be created and the lifetimes should have * been changed */ static void test_nib_pl_set__success_change(void) { gnrc_ipv6_nib_pl_t ple; void *iter_state = NULL; static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, TEST_UINT32, TEST_UINT32 - TEST_UINT8)); TEST_ASSERT(gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)); TEST_ASSERT(ple.valid_until != UINT32_MAX); TEST_ASSERT(ple.pref_until != UINT32_MAX); TEST_ASSERT(!gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)); } /* * Creates a prefix list entry then creates it again with a different valid and * preferred lifetime. * Expected result: a new entry should exist and contain the given prefix, * interface, and lifetimes */ static void test_nib_pl_set__success(void) { gnrc_ipv6_nib_pl_t ple; void *iter_state = NULL; static const ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); TEST_ASSERT(gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)); TEST_ASSERT(ipv6_addr_match_prefix(&ple.pfx, &pfx) >= GLOBAL_PREFIX_LEN); TEST_ASSERT_EQUAL_INT(GLOBAL_PREFIX_LEN, ple.pfx_len); TEST_ASSERT_EQUAL_INT(IFACE, ple.iface); TEST_ASSERT_EQUAL_INT(UINT32_MAX, ple.valid_until); TEST_ASSERT_EQUAL_INT(UINT32_MAX, ple.pref_until); TEST_ASSERT(!gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)); } /* * Creates MAX_NUMOF prefix list entries with different prefix and interfaces * and then tries to delete one with yet another prefix and interface. * Expected result: There should be still GNRC_IPV6_NIB_NUMOF entries in the * neigbor cache */ static void test_nib_pl_del__unknown(void) { void *iter_state = NULL; ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; gnrc_ipv6_nib_pl_t ple; unsigned pfx_len = GLOBAL_PREFIX_LEN, iface = IFACE, count = 0; for (unsigned i = 0; i < MAX_NUMOF; i++) { TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(iface, &pfx, pfx_len, UINT32_MAX, UINT32_MAX)); pfx_len--; pfx.u16[0].u16++; iface++; } gnrc_ipv6_nib_pl_del(iface, &pfx, pfx_len); while (gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)) { count++; } TEST_ASSERT_EQUAL_INT(MAX_NUMOF, count); } /* * Creates a prefix entry and removes it. * Expected result: prefix entry should be empty */ static void test_nib_pl_del__success(void) { void *iter_state = NULL; ipv6_addr_t pfx = { .u64 = { { .u8 = GLOBAL_PREFIX }, { .u64 = TEST_UINT64 } } }; gnrc_ipv6_nib_pl_t ple; TEST_ASSERT_EQUAL_INT(0, gnrc_ipv6_nib_pl_set(IFACE, &pfx, GLOBAL_PREFIX_LEN, UINT32_MAX, UINT32_MAX)); gnrc_ipv6_nib_pl_del(IFACE, &pfx, GLOBAL_PREFIX_LEN); TEST_ASSERT(!gnrc_ipv6_nib_pl_iter(0, &iter_state, &ple)); } Test *tests_gnrc_ipv6_nib_pl_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { new_TestFixture(test_nib_pl_set__EINVAL_unspec_addr), new_TestFixture(test_nib_pl_set__EINVAL_link_local), new_TestFixture(test_nib_pl_set__EINVAL_mc_addr), new_TestFixture(test_nib_pl_set__EINVAL_pfx_len), new_TestFixture(test_nib_pl_set__ENOMEM_diff_pfx), new_TestFixture(test_nib_pl_set__ENOMEM_diff_iface), new_TestFixture(test_nib_pl_set__ENOMEM_diff_iface_pfx), new_TestFixture(test_nib_pl_set__ENOMEM_diff_pfx_len), new_TestFixture(test_nib_pl_set__ENOMEM_diff_iface_pfx_len), new_TestFixture(test_nib_pl_set__ENOMEM_diff_pfx_pfx_len), new_TestFixture(test_nib_pl_set__ENOMEM_diff_iface_pfx_pfx_len), new_TestFixture(test_nib_pl_set__success_duplicate), new_TestFixture(test_nib_pl_set__success_change), new_TestFixture(test_nib_pl_set__success), new_TestFixture(test_nib_pl_del__unknown), new_TestFixture(test_nib_pl_del__success), /* gnrc_ipv6_nib_pl_iter() is tested during all the tests above */ }; EMB_UNIT_TESTCALLER(tests, set_up, NULL, fixtures); return (Test *)&tests; }