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 /* Custom PTP device name to avoid conflicts with PTP devices on SOC */
11 #define PTP_VIRT_CLOCK_NAME "PTP_CLOCK_VIRT"
12 
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
15 
16 #include <zephyr/types.h>
17 #include <stdbool.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <zephyr/sys/printk.h>
22 #include <zephyr/linker/sections.h>
23 
24 #include <zephyr/ztest.h>
25 
26 #include <zephyr/drivers/ptp_clock.h>
27 #include <zephyr/net/ptp_time.h>
28 
29 #include <zephyr/net/ethernet.h>
30 #include <zephyr/net/buf.h>
31 #include <zephyr/net/net_ip.h>
32 #include <zephyr/net/net_l2.h>
33 
34 #include <zephyr/random/random.h>
35 
36 #define NET_LOG_ENABLED 1
37 #include "net_private.h"
38 
39 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
40 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
41 #else
42 #define DBG(fmt, ...)
43 #endif
44 
45 /* Interface 1 addresses */
46 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
47 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
48 
49 /* Interface 2 addresses */
50 static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
51 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
52 
53 /* Interface 3 addresses */
54 static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0,
55 					0, 0, 0, 0, 0, 0, 0, 0x1 } } };
56 
57 /* Extra address is assigned to ll_addr */
58 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
59 				       0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
60 				       0x04 } } };
61 
62 #define MAX_NUM_INTERFACES 3
63 
64 /* Keep track of all ethernet interfaces */
65 static struct net_if *eth_interfaces[MAX_NUM_INTERFACES];
66 
67 static ZTEST_BMEM int ptp_clocks[MAX_NUM_INTERFACES - 1];
68 static int ptp_interface[MAX_NUM_INTERFACES - 1];
69 static int non_ptp_interface;
70 static bool test_failed;
71 static bool test_started;
72 
73 static K_SEM_DEFINE(wait_data, 0, UINT_MAX);
74 
75 #define WAIT_TIME K_SECONDS(1)
76 
77 struct eth_context {
78 	struct net_if *iface;
79 	uint8_t mac_addr[6];
80 
81 	struct net_ptp_time time;
82 	const struct device *ptp_clock;
83 };
84 
85 static struct eth_context eth_context_1;
86 static struct eth_context eth_context_2;
87 static struct eth_context eth_context_3;
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 	struct eth_context *context = dev->data;
104 
105 	if (&eth_context_1 != context && &eth_context_2 != context) {
106 		zassert_true(false, "Context pointers do not match\n");
107 	}
108 
109 	if (!pkt->frags) {
110 		DBG("No data to send!\n");
111 		return -ENODATA;
112 	}
113 
114 	if (test_started) {
115 		k_sem_give(&wait_data);
116 	}
117 
118 
119 	return 0;
120 }
121 
eth_capabilities(const struct device * dev)122 static enum ethernet_hw_caps eth_capabilities(const struct device *dev)
123 {
124 	return ETHERNET_PTP;
125 }
126 
eth_get_ptp_clock(const struct device * dev)127 static const struct device *eth_get_ptp_clock(const struct device *dev)
128 {
129 	struct eth_context *context = dev->data;
130 
131 	return context->ptp_clock;
132 }
133 
134 static struct ethernet_api api_funcs = {
135 	.iface_api.init = eth_iface_init,
136 
137 	.get_capabilities = eth_capabilities,
138 	.get_ptp_clock = eth_get_ptp_clock,
139 	.send = eth_tx,
140 };
141 
generate_mac(uint8_t * mac_addr)142 static void generate_mac(uint8_t *mac_addr)
143 {
144 	/* 00-00-5E-00-53-xx Documentation RFC 7042 */
145 	mac_addr[0] = 0x00;
146 	mac_addr[1] = 0x00;
147 	mac_addr[2] = 0x5E;
148 	mac_addr[3] = 0x00;
149 	mac_addr[4] = 0x53;
150 	mac_addr[5] = sys_rand8_get();
151 }
152 
eth_init(const struct device * dev)153 static int eth_init(const struct device *dev)
154 {
155 	struct eth_context *context = dev->data;
156 
157 	generate_mac(context->mac_addr);
158 
159 	return 0;
160 }
161 
162 ETH_NET_DEVICE_INIT(eth3_test, "eth3_test", eth_init, NULL,
163 		    &eth_context_3, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs,
164 		    NET_ETH_MTU);
165 
166 ETH_NET_DEVICE_INIT(eth2_test, "eth2_test", eth_init, NULL,
167 		    &eth_context_2, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs,
168 		    NET_ETH_MTU);
169 
170 ETH_NET_DEVICE_INIT(eth1_test, "eth1_test", eth_init, NULL,
171 		    &eth_context_1, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs,
172 		    NET_ETH_MTU);
173 
timestamp_to_nsec(struct net_ptp_time * ts)174 static uint64_t timestamp_to_nsec(struct net_ptp_time *ts)
175 {
176 	if (!ts) {
177 		return 0;
178 	}
179 
180 	return (ts->second * NSEC_PER_SEC) + ts->nanosecond;
181 }
182 
183 struct ptp_context {
184 	struct eth_context *eth_context;
185 };
186 
my_ptp_clock_set(const struct device * dev,struct net_ptp_time * tm)187 static int my_ptp_clock_set(const struct device *dev, struct net_ptp_time *tm)
188 {
189 	struct ptp_context *ptp_ctx = dev->data;
190 	struct eth_context *eth_ctx = ptp_ctx->eth_context;
191 
192 	if (&eth_context_3 != eth_ctx && &eth_context_2 != eth_ctx) {
193 		zassert_true(false, "Context pointers do not match\n");
194 	}
195 
196 	memcpy(&eth_ctx->time, tm, sizeof(struct net_ptp_time));
197 
198 	return 0;
199 }
200 
my_ptp_clock_get(const struct device * dev,struct net_ptp_time * tm)201 static int my_ptp_clock_get(const struct device *dev, struct net_ptp_time *tm)
202 {
203 	struct ptp_context *ptp_ctx = dev->data;
204 	struct eth_context *eth_ctx = ptp_ctx->eth_context;
205 
206 	memcpy(tm, &eth_ctx->time, sizeof(struct net_ptp_time));
207 
208 	return 0;
209 }
210 
my_ptp_clock_adjust(const struct device * dev,int increment)211 static int my_ptp_clock_adjust(const struct device *dev, int increment)
212 {
213 	struct ptp_context *ptp_ctx = dev->data;
214 	struct eth_context *eth_ctx = ptp_ctx->eth_context;
215 
216 	eth_ctx->time.nanosecond += increment;
217 
218 	return 0;
219 }
220 
my_ptp_clock_rate_adjust(const struct device * dev,double ratio)221 static int my_ptp_clock_rate_adjust(const struct device *dev, double ratio)
222 {
223 	return 0;
224 }
225 
226 static struct ptp_context ptp_test_1_context;
227 static struct ptp_context ptp_test_2_context;
228 
229 static const struct ptp_clock_driver_api api = {
230 	.set = my_ptp_clock_set,
231 	.get = my_ptp_clock_get,
232 	.adjust = my_ptp_clock_adjust,
233 	.rate_adjust = my_ptp_clock_rate_adjust,
234 };
235 
ptp_test_1_init(const struct device * port)236 static int ptp_test_1_init(const struct device *port)
237 {
238 	const struct device *const eth_dev = DEVICE_GET(eth3_test);
239 	struct eth_context *context = eth_dev->data;
240 	struct ptp_context *ptp_context = port->data;
241 
242 	context->ptp_clock = port;
243 	ptp_context->eth_context = context;
244 
245 	return 0;
246 }
247 
248 DEVICE_DEFINE(ptp_clock_1, PTP_VIRT_CLOCK_NAME, ptp_test_1_init,
249 		NULL, &ptp_test_1_context, NULL,
250 		POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, &api);
251 
ptp_test_2_init(const struct device * port)252 static int ptp_test_2_init(const struct device *port)
253 {
254 	const struct device *const eth_dev = DEVICE_GET(eth2_test);
255 	struct eth_context *context = eth_dev->data;
256 	struct ptp_context *ptp_context = port->data;
257 
258 	context->ptp_clock = port;
259 	ptp_context->eth_context = context;
260 
261 	return 0;
262 }
263 
264 DEVICE_DEFINE(ptp_clock_2, PTP_VIRT_CLOCK_NAME, ptp_test_2_init,
265 		NULL, &ptp_test_2_context, NULL,
266 		POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, &api);
267 
268 struct user_data {
269 	int eth_if_count;
270 	int total_if_count;
271 };
272 
273 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)274 static const char *iface2str(struct net_if *iface)
275 {
276 #ifdef CONFIG_NET_L2_ETHERNET
277 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
278 		return "Ethernet";
279 	}
280 #endif
281 
282 	return "<unknown type>";
283 }
284 #endif
285 
iface_cb(struct net_if * iface,void * user_data)286 static void iface_cb(struct net_if *iface, void *user_data)
287 {
288 	struct user_data *ud = user_data;
289 
290 	/*
291 	 * The below code is to only use struct net_if devices defined in this
292 	 * test as board on which it is run can have its own set of interfaces.
293 	 *
294 	 * As a result one will not rely on linker's specific 'net_if_area'
295 	 * placement.
296 	 */
297 	if ((iface != net_if_lookup_by_dev(DEVICE_GET(eth3_test))) &&
298 	    (iface != net_if_lookup_by_dev(DEVICE_GET(eth2_test))) &&
299 	    (iface != net_if_lookup_by_dev(DEVICE_GET(eth1_test)))) {
300 		return;
301 	}
302 
303 	DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
304 	    net_if_get_by_iface(iface));
305 
306 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
307 		static int ptp_iface_idx;
308 		const struct device *clk;
309 
310 		if (ud->eth_if_count >= ARRAY_SIZE(eth_interfaces)) {
311 			DBG("Invalid interface %p\n", iface);
312 			return;
313 		}
314 
315 		clk = net_eth_get_ptp_clock(iface);
316 		if (!clk) {
317 			non_ptp_interface = ud->eth_if_count;
318 		} else {
319 			ptp_interface[ptp_iface_idx] = ud->eth_if_count;
320 			ptp_clocks[ptp_iface_idx] = net_if_get_by_iface(iface);
321 			ptp_iface_idx++;
322 		}
323 
324 		eth_interfaces[ud->eth_if_count++] = iface;
325 	}
326 
327 	/* By default all interfaces are down initially */
328 	net_if_down(iface);
329 
330 	ud->total_if_count++;
331 }
332 
test_check_interfaces(void)333 static void test_check_interfaces(void)
334 {
335 	struct user_data ud = { 0 };
336 
337 	/* Make sure we have enough interfaces */
338 	net_if_foreach(iface_cb, &ud);
339 
340 	zassert_equal(ud.eth_if_count, MAX_NUM_INTERFACES,
341 		      "Invalid number of ethernet interfaces %d vs %d\n",
342 		      ud.eth_if_count, MAX_NUM_INTERFACES);
343 
344 	zassert_equal(ud.total_if_count, ud.eth_if_count,
345 		      "Invalid number of interfaces %d vs %d\n",
346 		      ud.total_if_count, ud.eth_if_count);
347 }
348 
349 /* As we are testing the ethernet controller clock, the IP addresses are not
350  * relevant for this testing. Anyway, set the IP addresses to the interfaces so
351  * we have a real life scenario.
352  */
test_address_setup(void)353 static void test_address_setup(void)
354 {
355 	struct net_if_addr *ifaddr;
356 	struct net_if *iface1, *iface2, *iface3;
357 
358 	iface1 = eth_interfaces[0];
359 	iface2 = eth_interfaces[1];
360 	iface3 = eth_interfaces[2];
361 
362 	zassert_not_null(iface1, "Interface 1\n");
363 	zassert_not_null(iface2, "Interface 2\n");
364 	zassert_not_null(iface3, "Interface 3\n");
365 
366 	ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
367 				      NET_ADDR_MANUAL, 0);
368 	if (!ifaddr) {
369 		DBG("Cannot add IPv6 address %s\n",
370 		       net_sprint_ipv6_addr(&my_addr1));
371 		zassert_not_null(ifaddr, "addr1\n");
372 	}
373 
374 	/* For testing purposes we need to set the addresses preferred */
375 	ifaddr->addr_state = NET_ADDR_PREFERRED;
376 
377 	ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
378 				      NET_ADDR_MANUAL, 0);
379 	if (!ifaddr) {
380 		DBG("Cannot add IPv6 address %s\n",
381 		       net_sprint_ipv6_addr(&ll_addr));
382 		zassert_not_null(ifaddr, "ll_addr\n");
383 	}
384 
385 	ifaddr->addr_state = NET_ADDR_PREFERRED;
386 
387 	ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
388 				      NET_ADDR_MANUAL, 0);
389 	if (!ifaddr) {
390 		DBG("Cannot add IPv6 address %s\n",
391 		       net_sprint_ipv6_addr(&my_addr2));
392 		zassert_not_null(ifaddr, "addr2\n");
393 	}
394 
395 	ifaddr->addr_state = NET_ADDR_PREFERRED;
396 
397 	ifaddr = net_if_ipv6_addr_add(iface3, &my_addr3,
398 				      NET_ADDR_MANUAL, 0);
399 	if (!ifaddr) {
400 		DBG("Cannot add IPv6 address %s\n",
401 		       net_sprint_ipv6_addr(&my_addr3));
402 		zassert_not_null(ifaddr, "addr3\n");
403 	}
404 
405 	net_if_up(iface1);
406 	net_if_up(iface2);
407 	net_if_up(iface3);
408 
409 	test_failed = false;
410 }
411 
test_ptp_clock_interfaces(void)412 static void test_ptp_clock_interfaces(void)
413 {
414 	const struct device *clk_by_index;
415 	const struct device *clk;
416 	int idx;
417 
418 	idx = ptp_interface[0];
419 	clk = net_eth_get_ptp_clock(eth_interfaces[idx]);
420 	zassert_not_null(clk, "Clock not found for interface %p\n",
421 			 eth_interfaces[idx]);
422 
423 	idx = ptp_interface[1];
424 	clk = net_eth_get_ptp_clock(eth_interfaces[idx]);
425 	zassert_not_null(clk, "Clock not found for interface %p\n",
426 			 eth_interfaces[idx]);
427 
428 	clk = net_eth_get_ptp_clock(eth_interfaces[non_ptp_interface]);
429 	zassert_is_null(clk, "Clock found for interface %p\n",
430 			eth_interfaces[non_ptp_interface]);
431 
432 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
433 	zassert_not_null(clk_by_index,
434 			 "Clock not found for interface index %d\n",
435 			 ptp_clocks[0]);
436 }
437 
test_ptp_clock_iface(int idx)438 static void test_ptp_clock_iface(int idx)
439 {
440 	int rnd_value = sys_rand32_get();
441 	struct net_ptp_time tm = {
442 		.second = 1,
443 		.nanosecond = 1,
444 	};
445 	const struct device *clk;
446 	uint64_t orig, new_value;
447 
448 	clk = net_eth_get_ptp_clock(eth_interfaces[idx]);
449 
450 	zassert_not_null(clk, "Clock not found for interface %p\n",
451 			 eth_interfaces[idx]);
452 
453 	ptp_clock_set(clk, &tm);
454 
455 	orig = timestamp_to_nsec(&tm);
456 
457 	if (rnd_value == 0 || rnd_value < 0) {
458 		rnd_value = 2;
459 	}
460 
461 	ptp_clock_adjust(clk, rnd_value);
462 
463 	(void)memset(&tm, 0, sizeof(tm));
464 	ptp_clock_get(clk, &tm);
465 
466 	new_value = timestamp_to_nsec(&tm);
467 
468 	/* The clock value must be the same after incrementing it */
469 	zassert_equal(orig + rnd_value, new_value,
470 		      "Time adjust failure (%llu vs %llu)\n",
471 		      orig + rnd_value, new_value);
472 }
473 
test_ptp_clock_iface_1(void)474 static void test_ptp_clock_iface_1(void)
475 {
476 	test_ptp_clock_iface(ptp_interface[0]);
477 }
478 
test_ptp_clock_iface_2(void)479 static void test_ptp_clock_iface_2(void)
480 {
481 	test_ptp_clock_iface(ptp_interface[1]);
482 }
483 
484 static ZTEST_BMEM const struct device *clk0;
485 static ZTEST_BMEM const struct device *clk1;
486 
test_ptp_clock_get_by_index(void)487 static void test_ptp_clock_get_by_index(void)
488 {
489 	const struct device *clk, *clk_by_index;
490 	int idx;
491 
492 	idx = ptp_interface[0];
493 
494 	clk = net_eth_get_ptp_clock(eth_interfaces[idx]);
495 	zassert_not_null(clk, "PTP 0 not found");
496 
497 	clk0 = clk;
498 
499 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
500 	zassert_not_null(clk_by_index, "PTP 0 not found");
501 
502 	zassert_equal(clk, clk_by_index, "Interface index %d invalid", idx);
503 
504 	idx = ptp_interface[1];
505 
506 	clk = net_eth_get_ptp_clock(eth_interfaces[idx]);
507 	zassert_not_null(clk, "PTP 1 not found");
508 
509 	clk1 = clk;
510 
511 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[1]);
512 	zassert_not_null(clk_by_index, "PTP 1 not found");
513 
514 	zassert_equal(clk, clk_by_index, "Interface index %d invalid", idx);
515 }
516 
test_ptp_clock_get_by_index_user(void)517 static void test_ptp_clock_get_by_index_user(void)
518 {
519 	const struct device *clk_by_index;
520 
521 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
522 	zassert_not_null(clk_by_index, "PTP 0 not found");
523 	zassert_equal(clk0, clk_by_index, "Invalid PTP clock 0");
524 
525 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[1]);
526 	zassert_not_null(clk_by_index, "PTP 1 not found");
527 	zassert_equal(clk1, clk_by_index, "Invalid PTP clock 1");
528 }
529 
530 static ZTEST_BMEM struct net_ptp_time tm;
531 static ZTEST_BMEM struct net_ptp_time empty;
532 
test_ptp_clock_get_by_xxx(const char * who)533 static void test_ptp_clock_get_by_xxx(const char *who)
534 {
535 	const struct device *clk_by_index;
536 	int ret;
537 
538 	clk_by_index = net_eth_get_ptp_clock_by_index(ptp_clocks[0]);
539 	zassert_not_null(clk_by_index, "PTP 0 not found (%s)", who);
540 	zassert_equal(clk0, clk_by_index, "Invalid PTP clock 0 (%s)", who);
541 
542 	(void)memset(&tm, 0, sizeof(tm));
543 	ptp_clock_get(clk_by_index, &tm);
544 
545 	ret = memcmp(&tm, &empty, sizeof(tm));
546 	zassert_not_equal(ret, 0, "ptp_clock_get() failed in %s mode", who);
547 }
548 
test_ptp_clock_get_kernel(void)549 static void test_ptp_clock_get_kernel(void)
550 {
551 	const struct device *clk;
552 
553 	/* Make sure that this function is really run in kernel mode by
554 	 * calling a function that will not work in user mode.
555 	 */
556 	clk = net_eth_get_ptp_clock(eth_interfaces[0]);
557 
558 	test_ptp_clock_get_by_xxx("kernel");
559 }
560 
test_ptp_clock_get_user(void)561 static void test_ptp_clock_get_user(void)
562 {
563 	test_ptp_clock_get_by_xxx("user");
564 }
565 
setup(void)566 void *setup(void)
567 {
568 	const struct device *clk;
569 
570 	clk = device_get_binding(PTP_VIRT_CLOCK_NAME);
571 	if (clk != NULL) {
572 		k_object_access_grant(clk, k_current_get());
573 	}
574 	return NULL;
575 }
576 
ZTEST(ptp_clock_test_suite,test_ptp_clock)577 ZTEST(ptp_clock_test_suite, test_ptp_clock)
578 {
579 	test_check_interfaces();
580 	test_address_setup();
581 	test_ptp_clock_interfaces();
582 	test_ptp_clock_iface_1();
583 	test_ptp_clock_iface_2();
584 	test_ptp_clock_get_by_index();
585 	test_ptp_clock_get_by_index_user();
586 	test_ptp_clock_get_kernel();
587 	test_ptp_clock_get_user();
588 }
589 
590 ZTEST_SUITE(ptp_clock_test_suite, NULL, setup, NULL, NULL, NULL);
591