diff mbox series

[U-Boot,v2,02/10] net: sandbox: Refactor sandbox send function

Message ID 20180926214902.38803-3-joe.hershberger@ni.com
State Accepted
Commit e95bb1611043ff1ad5b63602e32bba302e402491
Delegated to: Joe Hershberger
Headers show
Series net: Fix packet corruption issue when handling asynch replies | expand

Commit Message

Joe Hershberger Sept. 26, 2018, 9:48 p.m. UTC
Make the behavior of the send function reusable.

Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>

---

Changes in v2:
- Added parameter comments
- Changed return value to use typical error approach
- In test, stop calling reply functions when one matches

 arch/sandbox/include/asm/eth.h |  26 ++++++
 drivers/net/sandbox.c          | 180 ++++++++++++++++++++++++-----------------
 2 files changed, 132 insertions(+), 74 deletions(-)

Comments

Bin Meng Sept. 27, 2018, 6:38 a.m. UTC | #1
Hi Joe,

On Thu, Sep 27, 2018 at 5:49 AM Joe Hershberger <joe.hershberger@ni.com> wrote:
>
> Make the behavior of the send function reusable.
>
> Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
>
> ---
>
> Changes in v2:
> - Added parameter comments
> - Changed return value to use typical error approach
> - In test, stop calling reply functions when one matches
>
>  arch/sandbox/include/asm/eth.h |  26 ++++++
>  drivers/net/sandbox.c          | 180 ++++++++++++++++++++++++-----------------
>  2 files changed, 132 insertions(+), 74 deletions(-)
>

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 bfcd11b593..3dc84f0e4b 100644
> --- a/arch/sandbox/include/asm/eth.h
> +++ b/arch/sandbox/include/asm/eth.h
> @@ -13,4 +13,30 @@ void sandbox_eth_disable_response(int index, bool disable);
>
>  void sandbox_eth_skip_timeout(void);
>
> +/*
> + * sandbox_eth_arp_req_to_reply()
> + *
> + * Check for an arp request to be sent. If so, inject a reply
> + *
> + * @dev: device that received the packet
> + * @packet: pointer to the received pacaket buffer
> + * @len: length of received packet
> + * @return 0 if injected, -EAGAIN if not
> + */
> +int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet,
> +                                unsigned int len);
> +
> +/*
> + * sandbox_eth_ping_req_to_reply()
> + *
> + * Check for a ping request to be sent. If so, inject a reply
> + *
> + * @dev: device that received the packet
> + * @packet: pointer to the received pacaket buffer
> + * @len: length of received packet
> + * @return 0 if injected, -EAGAIN if not
> + */
> +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
> +                                 unsigned int len);
> +
>  #endif /* __ETH_H */
> diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
> index 60fe065ee5..c472261568 100644
> --- a/drivers/net/sandbox.c
> +++ b/drivers/net/sandbox.c
> @@ -63,6 +63,108 @@ void sandbox_eth_skip_timeout(void)
>         skip_timeout = true;
>  }
>
> +/*
> + * sandbox_eth_arp_req_to_reply()
> + *
> + * Check for an arp request to be sent. If so, inject a reply
> + *
> + * returns 0 if injected, -EAGAIN if not
> + */
> +int sandbox_eth_arp_req_to_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 ethernet_hdr *eth_recv;
> +       struct arp_hdr *arp_recv;
> +
> +       if (ntohs(eth->et_protlen) != PROT_ARP)
> +               return -EAGAIN;
> +
> +       arp = packet + ETHER_HDR_SIZE;
> +
> +       if (ntohs(arp->ar_op) != ARPOP_REQUEST)
> +               return -EAGAIN;
> +
> +       /* store this as the assumed IP of the fake host */
> +       priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
> +
> +       /* Formulate a fake response */
> +       eth_recv = (void *)priv->recv_packet_buffer;
> +       memcpy(eth_recv->et_dest, eth->et_src, 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_REPLY);
> +       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, &arp->ar_sha, ARP_HLEN);
> +       net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
> +
> +       priv->recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE;
> +
> +       return 0;
> +}
> +
> +/*
> + * sandbox_eth_ping_req_to_reply()
> + *
> + * Check for a ping request to be sent. If so, inject a reply
> + *
> + * returns 0 if injected, -EAGAIN if not
> + */
> +int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
> +                                 unsigned int len)
> +{
> +       struct eth_sandbox_priv *priv = dev_get_priv(dev);
> +       struct ethernet_hdr *eth = packet;
> +       struct ip_udp_hdr *ip;
> +       struct icmp_hdr *icmp;
> +       struct ethernet_hdr *eth_recv;
> +       struct ip_udp_hdr *ipr;
> +       struct icmp_hdr *icmpr;
> +
> +       if (ntohs(eth->et_protlen) != PROT_IP)
> +               return -EAGAIN;
> +
> +       ip = packet + ETHER_HDR_SIZE;
> +
> +       if (ip->ip_p != IPPROTO_ICMP)
> +               return -EAGAIN;
> +
> +       icmp = (struct icmp_hdr *)&ip->udp_src;
> +
> +       if (icmp->type != ICMP_ECHO_REQUEST)
> +               return -EAGAIN;
> +
> +       /* reply to the ping */
> +       eth_recv = (void *)priv->recv_packet_buffer;
> +       memcpy(eth_recv, packet, len);
> +       ipr = (void *)eth_recv + ETHER_HDR_SIZE;
> +       icmpr = (struct icmp_hdr *)&ipr->udp_src;
> +       memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
> +       memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
> +       ipr->ip_sum = 0;
> +       ipr->ip_off = 0;
> +       net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
> +       net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr);
> +       ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
> +
> +       icmpr->type = ICMP_ECHO_REPLY;
> +       icmpr->checksum = 0;
> +       icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE);
> +
> +       priv->recv_packet_length = len;
> +
> +       return 0;
> +}
> +
>  static int sb_eth_start(struct udevice *dev)
>  {
>         struct eth_sandbox_priv *priv = dev_get_priv(dev);
> @@ -77,86 +179,16 @@ static int sb_eth_start(struct udevice *dev)
>  static int sb_eth_send(struct udevice *dev, void *packet, int length)
>  {
>         struct eth_sandbox_priv *priv = dev_get_priv(dev);
> -       struct ethernet_hdr *eth = packet;
>
>         debug("eth_sandbox: Send packet %d\n", length);
>
>         if (priv->disabled)
>                 return 0;
>
> -       if (ntohs(eth->et_protlen) == PROT_ARP) {
> -               struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
> -
> -               if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
> -                       struct ethernet_hdr *eth_recv;
> -                       struct arp_hdr *arp_recv;
> -
> -                       /* store this as the assumed IP of the fake host */
> -                       priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
> -                       /* Formulate a fake response */
> -                       eth_recv = (void *)priv->recv_packet_buffer;
> -                       memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
> -                       memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
> -                              ARP_HLEN);
> -                       eth_recv->et_protlen = htons(PROT_ARP);
> -
> -                       arp_recv = (void *)priv->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, priv->fake_host_hwaddr,
> -                              ARP_HLEN);
> -                       net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
> -                       memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
> -                       net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
> -
> -                       priv->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) {
> -                               struct ethernet_hdr *eth_recv;
> -                               struct ip_udp_hdr *ipr;
> -                               struct icmp_hdr *icmpr;
> -
> -                               /* reply to the ping */
> -                               memcpy(priv->recv_packet_buffer, packet,
> -                                      length);
> -                               eth_recv = (void *)priv->recv_packet_buffer;
> -                               ipr = (void *)priv->recv_packet_buffer +
> -                                       ETHER_HDR_SIZE;
> -                               icmpr = (struct icmp_hdr *)&ipr->udp_src;
> -                               memcpy(eth_recv->et_dest, eth->et_src,
> -                                      ARP_HLEN);
> -                               memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
> -                                      ARP_HLEN);
> -                               ipr->ip_sum = 0;
> -                               ipr->ip_off = 0;
> -                               net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
> -                               net_write_ip((void *)&ipr->ip_src,
> -                                            priv->fake_host_ipaddr);
> -                               ipr->ip_sum = compute_ip_checksum(ipr,
> -                                       IP_HDR_SIZE);
> -
> -                               icmpr->type = ICMP_ECHO_REPLY;
> -                               icmpr->checksum = 0;
> -                               icmpr->checksum = compute_ip_checksum(icmpr,
> -                                       ICMP_HDR_SIZE);
> -
> -                               priv->recv_packet_length = length;
> -                       }
> -               }
> -       }
> -
> -       return 0;
> +       if (!sandbox_eth_arp_req_to_reply(dev, packet, length))
> +               return 0;
> +       if (!sandbox_eth_ping_req_to_reply(dev, packet, length))
> +               return 0;

I think you will get a warning here: no return value specified ..

>  }
>
>  static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp)
> --

Regards,
Bin
Joe Hershberger Oct. 11, 2018, 7:25 p.m. UTC | #2
Hi Joe,

https://patchwork.ozlabs.org/patch/975414/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git

Thanks!
-Joe
diff mbox series

Patch

diff --git a/arch/sandbox/include/asm/eth.h b/arch/sandbox/include/asm/eth.h
index bfcd11b593..3dc84f0e4b 100644
--- a/arch/sandbox/include/asm/eth.h
+++ b/arch/sandbox/include/asm/eth.h
@@ -13,4 +13,30 @@  void sandbox_eth_disable_response(int index, bool disable);
 
 void sandbox_eth_skip_timeout(void);
 
+/*
+ * sandbox_eth_arp_req_to_reply()
+ *
+ * Check for an arp request to be sent. If so, inject a reply
+ *
+ * @dev: device that received the packet
+ * @packet: pointer to the received pacaket buffer
+ * @len: length of received packet
+ * @return 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_arp_req_to_reply(struct udevice *dev, void *packet,
+				 unsigned int len);
+
+/*
+ * sandbox_eth_ping_req_to_reply()
+ *
+ * Check for a ping request to be sent. If so, inject a reply
+ *
+ * @dev: device that received the packet
+ * @packet: pointer to the received pacaket buffer
+ * @len: length of received packet
+ * @return 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
+				  unsigned int len);
+
 #endif /* __ETH_H */
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index 60fe065ee5..c472261568 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -63,6 +63,108 @@  void sandbox_eth_skip_timeout(void)
 	skip_timeout = true;
 }
 
+/*
+ * sandbox_eth_arp_req_to_reply()
+ *
+ * Check for an arp request to be sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_arp_req_to_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 ethernet_hdr *eth_recv;
+	struct arp_hdr *arp_recv;
+
+	if (ntohs(eth->et_protlen) != PROT_ARP)
+		return -EAGAIN;
+
+	arp = packet + ETHER_HDR_SIZE;
+
+	if (ntohs(arp->ar_op) != ARPOP_REQUEST)
+		return -EAGAIN;
+
+	/* store this as the assumed IP of the fake host */
+	priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
+
+	/* Formulate a fake response */
+	eth_recv = (void *)priv->recv_packet_buffer;
+	memcpy(eth_recv->et_dest, eth->et_src, 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_REPLY);
+	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, &arp->ar_sha, ARP_HLEN);
+	net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
+
+	priv->recv_packet_length = ETHER_HDR_SIZE + ARP_HDR_SIZE;
+
+	return 0;
+}
+
+/*
+ * sandbox_eth_ping_req_to_reply()
+ *
+ * Check for a ping request to be sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+int sandbox_eth_ping_req_to_reply(struct udevice *dev, void *packet,
+				  unsigned int len)
+{
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	struct ethernet_hdr *eth = packet;
+	struct ip_udp_hdr *ip;
+	struct icmp_hdr *icmp;
+	struct ethernet_hdr *eth_recv;
+	struct ip_udp_hdr *ipr;
+	struct icmp_hdr *icmpr;
+
+	if (ntohs(eth->et_protlen) != PROT_IP)
+		return -EAGAIN;
+
+	ip = packet + ETHER_HDR_SIZE;
+
+	if (ip->ip_p != IPPROTO_ICMP)
+		return -EAGAIN;
+
+	icmp = (struct icmp_hdr *)&ip->udp_src;
+
+	if (icmp->type != ICMP_ECHO_REQUEST)
+		return -EAGAIN;
+
+	/* reply to the ping */
+	eth_recv = (void *)priv->recv_packet_buffer;
+	memcpy(eth_recv, packet, len);
+	ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+	icmpr = (struct icmp_hdr *)&ipr->udp_src;
+	memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+	memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+	ipr->ip_sum = 0;
+	ipr->ip_off = 0;
+	net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
+	net_write_ip((void *)&ipr->ip_src, priv->fake_host_ipaddr);
+	ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+	icmpr->type = ICMP_ECHO_REPLY;
+	icmpr->checksum = 0;
+	icmpr->checksum = compute_ip_checksum(icmpr, ICMP_HDR_SIZE);
+
+	priv->recv_packet_length = len;
+
+	return 0;
+}
+
 static int sb_eth_start(struct udevice *dev)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
@@ -77,86 +179,16 @@  static int sb_eth_start(struct udevice *dev)
 static int sb_eth_send(struct udevice *dev, void *packet, int length)
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
-	struct ethernet_hdr *eth = packet;
 
 	debug("eth_sandbox: Send packet %d\n", length);
 
 	if (priv->disabled)
 		return 0;
 
-	if (ntohs(eth->et_protlen) == PROT_ARP) {
-		struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
-
-		if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
-			struct ethernet_hdr *eth_recv;
-			struct arp_hdr *arp_recv;
-
-			/* store this as the assumed IP of the fake host */
-			priv->fake_host_ipaddr = net_read_ip(&arp->ar_tpa);
-			/* Formulate a fake response */
-			eth_recv = (void *)priv->recv_packet_buffer;
-			memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
-			memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
-			       ARP_HLEN);
-			eth_recv->et_protlen = htons(PROT_ARP);
-
-			arp_recv = (void *)priv->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, priv->fake_host_hwaddr,
-			       ARP_HLEN);
-			net_write_ip(&arp_recv->ar_spa, priv->fake_host_ipaddr);
-			memcpy(&arp_recv->ar_tha, &arp->ar_sha, ARP_HLEN);
-			net_copy_ip(&arp_recv->ar_tpa, &arp->ar_spa);
-
-			priv->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) {
-				struct ethernet_hdr *eth_recv;
-				struct ip_udp_hdr *ipr;
-				struct icmp_hdr *icmpr;
-
-				/* reply to the ping */
-				memcpy(priv->recv_packet_buffer, packet,
-				       length);
-				eth_recv = (void *)priv->recv_packet_buffer;
-				ipr = (void *)priv->recv_packet_buffer +
-					ETHER_HDR_SIZE;
-				icmpr = (struct icmp_hdr *)&ipr->udp_src;
-				memcpy(eth_recv->et_dest, eth->et_src,
-				       ARP_HLEN);
-				memcpy(eth_recv->et_src, priv->fake_host_hwaddr,
-				       ARP_HLEN);
-				ipr->ip_sum = 0;
-				ipr->ip_off = 0;
-				net_copy_ip((void *)&ipr->ip_dst, &ip->ip_src);
-				net_write_ip((void *)&ipr->ip_src,
-					     priv->fake_host_ipaddr);
-				ipr->ip_sum = compute_ip_checksum(ipr,
-					IP_HDR_SIZE);
-
-				icmpr->type = ICMP_ECHO_REPLY;
-				icmpr->checksum = 0;
-				icmpr->checksum = compute_ip_checksum(icmpr,
-					ICMP_HDR_SIZE);
-
-				priv->recv_packet_length = length;
-			}
-		}
-	}
-
-	return 0;
+	if (!sandbox_eth_arp_req_to_reply(dev, packet, length))
+		return 0;
+	if (!sandbox_eth_ping_req_to_reply(dev, packet, length))
+		return 0;
 }
 
 static int sb_eth_recv(struct udevice *dev, int flags, uchar **packetp)