1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(net_test, CONFIG_NET_IPV6_NBR_CACHE_LOG_LEVEL);
11 
12 #include <zephyr/ztest.h>
13 #include <zephyr/types.h>
14 #include <stddef.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <errno.h>
18 #include <zephyr/device.h>
19 #include <zephyr/init.h>
20 #include <zephyr/sys/printk.h>
21 #include <zephyr/net/net_core.h>
22 #include <zephyr/net/net_ip.h>
23 #include <zephyr/net/ethernet.h>
24 #include <zephyr/linker/sections.h>
25 
26 #include "nbr.h"
27 
28 #define NET_LOG_ENABLED 1
29 #include "net_private.h"
30 
31 static int remove_count, add_count, clear_called;
32 
net_neighbor_data_remove(struct net_nbr * nbr)33 static void net_neighbor_data_remove(struct net_nbr *nbr)
34 {
35 	printk("Neighbor %p removed\n", nbr);
36 
37 	remove_count++;
38 }
39 
net_neighbor_table_clear(struct net_nbr_table * table)40 static void net_neighbor_table_clear(struct net_nbr_table *table)
41 {
42 	printk("Neighbor table %p cleared\n", table);
43 
44 	clear_called = true;
45 }
46 
47 NET_NBR_POOL_INIT(net_test_neighbor_pool, CONFIG_NET_IPV6_MAX_NEIGHBORS,
48 		  0, net_neighbor_data_remove);
49 
50 NET_NBR_TABLE_INIT(NET_NBR_LOCAL, test_neighbor, net_test_neighbor_pool,
51 		   net_neighbor_table_clear);
52 
53 
54 static struct net_eth_addr hwaddr1 = { { 0x42, 0x11, 0x69, 0xde, 0xfa, 0x01 } };
55 static struct net_eth_addr hwaddr2 = { { 0x5f, 0x1c, 0x04, 0xae, 0x99, 0x02 } };
56 static struct net_eth_addr hwaddr3 = { { 0xee, 0xe1, 0x55, 0xfe, 0x44, 0x03 } };
57 static struct net_eth_addr hwaddr4 = { { 0x61, 0xf2, 0xfe, 0x4e, 0x8e, 0x04 } };
58 static struct net_eth_addr hwaddr5 = { { 0x8a, 0x52, 0x01, 0x21, 0x11, 0x05 } };
59 
ZTEST(neighbor_test_suite,test_neighbor)60 ZTEST(neighbor_test_suite, test_neighbor)
61 {
62 	struct net_eth_addr *addrs[] = {
63 		&hwaddr1,
64 		&hwaddr2,
65 		&hwaddr3,
66 		&hwaddr4,
67 		&hwaddr5,
68 		NULL
69 	};
70 	struct net_nbr *nbrs[sizeof(addrs) - 1] = { 0 };
71 	struct net_eth_addr *eth_addr;
72 
73 	struct net_nbr *nbr;
74 	struct net_linkaddr lladdr;
75 	struct net_linkaddr *lladdr_ptr;
76 	struct net_if *iface1 = INT_TO_POINTER(1);
77 	struct net_if *iface2 = INT_TO_POINTER(2);
78 	int ret, i;
79 
80 	zassert_true(CONFIG_NET_IPV6_MAX_NEIGHBORS == (ARRAY_SIZE(addrs) - 2),
81 		     "There should be exactly %d valid entries in addrs array\n",
82 		     CONFIG_NET_IPV6_MAX_NEIGHBORS + 1);
83 
84 	/* First adding a neighbor and trying to add multiple hw addresses
85 	 * to it. Only the first one should succeed.
86 	 */
87 	nbr = net_nbr_get(&net_test_neighbor.table);
88 	zassert_not_null(nbr, "Cannot get neighbor from table %p\n",
89 			 &net_test_neighbor.table);
90 
91 	zassert_false(nbr->ref != 1, "Invalid ref count %d\n", nbr->ref);
92 
93 	lladdr.len = sizeof(struct net_eth_addr);
94 
95 	for (i = 0; i < 2; i++) {
96 		eth_addr = addrs[i];
97 
98 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
99 
100 		ret = net_nbr_link(nbr, iface1, &lladdr);
101 
102 		/* One neighbor can have only one lladdr */
103 		zassert_false(i == 0 && ret < 0, "Cannot add %s to nbr cache (%d)\n",
104 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
105 			      ret);
106 
107 		if (!ret) {
108 			printk("Adding %s\n",
109 			       net_sprint_ll_addr(eth_addr->addr,
110 						  sizeof(struct net_eth_addr)));
111 		}
112 	}
113 
114 	memcpy(lladdr.addr, addrs[0]->addr, sizeof(struct net_eth_addr));
115 
116 	nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr);
117 	zassert_true(nbr->idx == 0, "Wrong index %d should be %d\n", nbr->idx, 0);
118 
119 	for (i = 0; i < 2; i++) {
120 		eth_addr = addrs[i];
121 
122 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
123 
124 		ret = net_nbr_unlink(nbr, &lladdr);
125 		zassert_false(i == 0 && ret < 0, "Cannot add %s to nbr cache (%d)\n",
126 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
127 			      ret);
128 		if (!ret) {
129 			printk("Deleting %s\n",
130 			       net_sprint_ll_addr(eth_addr->addr,
131 						  sizeof(struct net_eth_addr)));
132 		}
133 	}
134 
135 	net_nbr_unref(nbr);
136 	zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n",
137 		      nbr->ref);
138 
139 	/* Then adding multiple neighbors.
140 	 */
141 	lladdr.len = sizeof(struct net_eth_addr);
142 
143 	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
144 		nbr = net_nbr_get(&net_test_neighbor.table);
145 		if (!nbr) {
146 			if (i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
147 				/* Ok, last entry will not fit cache */
148 				break;
149 			}
150 			zassert_true(1, "[%d] Cannot get neighbor from table %p\n",
151 				     i, &net_test_neighbor.table);
152 		}
153 
154 		zassert_true(nbr->ref == 1, "[%d] Invalid ref count %d\n", i, nbr->ref);
155 		nbrs[i] = nbr;
156 
157 		eth_addr = addrs[i];
158 
159 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
160 
161 		ret = net_nbr_link(nbr, iface1, &lladdr);
162 		zassert_false(ret < 0, "Cannot add %s to nbr cache (%d)\n",
163 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
164 			      ret);
165 		printk("Adding %s\n", net_sprint_ll_addr(eth_addr->addr,
166 							 sizeof(struct net_eth_addr)));
167 	}
168 
169 	for (i = 0; i < ARRAY_SIZE(addrs) - 2; i++) {
170 		memcpy(lladdr.addr, addrs[i]->addr, sizeof(struct net_eth_addr));
171 		nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr);
172 		zassert_false(nbr->idx != i, "Wrong index %d should be %d\n", nbr->idx, i);
173 	}
174 
175 	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
176 		eth_addr = addrs[i];
177 		nbr = nbrs[i];
178 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
179 
180 		if (!nbr || i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
181 			break;
182 		}
183 
184 		ret = net_nbr_unlink(nbr, &lladdr);
185 		zassert_false(ret < 0, "Cannot del %s from nbr cache (%d)\n",
186 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
187 			      ret);
188 		printk("Deleting %s\n", net_sprint_ll_addr(eth_addr->addr,
189 							   sizeof(struct net_eth_addr)));
190 
191 		net_nbr_unref(nbr);
192 		zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n",
193 			      nbr->ref);
194 	}
195 
196 	/* Then adding multiple neighbors but some of them in different
197 	 * interface.
198 	 */
199 	lladdr.len = sizeof(struct net_eth_addr);
200 	remove_count = add_count = 0;
201 
202 	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
203 		nbr = net_nbr_get(&net_test_neighbor.table);
204 		if (!nbr) {
205 			if (i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
206 				/* Ok, last entry will not fit cache */
207 				break;
208 			}
209 			zassert_true(1, "[%d] Cannot get neighbor from table %p\n",
210 				     i, &net_test_neighbor.table);
211 		}
212 
213 		zassert_false(nbr->ref != 1, "[%d] Invalid ref count %d\n", i, nbr->ref);
214 		nbrs[i] = nbr;
215 
216 		eth_addr = addrs[i];
217 
218 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
219 
220 		if (i % 2) {
221 			ret = net_nbr_link(nbr, iface1, &lladdr);
222 		} else {
223 			ret = net_nbr_link(nbr, iface2, &lladdr);
224 		}
225 		zassert_false(ret < 0, "Cannot add %s to nbr cache (%d)\n",
226 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
227 			      ret);
228 		printk("Adding %s iface %p\n",
229 		       net_sprint_ll_addr(eth_addr->addr,
230 					  sizeof(struct net_eth_addr)),
231 		       nbr->iface);
232 		add_count++;
233 	}
234 
235 	for (i = 0; i < ARRAY_SIZE(addrs) - 2; i++) {
236 		memcpy(lladdr.addr, addrs[i]->addr, sizeof(struct net_eth_addr));
237 
238 		if (i % 2) {
239 			nbr = net_nbr_lookup(&net_test_neighbor.table, iface1,
240 					     &lladdr);
241 		} else {
242 			nbr = net_nbr_lookup(&net_test_neighbor.table, iface2,
243 					     &lladdr);
244 		}
245 		zassert_false(nbr->idx != i, "Wrong index %d should be %d\n", nbr->idx, i);
246 
247 		lladdr_ptr = net_nbr_get_lladdr(i);
248 		if (memcmp(lladdr_ptr->addr, addrs[i]->addr,
249 			   sizeof(struct net_eth_addr))) {
250 			zassert_true(1, "Wrong lladdr %s in index %d\n",
251 				     net_sprint_ll_addr(lladdr_ptr->addr,
252 							lladdr_ptr->len),
253 				     i);
254 		}
255 	}
256 
257 	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
258 		struct net_if *iface;
259 
260 		eth_addr = addrs[i];
261 		nbr = nbrs[i];
262 		memcpy(lladdr.addr, eth_addr->addr, sizeof(struct net_eth_addr));
263 
264 		if (!nbr || i >= CONFIG_NET_IPV6_MAX_NEIGHBORS) {
265 			break;
266 		}
267 
268 		iface = nbr->iface;
269 
270 		ret = net_nbr_unlink(nbr, &lladdr);
271 		zassert_false(ret < 0, "Cannot del %s from nbr cache (%d)\n",
272 			      net_sprint_ll_addr(lladdr.addr, lladdr.len),
273 			      ret);
274 
275 		printk("Deleting %s iface %p\n", net_sprint_ll_addr(eth_addr->addr,
276 								    sizeof(struct net_eth_addr)), iface);
277 
278 		net_nbr_unref(nbr);
279 		zassert_false(nbr->ref != 0, "nbr still referenced, ref %d\n", nbr->ref);
280 	}
281 
282 	zassert_false(add_count != remove_count, "Remove count %d does not match add count %d\n",
283 		      remove_count, add_count);
284 
285 	net_nbr_clear_table(&net_test_neighbor.table);
286 
287 	zassert_true(clear_called, "Table clear check failed");
288 
289 	/* The table should be empty now */
290 	memcpy(lladdr.addr, addrs[0]->addr, sizeof(struct net_eth_addr));
291 
292 	nbr = net_nbr_lookup(&net_test_neighbor.table, iface1, &lladdr);
293 
294 	zassert_is_null(nbr, "Some entries still found in nbr cache");
295 
296 	return;
297 }
298 
setup(void)299 void *setup(void)
300 {
301 	if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) {
302 		k_thread_priority_set(k_current_get(),
303 				K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1));
304 	} else {
305 		k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9));
306 	}
307 	return NULL;
308 }
309 
310 /*test case main entry*/
311 ZTEST_SUITE(neighbor_test_suite, NULL, setup, NULL, NULL, NULL);
312