blob: d05d2a9abe1fedf9a32b9e99b1ebe6711939b974 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Joe Hershbergerbfacad72015-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 Hershbergerbfacad72015-03-22 17:09:15 -05007 */
8
9#include <common.h>
10#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060011#include <env.h>
Joe Hershbergerbfacad72015-03-22 17:09:15 -050012#include <fdtdec.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060013#include <log.h>
Joe Hershbergerbfacad72015-03-22 17:09:15 -050014#include <malloc.h>
15#include <net.h>
Viacheslav Mitrofanov184ded42022-12-02 12:18:09 +030016#include <net6.h>
Simon Glass0e1fad42020-07-19 10:15:37 -060017#include <asm/eth.h>
Joe Hershbergere721b882015-05-20 14:27:27 -050018#include <dm/test.h>
Bin Meng6d9764c2015-10-07 21:45:43 -070019#include <dm/device-internal.h>
20#include <dm/uclass-internal.h>
Simon Glass0e1fad42020-07-19 10:15:37 -060021#include <test/test.h>
Joe Hershbergere721b882015-05-20 14:27:27 -050022#include <test/ut.h>
Ehsan Mohandesi4c516802023-04-21 17:08:23 -070023#include <ndisc.h>
Joe Hershbergerbfacad72015-03-22 17:09:15 -050024
Bin Meng6d9764c2015-10-07 21:45:43 -070025#define DM_TEST_ETH_NUM 4
26
Viacheslav Mitrofanov184ded42022-12-02 12:18:09 +030027#if IS_ENABLED(CONFIG_IPV6)
28static int dm_test_string_to_ip6(struct unit_test_state *uts)
29{
30 char *str;
31 struct test_ip6_pair {
32 char *string_addr;
33 struct in6_addr ip6_addr;
34 };
35
36 struct in6_addr ip6 = {0};
37
38 /* Correct statements */
39 struct test_ip6_pair test_suite[] = {
40 {"2001:db8::0:1234:1", {.s6_addr32[0] = 0xb80d0120,
41 .s6_addr32[1] = 0x00000000,
42 .s6_addr32[2] = 0x00000000,
43 .s6_addr32[3] = 0x01003412}},
44 {"2001:0db8:0000:0000:0000:0000:1234:0001",
45 {.s6_addr32[0] = 0xb80d0120,
46 .s6_addr32[1] = 0x00000000,
47 .s6_addr32[2] = 0x00000000,
48 .s6_addr32[3] = 0x01003412}},
49 {"::1", {.s6_addr32[0] = 0x00000000,
50 .s6_addr32[1] = 0x00000000,
51 .s6_addr32[2] = 0x00000000,
52 .s6_addr32[3] = 0x01000000}},
53 {"::ffff:192.168.1.1", {.s6_addr32[0] = 0x00000000,
54 .s6_addr32[1] = 0x00000000,
55 .s6_addr32[2] = 0xffff0000,
56 .s6_addr32[3] = 0x0101a8c0}},
57 };
58
59 for (int i = 0; i < ARRAY_SIZE(test_suite); ++i) {
60 ut_assertok(string_to_ip6(test_suite[i].string_addr,
61 strlen(test_suite[i].string_addr), &ip6));
62 ut_asserteq_mem(&ip6, &test_suite[i].ip6_addr,
63 sizeof(struct in6_addr));
64 }
65
66 /* Incorrect statements */
67 str = "hello:world";
68 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
69 str = "2001:db8::0::0";
70 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
71 str = "2001:db8:192.168.1.1::1";
72 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
73 str = "192.168.1.1";
74 ut_assertok(!string_to_ip6(str, strlen(str), &ip6));
75
76 return 0;
77}
78DM_TEST(dm_test_string_to_ip6, 0);
Viacheslav Mitrofanovd9f5c412022-12-02 12:18:10 +030079
80static int dm_test_csum_ipv6_magic(struct unit_test_state *uts)
81{
82 unsigned short csum = 0xbeef;
83 /* Predefined correct parameters */
84 unsigned short correct_csum = 0xd8ac;
85 struct in6_addr saddr = {.s6_addr32[0] = 0x000080fe,
86 .s6_addr32[1] = 0x00000000,
87 .s6_addr32[2] = 0xffe9f242,
88 .s6_addr32[3] = 0xe8f66dfe};
89 struct in6_addr daddr = {.s6_addr32[0] = 0x000080fe,
90 .s6_addr32[1] = 0x00000000,
91 .s6_addr32[2] = 0xffd5b372,
92 .s6_addr32[3] = 0x3ef692fe};
93 u16 len = 1460;
94 unsigned short proto = 17;
95 unsigned int head_csum = 0x91f0;
96
97 csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
98 ut_asserteq(csum, correct_csum);
99
100 /* Broke a parameter */
101 proto--;
102 csum = csum_ipv6_magic(&saddr, &daddr, len, proto, head_csum);
103 ut_assert(csum != correct_csum);
104
105 return 0;
106}
107DM_TEST(dm_test_csum_ipv6_magic, 0);
Viacheslav Mitrofanov8576dcd2022-12-02 12:18:11 +0300108
109static int dm_test_ip6_addr_in_subnet(struct unit_test_state *uts)
110{
111 struct in6_addr our = {.s6_addr32[0] = 0x000080fe,
112 .s6_addr32[1] = 0x00000000,
113 .s6_addr32[2] = 0xffe9f242,
114 .s6_addr32[3] = 0xe8f66dfe};
115 struct in6_addr neigh1 = {.s6_addr32[0] = 0x000080fe,
116 .s6_addr32[1] = 0x00000000,
117 .s6_addr32[2] = 0xffd5b372,
118 .s6_addr32[3] = 0x3ef692fe};
119 struct in6_addr neigh2 = {.s6_addr32[0] = 0x60480120,
120 .s6_addr32[1] = 0x00006048,
121 .s6_addr32[2] = 0x00000000,
122 .s6_addr32[3] = 0x00008888};
123
124 /* in */
125 ut_assert(ip6_addr_in_subnet(&our, &neigh1, 64));
126 /* outside */
127 ut_assert(!ip6_addr_in_subnet(&our, &neigh2, 64));
128 ut_assert(!ip6_addr_in_subnet(&our, &neigh1, 128));
129
130 return 0;
131}
132DM_TEST(dm_test_ip6_addr_in_subnet, 0);
Viacheslav Mitrofanov789a2c72022-12-02 12:18:12 +0300133
134static int dm_test_ip6_make_snma(struct unit_test_state *uts)
135{
136 struct in6_addr mult = {0};
137 struct in6_addr correct_addr = {
138 .s6_addr32[0] = 0x000002ff,
139 .s6_addr32[1] = 0x00000000,
140 .s6_addr32[2] = 0x01000000,
141 .s6_addr32[3] = 0xe8f66dff};
142 struct in6_addr addr = { .s6_addr32[0] = 0x000080fe,
143 .s6_addr32[1] = 0x00000000,
144 .s6_addr32[2] = 0xffe9f242,
145 .s6_addr32[3] = 0xe8f66dfe};
146
147 ip6_make_snma(&mult, &addr);
148 ut_asserteq_mem(&mult, &correct_addr, sizeof(struct in6_addr));
149
150 return 0;
151}
152DM_TEST(dm_test_ip6_make_snma, 0);
Viacheslav Mitrofanove4d30fd2022-12-02 12:18:13 +0300153
154static int dm_test_ip6_make_lladdr(struct unit_test_state *uts)
155{
156 struct in6_addr generated_lladdr = {0};
157 struct in6_addr correct_lladdr = {
158 .s6_addr32[0] = 0x000080fe,
159 .s6_addr32[1] = 0x00000000,
160 .s6_addr32[2] = 0xffabf33a,
161 .s6_addr32[3] = 0xfbb352fe};
162 const unsigned char mac[6] = {0x38, 0xf3, 0xab, 0x52, 0xb3, 0xfb};
163
164 ip6_make_lladdr(&generated_lladdr, mac);
165 ut_asserteq_mem(&generated_lladdr, &correct_lladdr,
166 sizeof(struct in6_addr));
167
168 return 0;
169}
170DM_TEST(dm_test_ip6_make_lladdr, UT_TESTF_SCAN_FDT);
Viacheslav Mitrofanov184ded42022-12-02 12:18:09 +0300171#endif
172
Joe Hershbergere721b882015-05-20 14:27:27 -0500173static int dm_test_eth(struct unit_test_state *uts)
Joe Hershbergerbfacad72015-03-22 17:09:15 -0500174{
Joe Hershberger049a95a2015-04-08 01:41:01 -0500175 net_ping_ip = string_to_ip("1.1.2.2");
Joe Hershbergerbfacad72015-03-22 17:09:15 -0500176
Simon Glass382bee52017-08-03 12:22:09 -0600177 env_set("ethact", "eth@10002000");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500178 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600179 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergerbfacad72015-03-22 17:09:15 -0500180
Simon Glass382bee52017-08-03 12:22:09 -0600181 env_set("ethact", "eth@10003000");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500182 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600183 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershbergerbfacad72015-03-22 17:09:15 -0500184
Simon Glass382bee52017-08-03 12:22:09 -0600185 env_set("ethact", "eth@10004000");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500186 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600187 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergerbfacad72015-03-22 17:09:15 -0500188
189 return 0;
190}
Simon Glasse180c2b2020-07-28 19:41:12 -0600191DM_TEST(dm_test_eth, UT_TESTF_SCAN_FDT);
Joe Hershbergere58780d2015-03-22 17:09:16 -0500192
Joe Hershbergere721b882015-05-20 14:27:27 -0500193static int dm_test_eth_alias(struct unit_test_state *uts)
Joe Hershbergere58780d2015-03-22 17:09:16 -0500194{
Joe Hershberger049a95a2015-04-08 01:41:01 -0500195 net_ping_ip = string_to_ip("1.1.2.2");
Simon Glass382bee52017-08-03 12:22:09 -0600196 env_set("ethact", "eth0");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500197 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600198 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergere58780d2015-03-22 17:09:16 -0500199
Michael Wallebe1a6e92020-06-02 01:47:09 +0200200 env_set("ethact", "eth6");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500201 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600202 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershbergere58780d2015-03-22 17:09:16 -0500203
Claudiu Manoilff98da02021-03-14 20:14:57 +0800204 /* Expected to fail since eth1 is not defined in the device tree */
205 env_set("ethact", "eth1");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500206 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600207 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershbergere58780d2015-03-22 17:09:16 -0500208
Simon Glass382bee52017-08-03 12:22:09 -0600209 env_set("ethact", "eth5");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500210 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600211 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershbergere58780d2015-03-22 17:09:16 -0500212
213 return 0;
214}
Simon Glasse180c2b2020-07-28 19:41:12 -0600215DM_TEST(dm_test_eth_alias, UT_TESTF_SCAN_FDT);
Joe Hershberger6536b9b2015-03-22 17:09:17 -0500216
Joe Hershbergere721b882015-05-20 14:27:27 -0500217static int dm_test_eth_prime(struct unit_test_state *uts)
Joe Hershberger6536b9b2015-03-22 17:09:17 -0500218{
Joe Hershberger049a95a2015-04-08 01:41:01 -0500219 net_ping_ip = string_to_ip("1.1.2.2");
Joe Hershberger6536b9b2015-03-22 17:09:17 -0500220
221 /* Expected to be "eth@10003000" because of ethprime variable */
Simon Glass382bee52017-08-03 12:22:09 -0600222 env_set("ethact", NULL);
223 env_set("ethprime", "eth5");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500224 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600225 ut_asserteq_str("eth@10003000", env_get("ethact"));
Joe Hershberger6536b9b2015-03-22 17:09:17 -0500226
227 /* Expected to be "eth@10002000" because it is first */
Simon Glass382bee52017-08-03 12:22:09 -0600228 env_set("ethact", NULL);
229 env_set("ethprime", NULL);
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500230 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600231 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger6536b9b2015-03-22 17:09:17 -0500232
233 return 0;
234}
Simon Glasse180c2b2020-07-28 19:41:12 -0600235DM_TEST(dm_test_eth_prime, UT_TESTF_SCAN_FDT);
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500236
Bin Meng6d9764c2015-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{
253 struct udevice *dev[DM_TEST_ETH_NUM];
254 const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
255 "sbe5", "eth@10004000"};
256 const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
Michael Wallebe1a6e92020-06-02 01:47:09 +0200257 "eth3addr", "eth6addr"};
Bin Meng6d9764c2015-10-07 21:45:43 -0700258 char ethaddr[DM_TEST_ETH_NUM][18];
259 int i;
260
Tom Rinie2e6dae2017-09-26 14:08:30 -0400261 memset(ethaddr, '\0', sizeof(ethaddr));
Bin Meng6d9764c2015-10-07 21:45:43 -0700262 net_ping_ip = string_to_ip("1.1.2.2");
263
264 /* Prepare the test scenario */
265 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
266 ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
267 ethname[i], &dev[i]));
Stefan Roese706865a2017-03-20 12:51:48 +0100268 ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
Bin Meng6d9764c2015-10-07 21:45:43 -0700269
270 /* Invalidate MAC address */
Tom Rinie2e6dae2017-09-26 14:08:30 -0400271 strncpy(ethaddr[i], env_get(addrname[i]), 17);
Bin Meng6d9764c2015-10-07 21:45:43 -0700272 /* Must disable access protection for ethaddr before clearing */
Simon Glass382bee52017-08-03 12:22:09 -0600273 env_set(".flags", addrname[i]);
274 env_set(addrname[i], NULL);
Bin Meng6d9764c2015-10-07 21:45:43 -0700275 }
276
277 /* Set ethact to "eth@10002000" */
Simon Glass382bee52017-08-03 12:22:09 -0600278 env_set("ethact", ethname[0]);
Bin Meng6d9764c2015-10-07 21:45:43 -0700279
280 /* Segment fault might happen if something is wrong */
281 ut_asserteq(-ENODEV, net_loop(PING));
282
283 for (i = 0; i < DM_TEST_ETH_NUM; i++) {
284 /* Restore the env */
Simon Glass382bee52017-08-03 12:22:09 -0600285 env_set(".flags", addrname[i]);
286 env_set(addrname[i], ethaddr[i]);
Bin Meng6d9764c2015-10-07 21:45:43 -0700287
288 /* Probe the device again */
289 ut_assertok(device_probe(dev[i]));
290 }
Simon Glass382bee52017-08-03 12:22:09 -0600291 env_set(".flags", NULL);
292 env_set("ethact", NULL);
Bin Meng6d9764c2015-10-07 21:45:43 -0700293
294 return 0;
295}
Simon Glasse180c2b2020-07-28 19:41:12 -0600296DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
Bin Meng6d9764c2015-10-07 21:45:43 -0700297
Sean Andersondf33fd22022-05-05 13:11:32 -0400298/* Ensure that all addresses are loaded properly */
299static int dm_test_ethaddr(struct unit_test_state *uts)
300{
301 static const char *const addr[] = {
302 "02:00:11:22:33:44",
303 "02:00:11:22:33:48", /* dsa slave */
304 "02:00:11:22:33:45",
305 "02:00:11:22:33:48", /* dsa master */
306 "02:00:11:22:33:46",
307 "02:00:11:22:33:47",
308 "02:00:11:22:33:48", /* dsa slave */
309 "02:00:11:22:33:49",
310 };
311 int i;
312
313 for (i = 0; i < ARRAY_SIZE(addr); i++) {
314 char addrname[10];
315
316 if (i)
317 snprintf(addrname, sizeof(addrname), "eth%daddr", i + 1);
318 else
319 strcpy(addrname, "ethaddr");
320 ut_asserteq_str(addr[i], env_get(addrname));
321 }
322
323 return 0;
324}
325DM_TEST(dm_test_ethaddr, UT_TESTF_SCAN_FDT);
326
Joe Hershberger09129be2015-05-20 14:27:33 -0500327/* The asserts include a return on fail; cleanup in the caller */
328static int _dm_test_eth_rotate1(struct unit_test_state *uts)
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500329{
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500330 /* Make sure that the default is to rotate to the next interface */
Simon Glass382bee52017-08-03 12:22:09 -0600331 env_set("ethact", "eth@10004000");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500332 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600333 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500334
335 /* If ethrotate is no, then we should fail on a bad MAC */
Simon Glass382bee52017-08-03 12:22:09 -0600336 env_set("ethact", "eth@10004000");
337 env_set("ethrotate", "no");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500338 ut_asserteq(-EINVAL, net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600339 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500340
Joe Hershberger09129be2015-05-20 14:27:33 -0500341 return 0;
342}
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500343
Joe Hershberger09129be2015-05-20 14:27:33 -0500344static int _dm_test_eth_rotate2(struct unit_test_state *uts)
345{
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500346 /* Make sure we can skip invalid devices */
Simon Glass382bee52017-08-03 12:22:09 -0600347 env_set("ethact", "eth@10004000");
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500348 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600349 ut_asserteq_str("eth@10004000", env_get("ethact"));
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500350
Bin Meng71d79712015-08-27 22:25:53 -0700351 /* Make sure we can handle device name which is not eth# */
Simon Glass382bee52017-08-03 12:22:09 -0600352 env_set("ethact", "sbe5");
Bin Meng71d79712015-08-27 22:25:53 -0700353 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600354 ut_asserteq_str("sbe5", env_get("ethact"));
Bin Meng71d79712015-08-27 22:25:53 -0700355
Joe Hershberger09129be2015-05-20 14:27:33 -0500356 return 0;
357}
358
359static int dm_test_eth_rotate(struct unit_test_state *uts)
360{
361 char ethaddr[18];
362 int retval;
363
364 /* Set target IP to mock ping */
365 net_ping_ip = string_to_ip("1.1.2.2");
366
367 /* Invalidate eth1's MAC address */
Tom Rinie2e6dae2017-09-26 14:08:30 -0400368 memset(ethaddr, '\0', sizeof(ethaddr));
Michael Wallebe1a6e92020-06-02 01:47:09 +0200369 strncpy(ethaddr, env_get("eth6addr"), 17);
370 /* Must disable access protection for eth6addr before clearing */
371 env_set(".flags", "eth6addr");
372 env_set("eth6addr", NULL);
Joe Hershberger09129be2015-05-20 14:27:33 -0500373
374 retval = _dm_test_eth_rotate1(uts);
375
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500376 /* Restore the env */
Michael Wallebe1a6e92020-06-02 01:47:09 +0200377 env_set("eth6addr", ethaddr);
Simon Glass382bee52017-08-03 12:22:09 -0600378 env_set("ethrotate", NULL);
Joe Hershberger09129be2015-05-20 14:27:33 -0500379
380 if (!retval) {
381 /* Invalidate eth0's MAC address */
Tom Rinie2e6dae2017-09-26 14:08:30 -0400382 strncpy(ethaddr, env_get("ethaddr"), 17);
Joe Hershberger09129be2015-05-20 14:27:33 -0500383 /* Must disable access protection for ethaddr before clearing */
Simon Glass382bee52017-08-03 12:22:09 -0600384 env_set(".flags", "ethaddr");
385 env_set("ethaddr", NULL);
Joe Hershberger09129be2015-05-20 14:27:33 -0500386
387 retval = _dm_test_eth_rotate2(uts);
388
389 /* Restore the env */
Simon Glass382bee52017-08-03 12:22:09 -0600390 env_set("ethaddr", ethaddr);
Joe Hershberger09129be2015-05-20 14:27:33 -0500391 }
392 /* Restore the env */
Simon Glass382bee52017-08-03 12:22:09 -0600393 env_set(".flags", NULL);
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500394
Joe Hershberger09129be2015-05-20 14:27:33 -0500395 return retval;
Joe Hershberger7d104ea2015-03-22 17:09:18 -0500396}
Simon Glasse180c2b2020-07-28 19:41:12 -0600397DM_TEST(dm_test_eth_rotate, UT_TESTF_SCAN_FDT);
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500398
Joe Hershberger09129be2015-05-20 14:27:33 -0500399/* The asserts include a return on fail; cleanup in the caller */
400static int _dm_test_net_retry(struct unit_test_state *uts)
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500401{
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500402 /*
403 * eth1 is disabled and netretry is yes, so the ping should succeed and
404 * the active device should be eth0
405 */
406 sandbox_eth_disable_response(1, true);
Claudiu Manoilff98da02021-03-14 20:14:57 +0800407 env_set("ethact", "lan1");
Simon Glass382bee52017-08-03 12:22:09 -0600408 env_set("netretry", "yes");
Joe Hershberger172a31b2015-04-21 13:57:20 -0500409 sandbox_eth_skip_timeout();
Joe Hershbergerbc0571f2015-04-08 01:41:21 -0500410 ut_assertok(net_loop(PING));
Simon Glass00caae62017-08-03 12:22:12 -0600411 ut_asserteq_str("eth@10002000", env_get("ethact"));
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500412
413 /*
414 * eth1 is disabled and netretry is no, so the ping should fail and the
415 * active device should be eth1
416 */
Claudiu Manoilff98da02021-03-14 20:14:57 +0800417 env_set("ethact", "lan1");
Simon Glass382bee52017-08-03 12:22:09 -0600418 env_set("netretry", "no");
Joe Hershberger172a31b2015-04-21 13:57:20 -0500419 sandbox_eth_skip_timeout();
Thomas RIENOESSLa735e6e2018-11-21 15:56:07 +0100420 ut_asserteq(-ENONET, net_loop(PING));
Claudiu Manoilff98da02021-03-14 20:14:57 +0800421 ut_asserteq_str("lan1", env_get("ethact"));
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500422
Joe Hershberger09129be2015-05-20 14:27:33 -0500423 return 0;
424}
425
426static int dm_test_net_retry(struct unit_test_state *uts)
427{
428 int retval;
429
430 net_ping_ip = string_to_ip("1.1.2.2");
431
432 retval = _dm_test_net_retry(uts);
433
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500434 /* Restore the env */
Simon Glass382bee52017-08-03 12:22:09 -0600435 env_set("netretry", NULL);
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500436 sandbox_eth_disable_response(1, false);
437
Joe Hershberger09129be2015-05-20 14:27:33 -0500438 return retval;
Joe Hershberger7ece1c62015-03-22 17:09:20 -0500439}
Simon Glasse180c2b2020-07-28 19:41:12 -0600440DM_TEST(dm_test_net_retry, UT_TESTF_SCAN_FDT);
Joe Hershberger45988da2018-09-26 16:49:00 -0500441
442static int sb_check_arp_reply(struct udevice *dev, void *packet,
443 unsigned int len)
444{
445 struct eth_sandbox_priv *priv = dev_get_priv(dev);
446 struct ethernet_hdr *eth = packet;
447 struct arp_hdr *arp;
448 /* Used by all of the ut_assert macros */
449 struct unit_test_state *uts = priv->priv;
450
451 if (ntohs(eth->et_protlen) != PROT_ARP)
452 return 0;
453
454 arp = packet + ETHER_HDR_SIZE;
455
456 if (ntohs(arp->ar_op) != ARPOP_REPLY)
457 return 0;
458
459 /* This test would be worthless if we are not waiting */
460 ut_assert(arp_is_waiting());
461
462 /* Validate response */
Simon Glassf91f3662020-05-10 12:52:45 -0600463 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
464 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger45988da2018-09-26 16:49:00 -0500465 ut_assert(eth->et_protlen == htons(PROT_ARP));
466
467 ut_assert(arp->ar_hrd == htons(ARP_ETHER));
468 ut_assert(arp->ar_pro == htons(PROT_IP));
469 ut_assert(arp->ar_hln == ARP_HLEN);
470 ut_assert(arp->ar_pln == ARP_PLEN);
Simon Glassf91f3662020-05-10 12:52:45 -0600471 ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
Joe Hershberger45988da2018-09-26 16:49:00 -0500472 ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
Simon Glassf91f3662020-05-10 12:52:45 -0600473 ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger45988da2018-09-26 16:49:00 -0500474 ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
475 string_to_ip("1.1.2.4").s_addr);
476
477 return 0;
478}
479
480static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
481 unsigned int len)
482{
483 struct eth_sandbox_priv *priv = dev_get_priv(dev);
484 struct ethernet_hdr *eth = packet;
485 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
486 int ret;
487
488 /*
489 * If we are about to generate a reply to ARP, first inject a request
490 * from another host
491 */
492 if (ntohs(eth->et_protlen) == PROT_ARP &&
493 ntohs(arp->ar_op) == ARPOP_REQUEST) {
494 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
495 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
496
497 ret = sandbox_eth_recv_arp_req(dev);
498 if (ret)
499 return ret;
500 }
501
502 sandbox_eth_arp_req_to_reply(dev, packet, len);
503 sandbox_eth_ping_req_to_reply(dev, packet, len);
504
505 return sb_check_arp_reply(dev, packet, len);
506}
507
508static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
509{
510 net_ping_ip = string_to_ip("1.1.2.2");
511
512 sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
513 /* Used by all of the ut_assert macros in the tx_handler */
514 sandbox_eth_set_priv(0, uts);
Joe Hershberger45988da2018-09-26 16:49:00 -0500515
516 env_set("ethact", "eth@10002000");
Joe Hershbergerac3f26c2018-09-26 16:49:02 -0500517 ut_assertok(net_loop(PING));
Joe Hershberger45988da2018-09-26 16:49:00 -0500518 ut_asserteq_str("eth@10002000", env_get("ethact"));
519
520 sandbox_eth_set_tx_handler(0, NULL);
521
522 return 0;
523}
524
Simon Glasse180c2b2020-07-28 19:41:12 -0600525DM_TEST(dm_test_eth_async_arp_reply, UT_TESTF_SCAN_FDT);
Joe Hershberger72ff0042018-09-26 16:49:01 -0500526
527static int sb_check_ping_reply(struct udevice *dev, void *packet,
528 unsigned int len)
529{
530 struct eth_sandbox_priv *priv = dev_get_priv(dev);
531 struct ethernet_hdr *eth = packet;
532 struct ip_udp_hdr *ip;
533 struct icmp_hdr *icmp;
534 /* Used by all of the ut_assert macros */
535 struct unit_test_state *uts = priv->priv;
536
537 if (ntohs(eth->et_protlen) != PROT_IP)
538 return 0;
539
540 ip = packet + ETHER_HDR_SIZE;
541
542 if (ip->ip_p != IPPROTO_ICMP)
543 return 0;
544
545 icmp = (struct icmp_hdr *)&ip->udp_src;
546
547 if (icmp->type != ICMP_ECHO_REPLY)
548 return 0;
549
550 /* This test would be worthless if we are not waiting */
551 ut_assert(arp_is_waiting());
552
553 /* Validate response */
Simon Glassf91f3662020-05-10 12:52:45 -0600554 ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
555 ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
Joe Hershberger72ff0042018-09-26 16:49:01 -0500556 ut_assert(eth->et_protlen == htons(PROT_IP));
557
558 ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
559 ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
560 string_to_ip("1.1.2.4").s_addr);
561
562 return 0;
563}
564
565static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
566 unsigned int len)
567{
568 struct eth_sandbox_priv *priv = dev_get_priv(dev);
569 struct ethernet_hdr *eth = packet;
570 struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
571 int ret;
572
573 /*
574 * If we are about to generate a reply to ARP, first inject a request
575 * from another host
576 */
577 if (ntohs(eth->et_protlen) == PROT_ARP &&
578 ntohs(arp->ar_op) == ARPOP_REQUEST) {
579 /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
580 priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
581
582 ret = sandbox_eth_recv_ping_req(dev);
583 if (ret)
584 return ret;
585 }
586
587 sandbox_eth_arp_req_to_reply(dev, packet, len);
588 sandbox_eth_ping_req_to_reply(dev, packet, len);
589
590 return sb_check_ping_reply(dev, packet, len);
591}
592
593static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
594{
595 net_ping_ip = string_to_ip("1.1.2.2");
596
597 sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
598 /* Used by all of the ut_assert macros in the tx_handler */
599 sandbox_eth_set_priv(0, uts);
Joe Hershberger72ff0042018-09-26 16:49:01 -0500600
601 env_set("ethact", "eth@10002000");
Joe Hershbergerac3f26c2018-09-26 16:49:02 -0500602 ut_assertok(net_loop(PING));
Joe Hershberger72ff0042018-09-26 16:49:01 -0500603 ut_asserteq_str("eth@10002000", env_get("ethact"));
604
605 sandbox_eth_set_tx_handler(0, NULL);
606
607 return 0;
608}
609
Simon Glasse180c2b2020-07-28 19:41:12 -0600610DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);
Ehsan Mohandesi4c516802023-04-21 17:08:23 -0700611
612#if IS_ENABLED(CONFIG_IPV6_ROUTER_DISCOVERY)
613
614static u8 ip6_ra_buf[] = {0x60, 0xf, 0xc5, 0x4a, 0x0, 0x38, 0x3a, 0xff, 0xfe,
615 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x85, 0xe6,
616 0x29, 0x77, 0xcb, 0xc8, 0x53, 0xff, 0x2, 0x0, 0x0,
617 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
618 0x1, 0x86, 0x0, 0xdc, 0x90, 0x40, 0x80, 0x15, 0x18,
619 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x4,
620 0x40, 0xc0, 0x0, 0x0, 0x37, 0xdc, 0x0, 0x0, 0x37,
621 0x78, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0xca, 0xfe, 0xca,
622 0xfe, 0xca, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
623 0x0, 0x1, 0x1, 0x0, 0x15, 0x5d, 0xe2, 0x8a, 0x2};
624
625static int dm_test_validate_ra(struct unit_test_state *uts)
626{
627 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
628 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
629 __be16 temp = 0;
630
631 ut_assert(validate_ra(ip6) == true);
632
633 temp = ip6->payload_len;
634 ip6->payload_len = 15;
635 ut_assert(validate_ra(ip6) == false);
636 ip6->payload_len = temp;
637
638 temp = ip6->saddr.s6_addr16[0];
639 ip6->saddr.s6_addr16[0] = 0x2001;
640 ut_assert(validate_ra(ip6) == false);
641 ip6->saddr.s6_addr16[0] = temp;
642
643 temp = ip6->hop_limit;
644 ip6->hop_limit = 15;
645 ut_assert(validate_ra(ip6) == false);
646 ip6->hop_limit = temp;
647
648 temp = icmp->icmp6_code;
649 icmp->icmp6_code = 15;
650 ut_assert(validate_ra(ip6) == false);
651 icmp->icmp6_code = temp;
652
653 return 0;
654}
655
656DM_TEST(dm_test_validate_ra, 0);
657
658static int dm_test_process_ra(struct unit_test_state *uts)
659{
660 int len = sizeof(ip6_ra_buf);
661 struct ip6_hdr *ip6 = (struct ip6_hdr *)ip6_ra_buf;
662 struct icmp6hdr *icmp = (struct icmp6hdr *)(ip6 + 1);
663 struct ra_msg *msg = (struct ra_msg *)icmp;
664 unsigned char *option = msg->opt;
665 struct icmp6_ra_prefix_info *prefix =
666 (struct icmp6_ra_prefix_info *)option;
667 __be16 temp = 0;
668 unsigned char option_len = option[1];
669
670 ut_assert(process_ra(ip6, len) == 0);
671
672 temp = icmp->icmp6_rt_lifetime;
673 icmp->icmp6_rt_lifetime = 0;
674 ut_assert(process_ra(ip6, len) != 0);
675 icmp->icmp6_rt_lifetime = temp;
676
677 ut_assert(process_ra(ip6, 0) != 0);
678
679 option[1] = 0;
680 ut_assert(process_ra(ip6, len) != 0);
681 option[1] = option_len;
682
683 prefix->on_link = false;
684 ut_assert(process_ra(ip6, len) != 0);
685 prefix->on_link = true;
686
687 temp = prefix->prefix.s6_addr16[0];
688 prefix->prefix.s6_addr16[0] = 0x80fe;
689 ut_assert(process_ra(ip6, len) != 0);
690 prefix->prefix.s6_addr16[0] = temp;
691
692 return 0;
693}
694
695DM_TEST(dm_test_process_ra, 0);
696
697#endif