blob: 467495863e193f566e6ed5534b4d19c129bd09a9 [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{
Joe Hershberger5874dec2015-04-08 01:41:01 -0500174 net_ping_ip = string_to_ip("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");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500177 ut_assertok(net_loop(PING));
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");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500181 ut_assertok(net_loop(PING));
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");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500185 ut_assertok(net_loop(PING));
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{
Joe Hershberger5874dec2015-04-08 01:41:01 -0500194 net_ping_ip = string_to_ip("1.1.2.2");
Simon Glass6a38e412017-08-03 12:22:09 -0600195 env_set("ethact", "eth0");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500196 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600197 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500198
Michael Walle7c41a222020-06-02 01:47:09 +0200199 env_set("ethact", "eth6");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500200 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600201 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500202
Claudiu Manoild9eaa922021-03-14 20:14:57 +0800203 /* Expected to fail since eth1 is not defined in the device tree */
204 env_set("ethact", "eth1");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500205 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600206 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500207
Simon Glass6a38e412017-08-03 12:22:09 -0600208 env_set("ethact", "eth5");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500209 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600210 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershberger279d2f62015-03-22 17:09:16 -0500211
212 return 0;
213}
Simon Glass1a92f832024-08-22 07:57:48 -0600214DM_TEST(dm_test_eth_alias, UTF_SCAN_FDT);
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500215
Joe Hershberger3a77be52015-05-20 14:27:27 -0500216static int dm_test_eth_prime(struct unit_test_state *uts)
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500217{
Joe Hershberger5874dec2015-04-08 01:41:01 -0500218 net_ping_ip = string_to_ip("1.1.2.2");
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500219
220 /* Expected to be "eth@10003000" because of ethprime variable */
Simon Glass6a38e412017-08-03 12:22:09 -0600221 env_set("ethact", NULL);
222 env_set("ethprime", "eth5");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500223 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600224 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500225
226 /* Expected to be "eth@10002000" because it is first */
Simon Glass6a38e412017-08-03 12:22:09 -0600227 env_set("ethact", NULL);
228 env_set("ethprime", NULL);
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500229 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600230 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergeraa52edd2015-03-22 17:09:17 -0500231
232 return 0;
233}
Simon Glass1a92f832024-08-22 07:57:48 -0600234DM_TEST(dm_test_eth_prime, UTF_SCAN_FDT);
Joe Hershbergerf340e542015-03-22 17:09:18 -0500235
Bin Meng111473a2015-10-07 21:45:43 -0700236/**
237 * This test case is trying to test the following scenario:
238 * - All ethernet devices are not probed
239 * - "ethaddr" for all ethernet devices are not set
240 * - "ethact" is set to a valid ethernet device name
241 *
242 * With Sandbox default test configuration, all ethernet devices are
243 * probed after power-up, so we have to manually create such scenario:
244 * - Remove all ethernet devices
245 * - Remove all "ethaddr" environment variables
246 * - Set "ethact" to the first ethernet device
247 *
248 * Do a ping test to see if anything goes wrong.
249 */
250static int dm_test_eth_act(struct unit_test_state *uts)
251{
252 struct udevice *dev[DM_TEST_ETH_NUM];
253 const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
254 "sbe5", "eth@10004000"};
255 const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
Michael Walle7c41a222020-06-02 01:47:09 +0200256 "eth3addr", "eth6addr"};
Bin Meng111473a2015-10-07 21:45:43 -0700257 char ethaddr[DM_TEST_ETH_NUM][18];
258 int i;
259
Tom Rini0ac17d82017-09-26 14:08:30 -0400260 memset(ethaddr, '\0', sizeof(ethaddr));
Bin Meng111473a2015-10-07 21:45:43 -0700261 net_ping_ip = string_to_ip("1.1.2.2");
262
263 /* Prepare the test scenario */
264 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
Sean Anderson85e8fc82023-10-28 18:57:27 -0400265 char *addr;
266
Bin Meng111473a2015-10-07 21:45:43 -0700267 ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
268 ethname[i], &dev[i]));
Stefan Roese80b5bc92017-03-20 12:51:48 +0100269 ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
Bin Meng111473a2015-10-07 21:45:43 -0700270
271 /* Invalidate MAC address */
Sean Anderson85e8fc82023-10-28 18:57:27 -0400272 addr = env_get(addrname[i]);
273 ut_assertnonnull(addr);
274 strncpy(ethaddr[i], addr, 17);
Bin Meng111473a2015-10-07 21:45:43 -0700275 /* Must disable access protection for ethaddr before clearing */
Simon Glass6a38e412017-08-03 12:22:09 -0600276 env_set(".flags", addrname[i]);
277 env_set(addrname[i], NULL);
Bin Meng111473a2015-10-07 21:45:43 -0700278 }
279
280 /* Set ethact to "eth@10002000" */
Simon Glass6a38e412017-08-03 12:22:09 -0600281 env_set("ethact", ethname[0]);
Bin Meng111473a2015-10-07 21:45:43 -0700282
283 /* Segment fault might happen if something is wrong */
284 ut_asserteq(-ENODEV, net_loop(PING));
285
286 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
287 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600288 env_set(".flags", addrname[i]);
289 env_set(addrname[i], ethaddr[i]);
Bin Meng111473a2015-10-07 21:45:43 -0700290
291 /* Probe the device again */
292 ut_assertok(device_probe(dev[i]));
293 }
Simon Glass6a38e412017-08-03 12:22:09 -0600294 env_set(".flags", NULL);
295 env_set("ethact", NULL);
Bin Meng111473a2015-10-07 21:45:43 -0700296
297 return 0;
298}
Simon Glass1a92f832024-08-22 07:57:48 -0600299DM_TEST(dm_test_eth_act, UTF_SCAN_FDT);
Bin Meng111473a2015-10-07 21:45:43 -0700300
Sean Anderson86f5cc72022-05-05 13:11:32 -0400301/* Ensure that all addresses are loaded properly */
302static int dm_test_ethaddr(struct unit_test_state *uts)
303{
304 static const char *const addr[] = {
305 "02:00:11:22:33:44",
306 "02:00:11:22:33:48", /* dsa slave */
307 "02:00:11:22:33:45",
308 "02:00:11:22:33:48", /* dsa master */
309 "02:00:11:22:33:46",
310 "02:00:11:22:33:47",
311 "02:00:11:22:33:48", /* dsa slave */
312 "02:00:11:22:33:49",
313 };
314 int i;
315
316 for (i = 0; i < ARRAY_SIZE(addr); i++) {
317 char addrname[10];
Sean Anderson85e8fc82023-10-28 18:57:27 -0400318 char *env_addr;
Sean Anderson86f5cc72022-05-05 13:11:32 -0400319
320 if (i)
321 snprintf(addrname, sizeof(addrname), "eth%daddr", i + 1);
322 else
323 strcpy(addrname, "ethaddr");
Sean Anderson85e8fc82023-10-28 18:57:27 -0400324
325 env_addr = env_get(addrname);
326 ut_assertnonnull(env_addr);
327 ut_asserteq_str(addr[i], env_addr);
Sean Anderson86f5cc72022-05-05 13:11:32 -0400328 }
329
330 return 0;
331}
Simon Glass1a92f832024-08-22 07:57:48 -0600332DM_TEST(dm_test_ethaddr, UTF_SCAN_FDT);
Sean Anderson86f5cc72022-05-05 13:11:32 -0400333
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500334/* The asserts include a return on fail; cleanup in the caller */
335static int _dm_test_eth_rotate1(struct unit_test_state *uts)
Joe Hershbergerf340e542015-03-22 17:09:18 -0500336{
Joe Hershbergerf340e542015-03-22 17:09:18 -0500337 /* Make sure that the default is to rotate to the next interface */
Simon Glass6a38e412017-08-03 12:22:09 -0600338 env_set("ethact", "eth@10004000");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500339 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600340 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500341
342 /* If ethrotate is no, then we should fail on a bad MAC */
Simon Glass6a38e412017-08-03 12:22:09 -0600343 env_set("ethact", "eth@10004000");
344 env_set("ethrotate", "no");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500345 ut_asserteq(-EINVAL, net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600346 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500347
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500348 return 0;
349}
Joe Hershbergerf340e542015-03-22 17:09:18 -0500350
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500351static int _dm_test_eth_rotate2(struct unit_test_state *uts)
352{
Joe Hershbergerf340e542015-03-22 17:09:18 -0500353 /* Make sure we can skip invalid devices */
Simon Glass6a38e412017-08-03 12:22:09 -0600354 env_set("ethact", "eth@10004000");
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500355 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600356 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergerf340e542015-03-22 17:09:18 -0500357
Bin Meng04a11cb2015-08-27 22:25:53 -0700358 /* Make sure we can handle device name which is not eth# */
Simon Glass6a38e412017-08-03 12:22:09 -0600359 env_set("ethact", "sbe5");
Bin Meng04a11cb2015-08-27 22:25:53 -0700360 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600361 ut_asserteq_str("sbe5", env_get("ethact"));
Bin Meng04a11cb2015-08-27 22:25:53 -0700362
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500363 return 0;
364}
365
366static int dm_test_eth_rotate(struct unit_test_state *uts)
367{
368 char ethaddr[18];
369 int retval;
370
371 /* Set target IP to mock ping */
372 net_ping_ip = string_to_ip("1.1.2.2");
373
374 /* Invalidate eth1's MAC address */
Tom Rini0ac17d82017-09-26 14:08:30 -0400375 memset(ethaddr, '\0', sizeof(ethaddr));
Michael Walle7c41a222020-06-02 01:47:09 +0200376 strncpy(ethaddr, env_get("eth6addr"), 17);
377 /* Must disable access protection for eth6addr before clearing */
378 env_set(".flags", "eth6addr");
379 env_set("eth6addr", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500380
381 retval = _dm_test_eth_rotate1(uts);
382
Joe Hershbergerf340e542015-03-22 17:09:18 -0500383 /* Restore the env */
Michael Walle7c41a222020-06-02 01:47:09 +0200384 env_set("eth6addr", ethaddr);
Simon Glass6a38e412017-08-03 12:22:09 -0600385 env_set("ethrotate", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500386
387 if (!retval) {
388 /* Invalidate eth0's MAC address */
Tom Rini0ac17d82017-09-26 14:08:30 -0400389 strncpy(ethaddr, env_get("ethaddr"), 17);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500390 /* Must disable access protection for ethaddr before clearing */
Simon Glass6a38e412017-08-03 12:22:09 -0600391 env_set(".flags", "ethaddr");
392 env_set("ethaddr", NULL);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500393
394 retval = _dm_test_eth_rotate2(uts);
395
396 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600397 env_set("ethaddr", ethaddr);
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500398 }
399 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600400 env_set(".flags", NULL);
Joe Hershbergerf340e542015-03-22 17:09:18 -0500401
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500402 return retval;
Joe Hershbergerf340e542015-03-22 17:09:18 -0500403}
Simon Glass1a92f832024-08-22 07:57:48 -0600404DM_TEST(dm_test_eth_rotate, UTF_SCAN_FDT);
Joe Hershbergerf933a932015-03-22 17:09:20 -0500405
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500406/* The asserts include a return on fail; cleanup in the caller */
407static int _dm_test_net_retry(struct unit_test_state *uts)
Joe Hershbergerf933a932015-03-22 17:09:20 -0500408{
Joe Hershbergerf933a932015-03-22 17:09:20 -0500409 /*
410 * eth1 is disabled and netretry is yes, so the ping should succeed and
411 * the active device should be eth0
412 */
413 sandbox_eth_disable_response(1, true);
Claudiu Manoild9eaa922021-03-14 20:14:57 +0800414 env_set("ethact", "lan1");
Simon Glass6a38e412017-08-03 12:22:09 -0600415 env_set("netretry", "yes");
Joe Hershberger6901f432015-04-21 13:57:20 -0500416 sandbox_eth_skip_timeout();
Joe Hershbergerc80b41b02015-04-08 01:41:21 -0500417 ut_assertok(net_loop(PING));
Simon Glass64b723f2017-08-03 12:22:12 -0600418 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergerf933a932015-03-22 17:09:20 -0500419
420 /*
421 * eth1 is disabled and netretry is no, so the ping should fail and the
422 * active device should be eth1
423 */
Claudiu Manoild9eaa922021-03-14 20:14:57 +0800424 env_set("ethact", "lan1");
Simon Glass6a38e412017-08-03 12:22:09 -0600425 env_set("netretry", "no");
Joe Hershberger6901f432015-04-21 13:57:20 -0500426 sandbox_eth_skip_timeout();
Thomas RIENOESSL2dee4192018-11-21 15:56:07 +0100427 ut_asserteq(-ENONET, net_loop(PING));
Claudiu Manoild9eaa922021-03-14 20:14:57 +0800428 ut_asserteq_str("lan1", env_get("ethact"));
Joe Hershbergerf933a932015-03-22 17:09:20 -0500429
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500430 return 0;
431}
432
433static int dm_test_net_retry(struct unit_test_state *uts)
434{
435 int retval;
436
437 net_ping_ip = string_to_ip("1.1.2.2");
438
439 retval = _dm_test_net_retry(uts);
440
Joe Hershbergerf933a932015-03-22 17:09:20 -0500441 /* Restore the env */
Simon Glass6a38e412017-08-03 12:22:09 -0600442 env_set("netretry", NULL);
Joe Hershbergerf933a932015-03-22 17:09:20 -0500443 sandbox_eth_disable_response(1, false);
444
Joe Hershbergerfc755f92015-05-20 14:27:33 -0500445 return retval;
Joe Hershbergerf933a932015-03-22 17:09:20 -0500446}
Simon Glass1a92f832024-08-22 07:57:48 -0600447DM_TEST(dm_test_net_retry, UTF_SCAN_FDT);
Joe Hershberger54418d02018-09-26 16:49:00 -0500448
449static int sb_check_arp_reply(struct udevice *dev, void *packet,
450 unsigned int len)
451{
452 struct eth_sandbox_priv *priv = dev_get_priv(dev);
453 struct ethernet_hdr *eth = packet;
454 struct arp_hdr *arp;
455 /* Used by all of the ut_assert macros */
456 struct unit_test_state *uts = priv->priv;
457
458 if (ntohs(eth->et_protlen) != PROT_ARP)
459 return 0;
460
461 arp = packet + ETHER_HDR_SIZE;
462
463 if (ntohs(arp->ar_op) != ARPOP_REPLY)
464 return 0;
465
466 /* This test would be worthless if we are not waiting */
467 ut_assert(arp_is_waiting());
468
469 /* Validate response */
Simon Glassa3186e62020-05-10 12:52:45 -0600470 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
471 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500472 ut_assert(eth->et_protlen == htons(PROT_ARP));
473
474 ut_assert(arp->ar_hrd == htons(ARP_ETHER));
475 ut_assert(arp->ar_pro == htons(PROT_IP));
476 ut_assert(arp->ar_hln == ARP_HLEN);
477 ut_assert(arp->ar_pln == ARP_PLEN);
Simon Glassa3186e62020-05-10 12:52:45 -0600478 ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500479 ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
Simon Glassa3186e62020-05-10 12:52:45 -0600480 ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger54418d02018-09-26 16:49:00 -0500481 ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
482 string_to_ip("1.1.2.4").s_addr);
483
484 return 0;
485}
486
487static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
488 unsigned int len)
489{
490 struct eth_sandbox_priv *priv = dev_get_priv(dev);
491 struct ethernet_hdr *eth = packet;
492 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
493 int ret;
494
495 /*
496 * If we are about to generate a reply to ARP, first inject a request
497 * from another host
498 */
499 if (ntohs(eth->et_protlen) == PROT_ARP &&
500 ntohs(arp->ar_op) == ARPOP_REQUEST) {
501 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
502 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
503
504 ret = sandbox_eth_recv_arp_req(dev);
505 if (ret)
506 return ret;
507 }
508
509 sandbox_eth_arp_req_to_reply(dev, packet, len);
510 sandbox_eth_ping_req_to_reply(dev, packet, len);
511
512 return sb_check_arp_reply(dev, packet, len);
513}
514
515static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
516{
517 net_ping_ip = string_to_ip("1.1.2.2");
518
519 sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
520 /* Used by all of the ut_assert macros in the tx_handler */
521 sandbox_eth_set_priv(0, uts);
Joe Hershberger54418d02018-09-26 16:49:00 -0500522
523 env_set("ethact", "eth@10002000");
Joe Hershbergere79a5182018-09-26 16:49:02 -0500524 ut_assertok(net_loop(PING));
Joe Hershberger54418d02018-09-26 16:49:00 -0500525 ut_asserteq_str("eth@10002000", env_get("ethact"));
526
527 sandbox_eth_set_tx_handler(0, NULL);
528
529 return 0;
530}
Simon Glass1a92f832024-08-22 07:57:48 -0600531DM_TEST(dm_test_eth_async_arp_reply, UTF_SCAN_FDT);
Joe Hershberger9716dc12018-09-26 16:49:01 -0500532
533static int sb_check_ping_reply(struct udevice *dev, void *packet,
534 unsigned int len)
535{
536 struct eth_sandbox_priv *priv = dev_get_priv(dev);
537 struct ethernet_hdr *eth = packet;
538 struct ip_udp_hdr *ip;
539 struct icmp_hdr *icmp;
540 /* Used by all of the ut_assert macros */
541 struct unit_test_state *uts = priv->priv;
542
543 if (ntohs(eth->et_protlen) != PROT_IP)
544 return 0;
545
546 ip = packet + ETHER_HDR_SIZE;
547
548 if (ip->ip_p != IPPROTO_ICMP)
549 return 0;
550
551 icmp = (struct icmp_hdr *)&ip->udp_src;
552
553 if (icmp->type != ICMP_ECHO_REPLY)
554 return 0;
555
556 /* This test would be worthless if we are not waiting */
557 ut_assert(arp_is_waiting());
558
559 /* Validate response */
Simon Glassa3186e62020-05-10 12:52:45 -0600560 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
561 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger9716dc12018-09-26 16:49:01 -0500562 ut_assert(eth->et_protlen == htons(PROT_IP));
563
564 ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
565 ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
566 string_to_ip("1.1.2.4").s_addr);
567
568 return 0;
569}
570
571static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
572 unsigned int len)
573{
574 struct eth_sandbox_priv *priv = dev_get_priv(dev);
575 struct ethernet_hdr *eth = packet;
576 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
577 int ret;
578
579 /*
580 * If we are about to generate a reply to ARP, first inject a request
581 * from another host
582 */
583 if (ntohs(eth->et_protlen) == PROT_ARP &&
584 ntohs(arp->ar_op) == ARPOP_REQUEST) {
585 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
586 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
587
588 ret = sandbox_eth_recv_ping_req(dev);
589 if (ret)
590 return ret;
591 }
592
593 sandbox_eth_arp_req_to_reply(dev, packet, len);
594 sandbox_eth_ping_req_to_reply(dev, packet, len);
595
596 return sb_check_ping_reply(dev, packet, len);
597}
598
599static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
600{
601 net_ping_ip = string_to_ip("1.1.2.2");
602
603 sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
604 /* Used by all of the ut_assert macros in the tx_handler */
605 sandbox_eth_set_priv(0, uts);
Joe Hershberger9716dc12018-09-26 16:49:01 -0500606
607 env_set("ethact", "eth@10002000");
Joe Hershbergere79a5182018-09-26 16:49:02 -0500608 ut_assertok(net_loop(PING));
Joe Hershberger9716dc12018-09-26 16:49:01 -0500609 ut_asserteq_str("eth@10002000", env_get("ethact"));
610
611 sandbox_eth_set_tx_handler(0, NULL);
612
613 return 0;
614}
Simon Glass1a92f832024-08-22 07:57:48 -0600615DM_TEST(dm_test_eth_async_ping_reply, UTF_SCAN_FDT);
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700616
617#if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
618
619static u8 ip6_ra_buf[] = {0x60, 0xf, 0xc5, 0x4a, 0x0, 0x38, 0x3a, 0xff, 0xfe,
620 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x85, 0xe6,
621 0x29, 0x77, 0xcb, 0xc8, 0x53, 0xff, 0x2, 0x0, 0x0,
622 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
623 0x1, 0x86, 0x0, 0xdc, 0x90, 0x40, 0x80, 0x15, 0x18,
624 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x4,
625 0x40, 0xc0, 0x0, 0x0, 0x37, 0xdc, 0x0, 0x0, 0x37,
626 0x78, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0xca, 0xfe, 0xca,
627 0xfe, 0xca, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
628 0x0, 0x1, 0x1, 0x0, 0x15, 0x5d, 0xe2, 0x8a, 0x2};
629
630static int dm_test_validate_ra(struct unit_test_state *uts)
631{
632 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
633 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
634 __be16 temp = 0;
635
636 ut_assert(validate_ra(ip6) == true);
637
638 temp = ip6->payload_len;
639 ip6->payload_len = 15;
640 ut_assert(validate_ra(ip6) == false);
641 ip6->payload_len = temp;
642
643 temp = ip6->saddr.s6_addr16[0];
644 ip6->saddr.s6_addr16[0] = 0x2001;
645 ut_assert(validate_ra(ip6) == false);
646 ip6->saddr.s6_addr16[0] = temp;
647
648 temp = ip6->hop_limit;
649 ip6->hop_limit = 15;
650 ut_assert(validate_ra(ip6) == false);
651 ip6->hop_limit = temp;
652
653 temp = icmp->icmp6_code;
654 icmp->icmp6_code = 15;
655 ut_assert(validate_ra(ip6) == false);
656 icmp->icmp6_code = temp;
657
658 return 0;
659}
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700660DM_TEST(dm_test_validate_ra, 0);
661
662static int dm_test_process_ra(struct unit_test_state *uts)
663{
664 int len = sizeof(ip6_ra_buf);
665 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
666 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
667 struct ra_msg *msg = (struct ra_msg *)icmp;
668 unsigned char *option = msg->opt;
669 struct icmp6_ra_prefix_info *prefix =
670 (struct icmp6_ra_prefix_info *)option;
671 __be16 temp = 0;
672 unsigned char option_len = option[1];
673
674 ut_assert(process_ra(ip6, len) == 0);
675
676 temp = icmp->icmp6_rt_lifetime;
677 icmp->icmp6_rt_lifetime = 0;
678 ut_assert(process_ra(ip6, len) != 0);
679 icmp->icmp6_rt_lifetime = temp;
680
681 ut_assert(process_ra(ip6, 0) != 0);
682
683 option[1] = 0;
684 ut_assert(process_ra(ip6, len) != 0);
685 option[1] = option_len;
686
687 prefix->on_link = false;
688 ut_assert(process_ra(ip6, len) != 0);
689 prefix->on_link = true;
690
691 temp = prefix->prefix.s6_addr16[0];
692 prefix->prefix.s6_addr16[0] = 0x80fe;
693 ut_assert(process_ra(ip6, len) != 0);
694 prefix->prefix.s6_addr16[0] = temp;
695
696 return 0;
697}
Ehsan Mohandesi63c76c02023-04-21 17:08:23 -0700698DM_TEST(dm_test_process_ra, 0);
699
700#endif