From patchwork Thu Mar 8 04:43:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Duncan Hare X-Patchwork-Id: 882962 X-Patchwork-Delegate: joe.hershberger@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=synoia.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=yahoo.com header.i=@yahoo.com header.b="uWyVNenR"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zxdFW47Jkz9sfP for ; Thu, 8 Mar 2018 15:43:58 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id EFB63C21F9D; Thu, 8 Mar 2018 04:43:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id ACE1EC21E62; Thu, 8 Mar 2018 04:43:49 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id E71B4C21E62; Thu, 8 Mar 2018 04:43:47 +0000 (UTC) Received: from sonic317-41.consmr.mail.ne1.yahoo.com (sonic317-41.consmr.mail.ne1.yahoo.com [66.163.184.52]) by lists.denx.de (Postfix) with ESMTPS id 55D45C21C2F for ; Thu, 8 Mar 2018 04:43:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1520484225; bh=9s2qyiwEPXKImAmEMg8mrpuUB7tUrKNvKmbIq82SCX8=; h=From:To:Cc:Subject:Date:From:Subject; b=uWyVNenRko6/y4EWlcd2yIsbS3WgKVcp7W7vTv0S9hCFzD6tEW8aqvuk5nhSFuPYYRcwuoWsbkUjIkU0XrRNBmNGB5fP76r/yYD5dDyVP7wvRUXLYsgqH8ox0wFaWRjFP8TVqxmRC2c9BJ1dpJcNBVsyPBT5rwKaFc3akWVRflboX5gn27xHMs+Bc11+9r0Dk+pJynwOdhhNCyLRhH3KcdmIslxuH+1OylhWyCKf4OGol+eHneHAX4X1+25IHBrliNoonO7rfwYvV5Zdd6WhC9eoAA0kXBdieczWJXY4DdMLD/AO8Vjrq9Luho9N7gt6U0teLz2REkSDDNIPDcuIfg== X-YMail-OSG: rDXMtCcVM1kapt6FqekT0dvFCG4QC7VRvgourMh8mbZhWA6YGPpF6nrfT4VDmO9 DNM3XYqYwVKaLPNjtme64XH9jeqjRtl.AdheWrbbnR2G9wexAChsFti9oagHHopDRDKQZOWMQjbf K.7VArGUSX8Wlm1O9rBQaT0qy0CqRINSae.QVF91E7X4I4cAhIluJtMYPlBQDlOCMRJyJywWfZbM 7n18UJJco98fK6_8IDorjl50vJFQELkpo9kWuuW7GcDTOFTmELGxpxZRfgA0tuAEADufHFfDKbA2 GMR.lb3JV2o42id7yBmj2sp_Y251PmmyaJLakofp4J4fxvmViReGrJ73QfI9oJM8TG5.atdVxJWd On41MGAHWeGxANJB5O5xmu58gWlrVTD7QFWsEQ9f1e8u8FEkiFVvlhqoNQsZLEReHthWZbNUiJTp K51V9Fo7x5teZFUfPkhhTBCGE8fn_7437jHvKZNtnEYt3QuAlVeKIfahFt4pilTLesgJpxMgExVi 0FrB8nQZ_JWOmX4xgUfX7Yy2yecHU3IQGgbES9Ui7Dec04JpQjQ-- Received: from sonic.gate.mail.ne1.yahoo.com by sonic317.consmr.mail.ne1.yahoo.com with HTTP; Thu, 8 Mar 2018 04:43:45 +0000 Received: from smtp232.mail.ne1.yahoo.com (EHLO raspberrypi.Danum.local) ([10.218.253.209]) by smtp413.mail.ne1.yahoo.com (JAMES SMTP Server ) with ESMTPA ID c95d066c278b766994454db6eee0d9dc; Thu, 08 Mar 2018 04:43:41 +0000 (UTC) From: DH@synoia.com To: DuncanCHare@yahoo.com Date: Wed, 7 Mar 2018 20:43:33 -0800 Message-Id: <20180308044336.4345-1-DH@synoia.com> X-Mailer: git-send-email 2.11.0 Cc: Duncan Hare , Joe Hershberger , u-boot@lists.denx.de Subject: [U-Boot] [PATCH v8 1/3] Adding TCP and wget into u-boot X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Duncan Hare >>>>> <<<< cover-letter: Why netboot: Central management, including logs and change control, coupled with with enhanced security and unauthorized change detection and remediation by exposing a small attack surface. Why TCP: Currently file transfer are done using tftp or NFS both over udp. This requires a request to be sent from client (u-boot) to the boot server. For a 4 Mbyte kernel, with a 1k block size this requires 4,000 request for a block. Using a large block size, one greater than the Ethernet maximum frame size limitation, would require fragmentation, which u-boot supports. However missing fragment recovery requires timeout detection and re-transmission requests for missing fragments. UDP is ideally suited to fast single packet exchanges, inquiry/response, for example dns, becuse of the lack of connection overhead. UDP as a file transport mechanism is slow, even in low latency networks, because file transfer with udp requires poll/response mechanism to provide transfer integrity. In networks with large latency, for example: the internet, UDP is even slower. What is a 30 second transfer on a local boot server and LAN increase to over 3 minutes, because of all the requests/response traffic. This was anticipated in the evolution of the IP protocols and TCP was developed and then enhanced for high latency high bandwidth networks. The current standard is TCP with selective acknowledgment. In our testing we have reduce kernel transmission time to around 0.4 seconds for a 4Mbyte kernel, with a 100 Mbps downlink. Why http and wget: HTTP is the most efficient file retrieval protocol in common use. The client send a single request, after TCP connection, to receive a file of any length. WGET is the application which implements http file transfer outside browsers as a file transfer protocol. Versions of wget exists on many operating systems. END Signed-off-by: Duncan Hare --- Changed in this patch: include/net.h net/net.c Added a protocol parameter to ip packet sending in net.c Added UDP protocol for current applications to minimize code changes to existing net apps. All the code is new, and not copied from any source. Changes in v8: Initial changes for adding TCP include/net.h | 25 +++++++++++++++++++------ net/net.c | 52 ++++++++++++++++++++++++++++++++++------------------ net/ping.c | 9 ++------- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/include/net.h b/include/net.h index 455b48f6c7..7e5f5a6a5b 100644 --- a/include/net.h +++ b/include/net.h @@ -15,17 +15,26 @@ #include #include /* for nton* / ntoh* stuff */ -#define DEBUG_LL_STATE 0 /* Link local state machine changes */ -#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */ -#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */ +#define DEBUG_LL_STATE 0 /* Link local state machine changes */ +#define DEBUG_DEV_PKT 0 /* Packets or info directed to the device */ +#define DEBUG_NET_PKT 0 /* Packets on info on the network at large */ #define DEBUG_INT_STATE 0 /* Internal network state changes */ /* * The number of receive packet buffers, and the required packet buffer * alignment in memory. * + * The number of buffers for TCP is used to calculate a static TCP window + * size, becuse TCP window size is a promise to the sending TCP to be able + * to buffer up to the window size of data. + * When the sending TCP has a window size of outstanding unacknowledged + * data, the sending TCP will stop sending. */ +#if defined(CONFIG_TCP) +#define CONFIG_SYS_RX_ETH_BUFFER 12 /* For TCP */ +#endif + #ifdef CONFIG_SYS_RX_ETH_BUFFER # define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER #else @@ -354,6 +363,7 @@ struct vlan_ethernet_hdr { #define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ #define IPPROTO_UDP 17 /* User Datagram Protocol */ +#define IPPROTO_TCP 6 /* Transmission Control Protocol */ /* * Internet Protocol (IP) header. @@ -596,10 +606,10 @@ int net_set_ether(uchar *xet, const uchar *dest_ethaddr, uint prot); int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot); /* Set IP header */ -void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source); +void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source, + u16 pkt_len, u8 prot); void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, - int sport, int len); - + int sport, int len); /** * compute_ip_checksum() - Compute IP checksum * @@ -670,6 +680,9 @@ static inline void net_send_packet(uchar *pkt, int len) * @param sport Source UDP port * @param payload_len Length of data after the UDP header */ +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto); + int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len); diff --git a/net/net.c b/net/net.c index 4259c9e321..df4e7317e7 100644 --- a/net/net.c +++ b/net/net.c @@ -181,6 +181,7 @@ int net_ntp_time_offset; static uchar net_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; /* Receive packets */ uchar *net_rx_packets[PKTBUFSRX]; + /* Current UDP RX packet handler */ static rxhand_f *udp_packet_handler; /* Current ARP RX packet handler */ @@ -777,11 +778,23 @@ void net_set_timeout_handler(ulong iv, thand_f *f) } int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, - int payload_len) + int payload_len) +{ + return net_send_ip_packet(ether, dest, dport, sport, payload_len, + IPPROTO_UDP); +} + +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto) { uchar *pkt; int eth_hdr_size; int pkt_hdr_size; + if (proto == IPPROTO_UDP) { + debug_cond(DEBUG_DEV_PKT, + "UDP Send (to=%pI4, from=%pI4, len=%d)\n", + &dest, &net_ip, payload_len); + } /* make sure the net_tx_packet is initialized (net_init() was called) */ assert(net_tx_packet != NULL); @@ -799,9 +812,15 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, pkt = (uchar *)net_tx_packet; eth_hdr_size = net_set_ether(pkt, ether, PROT_IP); - pkt += eth_hdr_size; - net_set_udp_header(pkt, dest, dport, sport, payload_len); - pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + switch (proto) { + case IPPROTO_UDP: + net_set_udp_header(pkt + eth_hdr_size, dest, + dport, sport, payload_len); + pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + break; + default: + return -1; + } /* if MAC address was not discovered yet, do an ARP request */ if (memcmp(ether, net_null_ethaddr, 6) == 0) { @@ -1157,9 +1176,6 @@ void net_process_received_packet(uchar *in_packet, int len) /* Can't deal with anything except IPv4 */ if ((ip->ip_hl_v & 0xf0) != 0x40) return; - /* Can't deal with IP options (headers != 20 bytes) */ - if ((ip->ip_hl_v & 0x0f) > 0x05) - return; /* Check the Checksum of the header */ if (!ip_checksum_ok((uchar *)ip, IP_HDR_SIZE)) { debug("checksum bad\n"); @@ -1205,6 +1221,7 @@ void net_process_received_packet(uchar *in_packet, int len) * we send a tftp packet to a dead connection, or when * there is no server at the other end. */ + if (ip->ip_p == IPPROTO_ICMP) { receive_icmp(ip, len, src_ip, et); return; @@ -1365,8 +1382,7 @@ common: } /**********************************************************************/ -int -net_eth_hdr_size(void) +int net_eth_hdr_size(void) { ushort myvlanid; @@ -1426,25 +1442,28 @@ int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot) } } -void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) +void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source, + u16 pkt_len, u8 prot) { struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; /* - * Construct an IP header. + * Construct an IP header. */ /* IP_HDR_SIZE / 4 (not including UDP) */ ip->ip_hl_v = 0x45; ip->ip_tos = 0; - ip->ip_len = htons(IP_HDR_SIZE); + ip->ip_len = htons(pkt_len); ip->ip_id = htons(net_ip_id++); - ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ + ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ ip->ip_ttl = 255; + ip->ip_p = prot; ip->ip_sum = 0; /* already in network byte order */ net_copy_ip((void *)&ip->ip_src, &source); /* already in network byte order */ net_copy_ip((void *)&ip->ip_dst, &dest); + ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); } void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, @@ -1460,11 +1479,8 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, if (len & 1) pkt[IP_UDP_HDR_SIZE + len] = 0; - net_set_ip_header(pkt, dest, net_ip); - ip->ip_len = htons(IP_UDP_HDR_SIZE + len); - ip->ip_p = IPPROTO_UDP; - ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); - + net_set_ip_header(pkt, dest, net_ip, IP_UDP_HDR_SIZE + len, + IPPROTO_UDP); ip->udp_src = htons(sport); ip->udp_dst = htons(dport); ip->udp_len = htons(UDP_HDR_SIZE + len); diff --git a/net/ping.c b/net/ping.c index 9508cf1160..254b646193 100644 --- a/net/ping.c +++ b/net/ping.c @@ -20,16 +20,11 @@ struct in_addr net_ping_ip; static void set_icmp_header(uchar *pkt, struct in_addr dest) { /* - * Construct an IP and ICMP header. + * Construct an ICMP header. */ - struct ip_hdr *ip = (struct ip_hdr *)pkt; struct icmp_hdr *icmp = (struct icmp_hdr *)(pkt + IP_HDR_SIZE); - net_set_ip_header(pkt, dest, net_ip); - - ip->ip_len = htons(IP_ICMP_HDR_SIZE); - ip->ip_p = IPPROTO_ICMP; - ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); + net_set_ip_header(pkt, dest, net_ip, IP_ICMP_HDR_SIZE, IPPROTO_ICMP); icmp->type = ICMP_ECHO_REQUEST; icmp->code = 0;