eth.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2015 National Instruments
  4. *
  5. * (C) Copyright 2015
  6. * Joe Hershberger <joe.hershberger@ni.com>
  7. */
  8. #include <common.h>
  9. #include <dm.h>
  10. #include <env.h>
  11. #include <fdtdec.h>
  12. #include <log.h>
  13. #include <malloc.h>
  14. #include <net.h>
  15. #include <asm/eth.h>
  16. #include <dm/test.h>
  17. #include <dm/device-internal.h>
  18. #include <dm/uclass-internal.h>
  19. #include <test/test.h>
  20. #include <test/ut.h>
  21. #define DM_TEST_ETH_NUM 4
  22. static int dm_test_eth(struct unit_test_state *uts)
  23. {
  24. net_ping_ip = string_to_ip("1.1.2.2");
  25. env_set("ethact", "eth@10002000");
  26. ut_assertok(net_loop(PING));
  27. ut_asserteq_str("eth@10002000", env_get("ethact"));
  28. env_set("ethact", "eth@10003000");
  29. ut_assertok(net_loop(PING));
  30. ut_asserteq_str("eth@10003000", env_get("ethact"));
  31. env_set("ethact", "eth@10004000");
  32. ut_assertok(net_loop(PING));
  33. ut_asserteq_str("eth@10004000", env_get("ethact"));
  34. return 0;
  35. }
  36. DM_TEST(dm_test_eth, UT_TESTF_SCAN_FDT);
  37. static int dm_test_eth_alias(struct unit_test_state *uts)
  38. {
  39. net_ping_ip = string_to_ip("1.1.2.2");
  40. env_set("ethact", "eth0");
  41. ut_assertok(net_loop(PING));
  42. ut_asserteq_str("eth@10002000", env_get("ethact"));
  43. env_set("ethact", "eth6");
  44. ut_assertok(net_loop(PING));
  45. ut_asserteq_str("eth@10004000", env_get("ethact"));
  46. /* Expected to fail since eth2 is not defined in the device tree */
  47. env_set("ethact", "eth2");
  48. ut_assertok(net_loop(PING));
  49. ut_asserteq_str("eth@10002000", env_get("ethact"));
  50. env_set("ethact", "eth5");
  51. ut_assertok(net_loop(PING));
  52. ut_asserteq_str("eth@10003000", env_get("ethact"));
  53. return 0;
  54. }
  55. DM_TEST(dm_test_eth_alias, UT_TESTF_SCAN_FDT);
  56. static int dm_test_eth_prime(struct unit_test_state *uts)
  57. {
  58. net_ping_ip = string_to_ip("1.1.2.2");
  59. /* Expected to be "eth@10003000" because of ethprime variable */
  60. env_set("ethact", NULL);
  61. env_set("ethprime", "eth5");
  62. ut_assertok(net_loop(PING));
  63. ut_asserteq_str("eth@10003000", env_get("ethact"));
  64. /* Expected to be "eth@10002000" because it is first */
  65. env_set("ethact", NULL);
  66. env_set("ethprime", NULL);
  67. ut_assertok(net_loop(PING));
  68. ut_asserteq_str("eth@10002000", env_get("ethact"));
  69. return 0;
  70. }
  71. DM_TEST(dm_test_eth_prime, UT_TESTF_SCAN_FDT);
  72. /**
  73. * This test case is trying to test the following scenario:
  74. * - All ethernet devices are not probed
  75. * - "ethaddr" for all ethernet devices are not set
  76. * - "ethact" is set to a valid ethernet device name
  77. *
  78. * With Sandbox default test configuration, all ethernet devices are
  79. * probed after power-up, so we have to manually create such scenario:
  80. * - Remove all ethernet devices
  81. * - Remove all "ethaddr" environment variables
  82. * - Set "ethact" to the first ethernet device
  83. *
  84. * Do a ping test to see if anything goes wrong.
  85. */
  86. static int dm_test_eth_act(struct unit_test_state *uts)
  87. {
  88. struct udevice *dev[DM_TEST_ETH_NUM];
  89. const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000",
  90. "sbe5", "eth@10004000"};
  91. const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr",
  92. "eth3addr", "eth6addr"};
  93. char ethaddr[DM_TEST_ETH_NUM][18];
  94. int i;
  95. memset(ethaddr, '\0', sizeof(ethaddr));
  96. net_ping_ip = string_to_ip("1.1.2.2");
  97. /* Prepare the test scenario */
  98. for (i = 0; i < DM_TEST_ETH_NUM; i++) {
  99. ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
  100. ethname[i], &dev[i]));
  101. ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
  102. /* Invalidate MAC address */
  103. strncpy(ethaddr[i], env_get(addrname[i]), 17);
  104. /* Must disable access protection for ethaddr before clearing */
  105. env_set(".flags", addrname[i]);
  106. env_set(addrname[i], NULL);
  107. }
  108. /* Set ethact to "eth@10002000" */
  109. env_set("ethact", ethname[0]);
  110. /* Segment fault might happen if something is wrong */
  111. ut_asserteq(-ENODEV, net_loop(PING));
  112. for (i = 0; i < DM_TEST_ETH_NUM; i++) {
  113. /* Restore the env */
  114. env_set(".flags", addrname[i]);
  115. env_set(addrname[i], ethaddr[i]);
  116. /* Probe the device again */
  117. ut_assertok(device_probe(dev[i]));
  118. }
  119. env_set(".flags", NULL);
  120. env_set("ethact", NULL);
  121. return 0;
  122. }
  123. DM_TEST(dm_test_eth_act, UT_TESTF_SCAN_FDT);
  124. /* The asserts include a return on fail; cleanup in the caller */
  125. static int _dm_test_eth_rotate1(struct unit_test_state *uts)
  126. {
  127. /* Make sure that the default is to rotate to the next interface */
  128. env_set("ethact", "eth@10004000");
  129. ut_assertok(net_loop(PING));
  130. ut_asserteq_str("eth@10002000", env_get("ethact"));
  131. /* If ethrotate is no, then we should fail on a bad MAC */
  132. env_set("ethact", "eth@10004000");
  133. env_set("ethrotate", "no");
  134. ut_asserteq(-EINVAL, net_loop(PING));
  135. ut_asserteq_str("eth@10004000", env_get("ethact"));
  136. return 0;
  137. }
  138. static int _dm_test_eth_rotate2(struct unit_test_state *uts)
  139. {
  140. /* Make sure we can skip invalid devices */
  141. env_set("ethact", "eth@10004000");
  142. ut_assertok(net_loop(PING));
  143. ut_asserteq_str("eth@10004000", env_get("ethact"));
  144. /* Make sure we can handle device name which is not eth# */
  145. env_set("ethact", "sbe5");
  146. ut_assertok(net_loop(PING));
  147. ut_asserteq_str("sbe5", env_get("ethact"));
  148. return 0;
  149. }
  150. static int dm_test_eth_rotate(struct unit_test_state *uts)
  151. {
  152. char ethaddr[18];
  153. int retval;
  154. /* Set target IP to mock ping */
  155. net_ping_ip = string_to_ip("1.1.2.2");
  156. /* Invalidate eth1's MAC address */
  157. memset(ethaddr, '\0', sizeof(ethaddr));
  158. strncpy(ethaddr, env_get("eth6addr"), 17);
  159. /* Must disable access protection for eth6addr before clearing */
  160. env_set(".flags", "eth6addr");
  161. env_set("eth6addr", NULL);
  162. retval = _dm_test_eth_rotate1(uts);
  163. /* Restore the env */
  164. env_set("eth6addr", ethaddr);
  165. env_set("ethrotate", NULL);
  166. if (!retval) {
  167. /* Invalidate eth0's MAC address */
  168. strncpy(ethaddr, env_get("ethaddr"), 17);
  169. /* Must disable access protection for ethaddr before clearing */
  170. env_set(".flags", "ethaddr");
  171. env_set("ethaddr", NULL);
  172. retval = _dm_test_eth_rotate2(uts);
  173. /* Restore the env */
  174. env_set("ethaddr", ethaddr);
  175. }
  176. /* Restore the env */
  177. env_set(".flags", NULL);
  178. return retval;
  179. }
  180. DM_TEST(dm_test_eth_rotate, UT_TESTF_SCAN_FDT);
  181. /* The asserts include a return on fail; cleanup in the caller */
  182. static int _dm_test_net_retry(struct unit_test_state *uts)
  183. {
  184. /*
  185. * eth1 is disabled and netretry is yes, so the ping should succeed and
  186. * the active device should be eth0
  187. */
  188. sandbox_eth_disable_response(1, true);
  189. env_set("ethact", "eth@10004000");
  190. env_set("netretry", "yes");
  191. sandbox_eth_skip_timeout();
  192. ut_assertok(net_loop(PING));
  193. ut_asserteq_str("eth@10002000", env_get("ethact"));
  194. /*
  195. * eth1 is disabled and netretry is no, so the ping should fail and the
  196. * active device should be eth1
  197. */
  198. env_set("ethact", "eth@10004000");
  199. env_set("netretry", "no");
  200. sandbox_eth_skip_timeout();
  201. ut_asserteq(-ENONET, net_loop(PING));
  202. ut_asserteq_str("eth@10004000", env_get("ethact"));
  203. return 0;
  204. }
  205. static int dm_test_net_retry(struct unit_test_state *uts)
  206. {
  207. int retval;
  208. net_ping_ip = string_to_ip("1.1.2.2");
  209. retval = _dm_test_net_retry(uts);
  210. /* Restore the env */
  211. env_set("netretry", NULL);
  212. sandbox_eth_disable_response(1, false);
  213. return retval;
  214. }
  215. DM_TEST(dm_test_net_retry, UT_TESTF_SCAN_FDT);
  216. static int sb_check_arp_reply(struct udevice *dev, void *packet,
  217. unsigned int len)
  218. {
  219. struct eth_sandbox_priv *priv = dev_get_priv(dev);
  220. struct ethernet_hdr *eth = packet;
  221. struct arp_hdr *arp;
  222. /* Used by all of the ut_assert macros */
  223. struct unit_test_state *uts = priv->priv;
  224. if (ntohs(eth->et_protlen) != PROT_ARP)
  225. return 0;
  226. arp = packet + ETHER_HDR_SIZE;
  227. if (ntohs(arp->ar_op) != ARPOP_REPLY)
  228. return 0;
  229. /* This test would be worthless if we are not waiting */
  230. ut_assert(arp_is_waiting());
  231. /* Validate response */
  232. ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
  233. ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
  234. ut_assert(eth->et_protlen == htons(PROT_ARP));
  235. ut_assert(arp->ar_hrd == htons(ARP_ETHER));
  236. ut_assert(arp->ar_pro == htons(PROT_IP));
  237. ut_assert(arp->ar_hln == ARP_HLEN);
  238. ut_assert(arp->ar_pln == ARP_PLEN);
  239. ut_asserteq_mem(&arp->ar_sha, net_ethaddr, ARP_HLEN);
  240. ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
  241. ut_asserteq_mem(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN);
  242. ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
  243. string_to_ip("1.1.2.4").s_addr);
  244. return 0;
  245. }
  246. static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
  247. unsigned int len)
  248. {
  249. struct eth_sandbox_priv *priv = dev_get_priv(dev);
  250. struct ethernet_hdr *eth = packet;
  251. struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
  252. int ret;
  253. /*
  254. * If we are about to generate a reply to ARP, first inject a request
  255. * from another host
  256. */
  257. if (ntohs(eth->et_protlen) == PROT_ARP &&
  258. ntohs(arp->ar_op) == ARPOP_REQUEST) {
  259. /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
  260. priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
  261. ret = sandbox_eth_recv_arp_req(dev);
  262. if (ret)
  263. return ret;
  264. }
  265. sandbox_eth_arp_req_to_reply(dev, packet, len);
  266. sandbox_eth_ping_req_to_reply(dev, packet, len);
  267. return sb_check_arp_reply(dev, packet, len);
  268. }
  269. static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
  270. {
  271. net_ping_ip = string_to_ip("1.1.2.2");
  272. sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
  273. /* Used by all of the ut_assert macros in the tx_handler */
  274. sandbox_eth_set_priv(0, uts);
  275. env_set("ethact", "eth@10002000");
  276. ut_assertok(net_loop(PING));
  277. ut_asserteq_str("eth@10002000", env_get("ethact"));
  278. sandbox_eth_set_tx_handler(0, NULL);
  279. return 0;
  280. }
  281. DM_TEST(dm_test_eth_async_arp_reply, UT_TESTF_SCAN_FDT);
  282. static int sb_check_ping_reply(struct udevice *dev, void *packet,
  283. unsigned int len)
  284. {
  285. struct eth_sandbox_priv *priv = dev_get_priv(dev);
  286. struct ethernet_hdr *eth = packet;
  287. struct ip_udp_hdr *ip;
  288. struct icmp_hdr *icmp;
  289. /* Used by all of the ut_assert macros */
  290. struct unit_test_state *uts = priv->priv;
  291. if (ntohs(eth->et_protlen) != PROT_IP)
  292. return 0;
  293. ip = packet + ETHER_HDR_SIZE;
  294. if (ip->ip_p != IPPROTO_ICMP)
  295. return 0;
  296. icmp = (struct icmp_hdr *)&ip->udp_src;
  297. if (icmp->type != ICMP_ECHO_REPLY)
  298. return 0;
  299. /* This test would be worthless if we are not waiting */
  300. ut_assert(arp_is_waiting());
  301. /* Validate response */
  302. ut_asserteq_mem(eth->et_src, net_ethaddr, ARP_HLEN);
  303. ut_asserteq_mem(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN);
  304. ut_assert(eth->et_protlen == htons(PROT_IP));
  305. ut_assert(net_read_ip(&ip->ip_src).s_addr == net_ip.s_addr);
  306. ut_assert(net_read_ip(&ip->ip_dst).s_addr ==
  307. string_to_ip("1.1.2.4").s_addr);
  308. return 0;
  309. }
  310. static int sb_with_async_ping_handler(struct udevice *dev, void *packet,
  311. unsigned int len)
  312. {
  313. struct eth_sandbox_priv *priv = dev_get_priv(dev);
  314. struct ethernet_hdr *eth = packet;
  315. struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
  316. int ret;
  317. /*
  318. * If we are about to generate a reply to ARP, first inject a request
  319. * from another host
  320. */
  321. if (ntohs(eth->et_protlen) == PROT_ARP &&
  322. ntohs(arp->ar_op) == ARPOP_REQUEST) {
  323. /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
  324. priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
  325. ret = sandbox_eth_recv_ping_req(dev);
  326. if (ret)
  327. return ret;
  328. }
  329. sandbox_eth_arp_req_to_reply(dev, packet, len);
  330. sandbox_eth_ping_req_to_reply(dev, packet, len);
  331. return sb_check_ping_reply(dev, packet, len);
  332. }
  333. static int dm_test_eth_async_ping_reply(struct unit_test_state *uts)
  334. {
  335. net_ping_ip = string_to_ip("1.1.2.2");
  336. sandbox_eth_set_tx_handler(0, sb_with_async_ping_handler);
  337. /* Used by all of the ut_assert macros in the tx_handler */
  338. sandbox_eth_set_priv(0, uts);
  339. env_set("ethact", "eth@10002000");
  340. ut_assertok(net_loop(PING));
  341. ut_asserteq_str("eth@10002000", env_get("ethact"));
  342. sandbox_eth_set_tx_handler(0, NULL);
  343. return 0;
  344. }
  345. DM_TEST(dm_test_eth_async_ping_reply, UT_TESTF_SCAN_FDT);