
Hi Joe,
On Wed, Jul 25, 2018 at 5:43 AM Joe Hershberger joe.hershberger@ni.com wrote:
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
arch/sandbox/include/asm/eth.h | 9 +++++ drivers/net/sandbox.c | 41 +++++++++++++++++++++ test/dm/eth.c | 81 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com
But please see comments below:
diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h index 6bb3f1bbfd..7cd5b551d9 100644 --- a/arch/sandbox/include/asm/eth.h +++ b/arch/sandbox/include/asm/eth.h @@ -33,6 +33,15 @@ int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet, int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, unsigned int len);
+/*
- sandbox_eth_recv_arp_req()
- Inject an ARP request for this target
- returns 1 if injected, 0 if not
again the return codes, can we use -Exxx instead? I see the return error is not checked anywhere, maybe we should just make it return void?
- */
+int sandbox_eth_recv_arp_req(struct udevice *dev);
/**
- A packet handler
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 29767ef291..2c2a2c6311 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -161,6 +161,47 @@ int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet, }
/*
- sandbox_eth_recv_arp_req()
- Inject an ARP request for this target
- returns 1 if injected, 0 if not
- */
+int sandbox_eth_recv_arp_req(struct udevice *dev) +{
struct eth_sandbox_priv *priv = dev_get_priv(dev);
struct ethernet_hdr *eth_recv;
struct arp_hdr *arp_recv;
/* Don't allow the buffer to overrun */
if (priv->recv_packets >= PKTBUFSRX)
return 0;
/* Formulate a fake request */
eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
memcpy(eth_recv->et_dest, net_bcast_ethaddr, ARP_HLEN);
memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
eth_recv->et_protlen = htons(PROT_ARP);
arp_recv = (void *)eth_recv + ETHER_HDR_SIZE;
arp_recv->ar_hrd = htons(ARP_ETHER);
arp_recv->ar_pro = htons(PROT_IP);
arp_recv->ar_hln = ARP_HLEN;
arp_recv->ar_pln = ARP_PLEN;
arp_recv->ar_op = htons(ARPOP_REQUEST);
memcpy(&arp_recv->ar_sha, priv->fake_host_hwaddr, ARP_HLEN);
net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
memcpy(&arp_recv->ar_tha, net_null_ethaddr, ARP_HLEN);
net_write_ip(&arp_recv->ar_tpa, net_ip);
priv->recv_packet_length[priv->recv_packets] =
ETHER_HDR_SIZE + ARP_HDR_SIZE;
++priv->recv_packets;
return 1;
+}
+/*
- sb_default_handler()
- perform typical responses to simple ping
diff --git a/test/dm/eth.c b/test/dm/eth.c index 1a7684a887..9b5f53e819 100644 --- a/test/dm/eth.c +++ b/test/dm/eth.c @@ -258,3 +258,84 @@ 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;
struct unit_test_state *uts = priv->priv;
This is not used anywhere. What is this for?
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;
/*
* 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");
sandbox_eth_recv_arp_req(dev);
}
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);
sandbox_eth_set_priv(0, uts);
Looks this is not needed since it was not used anywhere.
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);
Regards, Bin