[U-Boot] [PATCH] TCP and wget implementation v3
Joe Hershberger
joe.hershberger at ni.com
Wed Jan 3 14:00:45 UTC 2018
On Tue, Dec 19, 2017 at 11:02 AM, Duncan Hare <dh at synoia.com> wrote:
>>I'd like to see the shim and all changes to existing stack as a
>>separate patch to make review simpler.
>
> In this patch.
>
>>Also please make TCP and wget into 2 other separate patches.
>
> Yes, following.
>
>> Yes it should... you could have wget "selects" tcp.
> Please send a "how to" example.
Line 12 in net/Kconfig is an example. The NET_RANDOM_ETHADDR feature
selects the LIB_RAND feature since it is required.
>
>>> The rationale behind this change is that UDP file transfers elapsed
>>> time is twice the sum of network latency x number of pcckets, and
>>> TCP file transfer times are about 4x network latency plus data
>>> transit time.
>
>>What settings are used in this tftp benchmark for block size? It makes
>>a huge difference to the performance.
>
> We use the default blocksize.
>
> We decided on TCP becuse it is probably the best high performance,
> reliable protocol available, and the simplicity of the http protocol.
>
> UDP has its place. Relaible fast file transfer is a poor fit for UDP.
>
> We we lookin at a series of patches, or a concurrent set? The
> previous patch include all the pvarius change for setting up
> integration into u-boot. This patch standing by itself cannot
> be integrated. At a minimun it needs the slightly changed
> version of ping.
>
> Signed-off-by: Duncan Hare <DH at synoia.com>
> ---
>
> include/net.h | 32 ++++++++++++++----
> net/net.c | 102
> +++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files
> changed, 108 insertions(+), 26 deletions(-)
>
> diff --git a/include/net.h b/include/net.h
> index 455b48f6c7..d231987e6e 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -15,17 +15,26 @@
> #include <asm/cache.h>
> #include <asm/byteorder.h> /* 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 nuber 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 50 /* For TCP */
> +#endif
> +
> #ifdef CONFIG_SYS_RX_ETH_BUFFER
> # define PKTBUFSRX CONFIG_SYS_RX_ETH_BUFFER
> #else
> @@ -354,6 +363,8 @@ 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.
> @@ -538,7 +549,7 @@ extern int
> net_restart_wrap; /* Tried all network devices */
> enum proto_t {
> BOOTP, RARP, ARP, TFTPGET, DHCP, PING, DNS, NFS, CDP, NETCONS,
> SNTP,
> - TFTPSRV, TFTPPUT, LINKLOCAL
> + TFTPSRV, TFTPPUT, LINKLOCAL, WGET
> };
>
> extern char net_boot_file_name[1024];/* Boot File name */
> @@ -596,10 +607,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,9 +681,16 @@ 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, u8 action, u32
> tcp_seq_num,
> + u32 tcp_ack_num);
> +
> int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport,
> int sport, int payload_len);
>
> +int net_send_tcp_packet(int payload_len, int dport, int sport, u8
> action,
> + u32 tcp_seq_num, u32 tcp_ack_num);
> +
> /* Processes a received packet */
> void net_process_received_packet(uchar *in_packet, int len);
>
> diff --git a/net/net.c b/net/net.c
> index 4259c9e321..79255c11eb 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -107,6 +107,12 @@
> #if defined(CONFIG_CMD_SNTP)
> #include "sntp.h"
> #endif
> +#if defined(CONFIG_TCP)
> +#include "tcp.h"
> +#endif
> +#if defined(CONFIG_CMD_WGET)
> +#include "wget.h"
> +#endif
>
> DECLARE_GLOBAL_DATA_PTR;
>
> @@ -181,6 +187,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 */
> @@ -381,6 +388,9 @@ void net_init(void)
>
> /* Only need to setup buffer pointers once. */
> first_call = 0;
> +#if defined(CONFIG_TCP)
> + tcp_set_tcp_state(TCP_CLOSED);
> +#endif
> }
>
> net_init_loop();
> @@ -484,6 +494,11 @@ restart:
> nfs_start();
> break;
> #endif
> +#if defined(CONFIG_CMD_WGET)
> + case WGET:
> + wget_start();
> + break;
> +#endif
> #if defined(CONFIG_CMD_CDP)
> case CDP:
> cdp_start();
> @@ -777,11 +792,41 @@ 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, 0, 0, 0);
> +}
> +
> +#if defined(CONFIG_TCP)
> +int net_send_tcp_packet(int payload_len, int dport, int sport, u8
> action,
> + u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> + return net_send_ip_packet(net_server_ethaddr, net_server_ip,
> dport,
> + sport, payload_len, IPPROTO_TCP,
> action,
> + tcp_seq_num, tcp_ack_num);
> +}
> +#endif
> +
> +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport,
> int sport,
> + int payload_len, int proto, u8 action, u32
> tcp_seq_num,
> + u32 tcp_ack_num)
> {
> 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);
> +#if defined(CONFIG_TCP)
> +
> + } else {
> + debug_cond(DEBUG_DEV_PKT,
> + "TCP Send (%pI4, %pI4, len=%d, A=%x)\n",
> + &dest, &net_ip, payload_len, action);
> +#endif
> + }
>
> /* make sure the net_tx_packet is initialized (net_init() was
> called) */ assert(net_tx_packet != NULL);
> @@ -799,9 +844,21 @@ 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;
> +#if defined(CONFIG_TCP)
> + if (proto == IPPROTO_UDP) {
> +#endif
> + net_set_udp_header(pkt + eth_hdr_size, dest,
> + dport, sport, payload_len);
> + pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
> +
> +#if defined(CONFIG_TCP)
> + } else {
> + pkt_hdr_size = eth_hdr_size +
> + tcp_set_tcp_header(pkt + eth_hdr_size, dport, sport,
> + payload_len, action,
> + tcp_seq_num, tcp_ack_num);
> + }
> +#endif
>
> /* if MAC address was not discovered yet, do an ARP request */
> if (memcmp(ether, net_null_ethaddr, 6) == 0) {
> @@ -1157,9 +1214,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,9 +1259,19 @@ 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;
> +#if defined(CONFIG_TCP)
> + } else if (ip->ip_p == IPPROTO_TCP) {
> + debug_cond(DEBUG_DEV_PKT,
> + "TCP PH (to=%pI4, from=%pI4,
> len=%d)\n",
> + &dst_ip, &src_ip, len);
> +
> + rxhand_tcp_f((union tcp_build_pkt
> *)ip, len);
> + return;
> +#endif
> } else if (ip->ip_p != IPPROTO_UDP) { /* Only
> UDP packets */ return;
> }
> @@ -1365,8 +1429,7 @@ common:
> }
> /**********************************************************************/
>
> -int
> -net_eth_hdr_size(void)
> +int net_eth_hdr_size(void)
> {
> ushort myvlanid;
>
> @@ -1426,25 +1489,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 +1526,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);
> @@ -1485,7 +1548,8 @@ void copy_filename(char *dst, const char *src,
> int size)
> #if defined(CONFIG_CMD_NFS) || \
> defined(CONFIG_CMD_SNTP) || \
> - defined(CONFIG_CMD_DNS)
> + defined(CONFIG_CMD_DNS) || \
> + defined(CONFIG_CMD_WGET)
> /*
> * make port a little random (1024-17407)
> * This keeps the math somewhat trivial to compute, and seems to work
> with
> --
> 2.11.0
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
More information about the U-Boot
mailing list