xref: /openbmc/u-boot/test/dm/eth.c (revision 316f0d0f8f3cbeeefda043e69f3e4e6aa57f7f1d)
1  /*
2   * Copyright (c) 2015 National Instruments
3   *
4   * (C) Copyright 2015
5   * Joe Hershberger <joe.hershberger@ni.com>
6   *
7   * SPDX-License-Identifier:	GPL-2.0
8   */
9  
10  #include <common.h>
11  #include <dm.h>
12  #include <fdtdec.h>
13  #include <malloc.h>
14  #include <net.h>
15  #include <dm/test.h>
16  #include <dm/device-internal.h>
17  #include <dm/uclass-internal.h>
18  #include <asm/eth.h>
19  #include <test/ut.h>
20  
21  DECLARE_GLOBAL_DATA_PTR;
22  
23  #define DM_TEST_ETH_NUM		4
24  
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, DM_TESTF_SCAN_FDT);
44  
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", "eth1");
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, DM_TESTF_SCAN_FDT);
68  
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, DM_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   */
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", "eth1addr"};
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, DM_TESTF_SCAN_FDT);
149  
150  /* The asserts include a return on fail; cleanup in the caller */
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  
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  
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("eth1addr"), 17);
193  	/* Must disable access protection for eth1addr before clearing */
194  	env_set(".flags", "eth1addr");
195  	env_set("eth1addr", NULL);
196  
197  	retval = _dm_test_eth_rotate1(uts);
198  
199  	/* Restore the env */
200  	env_set("eth1addr", 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, DM_TESTF_SCAN_FDT);
221  
222  /* The asserts include a return on fail; cleanup in the caller */
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(-ETIMEDOUT, net_loop(PING));
244  	ut_asserteq_str("eth@10004000", env_get("ethact"));
245  
246  	return 0;
247  }
248  
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, DM_TESTF_SCAN_FDT);
264