From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bin Meng Date: Thu, 27 Sep 2018 14:38:01 +0800 Subject: [U-Boot] [PATCH v2 02/10] net: sandbox: Refactor sandbox send function In-Reply-To: <20180926214902.38803-3-joe.hershberger@ni.com> References: <20180926214902.38803-1-joe.hershberger@ni.com> <20180926214902.38803-3-joe.hershberger@ni.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Joe, On Thu, Sep 27, 2018 at 5:49 AM Joe Hershberger wrote: > > Make the behavior of the send function reusable. > > Signed-off-by: Joe Hershberger > > --- > > 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 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