]> Git Repo - u-boot.git/blame - test/dm/eth.c
dm: core: Drop dm.h header file from dm-demo.h
[u-boot.git] / test / dm / eth.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0
bfacad7d
JH
2/*
3 * Copyright (c) 2015 National Instruments
4 *
5 * (C) Copyright 2015
6 * Joe Hershberger <[email protected]>
bfacad7d
JH
7 */
8
9#include <common.h>
10#include <dm.h>
9fb625ce 11#include <env.h>
bfacad7d 12#include <fdtdec.h>
f7ae49fc 13#include <log.h>
bfacad7d
JH
14#include <malloc.h>
15#include <net.h>
e721b882 16#include <dm/test.h>
6d9764c2
BM
17#include <dm/device-internal.h>
18#include <dm/uclass-internal.h>
7ece1c61 19#include <asm/eth.h>
e721b882 20#include <test/ut.h>
bfacad7d 21
6d9764c2
BM
22#define DM_TEST_ETH_NUM 4
23
e721b882 24static int dm_test_eth(struct unit_test_state *uts)
bfacad7d 25{
049a95a7 26 net_ping_ip = string_to_ip("1.1.2.2");
bfacad7d 27
382bee57 28 env_set("ethact", "eth@10002000");
bc0571fc 29 ut_assertok(net_loop(PING));
00caae6d 30 ut_asserteq_str("eth@10002000", env_get("ethact"));
bfacad7d 31
382bee57 32 env_set("ethact", "eth@10003000");
bc0571fc 33 ut_assertok(net_loop(PING));
00caae6d 34 ut_asserteq_str("eth@10003000", env_get("ethact"));
bfacad7d 35
382bee57 36 env_set("ethact", "eth@10004000");
bc0571fc 37 ut_assertok(net_loop(PING));
00caae6d 38 ut_asserteq_str("eth@10004000", env_get("ethact"));
bfacad7d
JH
39
40 return 0;
41}
42DM_TEST(dm_test_eth, DM_TESTF_SCAN_FDT);
e58780dc 43
e721b882 44static int dm_test_eth_alias(struct unit_test_state *uts)
e58780dc 45{
049a95a7 46 net_ping_ip = string_to_ip("1.1.2.2");
382bee57 47 env_set("ethact", "eth0");
bc0571fc 48 ut_assertok(net_loop(PING));
00caae6d 49 ut_asserteq_str("eth@10002000", env_get("ethact"));
e58780dc 50
be1a6e94 51 env_set("ethact", "eth6");
bc0571fc 52 ut_assertok(net_loop(PING));
00caae6d 53 ut_asserteq_str("eth@10004000", env_get("ethact"));
e58780dc
JH
54
55 /* Expected to fail since eth2 is not defined in the device tree */
382bee57 56 env_set("ethact", "eth2");
bc0571fc 57 ut_assertok(net_loop(PING));
00caae6d 58 ut_asserteq_str("eth@10002000", env_get("ethact"));
e58780dc 59
382bee57 60 env_set("ethact", "eth5");
bc0571fc 61 ut_assertok(net_loop(PING));
00caae6d 62 ut_asserteq_str("eth@10003000", env_get("ethact"));
e58780dc
JH
63
64 return 0;
65}
66DM_TEST(dm_test_eth_alias, DM_TESTF_SCAN_FDT);
6536b9bb 67
e721b882 68static int dm_test_eth_prime(struct unit_test_state *uts)
6536b9bb 69{
049a95a7 70 net_ping_ip = string_to_ip("1.1.2.2");
6536b9bb
JH
71
72 /* Expected to be "eth@10003000" because of ethprime variable */
382bee57
SG
73 env_set("ethact", NULL);
74 env_set("ethprime", "eth5");
bc0571fc 75 ut_assertok(net_loop(PING));
00caae6d 76 ut_asserteq_str("eth@10003000", env_get("ethact"));
6536b9bb
JH
77
78 /* Expected to be "eth@10002000" because it is first */
382bee57
SG
79 env_set("ethact", NULL);
80 env_set("ethprime", NULL);
bc0571fc 81 ut_assertok(net_loop(PING));
00caae6d 82 ut_asserteq_str("eth@10002000", env_get("ethact"));
6536b9bb
JH
83
84 return 0;
85}
86DM_TEST(dm_test_eth_prime, DM_TESTF_SCAN_FDT);
7d104eab 87
6d9764c2
BM
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 */
102static 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",
be1a6e94 108 "eth3addr", "eth6addr"};
6d9764c2
BM
109 char ethaddr[DM_TEST_ETH_NUM][18];
110 int i;
111
e2e6daed 112 memset(ethaddr, '\0', sizeof(ethaddr));
6d9764c2
BM
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]));
706865af 119 ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
6d9764c2
BM
120
121 /* Invalidate MAC address */
e2e6daed 122 strncpy(ethaddr[i], env_get(addrname[i]), 17);
6d9764c2 123 /* Must disable access protection for ethaddr before clearing */
382bee57
SG
124 env_set(".flags", addrname[i]);
125 env_set(addrname[i], NULL);
6d9764c2
BM
126 }
127
128 /* Set ethact to "eth@10002000" */
382bee57 129 env_set("ethact", ethname[0]);
6d9764c2
BM
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 */
382bee57
SG
136 env_set(".flags", addrname[i]);
137 env_set(addrname[i], ethaddr[i]);
6d9764c2
BM
138
139 /* Probe the device again */
140 ut_assertok(device_probe(dev[i]));
141 }
382bee57
SG
142 env_set(".flags", NULL);
143 env_set("ethact", NULL);
6d9764c2
BM
144
145 return 0;
146}
147DM_TEST(dm_test_eth_act, DM_TESTF_SCAN_FDT);
148
09129bec
JH
149/* The asserts include a return on fail; cleanup in the caller */
150static int _dm_test_eth_rotate1(struct unit_test_state *uts)
7d104eab 151{
7d104eab 152 /* Make sure that the default is to rotate to the next interface */
382bee57 153 env_set("ethact", "eth@10004000");
bc0571fc 154 ut_assertok(net_loop(PING));
00caae6d 155 ut_asserteq_str("eth@10002000", env_get("ethact"));
7d104eab
JH
156
157 /* If ethrotate is no, then we should fail on a bad MAC */
382bee57
SG
158 env_set("ethact", "eth@10004000");
159 env_set("ethrotate", "no");
bc0571fc 160 ut_asserteq(-EINVAL, net_loop(PING));
00caae6d 161 ut_asserteq_str("eth@10004000", env_get("ethact"));
7d104eab 162
09129bec
JH
163 return 0;
164}
7d104eab 165
09129bec
JH
166static int _dm_test_eth_rotate2(struct unit_test_state *uts)
167{
7d104eab 168 /* Make sure we can skip invalid devices */
382bee57 169 env_set("ethact", "eth@10004000");
bc0571fc 170 ut_assertok(net_loop(PING));
00caae6d 171 ut_asserteq_str("eth@10004000", env_get("ethact"));
7d104eab 172
71d7971f 173 /* Make sure we can handle device name which is not eth# */
382bee57 174 env_set("ethact", "sbe5");
71d7971f 175 ut_assertok(net_loop(PING));
00caae6d 176 ut_asserteq_str("sbe5", env_get("ethact"));
71d7971f 177
09129bec
JH
178 return 0;
179}
180
181static 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 */
e2e6daed 190 memset(ethaddr, '\0', sizeof(ethaddr));
be1a6e94
MW
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);
09129bec
JH
195
196 retval = _dm_test_eth_rotate1(uts);
197
198 /* Restore the env */
be1a6e94 199 env_set("eth6addr", ethaddr);
382bee57 200 env_set("ethrotate", NULL);
09129bec
JH
201
202 if (!retval) {
203 /* Invalidate eth0's MAC address */
e2e6daed 204 strncpy(ethaddr, env_get("ethaddr"), 17);
09129bec 205 /* Must disable access protection for ethaddr before clearing */
382bee57
SG
206 env_set(".flags", "ethaddr");
207 env_set("ethaddr", NULL);
09129bec
JH
208
209 retval = _dm_test_eth_rotate2(uts);
210
211 /* Restore the env */
382bee57 212 env_set("ethaddr", ethaddr);
09129bec 213 }
7d104eab 214 /* Restore the env */
382bee57 215 env_set(".flags", NULL);
7d104eab 216
09129bec 217 return retval;
7d104eab
JH
218}
219DM_TEST(dm_test_eth_rotate, DM_TESTF_SCAN_FDT);
7ece1c61 220
09129bec
JH
221/* The asserts include a return on fail; cleanup in the caller */
222static int _dm_test_net_retry(struct unit_test_state *uts)
7ece1c61 223{
7ece1c61
JH
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);
382bee57
SG
229 env_set("ethact", "eth@10004000");
230 env_set("netretry", "yes");
172a31bf 231 sandbox_eth_skip_timeout();
bc0571fc 232 ut_assertok(net_loop(PING));
00caae6d 233 ut_asserteq_str("eth@10002000", env_get("ethact"));
7ece1c61
JH
234
235 /*
236 * eth1 is disabled and netretry is no, so the ping should fail and the
237 * active device should be eth1
238 */
382bee57
SG
239 env_set("ethact", "eth@10004000");
240 env_set("netretry", "no");
172a31bf 241 sandbox_eth_skip_timeout();
a735e6e9 242 ut_asserteq(-ENONET, net_loop(PING));
00caae6d 243 ut_asserteq_str("eth@10004000", env_get("ethact"));
7ece1c61 244
09129bec
JH
245 return 0;
246}
247
248static 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
7ece1c61 256 /* Restore the env */
382bee57 257 env_set("netretry", NULL);
7ece1c61
JH
258 sandbox_eth_disable_response(1, false);
259
09129bec 260 return retval;
7ece1c61
JH
261}
262DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
45988dae
JH
263
264static 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 */
f91f366b
SG
285 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
286 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
45988dae
JH
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);
f91f366b 293 ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
45988dae 294 ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
f91f366b 295 ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
45988dae
JH
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
302static 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
330static 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);
45988dae
JH
337
338 env_set("ethact", "eth@10002000");
ac3f26cc 339 ut_assertok(net_loop(PING));
45988dae
JH
340 ut_asserteq_str("eth@10002000", env_get("ethact"));
341
342 sandbox_eth_set_tx_handler(0, NULL);
343
344 return 0;
345}
346
347DM_TEST(dm_test_eth_async_arp_reply, DM_TESTF_SCAN_FDT);
72ff0042
JH
348
349static 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 */
f91f366b
SG
376 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
377 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
72ff0042
JH
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
387static 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
415static 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);
72ff0042
JH
422
423 env_set("ethact", "eth@10002000");
ac3f26cc 424 ut_assertok(net_loop(PING));
72ff0042
JH
425 ut_asserteq_str("eth@10002000", env_get("ethact"));
426
427 sandbox_eth_set_tx_handler(0, NULL);
428
429 return 0;
430}
431
432DM_TEST(dm_test_eth_async_ping_reply, DM_TESTF_SCAN_FDT);
This page took 0.266533 seconds and 4 git commands to generate.