Merge pull request #2721 from authmillenon/ipv6_nc/feat/iterators

ipv6_nc: add iterators
dev/timer
Martine Lenders 8 years ago
commit 4741a01e36

@ -175,6 +175,24 @@ void ng_ipv6_nc_remove(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr);
*/
ng_ipv6_nc_t *ng_ipv6_nc_get(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr);
/**
* @brief Gets next entry in neighbor cache after @p prev.
*
* @param[in] prev Previous entry. NULL to start iteration.
*
* @return The next entry in neighbor cache.
*/
ng_ipv6_nc_t *ng_ipv6_nc_get_next(ng_ipv6_nc_t *prev);
/**
* @brief Gets next reachable router entry in neighbor cache after @p prev.
*
* @param[in] prev Previous router entry. NULL to start iteration.
*
* @return The next reachable router entry in neighbor cache.
*/
ng_ipv6_nc_t *ng_ipv6_nc_get_next_router(ng_ipv6_nc_t *prev);
/**
* @brief Searches for any neighbor cache entry fitting the @p ipv6_addr,
* where you currently can send a packet to (do not confuse with

@ -136,6 +136,50 @@ ng_ipv6_nc_t *ng_ipv6_nc_get(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr
return NULL;
}
ng_ipv6_nc_t *ng_ipv6_nc_get_next(ng_ipv6_nc_t *prev)
{
if (prev == NULL) {
prev = ncache;
}
else {
prev++; /* get next entry */
}
while (prev < (ncache + NG_IPV6_NC_SIZE)) { /* while not reached end */
if (!ng_ipv6_addr_is_unspecified(&(prev->ipv6_addr))) {
return prev;
}
prev++;
}
return NULL;
}
static inline bool _is_reachable(ng_ipv6_nc_t *entry)
{
switch ((entry->flags & NG_IPV6_NC_STATE_MASK) >> NG_IPV6_NC_STATE_POS) {
case NG_IPV6_NC_STATE_UNREACHABLE:
case NG_IPV6_NC_STATE_INCOMPLETE:
return false;
default:
return true;
}
}
ng_ipv6_nc_t *ng_ipv6_nc_get_next_router(ng_ipv6_nc_t *prev)
{
for (ng_ipv6_nc_t *router = ng_ipv6_nc_get_next(prev); router != NULL;
router = ng_ipv6_nc_get_next(router)) {
if (router->flags & NG_IPV6_NC_IS_ROUTER) {
return router;
}
}
return NULL;
}
ng_ipv6_nc_t *ng_ipv6_nc_get_reachable(kernel_pid_t iface,
const ng_ipv6_addr_t *ipv6_addr)
{
@ -148,17 +192,11 @@ ng_ipv6_nc_t *ng_ipv6_nc_get_reachable(kernel_pid_t iface,
return NULL;
}
switch ((entry->flags & NG_IPV6_NC_STATE_MASK) >> NG_IPV6_NC_STATE_POS) {
case NG_IPV6_NC_STATE_UNREACHABLE:
case NG_IPV6_NC_STATE_INCOMPLETE:
DEBUG("ipv6_nc: Entry %s is unreachable (flags = 0x%02x)\n",
ng_ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)),
entry->flags);
return NULL;
default:
return entry;
if (_is_reachable(entry)) {
return entry;
}
return NULL;
}
ng_ipv6_nc_t *ng_ipv6_nc_still_reachable(const ng_ipv6_addr_t *ipv6_addr)

@ -26,6 +26,64 @@
/* maximum length of L2 address */
#define MAX_L2_ADDR_LEN (8U)
static void _print_nc_state(ng_ipv6_nc_t *entry)
{
switch (entry->flags & NG_IPV6_NC_STATE_MASK) {
case NG_IPV6_NC_STATE_UNMANAGED:
printf("UNMANAGED");
break;
case NG_IPV6_NC_STATE_UNREACHABLE:
printf("UNREACHABLE");
break;
case NG_IPV6_NC_STATE_INCOMPLETE:
printf("INCOMPLETE");
break;
case NG_IPV6_NC_STATE_STALE:
printf("STALE");
break;
case NG_IPV6_NC_STATE_DELAY:
printf("DELAY");
break;
case NG_IPV6_NC_STATE_PROBE:
printf("PROBE");
break;
case NG_IPV6_NC_STATE_REACHABLE:
printf("REACHABLE");
break;
default:
printf("UNKNOWN");
break;
}
}
static void _print_nc_type(ng_ipv6_nc_t *entry)
{
switch (entry->flags & NG_IPV6_NC_TYPE_MASK) {
case NG_IPV6_NC_TYPE_GC:
printf("GC");
break;
case NG_IPV6_NC_TYPE_TENTATIVE:
printf("T");
break;
case NG_IPV6_NC_TYPE_REGISTERED:
printf("R");
break;
default:
printf("-");
break;
}
}
static bool _is_iface(kernel_pid_t iface)
{
#ifdef MODULE_NG_NETIF
@ -44,6 +102,30 @@ static bool _is_iface(kernel_pid_t iface)
#endif
}
static int _ipv6_nc_list(void)
{
char ipv6_str[NG_IPV6_ADDR_MAX_STR_LEN];
char l2addr_str[3 * MAX_L2_ADDR_LEN];
puts("IPv6 address if L2 address state type");
puts("-----------------------------------------------------------------------------");
for (ng_ipv6_nc_t *entry = ng_ipv6_nc_get_next(NULL);
entry != NULL;
entry = ng_ipv6_nc_get_next(entry)) {
printf("%-30s %2" PRIkernel_pid " %-24s ",
ng_ipv6_addr_to_str(ipv6_str, &entry->ipv6_addr, sizeof(ipv6_str)),
entry->iface,
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str),
entry->l2_addr, entry->l2_addr_len));
_print_nc_state(entry);
_print_nc_type(entry);
puts("");
}
return 0;
}
static int _ipv6_nc_add(kernel_pid_t iface, char *ipv6_addr_str,
char *l2_addr_str)
{
@ -88,6 +170,10 @@ static int _ipv6_nc_del(char *ipv6_addr_str)
int _ipv6_nc_manage(int argc, char **argv)
{
if ((argc == 1) || (strcmp("list", argv[1]) == 0)) {
return _ipv6_nc_list();
}
if (argc > 2) {
if ((argc > 4) && (strcmp("add", argv[1]) == 0)) {
kernel_pid_t iface = (kernel_pid_t)atoi(argv[2]);
@ -105,11 +191,46 @@ int _ipv6_nc_manage(int argc, char **argv)
}
}
printf("usage: %s add <iface pid> <ipv6_addr> <l2_addr>\n"
" or: %s del <ipv6_addr>\n", argv[0], argv[0]);
printf("usage: %s [list]\n"
" or: %s add <iface pid> <ipv6_addr> <l2_addr>\n"
" or: %s del <ipv6_addr>\n", argv[0], argv[0], argv[0]);
return 1;
}
int _ipv6_nc_routers(int argc, char **argv)
{
kernel_pid_t iface = KERNEL_PID_UNDEF;
char ipv6_str[NG_IPV6_ADDR_MAX_STR_LEN];
if (argc > 1) {
iface = atoi(argv[1]);
if (!_is_iface(iface)) {
printf("usage: %s [<iface pid>]\n", argv[0]);
return 1;
}
}
puts("if Router state type");
puts("---------------------------------------------------");
for (ng_ipv6_nc_t *entry = ng_ipv6_nc_get_next_router(NULL);
entry != NULL;
entry = ng_ipv6_nc_get_next_router(entry)) {
if ((iface != KERNEL_PID_UNDEF) && (iface != entry->iface)) {
continue;
}
printf("%2" PRIkernel_pid " %-30s ", entry->iface,
ng_ipv6_addr_to_str(ipv6_str, &entry->ipv6_addr, sizeof(ipv6_str)));
_print_nc_state(entry);
_print_nc_type(entry);
puts("");
}
return 0;
}
/**
* @}
*/

@ -165,6 +165,7 @@ extern int _fib_route_handler(int argc, char **argv);
#ifdef MODULE_NG_IPV6_NC
extern int _ipv6_nc_manage(int argc, char **argv);
extern int _ipv6_nc_routers(int argc, char **argv);
#endif
const shell_command_t _shell_command_list[] = {
@ -273,6 +274,7 @@ const shell_command_t _shell_command_list[] = {
#endif
#ifdef MODULE_NG_IPV6_NC
{"ncache", "manage neighbor cache by hand", _ipv6_nc_manage },
{"routers", "IPv6 default router list", _ipv6_nc_routers },
#endif
{NULL, NULL, NULL}
};

@ -40,6 +40,13 @@
} \
}
/* a third IPv6 addr for testing */
#define THIRD_TEST_IPV6_ADDR { { \
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f \
} \
}
static void set_up(void)
{
ng_ipv6_nc_init();
@ -207,6 +214,91 @@ static void test_ipv6_nc_get__success_if_global(void)
TEST_ASSERT_EQUAL_INT(0, entry->flags);
}
static void test_ipv6_nc_get_next__empty(void)
{
TEST_ASSERT_NULL(ng_ipv6_nc_get_next(NULL));
}
static void test_ipv6_nc_get_next__1_entry(void)
{
ng_ipv6_nc_t *entry = NULL;
test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(NULL)));
TEST_ASSERT_NULL(ng_ipv6_nc_get_next(entry));
}
static void test_ipv6_nc_get_next__2_entries(void)
{
ng_ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR;
ng_ipv6_nc_t *entry = NULL;
test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr,
TEST_STRING8, sizeof(TEST_STRING8) - 1, 0));
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(NULL)));
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(entry)));
TEST_ASSERT_NULL(ng_ipv6_nc_get_next(entry));
}
static void test_ipv6_nc_get_next__holey(void)
{
ng_ipv6_addr_t addr1 = OTHER_TEST_IPV6_ADDR;
ng_ipv6_addr_t addr2 = THIRD_TEST_IPV6_ADDR;
ng_ipv6_nc_t *entry = NULL, *exp_entry = NULL;
/* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
test_ipv6_nc_get_next__2_entries();
TEST_ASSERT_EQUAL_INT(0, ng_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr2,
TEST_STRING8,
sizeof(TEST_STRING8) - 2, 0));
TEST_ASSERT_NOT_NULL((exp_entry = ng_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr2)));
ng_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr1);
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(NULL)));
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(entry)));
TEST_ASSERT(exp_entry == entry);
TEST_ASSERT_NULL(ng_ipv6_nc_get_next(entry));
}
static void test_ipv6_nc_get_next_router__empty(void)
{
TEST_ASSERT_NULL(ng_ipv6_nc_get_next_router(NULL));
}
static void test_ipv6_nc_get_next_router__first_entry(void)
{
ng_ipv6_nc_t *entry = NULL;
/* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
test_ipv6_nc_get_next__2_entries();
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next(NULL)));
entry->flags = (NG_IPV6_NC_STATE_REACHABLE << NG_IPV6_NC_STATE_POS);
entry->flags |= NG_IPV6_NC_IS_ROUTER;
TEST_ASSERT_NOT_NULL((entry = ng_ipv6_nc_get_next_router(NULL)));
TEST_ASSERT_NULL(ng_ipv6_nc_get_next_router(entry));
}
static void test_ipv6_nc_get_next_router__second_entry(void)
{
ng_ipv6_nc_t *entry1 = NULL, *entry2 = NULL;
/* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
test_ipv6_nc_get_next__2_entries();
TEST_ASSERT_NOT_NULL((entry1 = ng_ipv6_nc_get_next(NULL)));
TEST_ASSERT_NOT_NULL((entry2 = ng_ipv6_nc_get_next(entry1)));
entry2->flags = (NG_IPV6_NC_STATE_REACHABLE << NG_IPV6_NC_STATE_POS);
entry2->flags |= NG_IPV6_NC_IS_ROUTER;
TEST_ASSERT_NOT_NULL((entry1 = ng_ipv6_nc_get_next_router(NULL)));
TEST_ASSERT(entry2 == entry1);
TEST_ASSERT_NULL(ng_ipv6_nc_get_next_router(entry1));
}
static void test_ipv6_nc_get_reachable__incomplete_if_local(void)
{
ng_ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR;
@ -318,6 +410,13 @@ Test *tests_ipv6_nc_tests(void)
new_TestFixture(test_ipv6_nc_get__different_addr),
new_TestFixture(test_ipv6_nc_get__success_if_local),
new_TestFixture(test_ipv6_nc_get__success_if_global),
new_TestFixture(test_ipv6_nc_get_next__empty),
new_TestFixture(test_ipv6_nc_get_next__1_entry),
new_TestFixture(test_ipv6_nc_get_next__2_entries),
new_TestFixture(test_ipv6_nc_get_next__holey),
new_TestFixture(test_ipv6_nc_get_next_router__empty),
new_TestFixture(test_ipv6_nc_get_next_router__first_entry),
new_TestFixture(test_ipv6_nc_get_next_router__second_entry),
new_TestFixture(test_ipv6_nc_get_reachable__incomplete_if_local),
new_TestFixture(test_ipv6_nc_get_reachable__incomplete_if_global),
new_TestFixture(test_ipv6_nc_get_reachable__reachable_if_local),

Loading…
Cancel
Save