
Hi Joe,
On 27 January 2015 at 16:27, Joe Hershberger joe.hershberger@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@ni.com
Looks like this can support ping. Very nice.
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).
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.
Regards, Simon