[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