blob: 1087ae9572da21c6a3a01b546f7b254956eb9f23 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Joe Hershberger4c197242015-03-22 17:09:15 -05002/*
3 * Copyright (c) 2015 National Instruments
4 *
5 * (C) Copyright 2015
6 * Joe Hershberger <joe.hershberger@ni.com>
Joe Hershberger4c197242015-03-22 17:09:15 -05007 */
8
Joe Hershberger4c197242015-03-22 17:09:15 -05009#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060010#include <env.h>
Joe Hershberger4c197242015-03-22 17:09:15 -050011#include <fdtdec.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Joe Hershberger4c197242015-03-22 17:09:15 -050013#include <malloc.h>
14#include <net.h>
Viacheslav Mitrofanovf96b1092022-12-02 12:18:09 +030015#include <net6.h>
Simon Glass75c4d412020-07-19 10:15:37 -060016#include <asm/eth.h>
Joe Hershberger3a77be52015-05-20 14:27:27 -050017#include <dm/test.h>
Bin Meng111473a2015-10-07 21:45:43 -070018#include <dm/device-internal.h>
19#include <dm/uclass-internal.h>
Simon Glass75c4d412020-07-19 10:15:37 -060020#include <test/test.h>
Joe Hershberger3a77be52015-05-20 14:27:27 -050021#include <test/ut.h>
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -070022#include <ndisc.h>
Joe Hershberger4c197242015-03-22 17:09:15 -050023
Bin Meng111473a2015-10-07 21:45:43 -070024#define DM_TEST_ETH_NUM 4
25
Viacheslav Mitrofanovf96b1092022-12-02 12:18:09 +030026#if IS_ENABLED(CONFIG_IPV6)
27static int dm_test_string_to_ip6(struct unit_test_state *uts)
28{
29 char *str;
30 struct test_ip6_pair {
31 char *string_addr;
32 struct in6_addr ip6_addr;
33 };
34
35 struct in6_addr ip6 = {0};
36
37 /* Correct statements */
38 struct test_ip6_pair test_suite[] = {
39 {"2001:db8::0:1234:1", {.s6_addr32[0] = 0xb80d0120,
40 .s6_addr32[1] = 0x00000000,
41 .s6_addr32[2] = 0x00000000,
42 .s6_addr32[3] = 0x01003412}},
43 {"2001:0db8:0000:0000:0000:0000:1234:0001",
44 {.s6_addr32[0] = 0xb80d0120,
45 .s6_addr32[1] = 0x00000000,
46 .s6_addr32[2] = 0x00000000,
47 .s6_addr32[3] = 0x01003412}},
48 {"::1", {.s6_addr32[0] = 0x00000000,
49 .s6_addr32[1] = 0x00000000,
50 .s6_addr32[2] = 0x00000000,
51 .s6_addr32[3] = 0x01000000}},
52 {"::ffff:192.168.1.1", {.s6_addr32[0] = 0x00000000,
53 .s6_addr32[1] = 0x00000000,
54 .s6_addr32[2] = 0xffff0000,
55 .s6_addr32[3] = 0x0101a8c0}},
56 };
57
58 for (int i = 0; i < ARRAY_SIZE(test_suite); ++i) {
59 ut_assertok(string_to_ip6(test_suite[i].string_addr,
60 strlen(test_suite[i].string_addr), &ip6));
61 ut_asserteq_mem(&ip6, &test_suite[i].ip6_addr,
62 sizeof(struct in6_addr));
63 }
64
65 /* Incorrect statements */
66 str = "hello:world";
67 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
68 str = "2001:db8::0::0";
69 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
70 str = "2001:db8:192.168.1.1::1";
71 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
72 str = "192.168.1.1";
73 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
74
75 return 0;
76}
77DM_TEST(dm_test_string_to_ip6, 0);
Viacheslav Mitrofanov224f5632022-12-02 12:18:10 +030078
79static int dm_test_csum_ipv6_magic(struct unit_test_state *uts)
80{
81 unsigned short csum = 0xbeef;
82 /* Predefined correct parameters */
83 unsigned short correct_csum = 0xd8ac;
84 struct in6_addr saddr = {.s6_addr32[0] = 0x000080fe,
85 .s6_addr32[1] = 0x00000000,
86 .s6_addr32[2] = 0xffe9f242,
87 .s6_addr32[3] = 0xe8f66dfe};
88 struct in6_addr daddr = {.s6_addr32[0] = 0x000080fe,
89 .s6_addr32[1] = 0x00000000,
90 .s6_addr32[2] = 0xffd5b372,
91 .s6_addr32[3] = 0x3ef692fe};
92 u16 len = 1460;
93 unsigned short proto = 17;
94 unsigned int head_csum = 0x91f0;
95
96 csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
97 ut_asserteq(csum, correct_csum);
98
99 /* Broke a parameter */
100 proto--;
101 csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
102 ut_assert(csum != correct_csum);
103
104 return 0;
105}
106DM_TEST(dm_test_csum_ipv6_magic, 0);
Viacheslav Mitrofanovac6a9ce2022-12-02 12:18:11 +0300107
108static int dm_test_ip6_addr_in_subnet(struct unit_test_state *uts)
109{
110 struct in6_addr our = {.s6_addr32[0] = 0x000080fe,
111 .s6_addr32[1] = 0x00000000,
112 .s6_addr32[2] = 0xffe9f242,
113 .s6_addr32[3] = 0xe8f66dfe};
114 struct in6_addr neigh1 = {.s6_addr32[0] = 0x000080fe,
115 .s6_addr32[1] = 0x00000000,
116 .s6_addr32[2] = 0xffd5b372,
117 .s6_addr32[3] = 0x3ef692fe};
118 struct in6_addr neigh2 = {.s6_addr32[0] = 0x60480120,
119 .s6_addr32[1] = 0x00006048,
120 .s6_addr32[2] = 0x00000000,
121 .s6_addr32[3] = 0x00008888};
122
123 /* in */
124 ut_assert(ip6_addr_in_subnet(&our, &neigh1, 64));
125 /* outside */
126 ut_assert(!ip6_addr_in_subnet(&our, &neigh2, 64));
127 ut_assert(!ip6_addr_in_subnet(&our, &neigh1, 128));
128
129 return 0;
130}
131DM_TEST(dm_test_ip6_addr_in_subnet, 0);
Viacheslav Mitrofanov3b673c02022-12-02 12:18:12 +0300132
133static int dm_test_ip6_make_snma(struct unit_test_state *uts)
134{
135 struct in6_addr mult = {0};
136 struct in6_addr correct_addr = {
137 .s6_addr32[0] = 0x000002ff,
138 .s6_addr32[1] = 0x00000000,
139 .s6_addr32[2] = 0x01000000,
140 .s6_addr32[3] = 0xe8f66dff};
141 struct in6_addr addr = { .s6_addr32[0] = 0x000080fe,
142 .s6_addr32[1] = 0x00000000,
143 .s6_addr32[2] = 0xffe9f242,
144 .s6_addr32[3] = 0xe8f66dfe};
145
146 ip6_make_snma(&mult, &addr);
147 ut_asserteq_mem(&mult, &correct_addr, sizeof(struct in6_addr));
148
149 return 0;
150}
151DM_TEST(dm_test_ip6_make_snma, 0);
Viacheslav Mitrofanov5c8e0a62022-12-02 12:18:13 +0300152
153static int dm_test_ip6_make_lladdr(struct unit_test_state *uts)
154{
155 struct in6_addr generated_lladdr = {0};
156 struct in6_addr correct_lladdr = {
157 .s6_addr32[0] = 0x000080fe,
158 .s6_addr32[1] = 0x00000000,
159 .s6_addr32[2] = 0xffabf33a,
160 .s6_addr32[3] = 0xfbb352fe};
161 const unsigned char mac[6] = {0x38, 0xf3, 0xab, 0x52, 0xb3, 0xfb};
162
163 ip6_make_lladdr(&generated_lladdr, mac);
164 ut_asserteq_mem(&generated_lladdr, &correct_lladdr,
165 sizeof(struct in6_addr));
166
167 return 0;
168}
Simon Glass1a92f832024-08-22 07:57:48 -0600169DM_TEST(dm_test_ip6_make_lladdr, UTF_SCAN_FDT);
Viacheslav Mitrofanovf96b1092022-12-02 12:18:09 +0300170#endif
171
Joe Hershberger3a77be52015-05-20 14:27:27 -0500172static int dm_test_eth(struct unit_test_state *uts)
Joe Hershberger4c197242015-03-22 17:09:15 -0500173{
Jerome Forissier717aa432025-04-15 23:17:43 +0200174 char *argv[] = { "ping", "1.1.2.2" };
Joe Hershberger4c197242015-03-22 17:09:15 -0500175
Simon Glass6a38e412017-08-03 12:22:09 -0600176 env_set("ethact", "eth@10002000");
Jerome Forissier717aa432025-04-15 23:17:43 +0200177 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600178 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger4c197242015-03-22 17:09:15 -0500179
Simon Glass6a38e412017-08-03 12:22:09 -0600180 env_set("ethact", "eth@10003000");
Jerome Forissier717aa432025-04-15 23:17:43 +0200181 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600182 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershberger4c197242015-03-22 17:09:15 -0500183
Simon Glass6a38e412017-08-03 12:22:09 -0600184 env_set("ethact", "eth@10004000");
Jerome Forissier717aa432025-04-15 23:17:43 +0200185 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600186 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershberger4c197242015-03-22 17:09:15 -0500187
188 return 0;
189}
Simon Glass1a92f832024-08-22 07:57:48 -0600190DM_TEST(dm_test_eth, UTF_SCAN_FDT);
Joe Hershberger279d2f62015-03-22 17:09:16 -0500191
Joe Hershberger3a77be52015-05-20 14:27:27 -0500192static int dm_test_eth_alias(struct unit_test_state *uts)
Joe Hershberger279d2f62015-03-22 17:09:16 -0500193{
Jerome Forissier717aa432025-04-15 23:17:43 +0200194 char *argv[] = { "ping", "1.1.2.2" };
195
Simon Glass6a38e412017-08-03 12:22:09 -0600196 env_set("ethact", "eth0");
Jerome Forissier717aa432025-04-15 23:17:43 +0200197 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600198 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500199
Michael Walle7c41a222020-06-02 01:47:09 +0200200 env_set("ethact", "eth6");
Jerome Forissier717aa432025-04-15 23:17:43 +0200201 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600202 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500203
Claudiu Manoild9eaa922021-03-14 20:14:57 +0800204 /* Expected to fail since eth1 is not defined in the device tree */
205 env_set("ethact", "eth1");
Jerome Forissier717aa432025-04-15 23:17:43 +0200206 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600207 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500208
Simon Glass6a38e412017-08-03 12:22:09 -0600209 env_set("ethact", "eth5");
Jerome Forissier717aa432025-04-15 23:17:43 +0200210 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600211 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500212
213 return 0;
214}
Simon Glass1a92f832024-08-22 07:57:48 -0600215DM_TEST(dm_test_eth_alias, UTF_SCAN_FDT);
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500216
Joe Hershberger3a77be52015-05-20 14:27:27 -0500217static int dm_test_eth_prime(struct unit_test_state *uts)
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500218{
Jerome Forissier717aa432025-04-15 23:17:43 +0200219 char *argv[] = { "ping", "1.1.2.2" };
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500220
221 /* Expected to be "eth@10003000" because of ethprime variable */
Simon Glass6a38e412017-08-03 12:22:09 -0600222 env_set("ethact", NULL);
223 env_set("ethprime", "eth5");
Jerome Forissier717aa432025-04-15 23:17:43 +0200224 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600225 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500226
227 /* Expected to be "eth@10002000" because it is first */
Simon Glass6a38e412017-08-03 12:22:09 -0600228 env_set("ethact", NULL);
229 env_set("ethprime", NULL);
Jerome Forissier717aa432025-04-15 23:17:43 +0200230 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600231 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500232
233 return 0;
234}
Simon Glass1a92f832024-08-22 07:57:48 -0600235DM_TEST(dm_test_eth_prime, UTF_SCAN_FDT);
Joe Hershbergerf340e542015-03-22 17:09:18 -0500236
Bin Meng111473a2015-10-07 21:45:43 -0700237/**
238 * This test case is trying to test the following scenario:
239 * - All ethernet devices are not probed
240 * - "ethaddr" for all ethernet devices are not set
241 * - "ethact" is set to a valid ethernet device name
242 *
243 * With Sandbox default test configuration, all ethernet devices are
244 * probed after power-up, so we have to manually create such scenario:
245 * - Remove all ethernet devices
246 * - Remove all "ethaddr" environment variables
247 * - Set "ethact" to the first ethernet device
248 *
249 * Do a ping test to see if anything goes wrong.
250 */
251static int dm_test_eth_act(struct unit_test_state *uts)
252{
Jerome Forissier717aa432025-04-15 23:17:43 +0200253 char *argv[] = { "ping", "1.1.2.2" };
Bin Meng111473a2015-10-07 21:45:43 -0700254 struct udevice *dev[DM_TEST_ETH_NUM];
255 const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
256 "sbe5", "eth@10004000"};
257 const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
Michael Walle7c41a222020-06-02 01:47:09 +0200258 "eth3addr", "eth6addr"};
Bin Meng111473a2015-10-07 21:45:43 -0700259 char ethaddr[DM_TEST_ETH_NUM][18];
260 int i;
261
Tom Rini0ac17d82017-09-26 14:08:30 -0400262 memset(ethaddr, '\0', sizeof(ethaddr));
Bin Meng111473a2015-10-07 21:45:43 -0700263
264 /* Prepare the test scenario */
265 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
Sean Anderson85e8fc82023-10-28 18:57:27 -0400266 char *addr;
267
Bin Meng111473a2015-10-07 21:45:43 -0700268 ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
269 ethname[i], &dev[i]));
Stefan Roese80b5bc92017-03-20 12:51:48 +0100270 ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
Bin Meng111473a2015-10-07 21:45:43 -0700271
272 /* Invalidate MAC address */
Sean Anderson85e8fc82023-10-28 18:57:27 -0400273 addr = env_get(addrname[i]);
274 ut_assertnonnull(addr);
275 strncpy(ethaddr[i], addr, 17);
Bin Meng111473a2015-10-07 21:45:43 -0700276 /* Must disable access protection for ethaddr before clearing */
Simon Glass6a38e412017-08-03 12:22:09 -0600277 env_set(".flags", addrname[i]);
278 env_set(addrname[i], NULL);
Bin Meng111473a2015-10-07 21:45:43 -0700279 }
280
281 /* Set ethact to "eth@10002000" */
Simon Glass6a38e412017-08-03 12:22:09 -0600282 env_set("ethact", ethname[0]);
Bin Meng111473a2015-10-07 21:45:43 -0700283
284 /* Segment fault might happen if something is wrong */
Jerome Forissier717aa432025-04-15 23:17:43 +0200285 ut_asserteq(CMD_RET_FAILURE, do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Bin Meng111473a2015-10-07 21:45:43 -0700286
287 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
288 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600289 env_set(".flags", addrname[i]);
290 env_set(addrname[i], ethaddr[i]);
Bin Meng111473a2015-10-07 21:45:43 -0700291
292 /* Probe the device again */
293 ut_assertok(device_probe(dev[i]));
294 }
Simon Glass6a38e412017-08-03 12:22:09 -0600295 env_set(".flags", NULL);
296 env_set("ethact", NULL);
Bin Meng111473a2015-10-07 21:45:43 -0700297
298 return 0;
299}
Simon Glass1a92f832024-08-22 07:57:48 -0600300DM_TEST(dm_test_eth_act, UTF_SCAN_FDT);
Bin Meng111473a2015-10-07 21:45:43 -0700301
Sean Anderson86f5cc72022-05-05 13:11:32 -0400302/* Ensure that all addresses are loaded properly */
303static int dm_test_ethaddr(struct unit_test_state *uts)
304{
305 static const char *const addr[] = {
306 "02:00:11:22:33:44",
307 "02:00:11:22:33:48", /* dsa slave */
308 "02:00:11:22:33:45",
309 "02:00:11:22:33:48", /* dsa master */
310 "02:00:11:22:33:46",
311 "02:00:11:22:33:47",
312 "02:00:11:22:33:48", /* dsa slave */
313 "02:00:11:22:33:49",
314 };
315 int i;
316
317 for (i = 0; i < ARRAY_SIZE(addr); i++) {
318 char addrname[10];
Sean Anderson85e8fc82023-10-28 18:57:27 -0400319 char *env_addr;
Sean Anderson86f5cc72022-05-05 13:11:32 -0400320
321 if (i)
322 snprintf(addrname, sizeof(addrname), "eth%daddr", i + 1);
323 else
324 strcpy(addrname, "ethaddr");
Sean Anderson85e8fc82023-10-28 18:57:27 -0400325
326 env_addr = env_get(addrname);
327 ut_assertnonnull(env_addr);
328 ut_asserteq_str(addr[i], env_addr);
Sean Anderson86f5cc72022-05-05 13:11:32 -0400329 }
330
331 return 0;
332}
Simon Glass1a92f832024-08-22 07:57:48 -0600333DM_TEST(dm_test_ethaddr, UTF_SCAN_FDT);
Sean Anderson86f5cc72022-05-05 13:11:32 -0400334
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500335/* The asserts include a return on fail; cleanup in the caller */
336static int _dm_test_eth_rotate1(struct unit_test_state *uts)
Joe Hershbergerf340e542015-03-22 17:09:18 -0500337{
Jerome Forissier717aa432025-04-15 23:17:43 +0200338 char *argv[] = { "ping", "1.1.2.2" };
339
Joe Hershbergerf340e542015-03-22 17:09:18 -0500340 /* Make sure that the default is to rotate to the next interface */
Simon Glass6a38e412017-08-03 12:22:09 -0600341 env_set("ethact", "eth@10004000");
Jerome Forissier717aa432025-04-15 23:17:43 +0200342 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600343 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500344
345 /* If ethrotate is no, then we should fail on a bad MAC */
Simon Glass6a38e412017-08-03 12:22:09 -0600346 env_set("ethact", "eth@10004000");
347 env_set("ethrotate", "no");
Jerome Forissier717aa432025-04-15 23:17:43 +0200348 ut_asserteq(CMD_RET_FAILURE, do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600349 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500350
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500351 return 0;
352}
Joe Hershbergerf340e542015-03-22 17:09:18 -0500353
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500354static int _dm_test_eth_rotate2(struct unit_test_state *uts)
355{
Jerome Forissier717aa432025-04-15 23:17:43 +0200356 char *argv[] = { "ping", "1.1.2.2" };
357
Joe Hershbergerf340e542015-03-22 17:09:18 -0500358 /* Make sure we can skip invalid devices */
Simon Glass6a38e412017-08-03 12:22:09 -0600359 env_set("ethact", "eth@10004000");
Jerome Forissier717aa432025-04-15 23:17:43 +0200360 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600361 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500362
Bin Meng04a11cb2015-08-27 22:25:53 -0700363 /* Make sure we can handle device name which is not eth# */
Simon Glass6a38e412017-08-03 12:22:09 -0600364 env_set("ethact", "sbe5");
Jerome Forissier717aa432025-04-15 23:17:43 +0200365 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
Simon Glass64b723f2017-08-03 12:22:12 -0600366 ut_asserteq_str("sbe5", env_get("ethact"));
Bin Meng04a11cb2015-08-27 22:25:53 -0700367
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500368 return 0;
369}
370
371static int dm_test_eth_rotate(struct unit_test_state *uts)
372{
373 char ethaddr[18];
374 int retval;
375
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500376 /* Invalidate eth1's MAC address */
Tom Rini0ac17d82017-09-26 14:08:30 -0400377 memset(ethaddr, '\0', sizeof(ethaddr));
Michael Walle7c41a222020-06-02 01:47:09 +0200378 strncpy(ethaddr, env_get("eth6addr"), 17);
379 /* Must disable access protection for eth6addr before clearing */
380 env_set(".flags", "eth6addr");
381 env_set("eth6addr", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500382
383 retval = _dm_test_eth_rotate1(uts);
384
Joe Hershbergerf340e542015-03-22 17:09:18 -0500385 /* Restore the env */
Michael Walle7c41a222020-06-02 01:47:09 +0200386 env_set("eth6addr", ethaddr);
Simon Glass6a38e412017-08-03 12:22:09 -0600387 env_set("ethrotate", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500388
389 if (!retval) {
390 /* Invalidate eth0's MAC address */
Tom Rini0ac17d82017-09-26 14:08:30 -0400391 strncpy(ethaddr, env_get("ethaddr"), 17);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500392 /* Must disable access protection for ethaddr before clearing */
Simon Glass6a38e412017-08-03 12:22:09 -0600393 env_set(".flags", "ethaddr");
394 env_set("ethaddr", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500395
396 retval = _dm_test_eth_rotate2(uts);
397
398 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600399 env_set("ethaddr", ethaddr);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500400 }
Jerome Forissier717aa432025-04-15 23:17:43 +0200401
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500402 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600403 env_set(".flags", NULL);
Joe Hershbergerf340e542015-03-22 17:09:18 -0500404
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500405 return retval;
Joe Hershbergerf340e542015-03-22 17:09:18 -0500406}
Simon Glass1a92f832024-08-22 07:57:48 -0600407DM_TEST(dm_test_eth_rotate, UTF_SCAN_FDT);
Joe Hershbergerf933a932015-03-22 17:09:20 -0500408
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500409/* The asserts include a return on fail; cleanup in the caller */
410static int _dm_test_net_retry(struct unit_test_state *uts)
Joe Hershbergerf933a932015-03-22 17:09:20 -0500411{
Jerome Forissier717aa432025-04-15 23:17:43 +0200412 char *argv[] = { "ping", "1.1.2.2" };
413
Joe Hershbergerf933a932015-03-22 17:09:20 -0500414 /*
Jerome Forissier717aa432025-04-15 23:17:43 +0200415 * eth0 is disabled and netretry is yes, so the ping should succeed and
416 * the active device should be eth1
Joe Hershbergerf933a932015-03-22 17:09:20 -0500417 */
Jerome Forissier717aa432025-04-15 23:17:43 +0200418 sandbox_eth_disable_response(0, true);
419 env_set("ethact", "eth@10002000");
Simon Glass6a38e412017-08-03 12:22:09 -0600420 env_set("netretry", "yes");
Joe Hershberger6901f432015-04-21 13:57:20 -0500421 sandbox_eth_skip_timeout();
Jerome Forissier717aa432025-04-15 23:17:43 +0200422 ut_assertok(do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
423 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershbergerf933a932015-03-22 17:09:20 -0500424
425 /*
Jerome Forissier717aa432025-04-15 23:17:43 +0200426 * eth0 is disabled and netretry is no, so the ping should fail and the
427 * active device should be eth0
Joe Hershbergerf933a932015-03-22 17:09:20 -0500428 */
Jerome Forissier717aa432025-04-15 23:17:43 +0200429 env_set("ethact", "eth@10002000");
Simon Glass6a38e412017-08-03 12:22:09 -0600430 env_set("netretry", "no");
Joe Hershberger6901f432015-04-21 13:57:20 -0500431 sandbox_eth_skip_timeout();
Jerome Forissier717aa432025-04-15 23:17:43 +0200432 ut_asserteq(CMD_RET_FAILURE, do_ping(NULL, 0, ARRAY_SIZE(argv), argv));
433 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergerf933a932015-03-22 17:09:20 -0500434
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500435 return 0;
436}
437
438static int dm_test_net_retry(struct unit_test_state *uts)
439{
440 int retval;
441
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500442 retval = _dm_test_net_retry(uts);
443
Joe Hershbergerf933a932015-03-22 17:09:20 -0500444 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600445 env_set("netretry", NULL);
Joe Hershbergerf933a932015-03-22 17:09:20 -0500446 sandbox_eth_disable_response(1, false);
447
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500448 return retval;
Joe Hershbergerf933a932015-03-22 17:09:20 -0500449}
Simon Glass1a92f832024-08-22 07:57:48 -0600450DM_TEST(dm_test_net_retry, UTF_SCAN_FDT);
Joe Hershberger54418d02018-09-26 16:49:00 -0500451
Jerome Forissier717aa432025-04-15 23:17:43 +0200452#if CONFIG_IS_ENABLED(NET)
Joe Hershberger54418d02018-09-26 16:49:00 -0500453static int sb_check_arp_reply(struct udevice *dev, void *packet,
454 unsigned int len)
455{
456 struct eth_sandbox_priv *priv = dev_get_priv(dev);
457 struct ethernet_hdr *eth = packet;
458 struct arp_hdr *arp;
459 /* Used by all of the ut_assert macros */
460 struct unit_test_state *uts = priv->priv;
461
462 if (ntohs(eth->et_protlen) != PROT_ARP)
463 return 0;
464
465 arp = packet + ETHER_HDR_SIZE;
466
467 if (ntohs(arp->ar_op) != ARPOP_REPLY)
468 return 0;
469
470 /* This test would be worthless if we are not waiting */
471 ut_assert(arp_is_waiting());
472
473 /* Validate response */
Simon Glassa3186e62020-05-10 12:52:45 -0600474 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
475 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500476 ut_assert(eth->et_protlen == htons(PROT_ARP));
477
478 ut_assert(arp->ar_hrd == htons(ARP_ETHER));
479 ut_assert(arp->ar_pro == htons(PROT_IP));
480 ut_assert(arp->ar_hln == ARP_HLEN);
481 ut_assert(arp->ar_pln == ARP_PLEN);
Simon Glassa3186e62020-05-10 12:52:45 -0600482 ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500483 ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
Simon Glassa3186e62020-05-10 12:52:45 -0600484 ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500485 ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
486 string_to_ip("1.1.2.4").s_addr);
487
488 return 0;
489}
490
491static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
492 unsigned int len)
493{
494 struct eth_sandbox_priv *priv = dev_get_priv(dev);
495 struct ethernet_hdr *eth = packet;
496 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
497 int ret;
498
499 /*
500 * If we are about to generate a reply to ARP, first inject a request
501 * from another host
502 */
503 if (ntohs(eth->et_protlen) == PROT_ARP &&
504 ntohs(arp->ar_op) == ARPOP_REQUEST) {
505 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
506 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
507
508 ret = sandbox_eth_recv_arp_req(dev);
509 if (ret)
510 return ret;
511 }
512
513 sandbox_eth_arp_req_to_reply(dev, packet, len);
514 sandbox_eth_ping_req_to_reply(dev, packet, len);
515
516 return sb_check_arp_reply(dev, packet, len);
517}
Jerome Forissier717aa432025-04-15 23:17:43 +0200518#endif
Joe Hershberger54418d02018-09-26 16:49:00 -0500519
Jerome Forissier717aa432025-04-15 23:17:43 +0200520#if CONFIG_IS_ENABLED(NET)
Joe Hershberger54418d02018-09-26 16:49:00 -0500521static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
522{
523 net_ping_ip = string_to_ip("1.1.2.2");
524
525 sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
526 /* Used by all of the ut_assert macros in the tx_handler */
527 sandbox_eth_set_priv(0, uts);
Joe Hershberger54418d02018-09-26 16:49:00 -0500528
529 env_set("ethact", "eth@10002000");
Joe Hershbergere79a5182018-09-26 16:49:02 -0500530 ut_assertok(net_loop(PING));
Joe Hershberger54418d02018-09-26 16:49:00 -0500531 ut_asserteq_str("eth@10002000", env_get("ethact"));
532
533 sandbox_eth_set_tx_handler(0, NULL);
534
535 return 0;
536}
Simon Glass1a92f832024-08-22 07:57:48 -0600537DM_TEST(dm_test_eth_async_arp_reply, UTF_SCAN_FDT);
Jerome Forissier717aa432025-04-15 23:17:43 +0200538#endif
Joe Hershberger9716dc12018-09-26 16:49:01 -0500539
Jerome Forissier717aa432025-04-15 23:17:43 +0200540#if CONFIG_IS_ENABLED(NET)
Joe Hershberger9716dc12018-09-26 16:49:01 -0500541static int sb_check_ping_reply(struct udevice *dev, void *packet,
542 unsigned int len)
543{
544 struct eth_sandbox_priv *priv = dev_get_priv(dev);
545 struct ethernet_hdr *eth = packet;
546 struct ip_udp_hdr *ip;
547 struct icmp_hdr *icmp;
548 /* Used by all of the ut_assert macros */
549 struct unit_test_state *uts = priv->priv;
550
551 if (ntohs(eth->et_protlen) != PROT_IP)
552 return 0;
553
554 ip = packet + ETHER_HDR_SIZE;
555
556 if (ip->ip_p != IPPROTO_ICMP)
557 return 0;
558
559 icmp = (struct icmp_hdr *)&ip->udp_src;
560
561 if (icmp->type != ICMP_ECHO_REPLY)
562 return 0;
563
564 /* This test would be worthless if we are not waiting */
565 ut_assert(arp_is_waiting());
566
567 /* Validate response */
Simon Glassa3186e62020-05-10 12:52:45 -0600568 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
569 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger9716dc12018-09-26 16:49:01 -0500570 ut_assert(eth->et_protlen == htons(PROT_IP));
571
572 ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
573 ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
574 string_to_ip("1.1.2.4").s_addr);
575
576 return 0;
577}
578
579static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
580 unsigned int len)
581{
582 struct eth_sandbox_priv *priv = dev_get_priv(dev);
583 struct ethernet_hdr *eth = packet;
584 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
585 int ret;
586
587 /*
588 * If we are about to generate a reply to ARP, first inject a request
589 * from another host
590 */
591 if (ntohs(eth->et_protlen) == PROT_ARP &&
592 ntohs(arp->ar_op) == ARPOP_REQUEST) {
593 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
594 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
595
596 ret = sandbox_eth_recv_ping_req(dev);
597 if (ret)
598 return ret;
599 }
600
601 sandbox_eth_arp_req_to_reply(dev, packet, len);
602 sandbox_eth_ping_req_to_reply(dev, packet, len);
603
604 return sb_check_ping_reply(dev, packet, len);
605}
606
607static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
608{
609 net_ping_ip = string_to_ip("1.1.2.2");
610
611 sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
612 /* Used by all of the ut_assert macros in the tx_handler */
613 sandbox_eth_set_priv(0, uts);
Joe Hershberger9716dc12018-09-26 16:49:01 -0500614
615 env_set("ethact", "eth@10002000");
Joe Hershbergere79a5182018-09-26 16:49:02 -0500616 ut_assertok(net_loop(PING));
Joe Hershberger9716dc12018-09-26 16:49:01 -0500617 ut_asserteq_str("eth@10002000", env_get("ethact"));
618
619 sandbox_eth_set_tx_handler(0, NULL);
620
621 return 0;
622}
Simon Glass1a92f832024-08-22 07:57:48 -0600623DM_TEST(dm_test_eth_async_ping_reply, UTF_SCAN_FDT);
Jerome Forissier717aa432025-04-15 23:17:43 +0200624#endif
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700625
626#if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
627
628static u8 ip6_ra_buf[] = {0x60, 0xf, 0xc5, 0x4a, 0x0, 0x38, 0x3a, 0xff, 0xfe,
629 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x85, 0xe6,
630 0x29, 0x77, 0xcb, 0xc8, 0x53, 0xff, 0x2, 0x0, 0x0,
631 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
632 0x1, 0x86, 0x0, 0xdc, 0x90, 0x40, 0x80, 0x15, 0x18,
633 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x4,
634 0x40, 0xc0, 0x0, 0x0, 0x37, 0xdc, 0x0, 0x0, 0x37,
635 0x78, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0xca, 0xfe, 0xca,
636 0xfe, 0xca, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
637 0x0, 0x1, 0x1, 0x0, 0x15, 0x5d, 0xe2, 0x8a, 0x2};
638
639static int dm_test_validate_ra(struct unit_test_state *uts)
640{
641 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
642 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
643 __be16 temp = 0;
644
645 ut_assert(validate_ra(ip6) == true);
646
647 temp = ip6->payload_len;
648 ip6->payload_len = 15;
649 ut_assert(validate_ra(ip6) == false);
650 ip6->payload_len = temp;
651
652 temp = ip6->saddr.s6_addr16[0];
653 ip6->saddr.s6_addr16[0] = 0x2001;
654 ut_assert(validate_ra(ip6) == false);
655 ip6->saddr.s6_addr16[0] = temp;
656
657 temp = ip6->hop_limit;
658 ip6->hop_limit = 15;
659 ut_assert(validate_ra(ip6) == false);
660 ip6->hop_limit = temp;
661
662 temp = icmp->icmp6_code;
663 icmp->icmp6_code = 15;
664 ut_assert(validate_ra(ip6) == false);
665 icmp->icmp6_code = temp;
666
667 return 0;
668}
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700669DM_TEST(dm_test_validate_ra, 0);
670
671static int dm_test_process_ra(struct unit_test_state *uts)
672{
673 int len = sizeof(ip6_ra_buf);
674 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
675 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
676 struct ra_msg *msg = (struct ra_msg *)icmp;
677 unsigned char *option = msg->opt;
678 struct icmp6_ra_prefix_info *prefix =
679 (struct icmp6_ra_prefix_info *)option;
680 __be16 temp = 0;
681 unsigned char option_len = option[1];
682
683 ut_assert(process_ra(ip6, len) == 0);
684
685 temp = icmp->icmp6_rt_lifetime;
686 icmp->icmp6_rt_lifetime = 0;
687 ut_assert(process_ra(ip6, len) != 0);
688 icmp->icmp6_rt_lifetime = temp;
689
690 ut_assert(process_ra(ip6, 0) != 0);
691
692 option[1] = 0;
693 ut_assert(process_ra(ip6, len) != 0);
694 option[1] = option_len;
695
696 prefix->on_link = false;
697 ut_assert(process_ra(ip6, len) != 0);
698 prefix->on_link = true;
699
700 temp = prefix->prefix.s6_addr16[0];
701 prefix->prefix.s6_addr16[0] = 0x80fe;
702 ut_assert(process_ra(ip6, len) != 0);
703 prefix->prefix.s6_addr16[0] = temp;
704
705 return 0;
706}
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700707DM_TEST(dm_test_process_ra, 0);
708
709#endif