1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2015 National Instruments
4  *
5  * (C) Copyright 2015
6  * Joe Hershberger <joe.hershberger@ni.com>
7  */
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <env.h>
12 #include <fdtdec.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <net.h>
16 #include <asm/eth.h>
17 #include <dm/test.h>
18 #include <dm/device-internal.h>
19 #include <dm/uclass-internal.h>
20 #include <test/test.h>
21 #include <test/ut.h>
22 
23 #define DM_TEST_ETH_NUM		4
24 
dm_test_eth(struct unit_test_state * uts)25 static int dm_test_eth(struct unit_test_state *uts)
26 {
27 	net_ping_ip = string_to_ip("1.1.2.2");
28 
29 	env_set("ethact", "eth@10002000");
30 	ut_assertok(net_loop(PING));
31 	ut_asserteq_str("eth@10002000", env_get("ethact"));
32 
33 	env_set("ethact", "eth@10003000");
34 	ut_assertok(net_loop(PING));
35 	ut_asserteq_str("eth@10003000", env_get("ethact"));
36 
37 	env_set("ethact", "eth@10004000");
38 	ut_assertok(net_loop(PING));
39 	ut_asserteq_str("eth@10004000", env_get("ethact"));
40 
41 	return 0;
42 }
43 DM_TEST(dm_test_eth, UT_TESTF_SCAN_FDT);
44 
dm_test_eth_alias(struct unit_test_state * uts)45 static int dm_test_eth_alias(struct unit_test_state *uts)
46 {
47 	net_ping_ip = string_to_ip("1.1.2.2");
48 	env_set("ethact", "eth0");
49 	ut_assertok(net_loop(PING));
50 	ut_asserteq_str("eth@10002000", env_get("ethact"));
51 
52 	env_set("ethact", "eth6");
53 	ut_assertok(net_loop(PING));
54 	ut_asserteq_str("eth@10004000", env_get("ethact"));
55 
56 	/* Expected to fail since eth2 is not defined in the device tree */
57 	env_set("ethact", "eth2");
58 	ut_assertok(net_loop(PING));
59 	ut_asserteq_str("eth@10002000", env_get("ethact"));
60 
61 	env_set("ethact", "eth5");
62 	ut_assertok(net_loop(PING));
63 	ut_asserteq_str("eth@10003000", env_get("ethact"));
64 
65 	return 0;
66 }
67 DM_TEST(dm_test_eth_alias, UT_TESTF_SCAN_FDT);
68 
dm_test_eth_prime(struct unit_test_state * uts)69 static int dm_test_eth_prime(struct unit_test_state *uts)
70 {
71 	net_ping_ip = string_to_ip("1.1.2.2");
72 
73 	/* Expected to be "eth@10003000" because of ethprime variable */
74 	env_set("ethact", NULL);
75 	env_set("ethprime", "eth5");
76 	ut_assertok(net_loop(PING));
77 	ut_asserteq_str("eth@10003000", env_get("ethact"));
78 
79 	/* Expected to be "eth@10002000" because it is first */
80 	env_set("ethact", NULL);
81 	env_set("ethprime", NULL);
82 	ut_assertok(net_loop(PING));
83 	ut_asserteq_str("eth@10002000", env_get("ethact"));
84 
85 	return 0;
86 }
87 DM_TEST(dm_test_eth_prime, UT_TESTF_SCAN_FDT);
88 
89 /**
90  * This test case is trying to test the following scenario:
91  *	- All ethernet devices are not probed
92  *	- "ethaddr" for all ethernet devices are not set
93  *	- "ethact" is set to a valid ethernet device name
94  *
95  * With Sandbox default test configuration, all ethernet devices are
96  * probed after power-up, so we have to manually create such scenario:
97  *	- Remove all ethernet devices
98  *	- Remove all "ethaddr" environment variables
99  *	- Set "ethact" to the first ethernet device
100  *
101  * Do a ping test to see if anything goes wrong.
102  */
dm_test_eth_act(struct unit_test_state * uts)103 static int dm_test_eth_act(struct unit_test_state *uts)
104 {
105 	struct udevice *dev[DM_TEST_ETH_NUM];
106 	const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
107 						"sbe5", "eth@10004000"};
108 	const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
109 						 "eth3addr", "eth6addr"};
110 	char ethaddr[DM_TEST_ETH_NUM][18];
111 	int i;
112 
113 	memset(ethaddr, '\0', sizeof(ethaddr));
114 	net_ping_ip = string_to_ip("1.1.2.2");
115 
116 	/* Prepare the test scenario */
117 	for (i = 0; i < DM_TEST_ETH_NUM; i++) {
118 		ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
119 						       ethname[i], &dev[i]));
120 		ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
121 
122 		/* Invalidate MAC address */
123 		strncpy(ethaddr[i], env_get(addrname[i]), 17);
124 		/* Must disable access protection for ethaddr before clearing */
125 		env_set(".flags", addrname[i]);
126 		env_set(addrname[i], NULL);
127 	}
128 
129 	/* Set ethact to "eth@10002000" */
130 	env_set("ethact", ethname[0]);
131 
132 	/* Segment fault might happen if something is wrong */
133 	ut_asserteq(-ENODEV, net_loop(PING));
134 
135 	for (i = 0; i < DM_TEST_ETH_NUM; i++) {
136 		/* Restore the env */
137 		env_set(".flags", addrname[i]);
138 		env_set(addrname[i], ethaddr[i]);
139 
140 		/* Probe the device again */
141 		ut_assertok(device_probe(dev[i]));
142 	}
143 	env_set(".flags", NULL);
144 	env_set("ethact", NULL);
145 
146 	return 0;
147 }
148 DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
149 
150 /* The asserts include a return on fail; cleanup in the caller */
_dm_test_eth_rotate1(struct unit_test_state * uts)151 static int _dm_test_eth_rotate1(struct unit_test_state *uts)
152 {
153 	/* Make sure that the default is to rotate to the next interface */
154 	env_set("ethact", "eth@10004000");
155 	ut_assertok(net_loop(PING));
156 	ut_asserteq_str("eth@10002000", env_get("ethact"));
157 
158 	/* If ethrotate is no, then we should fail on a bad MAC */
159 	env_set("ethact", "eth@10004000");
160 	env_set("ethrotate", "no");
161 	ut_asserteq(-EINVAL, net_loop(PING));
162 	ut_asserteq_str("eth@10004000", env_get("ethact"));
163 
164 	return 0;
165 }
166 
_dm_test_eth_rotate2(struct unit_test_state * uts)167 static int _dm_test_eth_rotate2(struct unit_test_state *uts)
168 {
169 	/* Make sure we can skip invalid devices */
170 	env_set("ethact", "eth@10004000");
171 	ut_assertok(net_loop(PING));
172 	ut_asserteq_str("eth@10004000", env_get("ethact"));
173 
174 	/* Make sure we can handle device name which is not eth# */
175 	env_set("ethact", "sbe5");
176 	ut_assertok(net_loop(PING));
177 	ut_asserteq_str("sbe5", env_get("ethact"));
178 
179 	return 0;
180 }
181 
dm_test_eth_rotate(struct unit_test_state * uts)182 static int dm_test_eth_rotate(struct unit_test_state *uts)
183 {
184 	char ethaddr[18];
185 	int retval;
186 
187 	/* Set target IP to mock ping */
188 	net_ping_ip = string_to_ip("1.1.2.2");
189 
190 	/* Invalidate eth1's MAC address */
191 	memset(ethaddr, '\0', sizeof(ethaddr));
192 	strncpy(ethaddr, env_get("eth6addr"), 17);
193 	/* Must disable access protection for eth6addr before clearing */
194 	env_set(".flags", "eth6addr");
195 	env_set("eth6addr", NULL);
196 
197 	retval = _dm_test_eth_rotate1(uts);
198 
199 	/* Restore the env */
200 	env_set("eth6addr", ethaddr);
201 	env_set("ethrotate", NULL);
202 
203 	if (!retval) {
204 		/* Invalidate eth0's MAC address */
205 		strncpy(ethaddr, env_get("ethaddr"), 17);
206 		/* Must disable access protection for ethaddr before clearing */
207 		env_set(".flags", "ethaddr");
208 		env_set("ethaddr", NULL);
209 
210 		retval = _dm_test_eth_rotate2(uts);
211 
212 		/* Restore the env */
213 		env_set("ethaddr", ethaddr);
214 	}
215 	/* Restore the env */
216 	env_set(".flags", NULL);
217 
218 	return retval;
219 }
220 DM_TEST(dm_test_eth_rotate, UT_TESTF_SCAN_FDT);
221 
222 /* The asserts include a return on fail; cleanup in the caller */
_dm_test_net_retry(struct unit_test_state * uts)223 static int _dm_test_net_retry(struct unit_test_state *uts)
224 {
225 	/*
226 	 * eth1 is disabled and netretry is yes, so the ping should succeed and
227 	 * the active device should be eth0
228 	 */
229 	sandbox_eth_disable_response(1, true);
230 	env_set("ethact", "eth@10004000");
231 	env_set("netretry", "yes");
232 	sandbox_eth_skip_timeout();
233 	ut_assertok(net_loop(PING));
234 	ut_asserteq_str("eth@10002000", env_get("ethact"));
235 
236 	/*
237 	 * eth1 is disabled and netretry is no, so the ping should fail and the
238 	 * active device should be eth1
239 	 */
240 	env_set("ethact", "eth@10004000");
241 	env_set("netretry", "no");
242 	sandbox_eth_skip_timeout();
243 	ut_asserteq(-ENONET, net_loop(PING));
244 	ut_asserteq_str("eth@10004000", env_get("ethact"));
245 
246 	return 0;
247 }
248 
dm_test_net_retry(struct unit_test_state * uts)249 static int dm_test_net_retry(struct unit_test_state *uts)
250 {
251 	int retval;
252 
253 	net_ping_ip = string_to_ip("1.1.2.2");
254 
255 	retval = _dm_test_net_retry(uts);
256 
257 	/* Restore the env */
258 	env_set("netretry", NULL);
259 	sandbox_eth_disable_response(1, false);
260 
261 	return retval;
262 }
263 DM_TEST(dm_test_net_retry, UT_TESTF_SCAN_FDT);
264 
sb_check_arp_reply(struct udevice * dev,void * packet,unsigned int len)265 static int sb_check_arp_reply(struct udevice *dev, void *packet,
266 			      unsigned int len)
267 {
268 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
269 	struct ethernet_hdr *eth = packet;
270 	struct arp_hdr *arp;
271 	/* Used by all of the ut_assert macros */
272 	struct unit_test_state *uts = priv->priv;
273 
274 	if (ntohs(eth->et_protlen) != PROT_ARP)
275 		return 0;
276 
277 	arp = packet + ETHER_HDR_SIZE;
278 
279 	if (ntohs(arp->ar_op) != ARPOP_REPLY)
280 		return 0;
281 
282 	/* This test would be worthless if we are not waiting */
283 	ut_assert(arp_is_waiting());
284 
285 	/* Validate response */
286 	ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
287 	ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
288 	ut_assert(eth->et_protlen == htons(PROT_ARP));
289 
290 	ut_assert(arp->ar_hrd == htons(ARP_ETHER));
291 	ut_assert(arp->ar_pro == htons(PROT_IP));
292 	ut_assert(arp->ar_hln == ARP_HLEN);
293 	ut_assert(arp->ar_pln == ARP_PLEN);
294 	ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
295 	ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
296 	ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
297 	ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
298 		  string_to_ip("1.1.2.4").s_addr);
299 
300 	return 0;
301 }
302 
sb_with_async_arp_handler(struct udevice * dev,void * packet,unsigned int len)303 static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
304 				     unsigned int len)
305 {
306 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
307 	struct ethernet_hdr *eth = packet;
308 	struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
309 	int ret;
310 
311 	/*
312 	 * If we are about to generate a reply to ARP, first inject a request
313 	 * from another host
314 	 */
315 	if (ntohs(eth->et_protlen) == PROT_ARP &&
316 	    ntohs(arp->ar_op) == ARPOP_REQUEST) {
317 		/* Make sure sandbox_eth_recv_arp_req() knows who is asking */
318 		priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
319 
320 		ret = sandbox_eth_recv_arp_req(dev);
321 		if (ret)
322 			return ret;
323 	}
324 
325 	sandbox_eth_arp_req_to_reply(dev, packet, len);
326 	sandbox_eth_ping_req_to_reply(dev, packet, len);
327 
328 	return sb_check_arp_reply(dev, packet, len);
329 }
330 
dm_test_eth_async_arp_reply(struct unit_test_state * uts)331 static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
332 {
333 	net_ping_ip = string_to_ip("1.1.2.2");
334 
335 	sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
336 	/* Used by all of the ut_assert macros in the tx_handler */
337 	sandbox_eth_set_priv(0, uts);
338 
339 	env_set("ethact", "eth@10002000");
340 	ut_assertok(net_loop(PING));
341 	ut_asserteq_str("eth@10002000", env_get("ethact"));
342 
343 	sandbox_eth_set_tx_handler(0, NULL);
344 
345 	return 0;
346 }
347 
348 DM_TEST(dm_test_eth_async_arp_reply, UT_TESTF_SCAN_FDT);
349 
sb_check_ping_reply(struct udevice * dev,void * packet,unsigned int len)350 static int sb_check_ping_reply(struct udevice *dev, void *packet,
351 			       unsigned int len)
352 {
353 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
354 	struct ethernet_hdr *eth = packet;
355 	struct ip_udp_hdr *ip;
356 	struct icmp_hdr *icmp;
357 	/* Used by all of the ut_assert macros */
358 	struct unit_test_state *uts = priv->priv;
359 
360 	if (ntohs(eth->et_protlen) != PROT_IP)
361 		return 0;
362 
363 	ip = packet + ETHER_HDR_SIZE;
364 
365 	if (ip->ip_p != IPPROTO_ICMP)
366 		return 0;
367 
368 	icmp = (struct icmp_hdr *)&ip->udp_src;
369 
370 	if (icmp->type != ICMP_ECHO_REPLY)
371 		return 0;
372 
373 	/* This test would be worthless if we are not waiting */
374 	ut_assert(arp_is_waiting());
375 
376 	/* Validate response */
377 	ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
378 	ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
379 	ut_assert(eth->et_protlen == htons(PROT_IP));
380 
381 	ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
382 	ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
383 		  string_to_ip("1.1.2.4").s_addr);
384 
385 	return 0;
386 }
387 
sb_with_async_ping_handler(struct udevice * dev,void * packet,unsigned int len)388 static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
389 				      unsigned int len)
390 {
391 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
392 	struct ethernet_hdr *eth = packet;
393 	struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
394 	int ret;
395 
396 	/*
397 	 * If we are about to generate a reply to ARP, first inject a request
398 	 * from another host
399 	 */
400 	if (ntohs(eth->et_protlen) == PROT_ARP &&
401 	    ntohs(arp->ar_op) == ARPOP_REQUEST) {
402 		/* Make sure sandbox_eth_recv_arp_req() knows who is asking */
403 		priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
404 
405 		ret = sandbox_eth_recv_ping_req(dev);
406 		if (ret)
407 			return ret;
408 	}
409 
410 	sandbox_eth_arp_req_to_reply(dev, packet, len);
411 	sandbox_eth_ping_req_to_reply(dev, packet, len);
412 
413 	return sb_check_ping_reply(dev, packet, len);
414 }
415 
dm_test_eth_async_ping_reply(struct unit_test_state * uts)416 static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
417 {
418 	net_ping_ip = string_to_ip("1.1.2.2");
419 
420 	sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
421 	/* Used by all of the ut_assert macros in the tx_handler */
422 	sandbox_eth_set_priv(0, uts);
423 
424 	env_set("ethact", "eth@10002000");
425 	ut_assertok(net_loop(PING));
426 	ut_asserteq_str("eth@10002000", env_get("ethact"));
427 
428 	sandbox_eth_set_tx_handler(0, NULL);
429 
430 	return 0;
431 }
432 
433 DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
434