summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJoe Hershberger <joe.hershberger@ni.com>2018-09-26 16:49:00 -0500
committerJoe Hershberger <joe.hershberger@ni.com>2018-10-10 12:29:00 -0500
commit45988dae4cf05f783e40e027c83594a9dc6551cd (patch)
treedef10679c4392ebc7282d80efb200d6cbba534e4 /test
parent9cbe5972c3c00e974482181cd4062d9229a9b7d5 (diff)
test: eth: Add a test for ARP requests
This tests that ARP requests made to this target's IP address are responded-to by the target when it is doing other networking operations. This currently corrupts the ongoing operation of the device if it happens to be awaiting an ARP reply of its own to whatever serverip it is attempting to communicate with. In the test, add an expectation that the user operation (ping, in this case) will fail. A later patch will address this problem. Signed-off-by: Joe Hershberger <joe.hershberger@ni.com> Reviewed-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'test')
-rw-r--r--test/dm/eth.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/test/dm/eth.c b/test/dm/eth.c
index 1a7684a887..9e52d5cdfe 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -258,3 +258,89 @@ static int dm_test_net_retry(struct unit_test_state *uts)
return retval;
}
DM_TEST(dm_test_net_retry, DM_TESTF_SCAN_FDT);
+
+static int sb_check_arp_reply(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth = packet;
+ struct arp_hdr *arp;
+ /* Used by all of the ut_assert macros */
+ struct unit_test_state *uts = priv->priv;
+
+ if (ntohs(eth->et_protlen) != PROT_ARP)
+ return 0;
+
+ arp = packet + ETHER_HDR_SIZE;
+
+ if (ntohs(arp->ar_op) != ARPOP_REPLY)
+ return 0;
+
+ /* This test would be worthless if we are not waiting */
+ ut_assert(arp_is_waiting());
+
+ /* Validate response */
+ ut_assert(memcmp(eth->et_src, net_ethaddr, ARP_HLEN) == 0);
+ ut_assert(memcmp(eth->et_dest, priv->fake_host_hwaddr, ARP_HLEN) == 0);
+ ut_assert(eth->et_protlen == htons(PROT_ARP));
+
+ ut_assert(arp->ar_hrd == htons(ARP_ETHER));
+ ut_assert(arp->ar_pro == htons(PROT_IP));
+ ut_assert(arp->ar_hln == ARP_HLEN);
+ ut_assert(arp->ar_pln == ARP_PLEN);
+ ut_assert(memcmp(&arp->ar_sha, net_ethaddr, ARP_HLEN) == 0);
+ ut_assert(net_read_ip(&arp->ar_spa).s_addr == net_ip.s_addr);
+ ut_assert(memcmp(&arp->ar_tha, priv->fake_host_hwaddr, ARP_HLEN) == 0);
+ ut_assert(net_read_ip(&arp->ar_tpa).s_addr ==
+ string_to_ip("1.1.2.4").s_addr);
+
+ return 0;
+}
+
+static int sb_with_async_arp_handler(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth = packet;
+ struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
+ int ret;
+
+ /*
+ * If we are about to generate a reply to ARP, first inject a request
+ * from another host
+ */
+ if (ntohs(eth->et_protlen) == PROT_ARP &&
+ ntohs(arp->ar_op) == ARPOP_REQUEST) {
+ /* Make sure sandbox_eth_recv_arp_req() knows who is asking */
+ priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
+
+ ret = sandbox_eth_recv_arp_req(dev);
+ if (ret)
+ return ret;
+ }
+
+ sandbox_eth_arp_req_to_reply(dev, packet, len);
+ sandbox_eth_ping_req_to_reply(dev, packet, len);
+
+ return sb_check_arp_reply(dev, packet, len);
+}
+
+static int dm_test_eth_async_arp_reply(struct unit_test_state *uts)
+{
+ net_ping_ip = string_to_ip("1.1.2.2");
+
+ sandbox_eth_set_tx_handler(0, sb_with_async_arp_handler);
+ /* Used by all of the ut_assert macros in the tx_handler */
+ sandbox_eth_set_priv(0, uts);
+ sandbox_eth_skip_timeout();
+
+ env_set("ethact", "eth@10002000");
+ ut_assert(net_loop(PING) == -ETIMEDOUT);
+ ut_asserteq_str("eth@10002000", env_get("ethact"));
+
+ sandbox_eth_set_tx_handler(0, NULL);
+
+ return 0;
+}
+
+DM_TEST(dm_test_eth_async_arp_reply, DM_TESTF_SCAN_FDT);