[U-Boot] [RFC PATCH 7/7] net: Add ARP and PING response to sandbox driver

Joe Hershberger joe.hershberger at ni.com
Wed Jan 28 00:27:25 CET 2015


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>
---

 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;
+
 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;
 }
 
-- 
1.7.11.5



More information about the U-Boot mailing list