/* main.c - Application main entry point */ /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nbr.h" #define NET_LOG_ENABLED 1 #include "net_private.h" static int remove_count, add_count, clear_called; static void net_neighbor_data_remove(struct net_nbr *nbr) { printk("Neighbor %p removed\n", nbr); remove_count++; } static void net_neighbor_table_clear(struct net_nbr_table *table) { printk("Neighbor table %p cleared\n", table); clear_called = true; } NET_NBR_POOL_INIT(net_test_neighbor_pool, CONFIG_NET_IPV6_MAX_NEIGHBORS, 0, net_neighbor_data_remove); NET_NBR_TABLE_INIT(NET_NBR_LOCAL, test_neighbor, net_test_neighbor_pool, net_neighbor_table_clear); static struct net_eth_addr hwaddr1 = { { 0x42, 0x11, 0x69, 0xde, 0xfa, 0x01 } }; static struct net_eth_addr hwaddr2 = { { 0x5f, 0x1c, 0x04, 0xae, 0x99, 0x02 } }; static struct net_eth_addr hwaddr3 = { { 0xee, 0xe1, 0x55, 0xfe, 0x44, 0x03 } }; static struct net_eth_addr hwaddr4 = { { 0x61, 0xf2, 0xfe, 0x4e, 0x8e, 0x04 } }; static struct net_eth_addr hwaddr5 = { { 0x8a, 0x52, 0x01, 0x21, 0x11, 0x05 } }; ZTEST(neighbor_test_suite, test_neighbor) { struct net_eth_addr *addrs[] = { &hwaddr1, &hwaddr2, &hwaddr3, &hwaddr4, &hwaddr5, NULL }; struct net_nbr *nbrs[sizeof(addrs) - 1] = { 0 }; struct net_eth_addr *eth_addr; struct net_nbr *nbr; struct net_linkaddr lladdr; struct net_linkaddr_storage *lladdr_ptr; struct net_if *iface1 = INT_TO_POINTER(1); struct net_if *iface2 = INT_TO_POINTER(2); int ret, i; zassert_true(CONFIG_NET_IPV6_MAX_NEIGHBORS == (ARRAY_SIZE(addrs) - 2), "There should be exactly %d valid entries in addrs array\n", CONFIG_NET_IPV6_MAX_NEIGHBORS + 1); /* First adding a neighbor and trying to add multiple hw addresses * to it. Only the first one should succeed. */ nbr = net_nbr_get(&net_test_neighbor.table); zassert_not_null(nbr, "Cannot get neighbor from table %p\n", &net_test_neighbor.table); zassert_false(nbr->ref != 1, "Invalid ref count %d\n", nbr->ref); lladdr.len = sizeof(struct net_eth_addr); for (i = 0; i < 2; i++) { eth_addr = addrs[i]; lladdr.addr = eth_addr->addr; ret = net_nbr_link(nbr, iface1, &lladdr); /* One neighbor can have only one lladdr */ zassert_false(i == 0 && ret < 0, "Cannot add %s to nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); if (!ret) { printk("Adding %s\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr))); } } lladdr.addr = addrs[0]->addr; nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr); zassert_true(nbr->idx == 0, "Wrong index %d should be %d\n", nbr->idx, 0); for (i = 0; i < 2; i++) { eth_addr = addrs[i]; lladdr.addr = eth_addr->addr; ret = net_nbr_unlink(nbr, &lladdr); zassert_false(i == 0 && ret < 0, "Cannot add %s to nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); if (!ret) { printk("Deleting %s\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr))); } } net_nbr_unref(nbr); zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n", nbr->ref); /* Then adding multiple neighbors. */ lladdr.len = sizeof(struct net_eth_addr); for (i = 0; i < ARRAY_SIZE(addrs); i++) { nbr = net_nbr_get(&net_test_neighbor.table); if (!nbr) { if (i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { /* Ok, last entry will not fit cache */ break; } zassert_true(1, "[%d] Cannot get neighbor from table %p\n", i, &net_test_neighbor.table); } zassert_true(nbr->ref == 1, "[%d] Invalid ref count %d\n", i, nbr->ref); nbrs[i] = nbr; eth_addr = addrs[i]; lladdr.addr = eth_addr->addr; ret = net_nbr_link(nbr, iface1, &lladdr); zassert_false(ret < 0, "Cannot add %s to nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); printk("Adding %s\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr))); } for (i = 0; i < ARRAY_SIZE(addrs) - 2; i++) { lladdr.addr = addrs[i]->addr; nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr); zassert_false(nbr->idx != i, "Wrong index %d should be %d\n", nbr->idx, i); } for (i = 0; i < ARRAY_SIZE(addrs); i++) { eth_addr = addrs[i]; nbr = nbrs[i]; lladdr.addr = eth_addr->addr; if (!nbr || i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { break; } ret = net_nbr_unlink(nbr, &lladdr); zassert_false(ret < 0, "Cannot del %s from nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); printk("Deleting %s\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr))); net_nbr_unref(nbr); zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n", nbr->ref); } /* Then adding multiple neighbors but some of them in different * interface. */ lladdr.len = sizeof(struct net_eth_addr); remove_count = add_count = 0; for (i = 0; i < ARRAY_SIZE(addrs); i++) { nbr = net_nbr_get(&net_test_neighbor.table); if (!nbr) { if (i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { /* Ok, last entry will not fit cache */ break; } zassert_true(1, "[%d] Cannot get neighbor from table %p\n", i, &net_test_neighbor.table); } zassert_false(nbr->ref != 1, "[%d] Invalid ref count %d\n", i, nbr->ref); nbrs[i] = nbr; eth_addr = addrs[i]; lladdr.addr = eth_addr->addr; if (i % 2) { ret = net_nbr_link(nbr, iface1, &lladdr); } else { ret = net_nbr_link(nbr, iface2, &lladdr); } zassert_false(ret < 0, "Cannot add %s to nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); printk("Adding %s iface %p\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr)), nbr->iface); add_count++; } for (i = 0; i < ARRAY_SIZE(addrs) - 2; i++) { lladdr.addr = addrs[i]->addr; if (i % 2) { nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr); } else { nbr = net_nbr_lookup(&net_test_neighbor.table, iface2, &lladdr); } zassert_false(nbr->idx != i, "Wrong index %d should be %d\n", nbr->idx, i); lladdr_ptr = net_nbr_get_lladdr(i); if (memcmp(lladdr_ptr->addr, addrs[i]->addr, sizeof(struct net_eth_addr))) { zassert_true(1, "Wrong lladdr %s in index %d\n", net_sprint_ll_addr(lladdr_ptr->addr, lladdr_ptr->len), i); } } for (i = 0; i < ARRAY_SIZE(addrs); i++) { struct net_if *iface; eth_addr = addrs[i]; nbr = nbrs[i]; lladdr.addr = eth_addr->addr; if (!nbr || i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) { break; } iface = nbr->iface; ret = net_nbr_unlink(nbr, &lladdr); zassert_false(ret < 0, "Cannot del %s from nbr cache (%d)\n", net_sprint_ll_addr(lladdr.addr, lladdr.len), ret); printk("Deleting %s iface %p\n", net_sprint_ll_addr(eth_addr->addr, sizeof(struct net_eth_addr)), iface); net_nbr_unref(nbr); zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n", nbr->ref); } zassert_false(add_count != remove_count, "Remove count %d does not match add count %d\n", remove_count, add_count); net_nbr_clear_table(&net_test_neighbor.table); zassert_true(clear_called, "Table clear check failed"); /* The table should be empty now */ lladdr.addr = addrs[0]->addr; nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr); zassert_is_null(nbr, "Some entries still found in nbr cache"); return; } void *setup(void) { if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { k_thread_priority_set(k_current_get(), K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)); } else { k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9)); } return NULL; } /*test case main entry*/ ZTEST_SUITE(neighbor_test_suite, NULL, setup, NULL, NULL, NULL);