1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2018 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define NET_LOG_LEVEL CONFIG_NET_L2_ETHERNET_LOG_LEVEL
10 
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
13 
14 #include <zephyr/types.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <zephyr/sys/printk.h>
20 #include <zephyr/linker/sections.h>
21 #include <zephyr/random/random.h>
22 
23 #include <zephyr/ztest.h>
24 
25 #include <zephyr/net_buf.h>
26 #include <zephyr/net/net_ip.h>
27 #include <zephyr/net/net_pkt.h>
28 #include <zephyr/net/ethernet.h>
29 #include <zephyr/net/dummy.h>
30 #include <zephyr/net/net_l2.h>
31 
32 #include "ipv6.h"
33 
34 #define NET_LOG_ENABLED 1
35 #include "net_private.h"
36 
37 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
38 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
39 #else
40 #define DBG(fmt, ...)
41 #endif
42 
43 #define TEST_PORT 9999
44 
45 static char *test_data = "Test data to be sent";
46 
47 /* Interface 1 addresses */
48 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
49 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
50 
51 /* Interface 2 addresses */
52 static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
53 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
54 
55 /* Destination address for test packets */
56 static struct in6_addr dst_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 9, 0, 0, 0,
57 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
58 
59 /* Extra address is assigned to ll_addr */
60 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
61 				       0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
62 				       0x04 } } };
63 
64 /* Keep track of all ethernet interfaces */
65 static struct net_if *eth_interfaces[2];
66 
67 static struct net_context *udp_v6_ctx;
68 
69 static bool test_failed;
70 static bool test_started;
71 static bool do_timestamp;
72 static bool timestamp_cb_called;
73 static struct net_if_timestamp_cb timestamp_cb;
74 static struct net_if_timestamp_cb timestamp_cb_2;
75 static struct net_if_timestamp_cb timestamp_cb_3;
76 
77 static K_SEM_DEFINE(wait_data, 0, UINT_MAX);
78 
79 #define WAIT_TIME K_SECONDS(1)
80 
81 struct eth_context {
82 	struct net_if *iface;
83 	uint8_t mac_addr[6];
84 };
85 
86 static struct eth_context eth_context;
87 static struct eth_context eth_context2;
88 
eth_iface_init(struct net_if * iface)89 static void eth_iface_init(struct net_if *iface)
90 {
91 	const struct device *dev = net_if_get_device(iface);
92 	struct eth_context *context = dev->data;
93 
94 	net_if_set_link_addr(iface, context->mac_addr,
95 			     sizeof(context->mac_addr),
96 			     NET_LINK_ETHERNET);
97 
98 	ethernet_init(iface);
99 }
100 
eth_tx(const struct device * dev,struct net_pkt * pkt)101 static int eth_tx(const struct device *dev, struct net_pkt *pkt)
102 {
103 	if (!pkt->buffer) {
104 		DBG("No data to send!\n");
105 		return -ENODATA;
106 	}
107 
108 	if (test_started) {
109 		if (do_timestamp) {
110 			/* Simulate the clock advancing */
111 			pkt->timestamp.nanosecond = pkt->timestamp.second + 1;
112 
113 			net_if_add_tx_timestamp(pkt);
114 		} else {
115 			k_sem_give(&wait_data);
116 		}
117 	}
118 
119 	test_started = false;
120 
121 	return 0;
122 }
123 
eth_get_capabilities(const struct device * dev)124 static enum ethernet_hw_caps eth_get_capabilities(const struct device *dev)
125 {
126 	return 0;
127 }
128 
129 static struct ethernet_api api_funcs = {
130 	.iface_api.init = eth_iface_init,
131 
132 	.get_capabilities = eth_get_capabilities,
133 	.send = eth_tx,
134 };
135 
generate_mac(uint8_t * mac_addr)136 static void generate_mac(uint8_t *mac_addr)
137 {
138 	/* 00-00-5E-00-53-xx Documentation RFC 7042 */
139 	mac_addr[0] = 0x00;
140 	mac_addr[1] = 0x00;
141 	mac_addr[2] = 0x5E;
142 	mac_addr[3] = 0x00;
143 	mac_addr[4] = 0x53;
144 	mac_addr[5] = sys_rand8_get();
145 }
146 
eth_init(const struct device * dev)147 static int eth_init(const struct device *dev)
148 {
149 	struct eth_context *context = dev->data;
150 
151 	generate_mac(context->mac_addr);
152 
153 	return 0;
154 }
155 
156 ETH_NET_DEVICE_INIT(eth_test, "eth_test", eth_init, NULL,
157 		    &eth_context, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs,
158 		    NET_ETH_MTU);
159 
160 ETH_NET_DEVICE_INIT(eth_test2, "eth_test2", eth_init, NULL,
161 		    &eth_context2, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs,
162 		    NET_ETH_MTU);
163 
timestamp_callback(struct net_pkt * pkt)164 static void timestamp_callback(struct net_pkt *pkt)
165 {
166 	timestamp_cb_called = true;
167 
168 	if (do_timestamp) {
169 		/* This is very artificial test but make sure that we
170 		 * have advanced the time a bit.
171 		 */
172 		zassert_true(pkt->timestamp.nanosecond > pkt->timestamp.second,
173 			     "Timestamp not working ok (%d < %d)\n",
174 			     pkt->timestamp.nanosecond, pkt->timestamp.second);
175 	}
176 
177 	/* The pkt was ref'ed in send_some_data()() */
178 	net_pkt_unref(pkt);
179 
180 	if (do_timestamp) {
181 		k_sem_give(&wait_data);
182 	}
183 }
184 
test_timestamp_setup(void)185 void test_timestamp_setup(void)
186 {
187 	struct net_if *iface;
188 	struct net_pkt *pkt;
189 
190 	iface = eth_interfaces[0];
191 
192 	net_if_register_timestamp_cb(&timestamp_cb, NULL, iface,
193 				     timestamp_callback);
194 
195 	timestamp_cb_called = false;
196 	do_timestamp = false;
197 
198 	pkt = net_pkt_alloc_on_iface(iface, K_FOREVER);
199 
200 	/* Make sure that the callback function is called */
201 	net_if_call_timestamp_cb(pkt);
202 
203 	zassert_true(timestamp_cb_called, "Timestamp callback not called\n");
204 	zassert_equal(atomic_get(&pkt->atomic_ref), 0, "Pkt %p not released\n");
205 }
206 
timestamp_callback_2(struct net_pkt * pkt)207 static void timestamp_callback_2(struct net_pkt *pkt)
208 {
209 	timestamp_cb_called = true;
210 
211 	if (do_timestamp) {
212 		/* This is very artificial test but make sure that we
213 		 * have advanced the time a bit.
214 		 */
215 		zassert_true(pkt->timestamp.nanosecond > pkt->timestamp.second,
216 			     "Timestamp not working ok (%d < %d)\n",
217 			     pkt->timestamp.nanosecond, pkt->timestamp.second);
218 	}
219 
220 	zassert_equal(eth_interfaces[1], net_pkt_iface(pkt),
221 		      "Invalid interface");
222 
223 	/* The pkt was ref'ed in send_some_data()() */
224 	net_pkt_unref(pkt);
225 
226 	if (do_timestamp) {
227 		k_sem_give(&wait_data);
228 	}
229 }
230 
test_timestamp_setup_2nd_iface(void)231 void test_timestamp_setup_2nd_iface(void)
232 {
233 	struct net_if *iface;
234 	struct net_pkt *pkt;
235 
236 	iface = eth_interfaces[1];
237 
238 	net_if_register_timestamp_cb(&timestamp_cb_2, NULL, iface,
239 				     timestamp_callback_2);
240 
241 	timestamp_cb_called = false;
242 	do_timestamp = false;
243 
244 	pkt = net_pkt_alloc_on_iface(iface, K_FOREVER);
245 
246 	/* Make sure that the callback function is called */
247 	net_if_call_timestamp_cb(pkt);
248 
249 	zassert_true(timestamp_cb_called, "Timestamp callback not called\n");
250 	zassert_equal(atomic_get(&pkt->atomic_ref), 0, "Pkt %p not released\n");
251 }
252 
test_timestamp_setup_all(void)253 void test_timestamp_setup_all(void)
254 {
255 	struct net_pkt *pkt;
256 
257 	net_if_register_timestamp_cb(&timestamp_cb_3, NULL, NULL,
258 				     timestamp_callback);
259 
260 	timestamp_cb_called = false;
261 	do_timestamp = false;
262 
263 	pkt = net_pkt_alloc_on_iface(eth_interfaces[0], K_FOREVER);
264 
265 	/* The callback is called twice because we have two matching callbacks
266 	 * as the interface is set to NULL when registering cb. So we need to
267 	 * ref the pkt here because the callback releases pkt.
268 	 */
269 	net_pkt_ref(pkt);
270 
271 	/* Make sure that the callback function is called */
272 	net_if_call_timestamp_cb(pkt);
273 
274 	zassert_true(timestamp_cb_called, "Timestamp callback not called\n");
275 	zassert_equal(atomic_get(&pkt->atomic_ref), 0, "Pkt %p not released\n");
276 
277 	net_if_unregister_timestamp_cb(&timestamp_cb_3);
278 }
279 
test_timestamp_cleanup(void)280 void test_timestamp_cleanup(void)
281 {
282 	struct net_if *iface;
283 	struct net_pkt *pkt;
284 
285 	net_if_unregister_timestamp_cb(&timestamp_cb);
286 
287 	iface = eth_interfaces[0];
288 
289 	timestamp_cb_called = false;
290 	do_timestamp = false;
291 
292 	pkt = net_pkt_alloc_on_iface(iface, K_FOREVER);
293 
294 	/* Make sure that the callback function is not called after unregister
295 	 */
296 	net_if_call_timestamp_cb(pkt);
297 
298 	zassert_false(timestamp_cb_called, "Timestamp callback called\n");
299 	zassert_false(atomic_get(&pkt->atomic_ref) < 1, "Pkt %p released\n");
300 
301 	net_pkt_unref(pkt);
302 }
303 
304 struct user_data {
305 	int eth_if_count;
306 	int total_if_count;
307 };
308 
309 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)310 static const char *iface2str(struct net_if *iface)
311 {
312 #ifdef CONFIG_NET_L2_ETHERNET
313 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
314 		return "Ethernet";
315 	}
316 #endif
317 
318 	return "<unknown type>";
319 }
320 #endif
321 
iface_cb(struct net_if * iface,void * user_data)322 static void iface_cb(struct net_if *iface, void *user_data)
323 {
324 	struct user_data *ud = user_data;
325 
326 	DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
327 	    net_if_get_by_iface(iface));
328 
329 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
330 		if (ud->eth_if_count >= ARRAY_SIZE(eth_interfaces)) {
331 			DBG("Invalid interface %p\n", iface);
332 			return;
333 		}
334 
335 		eth_interfaces[ud->eth_if_count++] = iface;
336 	}
337 
338 	/* By default all interfaces are down initially */
339 	net_if_down(iface);
340 
341 	ud->total_if_count++;
342 }
343 
test_address_setup(void)344 void test_address_setup(void)
345 {
346 	struct net_if_addr *ifaddr;
347 	struct net_if *iface1, *iface2;
348 
349 	struct user_data ud = { 0 };
350 
351 	net_if_foreach(iface_cb, &ud);
352 
353 	iface1 = eth_interfaces[0];
354 	iface2 = eth_interfaces[1];
355 
356 	zassert_not_null(iface1, "Interface 1\n");
357 	zassert_not_null(iface2, "Interface 2\n");
358 
359 	ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
360 				      NET_ADDR_MANUAL, 0);
361 	if (!ifaddr) {
362 		DBG("Cannot add IPv6 address %s\n",
363 		       net_sprint_ipv6_addr(&my_addr1));
364 		zassert_not_null(ifaddr, "addr1\n");
365 	}
366 
367 	/* For testing purposes we need to set the addresses preferred */
368 	ifaddr->addr_state = NET_ADDR_PREFERRED;
369 
370 	ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
371 				      NET_ADDR_MANUAL, 0);
372 	if (!ifaddr) {
373 		DBG("Cannot add IPv6 address %s\n",
374 		       net_sprint_ipv6_addr(&ll_addr));
375 		zassert_not_null(ifaddr, "ll_addr\n");
376 	}
377 
378 	ifaddr->addr_state = NET_ADDR_PREFERRED;
379 
380 	ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
381 				      NET_ADDR_MANUAL, 0);
382 	if (!ifaddr) {
383 		DBG("Cannot add IPv6 address %s\n",
384 		       net_sprint_ipv6_addr(&my_addr2));
385 		zassert_not_null(ifaddr, "addr2\n");
386 	}
387 
388 	ifaddr->addr_state = NET_ADDR_PREFERRED;
389 
390 	net_if_up(iface1);
391 	net_if_up(iface2);
392 
393 	/* The interface might receive data which might fail the checks
394 	 * in the iface sending function, so we need to reset the failure
395 	 * flag.
396 	 */
397 	test_failed = false;
398 }
399 
add_neighbor(struct net_if * iface,struct in6_addr * addr)400 static bool add_neighbor(struct net_if *iface, struct in6_addr *addr)
401 {
402 	struct net_linkaddr_storage llstorage;
403 	struct net_linkaddr lladdr;
404 	struct net_nbr *nbr;
405 
406 	llstorage.addr[0] = 0x01;
407 	llstorage.addr[1] = 0x02;
408 	llstorage.addr[2] = 0x33;
409 	llstorage.addr[3] = 0x44;
410 	llstorage.addr[4] = 0x05;
411 	llstorage.addr[5] = 0x06;
412 
413 	lladdr.len = 6U;
414 	lladdr.addr = llstorage.addr;
415 	lladdr.type = NET_LINK_ETHERNET;
416 
417 	nbr = net_ipv6_nbr_add(iface, addr, &lladdr, false,
418 			       NET_IPV6_NBR_STATE_REACHABLE);
419 	if (!nbr) {
420 		DBG("Cannot add dst %s to neighbor cache\n",
421 		    net_sprint_ipv6_addr(addr));
422 		return false;
423 	}
424 
425 	return true;
426 }
427 
send_some_data(struct net_if * iface)428 static void send_some_data(struct net_if *iface)
429 {
430 	struct sockaddr_in6 dst_addr6 = {
431 		.sin6_family = AF_INET6,
432 		.sin6_port = htons(TEST_PORT),
433 	};
434 	struct sockaddr_in6 src_addr6 = {
435 		.sin6_family = AF_INET6,
436 		.sin6_port = 0,
437 	};
438 	int ret;
439 
440 	ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
441 			      &udp_v6_ctx);
442 	zassert_equal(ret, 0, "Create IPv6 UDP context failed\n");
443 
444 	memcpy(&src_addr6.sin6_addr, &my_addr1, sizeof(struct in6_addr));
445 	memcpy(&dst_addr6.sin6_addr, &dst_addr, sizeof(struct in6_addr));
446 
447 	ret = net_context_bind(udp_v6_ctx, (struct sockaddr *)&src_addr6,
448 			       sizeof(struct sockaddr_in6));
449 	zassert_equal(ret, 0, "Context bind failure test failed\n");
450 
451 	ret = add_neighbor(iface, &dst_addr);
452 	zassert_true(ret, "Cannot add neighbor\n");
453 
454 	ret = net_context_sendto(udp_v6_ctx, test_data, strlen(test_data),
455 				 (struct sockaddr *)&dst_addr6,
456 				 sizeof(struct sockaddr_in6),
457 				 NULL, K_NO_WAIT, NULL);
458 	zassert_true(ret > 0, "Send UDP pkt failed\n");
459 
460 	net_context_unref(udp_v6_ctx);
461 }
462 
test_check_timestamp_before_enabling(void)463 void test_check_timestamp_before_enabling(void)
464 {
465 	test_started = true;
466 	do_timestamp = false;
467 
468 	send_some_data(eth_interfaces[0]);
469 
470 	if (k_sem_take(&wait_data, WAIT_TIME)) {
471 		DBG("Timeout while waiting interface data\n");
472 		zassert_false(true, "Timeout\n");
473 	}
474 }
475 
test_check_timestamp_after_enabling(void)476 void test_check_timestamp_after_enabling(void)
477 {
478 	test_started = true;
479 	do_timestamp = true;
480 
481 	send_some_data(eth_interfaces[0]);
482 
483 	if (k_sem_take(&wait_data, WAIT_TIME)) {
484 		DBG("Timeout while waiting interface data\n");
485 		zassert_false(true, "Timeout\n");
486 	}
487 }
488 
ZTEST(net_tx_timestamp,test_tx_timestamp)489 ZTEST(net_tx_timestamp, test_tx_timestamp)
490 {
491 	test_address_setup();
492 	test_check_timestamp_before_enabling();
493 	test_timestamp_setup();
494 	test_timestamp_setup_2nd_iface();
495 	test_timestamp_setup_all();
496 	test_check_timestamp_after_enabling();
497 	test_timestamp_cleanup();
498 }
499 ZTEST_SUITE(net_tx_timestamp, NULL, NULL, NULL, NULL, NULL);
500