[U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver
Simon Glass
sjg at chromium.org
Thu Jan 29 02:58:41 CET 2015
Hi Joe,
On 28 January 2015 at 03:36, Joe Hershberger <joe.hershberger at gmail.com> wrote:
> On Tue, Jan 27, 2015 at 8:34 PM, Simon Glass <sjg at chromium.org> wrote:
>>
>> Hi Joe,
>>
>> On 27 January 2015 at 16:27, Joe Hershberger <joe.hershberger at ni.com>
>> wrote:
>> > The sandbox driver will now generate response traffic to exercise the
>> > ping command even when no network exists. This allows the basic data
>> > pathways of the DM to be tested.
>> >
>> > Signed-off-by: Joe Hershberger <joe.hershberger at ni.com>
>> > ---
>>
>> Looks like this can support ping. Very nice.
>
> I looked at other ways to test the network stack in sandbox, create tests in
> the test/ dir, etc., but this seemed like the best and most straightforward
> way to exercise it without tons of extra code, so I went for this approach.
Well we still need tests in the test/ directory - every uclass should
have tests. In this case the tests could start up a few devices and
try ping. Also the environment variable logic needs tests.
>
>> >
>> > drivers/net/sandbox.c | 75
>> > +++++++++++++++++++++++++++++++++++++++++++++++++++
>> > 1 file changed, 75 insertions(+)
>> >
>> > diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
>> > index e1ee69b..49413f2 100644
>> > --- a/drivers/net/sandbox.c
>> > +++ b/drivers/net/sandbox.c
>> > @@ -20,6 +20,11 @@ struct eth_sandbox_priv {
>> > int sd;
>> > };
>> >
>> > +static uchar fake_host_hwaddr[ARP_HLEN] = {0x00, 0x00, 0x66, 0x44,
>> > 0x22, 0x00};
>> > +static IPaddr_t fake_host_ipaddr;
>> > +static uchar recv_packet_buffer[PKTSIZE];
>> > +static int recv_packet_length;
>>
>> This could go in the driver's priv area (then we could support
>> multiple sandbox devices).
>
> Good idea.
>
>
>> > +
>> > int sb_eth_init(struct udevice *dev, bd_t *bis)
>> > {
>> > printf("eth_sandbox: Init\n");
>> > @@ -31,12 +36,82 @@ int sb_eth_send(struct udevice *dev, void *packet,
>> > int length)
>> > {
>> > printf("eth_sandbox: Send packet %d\n", length);
>> >
>> > + struct ethernet_hdr *eth = packet;
>> > + if (ntohs(eth->et_protlen) == PROT_ARP) {
>> > + struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
>> > + if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
>> > + /* store this as the assumed IP of the fake host
>> > */
>> > + fake_host_ipaddr = NetReadIP(&arp->ar_tpa);
>> > + /* Formulate a fake response */
>> > + struct ethernet_hdr *eth_recv =
>> > + (void *)recv_packet_buffer;
>> > + memcpy(eth_recv->et_dest, eth->et_src,
>> > ARP_HLEN);
>> > + memcpy(eth_recv->et_src, fake_host_hwaddr,
>> > ARP_HLEN);
>> > + eth_recv->et_protlen = htons(PROT_ARP);
>> > +
>> > + struct arp_hdr *arp_recv = (void
>> > *)recv_packet_buffer +
>> > + 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_REPLY);
>> > + memcpy(&arp_recv->ar_sha, fake_host_hwaddr,
>> > ARP_HLEN);
>> > + NetWriteIP(&arp_recv->ar_spa, fake_host_ipaddr);
>> > + memcpy(&arp_recv->ar_tha, &arp->ar_sha,
>> > ARP_HLEN);
>> > + NetCopyIP(&arp_recv->ar_tpa, &arp->ar_spa);
>> > +
>> > + recv_packet_length = ETHER_HDR_SIZE +
>> > ARP_HDR_SIZE;
>> > + }
>> > + } else if (ntohs(eth->et_protlen) == PROT_IP) {
>> > + struct ip_udp_hdr *ip = packet + ETHER_HDR_SIZE;
>> > + if (ip->ip_p == IPPROTO_ICMP) {
>> > + struct icmp_hdr *icmp = (struct icmp_hdr
>> > *)&ip->udp_src;
>> > + if (icmp->type == ICMP_ECHO_REQUEST) {
>> > + /* reply to the ping */
>> > + memcpy(recv_packet_buffer, packet,
>> > length);
>> > + struct ethernet_hdr *eth_recv =
>> > + (void *)recv_packet_buffer;
>> > + struct ip_udp_hdr *ipr =
>> > + (void *)recv_packet_buffer +
>> > + ETHER_HDR_SIZE;
>> > + struct icmp_hdr *icmpr =
>> > + (struct icmp_hdr
>> > *)&ipr->udp_src;
>> > + memcpy(eth_recv->et_dest, eth->et_src,
>> > + ARP_HLEN);
>> > + memcpy(eth_recv->et_src,
>> > fake_host_hwaddr,
>> > + ARP_HLEN);
>> > + ipr->ip_sum = 0;
>> > + ipr->ip_off = 0;
>> > + NetCopyIP((void *)&ipr->ip_dst,
>> > &ip->ip_src);
>> > + NetWriteIP((void *)&ipr->ip_src,
>> > + fake_host_ipaddr);
>> > + ipr->ip_sum = ~NetCksum((uchar *)ipr,
>> > + IP_HDR_SIZE >> 1);
>> > +
>> > + icmpr->type = ICMP_ECHO_REPLY;
>> > + icmpr->checksum = 0;
>> > + icmpr->checksum = ~NetCksum((uchar
>> > *)icmpr,
>> > + (length - ETHER_HDR_SIZE -
>> > + IP_HDR_SIZE) >> 1);
>> > +
>> > + recv_packet_length = length;
>> > + }
>> > + }
>> > + }
>> > +
>> > return 0;
>> > #endif
>> > }
>> >
>> > int sb_eth_recv(struct udevice *dev)
>> > {
>> > + if (recv_packet_length) {
>> > + int lcl_recv_packet_length = recv_packet_length;
>> > + printf("eth_sandbox: received packet %d\n",
>> > recv_packet_length);
>> > + recv_packet_length = 0;
>> > + NetReceive((void *)recv_packet_buffer,
>> > lcl_recv_packet_length);
>> > + }
>> > return 0;
>> > }
>> >
>>
>> Looks good.
>
> Thanks.
Regards,
Simon
More information about the U-Boot
mailing list