All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3
@ 2018-01-29  1:34 Duncan Hare
  2018-01-29  2:21 ` Heinrich Schuchardt
  0 siblings, 1 reply; 4+ messages in thread
From: Duncan Hare @ 2018-01-29  1:34 UTC (permalink / raw)
  To: u-boot

Date: Sun, 28 Jan 2018 11:25:51 -0800

This is the interface and Kconfig files for introducing TCP and wget 
into u-boot.

Interfaces are in net.c and net.h, ping is modified to the new ip send 
interface, and UDP and TCP have shim procedures call map the protocol 
interface to the ip interface. 

The UDP interface is unchanged, and the existing UDP programs need no 
changes.

All the code is new, and not copied from any source.

Makefile in the net directory is modified by hand. It appears not to be
generated by Kconfig.

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.

In tests this reduces kernel trnasfer time from about 15 to 20 seconds 
with tftp on a raspberry pi to about 0.4 seconds with wget.

The raspberry pi as a sink for the kernel runs at about 10 Mbits/sec.

It is not clear if all drivers use net_rx_packets as input buffers. 
Some driivers do. Some drivers also always start circular buffers use 
at buffer[0]. It would be better if circlar buffer pools were used 
in a truly circular manner at all times.



Signed-off-by: Duncan Hare <DuncanCHare@yahoo.com>
---

 include/net.h |  32 ++++++++++++++----
 net/Kconfig   |   5 +++
 net/net.c     | 102 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 net/ping.c    |   9 ++----
 4 files changed, 115 insertions(+), 33 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/Kconfig b/net/Kconfig
index 414c5497c7..625ad291bb 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -45,4 +45,9 @@ config BOOTP_VCI_STRING
 	default "U-Boot.arm" if ARM
 	default "U-Boot"
 
+config TCP
+	bool "Include Subset TCP stack for wget"
+	help
+	  TCP protocol support for wget.
+
 endif   # if NET
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
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;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3
  2018-01-29  1:34 [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3 Duncan Hare
@ 2018-01-29  2:21 ` Heinrich Schuchardt
       [not found]   ` <1876838587.2851978.1517245243033@mail.yahoo.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Heinrich Schuchardt @ 2018-01-29  2:21 UTC (permalink / raw)
  To: u-boot

On 01/29/2018 02:34 AM, Duncan Hare wrote:
> Date: Sun, 28 Jan 2018 11:25:51 -0800
> 
> This is the interface and Kconfig files for introducing TCP and wget 
> into u-boot.
> 
> Interfaces are in net.c and net.h, ping is modified to the new ip send 
> interface, and UDP and TCP have shim procedures call map the protocol 
> interface to the ip interface. 
> 
> The UDP interface is unchanged, and the existing UDP programs need no 
> changes.
> 
> All the code is new, and not copied from any source.
> 
> Makefile in the net directory is modified by hand. It appears not to be
> generated by Kconfig.
> 
> 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.
> 
> In tests this reduces kernel trnasfer time from about 15 to 20 seconds 
> with tftp on a raspberry pi to about 0.4 seconds with wget.
> 
> The raspberry pi as a sink for the kernel runs at about 10 Mbits/sec.
> 
> It is not clear if all drivers use net_rx_packets as input buffers. 
> Some driivers do. Some drivers also always start circular buffers use 
> at buffer[0]. It would be better if circlar buffer pools were used 
> in a truly circular manner at all times.
> 

The patch is trying to put everything into net.c. This is a mess and not
where we should head to.

We should have have one driver per protocol.

The IP driver should enumerate all drivers protocols like TCP and UDP
that want to listen to it using a Linux list. This way we get rid of all
those needless #ifdef CONFIGs. Using the list the IP driver will hand
out packets to the respective higher protocol driver.

A separate driver shall implement the TCP protocol and provide methods
to open a socket, to read and write to the socket and to close the socket.

Next we want a driver for the HTTP protocol. It should have function to
open a connection, to send a request, to receive a response, and to
close the connection. If this driver is requested to open a connection
it shall call the TCP driver to open a socket. It will then receive all
packets from the relevant IP address on the relevant port until it
closes the socket.

The wget command should be in a separate file. It will call the
appropriate functions of the HTTP driver to open a connection, post the
request, receive the response, and finally close the connection.

The work should start with refactoring the existing coding into separate
drivers for the existing protocols. When that is completed you can start
adding TCP relevant code.

Please, do not send single patches but complete patch series.

Best regards

Heinrich

> 
> 
> Signed-off-by: Duncan Hare <DuncanCHare@yahoo.com>
> ---
> 
>  include/net.h |  32 ++++++++++++++----
>  net/Kconfig   |   5 +++
>  net/net.c     | 102 +++++++++++++++++++++++++++++++++++++++++++++++-----------
>  net/ping.c    |   9 ++----
>  4 files changed, 115 insertions(+), 33 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/Kconfig b/net/Kconfig
> index 414c5497c7..625ad291bb 100644
> --- a/net/Kconfig
> +++ b/net/Kconfig
> @@ -45,4 +45,9 @@ config BOOTP_VCI_STRING
>  	default "U-Boot.arm" if ARM
>  	default "U-Boot"
>  
> +config TCP
> +	bool "Include Subset TCP stack for wget"
> +	help
> +	  TCP protocol support for wget.
> +
>  endif   # if NET
> 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
> 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;
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3
       [not found]     ` <47879340.2828440.1517245407426@mail.yahoo.com>
@ 2018-01-29 17:30       ` Duncan Hare
  2018-01-29 18:06         ` Heinrich Schuchardt
  0 siblings, 1 reply; 4+ messages in thread
From: Duncan Hare @ 2018-01-29 17:30 UTC (permalink / raw)
  To: u-boot

> The patch is trying to put everything into net.c. This is a mess and
> not where we should head to.

Not at all. I tried that and it was correctly rejected. The TCP
functions are in tcp.c, and the wget functions in wget.c

There is no  socket. There is no socket analogue. There is no
widespread correct re-ordering of packets, because in a kernel download 
the relative address of each block is derived for the tcp sequence
number, and the kernel image in memory itself is in the correct order,
as defined by tcp sequence number.

> 
> We should have have one driver per protocol.
> 
> The IP driver should enumerate all drivers protocols like TCP and UDP
> that want to listen to it using a Linux list. This way we get rid of
> all those needless #ifdef CONFIGs. Using the list the IP driver will
> hand out packets to the respective higher protocol driver.

The choice was to make minimal changes to the
current net.c, in consultation with other in the u-boot realm.

> 
> A separate driver shall implement the TCP protocol and provide methods
> to open a socket, to read and write to the socket and to close the
> socket.
> 
"shall"? Please do not use the imperative, unless you are approaching
me with money.

> Next we want a driver for the HTTP protocol. It should have function
> to open a connection, to send a request, to receive a response, and to
> close the connection. If this driver is requested to open a connection
> it shall call the TCP driver to open a socket. It will then receive
> all packets from the relevant IP address on the relevant port until it
> closes the socket.
> 
The http protocol is very simple, and consists of a TCP connection and a
header, both for request and response.

> The wget command should be in a separate file. It will call the
> appropriate functions of the HTTP driver to open a connection, post
> the request, receive the response, and finally close the connection.

It is and it does. It also include the http headers, bec‭ause of their
simplicity.

> 
> The work should start with refactoring the existing coding into
> separate drivers for the existing protocols. When that is completed
> you can start adding TCP relevant code.

Will you pay for that work?
 
> Please, do not send single patches but complete patch series.

I do the best I can with my limited knowledge of the tools. I have sent
a series. My understand of both git and patman is limited.

> 
> Best regards
> 
> Heinrich

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3
  2018-01-29 17:30       ` Duncan Hare
@ 2018-01-29 18:06         ` Heinrich Schuchardt
  0 siblings, 0 replies; 4+ messages in thread
From: Heinrich Schuchardt @ 2018-01-29 18:06 UTC (permalink / raw)
  To: u-boot

On 01/29/2018 06:30 PM, Duncan Hare wrote:
>> The patch is trying to put everything into net.c. This is a mess and
>> not where we should head to.
> 
> Not at all. I tried that and it was correctly rejected. The TCP
> functions are in tcp.c, and the wget functions in wget.c
> 
> There is no  socket. There is no socket analogue. There is no
> widespread correct re-ordering of packets, because in a kernel download 
> the relative address of each block is derived for the tcp sequence
> number, and the kernel image in memory itself is in the correct order,
> as defined by tcp sequence number.

You wouldn't implement a TCP protocol that cannot be reused to implement
other higher protocols?

TCP packets are not expected to arrive in sequence. And the length of
packets may vary. You need a buffer for a few packets to put them into
the right sequence again.

> 
>>
>> We should have have one driver per protocol.
>>
>> The IP driver should enumerate all drivers protocols like TCP and UDP
>> that want to listen to it using a Linux list. This way we get rid of
>> all those needless #ifdef CONFIGs. Using the list the IP driver will
>> hand out packets to the respective higher protocol driver.
> 
> The choice was to make minimal changes to the
> current net.c, in consultation with other in the u-boot realm.
> 
>>
>> A separate driver shall implement the TCP protocol and provide methods
>> to open a socket, to read and write to the socket and to close the
>> socket.
>>
> "shall"? Please do not use the imperative, unless you are approaching
> me with money.
> 
>> Next we want a driver for the HTTP protocol. It should have function
>> to open a connection, to send a request, to receive a response, and to
>> close the connection. If this driver is requested to open a connection
>> it shall call the TCP driver to open a socket. It will then receive
>> all packets from the relevant IP address on the relevant port until it
>> closes the socket.
>>
> The http protocol is very simple, and consists of a TCP connection and a
> header, both for request and response.

For first use implementing GET is sufficient. But the structure of the
driver should allow to easily add POST and CONNECT.

> 
>> The wget command should be in a separate file. It will call the
>> appropriate functions of the HTTP driver to open a connection, post
>> the request, receive the response, and finally close the connection.
> 
> It is and it does. It also include the http headers, bec‭ause of their
> simplicity.
> 
>>
>> The work should start with refactoring the existing coding into
>> separate drivers for the existing protocols. When that is completed
>> you can start adding TCP relevant code.
> 
> Will you pay for that work?

The only thing that needs to be factored out of net.c is the IP protocol.

>  
>> Please, do not send single patches but complete patch series.
> 
> I do the best I can with my limited knowledge of the tools. I have sent
> a series. My understand of both git and patman is limited.

This is how I send a patch series:

git format-patch HEAD~5 -ns --cover-letter --subject-prefix='PATCH v5'

Edit the cover letter.
Add in each patch after the first --- the changes relative to the prior
version of the patch. Add another ---.

Put only these files into a directory (let's assume it is named 'patches').

git send-email \
--from="author <author@example.com>" \
--to="maintainer <mantainer at example.com" \
--cc="interested <interested@example.com>" \
--cc=u-boot at lists.denx.de \
patches\*

Best regards

Heinrich

> 
>>
>> Best regards
>>
>> Heinrich
> 
> 
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-29 18:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-29  1:34 [U-Boot] [PATCH] TCP and wget implementation. Ptch V5 1 of 3 Duncan Hare
2018-01-29  2:21 ` Heinrich Schuchardt
     [not found]   ` <1876838587.2851978.1517245243033@mail.yahoo.com>
     [not found]     ` <47879340.2828440.1517245407426@mail.yahoo.com>
2018-01-29 17:30       ` Duncan Hare
2018-01-29 18:06         ` Heinrich Schuchardt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.