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