All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers
@ 2023-05-10 16:59 Dmitrii Merkurev
  2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
                   ` (5 more replies)
  0 siblings, 6 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

This allows us to reuse TCP logic between IP and IP6 stack.

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 include/net/tcp.h | 54 ++++++++++++++++--------------------
 net/tcp.c         | 70 +++++++++++++++++++++++------------------------
 test/cmd/wget.c   | 48 ++++++++++++++++++--------------
 3 files changed, 85 insertions(+), 87 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index c29d4ce24a..93ed728dfe 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -5,20 +5,16 @@
  * Copyright 2017 Duncan Hare, All rights reserved.
  */
 
+#ifndef __TCP_H__
+#define __TCP_H__
+
 #define TCP_ACTIVITY 127		/* Number of packets received   */
 					/* before console progress mark */
+
+#define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
+
 /**
- * struct ip_tcp_hdr - IP and TCP header
- * @ip_hl_v: header length and version
- * @ip_tos: type of service
- * @ip_len: total length
- * @ip_id: identification
- * @ip_off: fragment offset field
- * @ip_ttl: time to live
- * @ip_p: protocol
- * @ip_sum: checksum
- * @ip_src: Source IP address
- * @ip_dst: Destination IP address
+ * struct tcp_hdr - TCP header
  * @tcp_src: TCP source port
  * @tcp_dst: TCP destination port
  * @tcp_seq: TCP sequence number
@@ -28,18 +24,8 @@
  * @tcp_win: TCP windows size
  * @tcp_xsum: Checksum
  * @tcp_ugr: Pointer to urgent data
- */
-struct ip_tcp_hdr {
-	u8		ip_hl_v;
-	u8		ip_tos;
-	u16		ip_len;
-	u16		ip_id;
-	u16		ip_off;
-	u8		ip_ttl;
-	u8		ip_p;
-	u16		ip_sum;
-	struct in_addr	ip_src;
-	struct in_addr	ip_dst;
+*/
+struct tcp_hdr {
 	u16		tcp_src;
 	u16		tcp_dst;
 	u32		tcp_seq;
@@ -51,8 +37,8 @@ struct ip_tcp_hdr {
 	u16		tcp_ugr;
 } __packed;
 
-#define IP_TCP_HDR_SIZE		(sizeof(struct ip_tcp_hdr))
-#define TCP_HDR_SIZE		(IP_TCP_HDR_SIZE  - IP_HDR_SIZE)
+#define TCP_HDR_SIZE		(sizeof(struct tcp_hdr))
+#define IP_TCP_HDR_SIZE         (IP_HDR_SIZE + TCP_HDR_SIZE)
 
 #define TCP_DATA	0x00	/* Data Packet - internal use only	*/
 #define TCP_FIN		0x01	/* Finish flag				*/
@@ -178,7 +164,8 @@ struct tcp_t_opt {
 
 /**
  * struct ip_tcp_hdr_o - IP + TCP header + TCP options
- * @hdr: IP + TCP header
+ * @ip_hdr: IP + TCP header
+ * @tcp_hdr: TCP header
  * @mss: TCP MSS Option
  * @scale: TCP Windows Scale Option
  * @sack_p: TCP Sack-Permitted Option
@@ -186,7 +173,8 @@ struct tcp_t_opt {
  * @end: end of options
  */
 struct ip_tcp_hdr_o {
-	struct	ip_tcp_hdr hdr;
+	struct	ip_hdr     ip_hdr;
+	struct	tcp_hdr    tcp_hdr;
 	struct	tcp_mss	   mss;
 	struct	tcp_scale  scale;
 	struct	tcp_sack_p sack_p;
@@ -198,15 +186,17 @@ struct ip_tcp_hdr_o {
 
 /**
  * struct ip_tcp_hdr_s - IP + TCP header + TCP options
- * @hdr: IP + TCP header
+ * @ip_hdr: IP + TCP header
+ * @tcp_hdr: TCP header
  * @t_opt: TCP Timestamp Option
  * @sack_v: TCP SACK Option
  * @end: end of options
  */
 struct ip_tcp_hdr_s {
-	struct	ip_tcp_hdr	hdr;
-	struct	tcp_t_opt	t_opt;
-	struct	tcp_sack_v	sack_v;
+	struct	ip_hdr     ip_hdr;
+	struct	tcp_hdr    tcp_hdr;
+	struct	tcp_t_opt  t_opt;
+	struct	tcp_sack_v sack_v;
 	u8	end;
 } __packed;
 
@@ -303,3 +293,5 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int len);
 
 u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
 			  int tcp_len, int pkt_len);
+
+#endif // __TCP_H__
diff --git a/net/tcp.c b/net/tcp.c
index a713e1dd60..10ce799814 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -155,7 +155,7 @@ u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
  */
 int net_set_ack_options(union tcp_build_pkt *b)
 {
-	b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
+	b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
 
 	b->sack.t_opt.kind = TCP_O_TS;
 	b->sack.t_opt.len = TCP_OPT_LEN_A;
@@ -187,12 +187,12 @@ int net_set_ack_options(union tcp_build_pkt *b)
 			b->sack.sack_v.hill[3].r = TCP_O_NOP;
 		}
 
-		b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
+		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
 										 TCP_TSOPT_SIZE +
 										 tcp_lost.len));
 	} else {
 		b->sack.sack_v.kind = 0;
-		b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
+		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
 										 TCP_TSOPT_SIZE));
 	}
 
@@ -201,7 +201,7 @@ int net_set_ack_options(union tcp_build_pkt *b)
 	 * TCP header to add to the total packet length
 	 */
 
-	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.hdr.tcp_hlen);
+	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.tcp_hdr.tcp_hlen);
 }
 
 /**
@@ -213,7 +213,7 @@ void net_set_syn_options(union tcp_build_pkt *b)
 	if (IS_ENABLED(CONFIG_PROT_TCP_SACK))
 		tcp_lost.len = 0;
 
-	b->ip.hdr.tcp_hlen = 0xa0;
+	b->ip.tcp_hdr.tcp_hlen = 0xa0;
 
 	b->ip.mss.kind = TCP_O_MSS;
 	b->ip.mss.len = TCP_OPT_LEN_4;
@@ -249,9 +249,9 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 	 * Header: 5 32 bit words. 4 bits TCP header Length,
 	 *         4 bits reserved options
 	 */
-	b->ip.hdr.tcp_flags = action;
+	b->ip.tcp_hdr.tcp_flags = action;
 	pkt_hdr_len = IP_TCP_HDR_SIZE;
-	b->ip.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
+	b->ip.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
 
 	switch (action) {
 	case TCP_SYN:
@@ -274,7 +274,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 	case TCP_SYN | TCP_ACK:
 	case TCP_ACK:
 		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
-		b->ip.hdr.tcp_flags = action;
+		b->ip.tcp_hdr.tcp_flags = action;
 		debug_cond(DEBUG_DEV_PKT,
 			   "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
 			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num,
@@ -308,7 +308,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 		fallthrough;
 	default:
 		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
-		b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
+		b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
 		debug_cond(DEBUG_DEV_PKT,
 			   "TCP Hdr:dft  (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
 			   &net_server_ip, &net_ip,
@@ -320,10 +320,10 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 
 	tcp_ack_edge = tcp_ack_num;
 	/* TCP Header */
-	b->ip.hdr.tcp_ack = htonl(tcp_ack_edge);
-	b->ip.hdr.tcp_src = htons(sport);
-	b->ip.hdr.tcp_dst = htons(dport);
-	b->ip.hdr.tcp_seq = htonl(tcp_seq_num);
+	b->ip.tcp_hdr.tcp_ack = htonl(tcp_ack_edge);
+	b->ip.tcp_hdr.tcp_src = htons(sport);
+	b->ip.tcp_hdr.tcp_dst = htons(dport);
+	b->ip.tcp_hdr.tcp_seq = htonl(tcp_seq_num);
 
 	/*
 	 * TCP window size - TCP header variable tcp_win.
@@ -340,13 +340,13 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 	 * it is, then the u-boot tftp or nfs kernel netboot should be
 	 * considered.
 	 */
-	b->ip.hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
+	b->ip.tcp_hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
 
-	b->ip.hdr.tcp_xsum = 0;
-	b->ip.hdr.tcp_ugr = 0;
+	b->ip.tcp_hdr.tcp_xsum = 0;
+	b->ip.tcp_hdr.tcp_ugr = 0;
 
-	b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
-						   tcp_len, pkt_len);
+	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
+						       tcp_len, pkt_len);
 
 	net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip,
 			  pkt_len, IPPROTO_TCP);
@@ -638,7 +638,7 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
 void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 {
 	int tcp_len = pkt_len - IP_HDR_SIZE;
-	u16 tcp_rx_xsum = b->ip.hdr.ip_sum;
+	u16 tcp_rx_xsum = b->ip.ip_hdr.ip_sum;
 	u8  tcp_action = TCP_DATA;
 	u32 tcp_seq_num, tcp_ack_num;
 	int tcp_hdr_len, payload_len;
@@ -646,11 +646,11 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 	/* Verify IP header */
 	debug_cond(DEBUG_DEV_PKT,
 		   "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n",
-		   &b->ip.hdr.ip_src, &b->ip.hdr.ip_dst, pkt_len);
+		   &b->ip.ip_hdr.ip_src, &b->ip.ip_hdr.ip_dst, pkt_len);
 
-	b->ip.hdr.ip_src = net_server_ip;
-	b->ip.hdr.ip_dst = net_ip;
-	b->ip.hdr.ip_sum = 0;
+	b->ip.ip_hdr.ip_src = net_server_ip;
+	b->ip.ip_hdr.ip_dst = net_ip;
+	b->ip.ip_hdr.ip_sum = 0;
 	if (tcp_rx_xsum != compute_ip_checksum(b, IP_HDR_SIZE)) {
 		debug_cond(DEBUG_DEV_PKT,
 			   "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n",
@@ -659,10 +659,10 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 	}
 
 	/* Build pseudo header and verify TCP header */
-	tcp_rx_xsum = b->ip.hdr.tcp_xsum;
-	b->ip.hdr.tcp_xsum = 0;
-	if (tcp_rx_xsum != tcp_set_pseudo_header((uchar *)b, b->ip.hdr.ip_src,
-						 b->ip.hdr.ip_dst, tcp_len,
+	tcp_rx_xsum = b->ip.tcp_hdr.tcp_xsum;
+	b->ip.tcp_hdr.tcp_xsum = 0;
+	if (tcp_rx_xsum != tcp_set_pseudo_header((uchar *)b, b->ip.ip_hdr.ip_src,
+						 b->ip.ip_hdr.ip_dst, tcp_len,
 						 pkt_len)) {
 		debug_cond(DEBUG_DEV_PKT,
 			   "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n",
@@ -670,7 +670,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 		return;
 	}
 
-	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen);
+	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.tcp_hdr.tcp_hlen);
 	payload_len = tcp_len - tcp_hdr_len;
 
 	if (tcp_hdr_len > TCP_HDR_SIZE)
@@ -680,11 +680,11 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 	 * Incoming sequence and ack numbers are server's view of the numbers.
 	 * The app must swap the numbers when responding.
 	 */
-	tcp_seq_num = ntohl(b->ip.hdr.tcp_seq);
-	tcp_ack_num = ntohl(b->ip.hdr.tcp_ack);
+	tcp_seq_num = ntohl(b->ip.tcp_hdr.tcp_seq);
+	tcp_ack_num = ntohl(b->ip.tcp_hdr.tcp_ack);
 
 	/* Packets are not ordered. Send to app as received. */
-	tcp_action = tcp_state_machine(b->ip.hdr.tcp_flags,
+	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
 				       tcp_seq_num, payload_len);
 
 	tcp_activity_count++;
@@ -698,8 +698,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 			   "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
 			   tcp_action, tcp_seq_num, tcp_ack_num, payload_len);
 
-		(*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.hdr.tcp_dst,
-				       b->ip.hdr.ip_src, b->ip.hdr.tcp_src, tcp_seq_num,
+		(*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.tcp_hdr.tcp_dst,
+				       b->ip.ip_hdr.ip_src, b->ip.tcp_hdr.tcp_src, tcp_seq_num,
 				       tcp_ack_num, tcp_action, payload_len);
 
 	} else if (tcp_action != TCP_DATA) {
@@ -711,8 +711,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 		 * Warning: Incoming Ack & Seq sequence numbers are transposed
 		 * here to outgoing Seq & Ack sequence numbers
 		 */
-		net_send_tcp_packet(0, ntohs(b->ip.hdr.tcp_src),
-				    ntohs(b->ip.hdr.tcp_dst),
+		net_send_tcp_packet(0, ntohs(b->ip.tcp_hdr.tcp_src),
+				    ntohs(b->ip.tcp_hdr.tcp_dst),
 				    (tcp_action & (~TCP_PUSH)),
 				    tcp_ack_num, tcp_ack_edge);
 	}
diff --git a/test/cmd/wget.c b/test/cmd/wget.c
index ed83fc94a5..e2c11d3e76 100644
--- a/test/cmd/wget.c
+++ b/test/cmd/wget.c
@@ -52,9 +52,11 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
 	struct ethernet_hdr *eth = packet;
-	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
+	struct ip_hdr *ip = packet + ETHER_HDR_SIZE;
+	struct tcp_hdr *tcp = (void *)ip + IP_HDR_SIZE;
 	struct ethernet_hdr *eth_send;
-	struct ip_tcp_hdr *tcp_send;
+	struct ip_hdr *ip_send;
+	struct tcp_hdr *tcp_send;
 
 	/* Don't allow the buffer to overrun */
 	if (priv->recv_packets >= PKTBUFSRX)
@@ -64,7 +66,8 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
 	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
 	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
 	eth_send->et_protlen = htons(PROT_IP);
-	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
+	ip_send = (void *)eth_send + ETHER_HDR_SIZE;
+	tcp_send = (void *)ip_send + IP_HDR_SIZE;
 	tcp_send->tcp_src = tcp->tcp_dst;
 	tcp_send->tcp_dst = tcp->tcp_src;
 	tcp_send->tcp_seq = htonl(0);
@@ -74,14 +77,14 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
 	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
 	tcp_send->tcp_xsum = 0;
 	tcp_send->tcp_ugr = 0;
-	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
-						   tcp->ip_src,
-						   tcp->ip_dst,
+	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)ip_send,
+						   ip->ip_src,
+						   ip->ip_dst,
 						   TCP_HDR_SIZE,
 						   IP_TCP_HDR_SIZE);
-	net_set_ip_header((uchar *)tcp_send,
-			  tcp->ip_src,
-			  tcp->ip_dst,
+	net_set_ip_header((uchar *)ip_send,
+			  ip->ip_src,
+			  ip->ip_dst,
 			  IP_TCP_HDR_SIZE,
 			  IPPROTO_TCP);
 
@@ -97,9 +100,11 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
 {
 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
 	struct ethernet_hdr *eth = packet;
-	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
+	struct ip_hdr *ip = packet + ETHER_HDR_SIZE;
+	struct tcp_hdr *tcp = (void *)ip + IP_HDR_SIZE;
 	struct ethernet_hdr *eth_send;
-	struct ip_tcp_hdr *tcp_send;
+	struct ip_hdr *ip_send;
+	struct tcp_hdr *tcp_send;
 	void *data;
 	int pkt_len;
 	int payload_len = 0;
@@ -115,10 +120,11 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
 	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
 	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
 	eth_send->et_protlen = htons(PROT_IP);
-	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
+	ip_send = (void *)eth_send + ETHER_HDR_SIZE;
+	tcp_send = (void *)ip_send + IP_HDR_SIZE;
+	data = (void *)tcp_send + TCP_HDR_SIZE;
 	tcp_send->tcp_src = tcp->tcp_dst;
 	tcp_send->tcp_dst = tcp->tcp_src;
-	data = (void *)tcp_send + IP_TCP_HDR_SIZE;
 
 	if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1) {
 		tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
@@ -138,14 +144,14 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
 	tcp_send->tcp_xsum = 0;
 	tcp_send->tcp_ugr = 0;
 	pkt_len = IP_TCP_HDR_SIZE + payload_len;
-	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
-						   tcp->ip_src,
-						   tcp->ip_dst,
+	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)ip_send,
+						   ip->ip_src,
+						   ip->ip_dst,
 						   pkt_len - IP_HDR_SIZE,
 						   pkt_len);
-	net_set_ip_header((uchar *)tcp_send,
-			  tcp->ip_src,
-			  tcp->ip_dst,
+	net_set_ip_header((uchar *)ip_send,
+			  ip->ip_src,
+			  ip->ip_dst,
 			  pkt_len,
 			  IPPROTO_TCP);
 
@@ -163,14 +169,14 @@ static int sb_http_handler(struct udevice *dev, void *packet,
 {
 	struct ethernet_hdr *eth = packet;
 	struct ip_hdr *ip;
-	struct ip_tcp_hdr *tcp;
+	struct tcp_hdr *tcp;
 
 	if (ntohs(eth->et_protlen) == PROT_ARP) {
 		return sb_arp_handler(dev, packet, len);
 	} else if (ntohs(eth->et_protlen) == PROT_IP) {
 		ip = packet + ETHER_HDR_SIZE;
 		if (ip->ip_p == IPPROTO_TCP) {
-			tcp = packet + ETHER_HDR_SIZE;
+			tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE;
 			if (tcp->tcp_flags == TCP_SYN)
 				return sb_syn_handler(dev, packet, len);
 			else if (tcp->tcp_flags & TCP_ACK && !(tcp->tcp_flags & TCP_SYN))
-- 
2.40.1.606.ga4b1b128d6-goog


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

* [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
@ 2023-05-10 16:59 ` Dmitrii Merkurev
  2023-05-24 21:38   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  2023-05-10 16:59 ` [PATCH v2 3/6] net: introduce TCP/IP6 support Dmitrii Merkurev
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

Changes:
1. Separate reusable part from net_set_tcp_header to
net_set_tcp_header_common
2. Make TCP signatures reusable by receiving particular
IP agnostic TCP headers
3. Extract net_send_ip_packet6 from net_send_udp_packet6
to reuse the code
4. Expose TCP state machine related functions

This allows us to reuse TCP logic between IP and IP6 stack.

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 include/net/tcp.h | 109 +++++++++++++--
 net/net.c         |  18 ++-
 net/net6.c        |  78 ++++++++---
 net/tcp.c         | 337 ++++++++++++++++++++++++++++------------------
 4 files changed, 372 insertions(+), 170 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 93ed728dfe..344b4be2a4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -8,10 +8,20 @@
 #ifndef __TCP_H__
 #define __TCP_H__
 
+#include <net.h>
+
 #define TCP_ACTIVITY 127		/* Number of packets received   */
 					/* before console progress mark */
 
+/*
+ * TCP lengths are stored as a rounded up number of 32 bit words.
+ * Add 3 to length round up, rounded, then divided into the
+ * length in 32 bit words.
+ */
+#define LEN_B_TO_DW(x) ((x) >> 2)
+#define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
 #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
+#define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
 
 /**
  * struct tcp_hdr - TCP header
@@ -24,7 +34,7 @@
  * @tcp_win: TCP windows size
  * @tcp_xsum: Checksum
  * @tcp_ugr: Pointer to urgent data
-*/
+ */
 struct tcp_hdr {
 	u16		tcp_src;
 	u16		tcp_dst;
@@ -163,18 +173,14 @@ struct tcp_t_opt {
  */
 
 /**
- * struct ip_tcp_hdr_o - IP + TCP header + TCP options
- * @ip_hdr: IP + TCP header
- * @tcp_hdr: TCP header
+ * struct tcp_hdr_o - TCP options
  * @mss: TCP MSS Option
  * @scale: TCP Windows Scale Option
  * @sack_p: TCP Sack-Permitted Option
  * @t_opt: TCP Timestamp Option
  * @end: end of options
  */
-struct ip_tcp_hdr_o {
-	struct	ip_hdr     ip_hdr;
-	struct	tcp_hdr    tcp_hdr;
+struct tcp_hdr_o {
 	struct	tcp_mss	   mss;
 	struct	tcp_scale  scale;
 	struct	tcp_sack_p sack_p;
@@ -182,6 +188,22 @@ struct ip_tcp_hdr_o {
 	u8	end;
 } __packed;
 
+#define TCP_O_SIZE (sizeof(struct tcp_hdr_o))
+
+/**
+ * struct ip_tcp_hdr_o - IP + TCP header + TCP options
+ * @ip_hdr: IP + TCP header
+ * @tcp_hdr: TCP header
+ * @tcp_o: TCP options
+ * @end: end of IP/TCP header
+ */
+struct ip_tcp_hdr_o {
+	struct  ip_hdr     ip_hdr;
+	struct	tcp_hdr    tcp_hdr;
+	struct  tcp_hdr_o  tcp_o;
+	u8	end;
+} __packed;
+
 #define IP_TCP_O_SIZE (sizeof(struct ip_tcp_hdr_o))
 
 /**
@@ -209,7 +231,7 @@ struct ip_tcp_hdr_s {
 
 /**
  * struct pseudo_hdr - Pseudo Header
- * @padding: pseudo hdr size = ip_tcp hdr size
+ * @padding: pseudo hdr size = ip hdr size
  * @p_src: Source IP address
  * @p_dst: Destination IP address
  * @rsvd: reserved
@@ -236,7 +258,6 @@ struct pseudo_hdr {
  *
  * Build Pseudo header in packed buffer
  * first, calculate TCP checksum, then build IP header in packed buffer.
- *
  */
 union tcp_build_pkt {
 	struct pseudo_hdr ph;
@@ -269,9 +290,77 @@ enum tcp_state {
 
 enum tcp_state tcp_get_tcp_state(void);
 void tcp_set_tcp_state(enum tcp_state new_state);
-int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
+
+/**
+ * net_set_tcp_header_common() - IP version agnostic TCP header building implementation
+ *
+ * @tcp_hdr: pointer to TCP header struct
+ * @tcp_o: pointer to TCP options header struct
+ * @sack_t_opt: pointer to TCP sack options header struct
+ * @sack_v: pointer to TCP sack header struct
+ * @dport: destination TCP port
+ * @sport: source TCP port
+ * @payload_len: TCP payload len
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP header
+ */
+int net_set_tcp_header_common(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *tcp_o,
+			      struct tcp_t_opt *sack_t_opt, struct tcp_sack_v *sack_v,
+			      u16 dport, u16 sport, int payload_len, u8 action,
+			      u32 tcp_seq_num, u32 tcp_ack_num);
+
+/**
+ * net_set_tcp_header() - IPv4 TCP header bulding implementation
+ *
+ * @pkt: pointer to the IP header
+ * @dport: destination TCP port
+ * @sport: source TCP port
+ * @payload_len: TCP payload len
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP header
+ */
+int net_set_tcp_header(uchar *pkt, u16 dport, u16 sport, int payload_len,
 		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
 
+/**
+ * tcp_parse_options() - parsing TCP options
+ *
+ * @o: pointer to the option field.
+ * @o_len: length of the option field.
+ */
+void tcp_parse_options(uchar *o, int o_len);
+
+/**
+ * tcp_state_machine() - update TCP state in a reaction to incoming packet
+ *
+ * @tcp_flags: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_seq_num_out: TCP sequential number we expect to answer with
+ * @tcp_ack_num_out: TCP acknowledgment number we expect to answer with
+ * @payload_len: TCP payload len
+ *
+ * returns TCP action we expect to answer with
+ */
+u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, u32 *tcp_seq_num_out,
+		     u32 *tcp_ack_num_out, int payload_len);
+
+/**
+ * tcp_sent_state_machine() - update TCP state in a reaction to outcoming packet
+ *
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP action we expect to answer with
+ */
+u8 tcp_sent_state_machine(u8 action, u32 *tcp_seq_num, u32 *tcp_ack_num);
+
 /**
  * rxhand_tcp() - An incoming packet handler.
  * @pkt: pointer to the application packet
diff --git a/net/net.c b/net/net.c
index 43abbac7c3..0b68bf7b13 100644
--- a/net/net.c
+++ b/net/net.c
@@ -916,6 +916,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
 {
 	uchar *pkt;
 	int eth_hdr_size;
+	int ip_tcp_hdr_size;
 	int pkt_hdr_size;
 
 	/* make sure the net_tx_packet is initialized (net_init() was called) */
@@ -934,19 +935,24 @@ int net_send_ip_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_hdr_size = eth_hdr_size;
+	pkt += eth_hdr_size;
 
 	switch (proto) {
 	case IPPROTO_UDP:
-		net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport,
+		net_set_udp_header(pkt, dest, dport, sport,
 				   payload_len);
-		pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
+		pkt_hdr_size += IP_UDP_HDR_SIZE;
 		break;
 #if defined(CONFIG_PROT_TCP)
 	case IPPROTO_TCP:
-		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);
+		ip_tcp_hdr_size = IP_HDR_SIZE;
+		ip_tcp_hdr_size += net_set_tcp_header(pkt, dport, sport,
+						      payload_len, action, tcp_seq_num,
+						      tcp_ack_num);
+		net_set_ip_header(pkt, net_server_ip, net_ip,
+				  ip_tcp_hdr_size + payload_len, IPPROTO_TCP);
+		pkt_hdr_size += ip_tcp_hdr_size;
 		break;
 #endif
 	default:
diff --git a/net/net6.c b/net/net6.c
index 2dd64c0e16..e395b930b0 100644
--- a/net/net6.c
+++ b/net/net6.c
@@ -324,15 +324,13 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
 	return sizeof(struct ip6_hdr);
 }
 
-int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
-			 int sport, int len)
+int udp6_add_hdr(uchar *xip, struct in6_addr *dest, int dport, int sport,
+		 int len)
 {
-	uchar *pkt;
 	struct udp_hdr *udp;
 	u16 csum_p;
 
-	udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() +
-			IP6_HDR_SIZE);
+	udp = (struct udp_hdr *)xip;
 
 	udp->udp_dst = htons(dport);
 	udp->udp_src = htons(sport);
@@ -344,39 +342,75 @@ int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
 	udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + UDP_HDR_SIZE,
 					IPPROTO_UDP, csum_p);
 
+	return sizeof(struct udp_hdr);
+}
+
+int net_send_ip_packet6(uchar *ether, struct in6_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 ip_hdr_size;
+	int udp_hdr_size;
+	int tcp_hdr_size;
+	int pkt_hdr_size;
+
+	if (!net_tx_packet)
+		return -1;
+
+	pkt = (uchar *)net_tx_packet;
+
+	eth_hdr_size = net_set_ether(pkt, ether, PROT_IP6);
+	pkt_hdr_size += eth_hdr_size;
+	pkt = eth_hdr_size;
+
+	switch (proto) {
+#if defined(CONFIG_PROT_UDP)
+	case IPPROTO_UDP:
+		ip_hdr_size = ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
+					  payload_len + UDP_HDR_SIZE);
+		pkt_hdr_size += ip_hdr_size;
+		pkt += ip_hdr_size;
+
+		udp_hdr_size = udp6_add_hdr(pkt, dest, dport, sport, payload_len);
+		pkt_hdr_size += udp_hdr_size;
+		pkt += udp_hdr_size;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
 	/* if MAC address was not discovered yet, save the packet and do
 	 * neighbour discovery
 	 */
-	if (!memcmp(ether, net_null_ethaddr, 6)) {
+	if (memcmp(ether, net_null_ethaddr, 6) == 0) {
+		memcpy((uchar *)net_nd_tx_packet,
+		       (uchar *)net_tx_packet, pkt_hdr_size + payload_len);
+		memset((uchar *)net_tx_packet, 0, pkt_hdr_size + payload_len);
+
 		net_copy_ip6(&net_nd_sol_packet_ip6, dest);
 		net_nd_packet_mac = ether;
-
-		pkt = net_nd_tx_packet;
-		pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6);
-		pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
-				len + UDP_HDR_SIZE);
-		memcpy(pkt, (uchar *)udp, len + UDP_HDR_SIZE);
-
 		/* size of the waiting packet */
-		net_nd_tx_packet_size = (pkt - net_nd_tx_packet) +
-			UDP_HDR_SIZE + len;
-
-		/* and do the neighbor solicitation */
+		net_nd_tx_packet_size = pkt_hdr_size + payload_len;
 		net_nd_try = 1;
 		net_nd_timer_start = get_timer(0);
 		ndisc_request();
 		return 1;	/* waiting */
 	}
 
-	pkt = (uchar *)net_tx_packet;
-	pkt += net_set_ether(pkt, ether, PROT_IP6);
-	pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
-			len + UDP_HDR_SIZE);
-	(void)eth_send(net_tx_packet, pkt - net_tx_packet + UDP_HDR_SIZE + len);
+	(void)eth_send(net_tx_packet, pkt_hdr_size + payload_len);
 
 	return 0;	/* transmitted */
 }
 
+int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
+			 int sport, int len)
+{
+	return net_send_ip_packet6(ether, dest, dport, sport, len, IPPROTO_UDP, 0, 0, 0);
+}
+
 int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
 {
 	struct in_addr zero_ip = {.s_addr = 0 };
diff --git a/net/tcp.c b/net/tcp.c
index 10ce799814..483c03a595 100644
--- a/net/tcp.c
+++ b/net/tcp.c
@@ -54,16 +54,6 @@ static struct sack_r edge_a[TCP_SACK];
 static unsigned int sack_idx;
 static unsigned int prev_len;
 
-/*
- * TCP lengths are stored as a rounded up number of 32 bit words.
- * Add 3 to length round up, rounded, then divided into the
- * length in 32 bit words.
- */
-#define LEN_B_TO_DW(x) ((x) >> 2)
-#define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
-#define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
-#define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
-
 /* TCP connection state */
 static enum tcp_state current_tcp_state;
 
@@ -149,29 +139,32 @@ u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
 
 /**
  * net_set_ack_options() - set TCP options in acknowledge packets
- * @b: the packet
+ * @tcp_hdr: pointer to TCP header struct
+ * @t_opt: pointer to TCP t opt header struct
+ * @sack_v: pointer to TCP sack header struct
  *
  * Return: TCP header length
  */
-int net_set_ack_options(union tcp_build_pkt *b)
+int net_set_ack_options(struct tcp_hdr *tcp_hdr, struct tcp_t_opt *t_opt,
+			struct tcp_sack_v *sack_v)
 {
-	b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
+	tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
 
-	b->sack.t_opt.kind = TCP_O_TS;
-	b->sack.t_opt.len = TCP_OPT_LEN_A;
-	b->sack.t_opt.t_snd = htons(loc_timestamp);
-	b->sack.t_opt.t_rcv = rmt_timestamp;
-	b->sack.sack_v.kind = TCP_1_NOP;
-	b->sack.sack_v.len = 0;
+	t_opt->kind = TCP_O_TS;
+	t_opt->len = TCP_OPT_LEN_A;
+	t_opt->t_snd = htons(loc_timestamp);
+	t_opt->t_rcv = rmt_timestamp;
+	sack_v->kind = TCP_1_NOP;
+	sack_v->len = 0;
 
 	if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
 		if (tcp_lost.len > TCP_OPT_LEN_2) {
 			debug_cond(DEBUG_DEV_PKT, "TCP ack opt lost.len %x\n",
 				   tcp_lost.len);
-			b->sack.sack_v.len = tcp_lost.len;
-			b->sack.sack_v.kind = TCP_V_SACK;
-			b->sack.sack_v.hill[0].l = htonl(tcp_lost.hill[0].l);
-			b->sack.sack_v.hill[0].r = htonl(tcp_lost.hill[0].r);
+			sack_v->len = tcp_lost.len;
+			sack_v->kind = TCP_V_SACK;
+			sack_v->hill[0].l = htonl(tcp_lost.hill[0].l);
+			sack_v->hill[0].r = htonl(tcp_lost.hill[0].r);
 
 			/*
 			 * These SACK structures are initialized with NOPs to
@@ -179,21 +172,21 @@ int net_set_ack_options(union tcp_build_pkt *b)
 			 * SACK structures used for both header padding and
 			 * internally.
 			 */
-			b->sack.sack_v.hill[1].l = htonl(tcp_lost.hill[1].l);
-			b->sack.sack_v.hill[1].r = htonl(tcp_lost.hill[1].r);
-			b->sack.sack_v.hill[2].l = htonl(tcp_lost.hill[2].l);
-			b->sack.sack_v.hill[2].r = htonl(tcp_lost.hill[2].r);
-			b->sack.sack_v.hill[3].l = TCP_O_NOP;
-			b->sack.sack_v.hill[3].r = TCP_O_NOP;
+			sack_v->hill[1].l = htonl(tcp_lost.hill[1].l);
+			sack_v->hill[1].r = htonl(tcp_lost.hill[1].r);
+			sack_v->hill[2].l = htonl(tcp_lost.hill[2].l);
+			sack_v->hill[2].r = htonl(tcp_lost.hill[2].r);
+			sack_v->hill[3].l = TCP_O_NOP;
+			sack_v->hill[3].r = TCP_O_NOP;
 		}
 
-		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
-										 TCP_TSOPT_SIZE +
-										 tcp_lost.len));
+		tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
+									      TCP_TSOPT_SIZE +
+									      tcp_lost.len));
 	} else {
-		b->sack.sack_v.kind = 0;
-		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
-										 TCP_TSOPT_SIZE));
+		sack_v->kind = 0;
+		tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
+									      TCP_TSOPT_SIZE));
 	}
 
 	/*
@@ -201,69 +194,61 @@ int net_set_ack_options(union tcp_build_pkt *b)
 	 * TCP header to add to the total packet length
 	 */
 
-	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.tcp_hdr.tcp_hlen);
+	return GET_TCP_HDR_LEN_IN_BYTES(tcp_hdr->tcp_hlen);
 }
 
 /**
  * net_set_ack_options() - set TCP options in SYN packets
- * @b: the packet
+ * @tcp_hdr: pointer to TCP header struct
+ * @options: pointer to TCP header options struct
  */
-void net_set_syn_options(union tcp_build_pkt *b)
+void net_set_syn_options(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *options)
 {
 	if (IS_ENABLED(CONFIG_PROT_TCP_SACK))
 		tcp_lost.len = 0;
 
-	b->ip.tcp_hdr.tcp_hlen = 0xa0;
+	tcp_hdr->tcp_hlen = 0xa0;
 
-	b->ip.mss.kind = TCP_O_MSS;
-	b->ip.mss.len = TCP_OPT_LEN_4;
-	b->ip.mss.mss = htons(TCP_MSS);
-	b->ip.scale.kind = TCP_O_SCL;
-	b->ip.scale.scale = TCP_SCALE;
-	b->ip.scale.len = TCP_OPT_LEN_3;
+	options->mss.kind = TCP_O_MSS;
+	options->mss.len = TCP_OPT_LEN_4;
+	options->mss.mss = htons(TCP_MSS);
+	options->scale.kind = TCP_O_SCL;
+	options->scale.scale = TCP_SCALE;
+	options->scale.len = TCP_OPT_LEN_3;
 	if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
-		b->ip.sack_p.kind = TCP_P_SACK;
-		b->ip.sack_p.len = TCP_OPT_LEN_2;
+		options->sack_p.kind = TCP_P_SACK;
+		options->sack_p.len = TCP_OPT_LEN_2;
 	} else {
-		b->ip.sack_p.kind = TCP_1_NOP;
-		b->ip.sack_p.len = TCP_1_NOP;
+		options->sack_p.kind = TCP_1_NOP;
+		options->sack_p.len = TCP_1_NOP;
 	}
-	b->ip.t_opt.kind = TCP_O_TS;
-	b->ip.t_opt.len = TCP_OPT_LEN_A;
+	options->t_opt.kind = TCP_O_TS;
+	options->t_opt.len = TCP_OPT_LEN_A;
 	loc_timestamp = get_ticks();
 	rmt_timestamp = 0;
-	b->ip.t_opt.t_snd = 0;
-	b->ip.t_opt.t_rcv = 0;
-	b->ip.end = TCP_O_END;
+
+	options->t_opt.t_snd = 0;
+	options->t_opt.t_rcv = 0;
 }
 
-int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
-		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
+/**
+ * tcp_sent_state_machine() - update TCP state in a reaction to outcoming packet
+ *
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP action we expect to answer with
+ */
+u8 tcp_sent_state_machine(u8 action, u32 *tcp_seq_num, u32 *tcp_ack_num)
 {
-	union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
-	int pkt_hdr_len;
-	int pkt_len;
-	int tcp_len;
-
-	/*
-	 * Header: 5 32 bit words. 4 bits TCP header Length,
-	 *         4 bits reserved options
-	 */
-	b->ip.tcp_hdr.tcp_flags = action;
-	pkt_hdr_len = IP_TCP_HDR_SIZE;
-	b->ip.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
-
 	switch (action) {
 	case TCP_SYN:
 		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n",
-			   &net_server_ip, &net_ip,
-			   tcp_seq_num, tcp_ack_num);
+			   "TCP Hdr:SYN (sq=%u, ak=%u)\n", *tcp_seq_num, *tcp_ack_num);
 		tcp_activity_count = 0;
-		net_set_syn_options(b);
-		tcp_seq_num = 0;
-		tcp_ack_num = 0;
-		pkt_hdr_len = IP_TCP_O_SIZE;
+		*tcp_seq_num = 0;
+		*tcp_ack_num = 0;
 		if (current_tcp_state == TCP_SYN_SENT) {  /* Too many SYNs */
 			action = TCP_FIN;
 			current_tcp_state = TCP_FIN_WAIT_1;
@@ -273,57 +258,93 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 		break;
 	case TCP_SYN | TCP_ACK:
 	case TCP_ACK:
-		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
-		b->ip.tcp_hdr.tcp_flags = action;
 		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
-			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num,
-			   action);
+			   "TCP Hdr:ACK (s=%u, a=%u, A=%x)\n",
+			   *tcp_seq_num, *tcp_ack_num, action);
 		break;
 	case TCP_FIN:
 		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:FIN  (%pI4, %pI4, s=%u, a=%u)\n",
-			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num);
-		payload_len = 0;
-		pkt_hdr_len = IP_TCP_HDR_SIZE;
+			   "TCP Hdr:FIN  (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
 		current_tcp_state = TCP_FIN_WAIT_1;
 		break;
 	case TCP_RST | TCP_ACK:
 	case TCP_RST:
 		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:RST  (%pI4, %pI4, s=%u, a=%u)\n",
-			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num);
+			   "TCP Hdr:RST  (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
 		current_tcp_state = TCP_CLOSED;
 		break;
 	/* Notify connection closing */
 	case (TCP_FIN | TCP_ACK):
 	case (TCP_FIN | TCP_ACK | TCP_PUSH):
+		debug_cond(DEBUG_DEV_PKT,
+			   "TCP Hdr:FIN ACK PSH(s=%u, a=%u, A=%x)\n",
+			   *tcp_seq_num, *tcp_ack_num, action);
 		if (current_tcp_state == TCP_CLOSE_WAIT)
 			current_tcp_state = TCP_CLOSING;
-
-		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n",
-			   &net_server_ip, &net_ip,
-			   tcp_seq_num, tcp_ack_num, action);
 		fallthrough;
 	default:
-		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
-		b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
+		action = action | TCP_PUSH | TCP_ACK;
 		debug_cond(DEBUG_DEV_PKT,
-			   "TCP Hdr:dft  (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
-			   &net_server_ip, &net_ip,
-			   tcp_seq_num, tcp_ack_num, action);
+			   "TCP Hdr:dft  (s=%u, a=%u, A=%x)\n",
+			   *tcp_seq_num, *tcp_ack_num, action);
 	}
 
-	pkt_len	= pkt_hdr_len + payload_len;
-	tcp_len	= pkt_len - IP_HDR_SIZE;
+	return action;
+}
+
+/**
+ * net_set_tcp_header_common() - IP version agnostic TCP header building implementation
+ *
+ * @tcp_hdr: pointer to TCP header struct
+ * @tcp_o: pointer to TCP options header struct
+ * @sack_t_opt: pointer to TCP sack options header struct
+ * @sack_v: pointer to TCP sack header struct
+ * @dport: destination TCP port
+ * @sport: source TCP port
+ * @payload_len: TCP payload len
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP header size
+ */
+int net_set_tcp_header_common(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *tcp_o,
+			      struct tcp_t_opt *sack_t_opt, struct tcp_sack_v *sack_v,
+			      u16 dport, u16 sport, int payload_len, u8 action,
+			      u32 tcp_seq_num, u32 tcp_ack_num)
+{
+	u8  tcp_action = TCP_DATA;
+	int tcp_hdr_len;
+
+	/*
+	 * Header: 5 32 bit words. 4 bits TCP header Length,
+	 *         4 bits reserved options
+	 */
+	tcp_hdr_len = TCP_HDR_SIZE;
+	tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
+
+	switch (action) {
+	case TCP_SYN:
+		net_set_syn_options(tcp_hdr, tcp_o);
+		tcp_hdr_len = TCP_HDR_SIZE + TCP_O_SIZE;
+		break;
+	case TCP_RST | TCP_ACK:
+	case TCP_RST:
+	case TCP_FIN:
+		payload_len = 0;
+		break;
+	default:
+		tcp_hdr_len = net_set_ack_options(tcp_hdr, sack_t_opt, sack_v);
+	}
+
+	tcp_action = tcp_sent_state_machine(action, &tcp_seq_num, &tcp_ack_num);
+	tcp_hdr->tcp_flags = tcp_action;
 
 	tcp_ack_edge = tcp_ack_num;
-	/* TCP Header */
-	b->ip.tcp_hdr.tcp_ack = htonl(tcp_ack_edge);
-	b->ip.tcp_hdr.tcp_src = htons(sport);
-	b->ip.tcp_hdr.tcp_dst = htons(dport);
-	b->ip.tcp_hdr.tcp_seq = htonl(tcp_seq_num);
+	tcp_hdr->tcp_ack = htonl(tcp_ack_edge);
+	tcp_hdr->tcp_seq = htonl(tcp_seq_num);
+	tcp_hdr->tcp_src = htons(sport);
+	tcp_hdr->tcp_dst = htons(dport);
 
 	/*
 	 * TCP window size - TCP header variable tcp_win.
@@ -340,18 +361,46 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
 	 * it is, then the u-boot tftp or nfs kernel netboot should be
 	 * considered.
 	 */
-	b->ip.tcp_hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
+	tcp_hdr->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
 
-	b->ip.tcp_hdr.tcp_xsum = 0;
-	b->ip.tcp_hdr.tcp_ugr = 0;
+	tcp_hdr->tcp_xsum = 0;
+	tcp_hdr->tcp_ugr = 0;
 
-	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
-						       tcp_len, pkt_len);
+	return tcp_hdr_len;
+}
 
-	net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip,
-			  pkt_len, IPPROTO_TCP);
+/**
+ * net_set_tcp_header() - IPv4 TCP header bulding implementation
+ *
+ * @pkt: pointer to the IP header
+ * @dport: destination TCP port
+ * @sport: source TCP port
+ * @payload_len: TCP payload len
+ * @action: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP header + payload size
+ */
+int net_set_tcp_header(uchar *pkt, u16 dport, u16 sport, int payload_len,
+		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
+{
+	union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
+	int tcp_hdr_len;
+	int pkt_len;
 
-	return pkt_hdr_len;
+	pkt_len = IP_HDR_SIZE;
+	tcp_hdr_len = net_set_tcp_header_common(&b->ip.tcp_hdr, &b->ip.tcp_o,
+						&b->sack.t_opt, &b->sack.sack_v,
+						dport, sport, payload_len, action,
+						tcp_seq_num, tcp_ack_num);
+	pkt_len += tcp_hdr_len;
+	pkt_len += payload_len;
+
+	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
+						       tcp_hdr_len + payload_len, pkt_len);
+
+	return tcp_hdr_len;
 }
 
 /**
@@ -500,7 +549,31 @@ void tcp_parse_options(uchar *o, int o_len)
 	}
 }
 
-static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
+static void init_sack_options(u32 tcp_seq_num, u32 tcp_ack_num)
+{
+	tcp_seq_init = tcp_seq_num;
+	tcp_ack_edge = tcp_ack_num;
+	sack_idx = 0;
+	edge_a[sack_idx].se.l = tcp_ack_edge;
+	edge_a[sack_idx].se.r = tcp_ack_edge;
+	prev_len = 0;
+	for (int i = 0; i < TCP_SACK; i++)
+		edge_a[i].st = NOPKT;
+}
+
+/**
+ * tcp_state_machine() - update TCP state in a reaction to incoming request
+ *
+ * @tcp_flags: TCP action (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_seq_num_out: TCP sequential number we expect to answer with
+ * @tcp_ack_num_out: TCP acknowledgment number we expect to answer with
+ * @payload_len: TCP payload len
+ *
+ * returns TCP action we expect to answer with
+ */
+u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, u32 *tcp_seq_num_out,
+		     u32 *tcp_ack_num_out, int payload_len)
 {
 	u8 tcp_fin = tcp_flags & TCP_FIN;
 	u8 tcp_syn = tcp_flags & TCP_SYN;
@@ -508,7 +581,6 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
 	u8 tcp_push = tcp_flags & TCP_PUSH;
 	u8 tcp_ack = tcp_flags & TCP_ACK;
 	u8 action = TCP_DATA;
-	int i;
 
 	/*
 	 * tcp_flags are examined to determine TX action in a given state
@@ -533,34 +605,29 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
 		debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags);
 		if (tcp_syn) {
 			action = TCP_SYN | TCP_ACK;
-			tcp_seq_init = tcp_seq_num;
-			tcp_ack_edge = tcp_seq_num + 1;
+			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
 			current_tcp_state = TCP_SYN_RECEIVED;
 		} else if (tcp_ack || tcp_fin) {
 			action = TCP_DATA;
 		}
 		break;
 	case TCP_SYN_RECEIVED:
+		if (tcp_ack) {
+			action = TCP_DATA;
+			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
+			current_tcp_state = TCP_ESTABLISHED;
+		}
+		break;
 	case TCP_SYN_SENT:
 		debug_cond(DEBUG_INT_STATE, "TCP_SYN_SENT | TCP_SYN_RECEIVED %x, %u\n",
 			   tcp_flags, tcp_seq_num);
 		if (tcp_fin) {
 			action = action | TCP_PUSH;
 			current_tcp_state = TCP_CLOSE_WAIT;
-		} else if (tcp_ack || (tcp_syn && tcp_ack)) {
-			action |= TCP_ACK;
-			tcp_seq_init = tcp_seq_num;
-			tcp_ack_edge = tcp_seq_num + 1;
-			sack_idx = 0;
-			edge_a[sack_idx].se.l = tcp_ack_edge;
-			edge_a[sack_idx].se.r = tcp_ack_edge;
-			prev_len = 0;
+		} else if (tcp_syn && tcp_ack) {
+			action |= TCP_ACK | TCP_PUSH;
+			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
 			current_tcp_state = TCP_ESTABLISHED;
-			for (i = 0; i < TCP_SACK; i++)
-				edge_a[i].st = NOPKT;
-
-			if (tcp_syn && tcp_ack)
-				action |= TCP_PUSH;
 		} else {
 			action = TCP_DATA;
 		}
@@ -627,6 +694,10 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
 		}
 		break;
 	}
+
+	*tcp_seq_num_out = tcp_seq_num;
+	*tcp_ack_num_out = tcp_ack_edge;
+
 	return action;
 }
 
@@ -641,6 +712,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 	u16 tcp_rx_xsum = b->ip.ip_hdr.ip_sum;
 	u8  tcp_action = TCP_DATA;
 	u32 tcp_seq_num, tcp_ack_num;
+	u32 res_tcp_seq_num, res_tcp_ack_num;
 	int tcp_hdr_len, payload_len;
 
 	/* Verify IP header */
@@ -685,7 +757,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 
 	/* Packets are not ordered. Send to app as received. */
 	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
-				       tcp_seq_num, payload_len);
+				       tcp_seq_num, &res_tcp_seq_num,
+				       &res_tcp_ack_num, payload_len);
 
 	tcp_activity_count++;
 	if (tcp_activity_count > TCP_ACTIVITY) {
@@ -705,7 +778,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 	} else if (tcp_action != TCP_DATA) {
 		debug_cond(DEBUG_DEV_PKT,
 			   "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
-			   tcp_action, tcp_ack_num, tcp_ack_edge, payload_len);
+			   tcp_action, res_tcp_seq_num, res_tcp_ack_num, payload_len);
 
 		/*
 		 * Warning: Incoming Ack & Seq sequence numbers are transposed
@@ -714,6 +787,6 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
 		net_send_tcp_packet(0, ntohs(b->ip.tcp_hdr.tcp_src),
 				    ntohs(b->ip.tcp_hdr.tcp_dst),
 				    (tcp_action & (~TCP_PUSH)),
-				    tcp_ack_num, tcp_ack_edge);
+				    res_tcp_seq_num, res_tcp_ack_num);
 	}
 }
-- 
2.40.1.606.ga4b1b128d6-goog


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

* [PATCH v2 3/6] net: introduce TCP/IP6 support
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
  2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
@ 2023-05-10 16:59 ` Dmitrii Merkurev
  2023-05-25  4:52   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  2023-05-10 16:59 ` [PATCH v2 4/6] net: add fastboot TCP6 support Dmitrii Merkurev
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

Add TCP/IP6 related headers and reuse refactored TCP/IP
implementation

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 include/net/tcp6.h | 106 +++++++++++++++++++++++++++++++++++++++++++++
 include/net6.h     |  14 ++++++
 net/Makefile       |   1 +
 net/net.c          |   6 +++
 net/net6.c         |  72 +++++++++++++++++++++++++-----
 net/tcp6.c         |  99 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 288 insertions(+), 10 deletions(-)
 create mode 100644 include/net/tcp6.h
 create mode 100644 net/tcp6.c

diff --git a/include/net/tcp6.h b/include/net/tcp6.h
new file mode 100644
index 0000000000..3db125ecc5
--- /dev/null
+++ b/include/net/tcp6.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ */
+
+#ifndef __TCP6_H__
+#define __TCP6_H__
+
+#if defined(CONFIG_PROT_TCP)
+
+#include <net6.h>
+#include <net/tcp.h>
+
+/**
+ * typedef rxhand_tcp6_f() - An incoming TCP IPv6 packet handler.
+ * @pkt: pointer to the application packet
+ * @dport: destination TCP port
+ * @sip: source IP6 address
+ * @sport: source TCP port
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ * @action: TCP packet type (SYN, ACK, FIN, etc)
+ */
+typedef void rxhand_tcp6_f(uchar *pkt, u16 dport,
+			   struct in6_addr sip, u16 sport,
+			   u32 tcp_seq_num, u32 tcp_ack_num,
+			   u8 action, unsigned int len);
+
+/**
+ * struct ip6_tcp_hdr_o - IP6 + TCP header + TCP options
+ * @ip_hdr: IP6 + TCP header
+ * @tcp_hdr: TCP header
+ * @tcp_o: TCP options
+ * @end: end of IP6/TCP header
+ */
+struct ip6_tcp_hdr_o {
+	struct  ip6_hdr    ip_hdr;
+	struct  tcp_hdr    tcp_hdr;
+	struct  tcp_hdr_o  tcp_o;
+	u8	end;
+} __packed;
+
+#define IP6_TCP_O_SIZE (sizeof(struct ip6_tcp_hdr_o))
+
+/**
+ * struct ip6_tcp_hdr_s - IP6 + TCP header + TCP options
+ * @ip_hdr: IP6 + TCP header
+ * @tcp_hdr: TCP header
+ * @t_opt: TCP Timestamp Option
+ * @sack_v: TCP SACK Option
+ * @end: end of options
+ */
+struct ip6_tcp_hdr_s {
+	struct  ip6_hdr    ip_hdr;
+	struct  tcp_hdr    tcp_hdr;
+	struct  tcp_t_opt  t_opt;
+	struct  tcp_sack_v sack_v;
+	u8	end;
+} __packed;
+
+#define IP6_TCP_SACK_SIZE (sizeof(struct ip6_tcp_hdr_s))
+
+/**
+ * union tcp6_build_pkt - union for building TCP/IP6 packet.
+ * @ip: IP6 and TCP header plus TCP options
+ * @sack: IP6 and TCP header plus SACK options
+ * @raw: buffer
+ */
+union tcp6_build_pkt {
+	struct ip6_tcp_hdr_o ip;
+	struct ip6_tcp_hdr_s sack;
+	uchar  raw[1600];
+} __packed;
+
+/**
+ * net_set_tcp6_handler6() - set application TCP6 packet handler
+ * @param f pointer to callback function
+ */
+void net_set_tcp_handler6(rxhand_tcp6_f *f);
+
+/**
+ * net_set_tcp_header6() - set
+ * @pkt: pointer to IP6/TCP headers
+ * @dport: destination TCP port
+ * @sport: source TCP port
+ * @payload_len: payload length
+ * @action: TCP packet type (SYN, ACK, FIN, etc)
+ * @tcp_seq_num: TCP sequential number
+ * @tcp_ack_num: TCP acknowledgment number
+ *
+ * returns TCP header size
+ */
+int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
+			u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
+
+void net_set_tcp_handler6(rxhand_tcp6_f *f);
+
+/**
+ * rxhand_tcp6() - handle incoming IP6 TCP packet
+ * @param b pointer to IP6/TCP packet builder struct
+ * @param len full packet length
+ */
+void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len);
+
+#endif // CONFIG_PROT_TCP
+#endif // __TCP6_H__
diff --git a/include/net6.h b/include/net6.h
index beafc05338..fa926f07ac 100644
--- a/include/net6.h
+++ b/include/net6.h
@@ -344,6 +344,20 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
 int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
 			 int sport, int len);
 
+/**
+ * net_send_tcp_packet6() - Make up TCP packet and send it
+ *
+ * @payload_len: TCP payload length
+ * @dport:	 destination port
+ * @sport:	 source port
+ * @action:	 TCP flag (SYN, ACL, PUSH, etc)
+ * @tcp_seq_num: TCP sequence number
+ * @tcp_ack_num: TCP ackno
+ * Return: 0 if send successfully, -1 otherwise
+ */
+int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
+			 u32 tcp_seq_num, u32 tcp_ack_num);
+
 /**
  * net_ip6_handler() - Handle IPv6 packet
  *
diff --git a/net/Makefile b/net/Makefile
index 3e2d061338..002b0f68a2 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT)  += fastboot_tcp.o
 obj-$(CONFIG_CMD_WOL)  += wol.o
 obj-$(CONFIG_PROT_UDP) += udp.o
 obj-$(CONFIG_PROT_TCP) += tcp.o
+obj-$(CONFIG_IPV6) += tcp6.o
 obj-$(CONFIG_CMD_WGET) += wget.o
 
 # Disable this warning as it is triggered by:
diff --git a/net/net.c b/net/net.c
index 0b68bf7b13..9ef290dc41 100644
--- a/net/net.c
+++ b/net/net.c
@@ -92,6 +92,7 @@
 #include <log.h>
 #include <net.h>
 #include <net6.h>
+#include <net/tcp6.h>
 #include <ndisc.h>
 #include <net/fastboot_udp.h>
 #include <net/fastboot_tcp.h>
@@ -386,6 +387,9 @@ static void net_clear_handlers(void)
 	net_set_udp_handler(NULL);
 	net_set_arp_handler(NULL);
 	net_set_timeout_handler(0, NULL);
+#if defined(CONFIG_IPV6) && defined(CONFIG_PROT_TCP)
+	net_set_tcp_handler6(NULL);
+#endif
 }
 
 static void net_cleanup_loop(void)
@@ -916,7 +920,9 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
 {
 	uchar *pkt;
 	int eth_hdr_size;
+#if defined(CONFIG_PROT_TCP)
 	int ip_tcp_hdr_size;
+#endif
 	int pkt_hdr_size;
 
 	/* make sure the net_tx_packet is initialized (net_init() was called) */
diff --git a/net/net6.c b/net/net6.c
index e395b930b0..575726766e 100644
--- a/net/net6.c
+++ b/net/net6.c
@@ -14,6 +14,7 @@
 #include <malloc.h>
 #include <net.h>
 #include <net6.h>
+#include <net/tcp6.h>
 #include <ndisc.h>
 
 /* NULL IPv6 address */
@@ -350,11 +351,17 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
 			u32 tcp_ack_num)
 {
 	uchar *pkt;
+	int pkt_hdr_size;
 	int eth_hdr_size;
+#if defined(CONFIG_PROT_UDP) || defined(CONFIG_PROT_TCP)
 	int ip_hdr_size;
+#endif
+#if defined(CONFIG_PROT_UDP)
 	int udp_hdr_size;
+#endif
+#if defined(CONFIG_PROT_TCP)
 	int tcp_hdr_size;
-	int pkt_hdr_size;
+#endif
 
 	if (!net_tx_packet)
 		return -1;
@@ -362,8 +369,8 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
 	pkt = (uchar *)net_tx_packet;
 
 	eth_hdr_size = net_set_ether(pkt, ether, PROT_IP6);
-	pkt_hdr_size += eth_hdr_size;
-	pkt = eth_hdr_size;
+	pkt_hdr_size = eth_hdr_size;
+	pkt += eth_hdr_size;
 
 	switch (proto) {
 #if defined(CONFIG_PROT_UDP)
@@ -377,6 +384,18 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
 		pkt_hdr_size += udp_hdr_size;
 		pkt += udp_hdr_size;
 		break;
+#endif
+#if defined(CONFIG_PROT_TCP)
+	case IPPROTO_TCP:
+		tcp_hdr_size = net_set_tcp_header6(pkt, dport, sport,
+						   payload_len, action, tcp_seq_num,
+						   tcp_ack_num);
+		ip_hdr_size = ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_TCP, 64,
+					  tcp_hdr_size + payload_len);
+
+		pkt_hdr_size += ip_hdr_size + tcp_hdr_size;
+		pkt += ip_hdr_size + tcp_hdr_size;
+		break;
 #endif
 	default:
 		return -EINVAL;
@@ -411,11 +430,25 @@ int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
 	return net_send_ip_packet6(ether, dest, dport, sport, len, IPPROTO_UDP, 0, 0, 0);
 }
 
+int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
+			 u32 tcp_seq_num, u32 tcp_ack_num)
+{
+	return net_send_ip_packet6(net_server_ethaddr, &net_server_ip6, dport,
+				   sport, payload_len, IPPROTO_TCP, action,
+				   tcp_seq_num, tcp_ack_num);
+}
+
 int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
 {
-	struct in_addr zero_ip = {.s_addr = 0 };
 	struct icmp6hdr *icmp;
+#if defined(CONFIG_PROT_UDP)
+	struct in_addr zero_ip = {.s_addr = 0 };
 	struct udp_hdr *udp;
+#endif
+#if defined(CONFIG_PROT_TCP)
+	union tcp6_build_pkt *tcp_headers;
+	struct tcp_hdr *tcp;
+#endif
 	u16 csum;
 	u16 csum_p;
 	u16 hlen;
@@ -454,6 +487,7 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
 			break;
 		}
 		break;
+#if defined(CONFIG_PROT_UDP)
 	case IPPROTO_UDP:
 		udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
 		csum = udp->udp_xsum;
@@ -468,13 +502,31 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
 			return -EINVAL;
 
 		/* IP header OK. Pass the packet to the current handler. */
-		net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE +
-					UDP_HDR_SIZE,
-				ntohs(udp->udp_dst),
-				zero_ip,
-				ntohs(udp->udp_src),
-				ntohs(udp->udp_len) - 8);
+		net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE + UDP_HDR_SIZE,
+				      ntohs(udp->udp_dst),
+				      zero_ip,
+				      ntohs(udp->udp_src),
+				      ntohs(udp->udp_len) - 8);
+		break;
+#endif
+#if defined(CONFIG_PROT_TCP)
+	case IPPROTO_TCP:
+		tcp = (struct tcp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
+		csum = tcp->tcp_xsum;
+		hlen = ntohs(ip6->payload_len);
+		tcp->tcp_xsum = 0;
+		/* checksum */
+		csum_p = csum_partial((u8 *)tcp, hlen, 0);
+		tcp->tcp_xsum = csum_ipv6_magic(&ip6->saddr, &ip6->daddr,
+						hlen, IPPROTO_TCP, csum_p);
+
+		if (csum != tcp->tcp_xsum)
+			return -EINVAL;
+
+		tcp_headers = (union tcp6_build_pkt *)ip6;
+		rxhand_tcp6(tcp_headers, len);
 		break;
+#endif
 	default:
 		return -EINVAL;
 	}
diff --git a/net/tcp6.c b/net/tcp6.c
new file mode 100644
index 0000000000..09b2190db7
--- /dev/null
+++ b/net/tcp6.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ */
+
+#if defined(CONFIG_PROT_TCP)
+
+#include <common.h>
+#include <net/tcp.h>
+#include <net/tcp6.h>
+#include <net6.h>
+
+static rxhand_tcp6_f *tcp6_packet_handler;
+
+static void dummy_handler(uchar *pkt, u16 dport,
+			  struct in6_addr sip, u16 sport,
+			  u32 tcp_seq_num, u32 tcp_ack_num,
+			  u8 action, unsigned int len)
+{
+}
+
+void net_set_tcp_handler6(rxhand_tcp6_f *f)
+{
+	if (!f)
+		tcp6_packet_handler = dummy_handler;
+	else
+		tcp6_packet_handler = f;
+}
+
+int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
+			u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
+{
+	union tcp6_build_pkt *b = (union tcp6_build_pkt *)pkt;
+	int tcp_hdr_len;
+	int pkt_len;
+	u16 csum;
+
+	pkt_len = IP6_HDR_SIZE;
+	tcp_hdr_len = net_set_tcp_header_common(&b->ip.tcp_hdr, &b->ip.tcp_o,
+						&b->sack.t_opt, &b->sack.sack_v,
+						dport, sport, payload_len, action,
+						tcp_seq_num, tcp_ack_num);
+	pkt_len += tcp_hdr_len;
+	pkt_len += payload_len;
+
+	csum = csum_partial((u8 *)&b->ip.tcp_hdr, tcp_hdr_len + payload_len, 0);
+	b->ip.tcp_hdr.tcp_xsum = csum_ipv6_magic(&net_ip6, &net_server_ip6,
+						 tcp_hdr_len + payload_len,
+						 IPPROTO_TCP, csum);
+
+	return tcp_hdr_len;
+}
+
+void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len)
+{
+	int tcp_len = len - IP6_HDR_SIZE;
+	u8  tcp_action = TCP_DATA;
+	u32 tcp_seq_num, tcp_ack_num;
+	u32 res_tcp_seq_num, res_tcp_ack_num;
+	int tcp_hdr_len, payload_len;
+
+	net_copy_ip6(&net_server_ip6, &b->ip.ip_hdr.saddr);
+
+	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.tcp_hdr.tcp_hlen);
+	payload_len = tcp_len - tcp_hdr_len;
+
+	if (tcp_hdr_len > TCP_HDR_SIZE)
+		tcp_parse_options((uchar *)b + IP6_HDR_SIZE + TCP_HDR_SIZE,
+				  tcp_hdr_len - TCP_HDR_SIZE);
+
+	tcp_seq_num = ntohl(b->ip.tcp_hdr.tcp_seq);
+	tcp_ack_num = ntohl(b->ip.tcp_hdr.tcp_ack);
+
+	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
+				       tcp_seq_num, &res_tcp_seq_num, &res_tcp_ack_num,
+				       payload_len);
+
+	if ((tcp_action & TCP_PUSH) || payload_len > 0) {
+		debug_cond(DEBUG_DEV_PKT,
+			   "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
+			   tcp_action, tcp_seq_num, tcp_ack_num, payload_len);
+
+		(*tcp6_packet_handler) ((uchar *)b + len - payload_len, b->ip.tcp_hdr.tcp_dst,
+					b->ip.ip_hdr.saddr, b->ip.tcp_hdr.tcp_src, tcp_seq_num,
+					tcp_ack_num, tcp_action, payload_len);
+
+	} else if (tcp_action != TCP_DATA) {
+		debug_cond(DEBUG_DEV_PKT,
+			   "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
+			   tcp_action, res_tcp_seq_num, res_tcp_ack_num, payload_len);
+
+		net_send_tcp_packet6(0, ntohs(b->ip.tcp_hdr.tcp_src),
+				     ntohs(b->ip.tcp_hdr.tcp_dst),
+				     (tcp_action & (~TCP_PUSH)),
+				     res_tcp_seq_num, res_tcp_ack_num);
+	}
+}
+
+#endif // CONFIG_PROT_TCP
-- 
2.40.1.606.ga4b1b128d6-goog


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

* [PATCH v2 4/6] net: add fastboot TCP6 support
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
  2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
  2023-05-10 16:59 ` [PATCH v2 3/6] net: introduce TCP/IP6 support Dmitrii Merkurev
@ 2023-05-10 16:59 ` Dmitrii Merkurev
  2023-07-03 15:48   ` Paul Liu
  2023-07-23  3:48   ` Simon Glass
  2023-05-10 16:59 ` [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode Dmitrii Merkurev
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

fastboot tcp command remains the same, but started
listening IP6 in case it's enabled.

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 include/net/fastboot_tcp.h |  2 +-
 net/fastboot_tcp.c         | 72 ++++++++++++++++++++++++++++++++------
 2 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/include/net/fastboot_tcp.h b/include/net/fastboot_tcp.h
index 6cf29d52e9..98986fa10a 100644
--- a/include/net/fastboot_tcp.h
+++ b/include/net/fastboot_tcp.h
@@ -7,7 +7,7 @@
 #define __NET_FASTBOOT_TCP_H__
 
 /**
- * Wait for incoming tcp fastboot comands.
+ * Wait for incoming TCP fastboot comands.
  */
 void fastboot_tcp_start_server(void);
 
diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c
index 2eb52ea256..d93b52ede5 100644
--- a/net/fastboot_tcp.c
+++ b/net/fastboot_tcp.c
@@ -6,8 +6,10 @@
 #include <common.h>
 #include <fastboot.h>
 #include <net.h>
+#include <net6.h>
 #include <net/fastboot_tcp.h>
 #include <net/tcp.h>
+#include <net/tcp6.h>
 
 static char command[FASTBOOT_COMMAND_LEN] = {0};
 static char response[FASTBOOT_RESPONSE_LEN] = {0};
@@ -20,18 +22,30 @@ static u16 curr_dport;
 static u32 curr_tcp_seq_num;
 static u32 curr_tcp_ack_num;
 static unsigned int curr_request_len;
+static bool is_ipv6;
+static size_t ip_header_size;
 static enum fastboot_tcp_state {
 	FASTBOOT_CLOSED,
 	FASTBOOT_CONNECTED,
 	FASTBOOT_DISCONNECTING
 } state = FASTBOOT_CLOSED;
 
+static int command_handled_id;
+static bool command_handled_success;
+
 static void fastboot_tcp_answer(u8 action, unsigned int len)
 {
 	const u32 response_seq_num = curr_tcp_ack_num;
 	const u32 response_ack_num = curr_tcp_seq_num +
 		  (curr_request_len > 0 ? curr_request_len : 1);
 
+#if defined(CONFIG_IPV6)
+	if (is_ipv6) {
+		net_send_tcp_packet6(len, htons(curr_sport), htons(curr_dport),
+				     action, response_seq_num, response_ack_num);
+		return;
+	}
+#endif
 	net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport),
 			    action, response_seq_num, response_ack_num);
 }
@@ -47,7 +61,7 @@ static void fastboot_tcp_send_packet(u8 action, const uchar *data, unsigned int
 	uchar *pkt = net_get_async_tx_pkt_buf();
 
 	memset(pkt, '\0', PKTSIZE);
-	pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
+	pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
 	memcpy(pkt, data, len);
 	fastboot_tcp_answer(action, len);
 	memset(pkt, '\0', PKTSIZE);
@@ -59,7 +73,7 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len)
 	uchar *pkt = net_get_async_tx_pkt_buf();
 
 	memset(pkt, '\0', PKTSIZE);
-	pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
+	pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
 	// Put first 8 bytes as a big endian message length
 	memcpy(pkt, &len_be, 8);
 	pkt += 8;
@@ -68,10 +82,9 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len)
 	memset(pkt, '\0', PKTSIZE);
 }
 
-static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
-				      struct in_addr sip, u16 sport,
-				      u32 tcp_seq_num, u32 tcp_ack_num,
-				      u8 action, unsigned int len)
+static void fastboot_tcp_handler(uchar *pkt, u16 dport, u16 sport,
+				 u32 tcp_seq_num, u32 tcp_ack_num,
+				 u8 action, unsigned int len)
 {
 	int fastboot_command_id;
 	u64 command_size;
@@ -88,7 +101,6 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
 	case FASTBOOT_CLOSED:
 		if (tcp_push) {
 			if (len != handshake_length ||
-			    strlen(pkt) != handshake_length ||
 			    memcmp(pkt, handshake, handshake_length) != 0) {
 				fastboot_tcp_reset();
 				break;
@@ -111,18 +123,25 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
 			pkt += 8;
 
 			// Only single packet messages are supported ATM
-			if (strlen(pkt) != command_size) {
+			if (len != command_size) {
 				fastboot_tcp_reset();
 				break;
 			}
 			strlcpy(command, pkt, len + 1);
 			fastboot_command_id = fastboot_handle_command(command, response);
 			fastboot_tcp_send_message(response, strlen(response));
-			fastboot_handle_boot(fastboot_command_id,
-					     strncmp("OKAY", response, 4) == 0);
+
+			command_handled_id = fastboot_command_id;
+			command_handled_success = strncmp("OKAY", response, 4) == 0;
 		}
 		break;
 	case FASTBOOT_DISCONNECTING:
+		if (command_handled_success) {
+			fastboot_handle_boot(command_handled_id, command_handled_success);
+			command_handled_id = 0;
+			command_handled_success = false;
+		}
+
 		if (tcp_push)
 			state = FASTBOOT_CLOSED;
 		break;
@@ -137,10 +156,41 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
 	curr_request_len = 0;
 }
 
+static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
+				      struct in_addr sip, u16 sport,
+				      u32 tcp_seq_num, u32 tcp_ack_num,
+				      u8 action, unsigned int len)
+{
+	is_ipv6 = false;
+	ip_header_size = IP_HDR_SIZE;
+	fastboot_tcp_handler(pkt, dport, sport,
+			     tcp_seq_num, tcp_ack_num,
+			     action, len);
+}
+
+#if defined(CONFIG_IPV6)
+static void fastboot_tcp_handler_ipv6(uchar *pkt, u16 dport,
+				      struct in6_addr sip, u16 sport,
+				      u32 tcp_seq_num, u32 tcp_ack_num,
+				      u8 action, unsigned int len)
+{
+	is_ipv6 = true;
+	ip_header_size = IP6_HDR_SIZE;
+	fastboot_tcp_handler(pkt, dport, sport,
+			     tcp_seq_num, tcp_ack_num,
+			     action, len);
+}
+#endif
+
 void fastboot_tcp_start_server(void)
 {
 	printf("Using %s device\n", eth_get_name());
-	printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
 
+	printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
 	tcp_set_tcp_handler(fastboot_tcp_handler_ipv4);
+
+#if defined(CONFIG_IPV6)
+	printf("Listening for fastboot command on %pI6\n", &net_ip6);
+	net_set_tcp_handler6(fastboot_tcp_handler_ipv6);
+#endif
 }
-- 
2.40.1.606.ga4b1b128d6-goog


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

* [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
                   ` (2 preceding siblings ...)
  2023-05-10 16:59 ` [PATCH v2 4/6] net: add fastboot TCP6 support Dmitrii Merkurev
@ 2023-05-10 16:59 ` Dmitrii Merkurev
  2023-07-14 15:43   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  2023-05-10 16:59 ` [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed Dmitrii Merkurev
  2023-05-24 21:19 ` [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Ying-Chun Liu (PaulLiu)
  5 siblings, 2 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

Command to start IP6 only TCP fastboot:
fastboot tcp -ipv6

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 cmd/fastboot.c           | 29 +++++++++++++++++++++++++----
 doc/android/fastboot.rst |  8 +++++++-
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index 3d5ff951eb..36f744ae01 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -12,6 +12,7 @@
 #include <g_dnl.h>
 #include <fastboot.h>
 #include <net.h>
+#include <net6.h>
 #include <usb.h>
 #include <watchdog.h>
 #include <linux/stringify.h>
@@ -121,10 +122,23 @@ static int do_fastboot(struct cmd_tbl *cmdtp, int flag, int argc,
 {
 	uintptr_t buf_addr = (uintptr_t)NULL;
 	size_t buf_size = 0;
+	bool is_ipv6_only = false;
+	bool is_usb = false;
+	bool is_udp = false;
+	bool is_tcp = false;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
+	if (IS_ENABLED(CONFIG_IPV6)) {
+		use_ip6 = false;
+		/* IPv6 parameter has to be always *last* */
+		if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM)) {
+			is_ipv6_only = true;
+			--argc;
+		}
+	}
+
 	while (argc > 1 && **(argv + 1) == '-') {
 		char *arg = *++argv;
 
@@ -159,11 +173,18 @@ NXTARG:
 
 	fastboot_init((void *)buf_addr, buf_size);
 
-	if (!strcmp(argv[1], "udp"))
+	is_usb = strcmp(argv[1], "usb") == 0;
+	is_udp = strcmp(argv[1], "udp") == 0;
+	is_tcp = strcmp(argv[1], "tcp") == 0;
+
+	if (is_ipv6_only && is_tcp)
+		use_ip6 = true;
+
+	if (is_udp)
 		return do_fastboot_udp(argc, argv, buf_addr, buf_size);
-	if (!strcmp(argv[1], "tcp"))
+	if (is_tcp)
 		return do_fastboot_tcp(argc, argv, buf_addr, buf_size);
-	if (!strcmp(argv[1], "usb")) {
+	if (is_usb) {
 		argv++;
 		argc--;
 	}
@@ -174,7 +195,7 @@ NXTARG:
 U_BOOT_CMD(
 	fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
 	"run as a fastboot usb or udp device",
-	"[-l addr] [-s size] usb <controller> | udp\n"
+	"[-l addr] [-s size] usb <controller> | udp [-ipv6] | tcp [-ipv6]\n"
 	"\taddr - address of buffer used during data transfers ("
 	__stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
 	"\tsize - size of buffer used during data transfers ("
diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
index 1ad8a897c8..aa6e9e5a9e 100644
--- a/doc/android/fastboot.rst
+++ b/doc/android/fastboot.rst
@@ -181,13 +181,19 @@ Enter into fastboot by executing the fastboot command in U-Boot for either USB::
 
    => fastboot usb 0
 
-or UDP::
+UDP::
 
    => fastboot udp
    link up on port 0, speed 100, full duplex
    Using ethernet@4a100000 device
    Listening for fastboot command on 192.168.0.102
 
+or TCP::
+
+   => fastboot tcp
+   Using ethernet@4a100000 device
+   Listening for fastboot command on 192.168.0.102
+
 On the client side you can fetch the bootloader version for instance::
 
    $ fastboot getvar version-bootloader
-- 
2.40.1.606.ga4b1b128d6-goog


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

* [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
                   ` (3 preceding siblings ...)
  2023-05-10 16:59 ` [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode Dmitrii Merkurev
@ 2023-05-10 16:59 ` Dmitrii Merkurev
  2023-07-23  3:48   ` Simon Glass
  2023-05-24 21:19 ` [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Ying-Chun Liu (PaulLiu)
  5 siblings, 1 reply; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-05-10 16:59 UTC (permalink / raw)
  To: u-boot
  Cc: rammuthiah, rfried.dev, Dmitrii Merkurev, Ying-Chun Liu, Simon Glass

Current active eth device may be changed (due to ethprime), so make
sure current net_ip6 is updated as a reaction.

Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Simon Glass <sjg@chromium.org>
Сс: Joe Hershberger <joe.hershberger@ni.com>
Сс: Ramon Fried <rfried.dev@gmail.com>
---
 net/net.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/net.c b/net/net.c
index 9ef290dc41..0f14f29de8 100644
--- a/net/net.c
+++ b/net/net.c
@@ -359,10 +359,10 @@ static int net_init_loop(void)
 
 		if (IS_ENABLED(CONFIG_IPV6)) {
 			ip6_make_lladdr(&net_link_local_ip6, net_ethaddr);
-			if (!memcmp(&net_ip6, &net_null_addr_ip6,
-				    sizeof(struct in6_addr)))
-				memcpy(&net_ip6, &net_link_local_ip6,
-				       sizeof(struct in6_addr));
+			if (memcmp(&net_link_local_ip6, &net_null_addr_ip6,
+				   sizeof(struct in6_addr))) {
+				net_copy_ip6(&net_ip6, &net_link_local_ip6);
+			}
 		}
 	}
 	else
-- 
2.40.1.606.ga4b1b128d6-goog


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

* Re: [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers
  2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
                   ` (4 preceding siblings ...)
  2023-05-10 16:59 ` [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed Dmitrii Merkurev
@ 2023-05-24 21:19 ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  5 siblings, 1 reply; 21+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2023-05-24 21:19 UTC (permalink / raw)
  To: Dmitrii Merkurev, u-boot; +Cc: rammuthiah, rfried.dev, Simon Glass

Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>

On 2023/5/11 00:59, Dmitrii Merkurev wrote:
> This allows us to reuse TCP logic between IP and IP6 stack.
> 
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>   include/net/tcp.h | 54 ++++++++++++++++--------------------
>   net/tcp.c         | 70 +++++++++++++++++++++++------------------------
>   test/cmd/wget.c   | 48 ++++++++++++++++++--------------
>   3 files changed, 85 insertions(+), 87 deletions(-)
> 
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index c29d4ce24a..93ed728dfe 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -5,20 +5,16 @@
>    * Copyright 2017 Duncan Hare, All rights reserved.
>    */
>   
> +#ifndef __TCP_H__
> +#define __TCP_H__
> +
>   #define TCP_ACTIVITY 127		/* Number of packets received   */
>   					/* before console progress mark */
> +
> +#define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
> +
>   /**
> - * struct ip_tcp_hdr - IP and TCP header
> - * @ip_hl_v: header length and version
> - * @ip_tos: type of service
> - * @ip_len: total length
> - * @ip_id: identification
> - * @ip_off: fragment offset field
> - * @ip_ttl: time to live
> - * @ip_p: protocol
> - * @ip_sum: checksum
> - * @ip_src: Source IP address
> - * @ip_dst: Destination IP address
> + * struct tcp_hdr - TCP header
>    * @tcp_src: TCP source port
>    * @tcp_dst: TCP destination port
>    * @tcp_seq: TCP sequence number
> @@ -28,18 +24,8 @@
>    * @tcp_win: TCP windows size
>    * @tcp_xsum: Checksum
>    * @tcp_ugr: Pointer to urgent data
> - */
> -struct ip_tcp_hdr {
> -	u8		ip_hl_v;
> -	u8		ip_tos;
> -	u16		ip_len;
> -	u16		ip_id;
> -	u16		ip_off;
> -	u8		ip_ttl;
> -	u8		ip_p;
> -	u16		ip_sum;
> -	struct in_addr	ip_src;
> -	struct in_addr	ip_dst;
> +*/
> +struct tcp_hdr {
>   	u16		tcp_src;
>   	u16		tcp_dst;
>   	u32		tcp_seq;
> @@ -51,8 +37,8 @@ struct ip_tcp_hdr {
>   	u16		tcp_ugr;
>   } __packed;
>   
> -#define IP_TCP_HDR_SIZE		(sizeof(struct ip_tcp_hdr))
> -#define TCP_HDR_SIZE		(IP_TCP_HDR_SIZE  - IP_HDR_SIZE)
> +#define TCP_HDR_SIZE		(sizeof(struct tcp_hdr))
> +#define IP_TCP_HDR_SIZE         (IP_HDR_SIZE + TCP_HDR_SIZE)
>   
>   #define TCP_DATA	0x00	/* Data Packet - internal use only	*/
>   #define TCP_FIN		0x01	/* Finish flag				*/
> @@ -178,7 +164,8 @@ struct tcp_t_opt {
>   
>   /**
>    * struct ip_tcp_hdr_o - IP + TCP header + TCP options
> - * @hdr: IP + TCP header
> + * @ip_hdr: IP + TCP header
> + * @tcp_hdr: TCP header
>    * @mss: TCP MSS Option
>    * @scale: TCP Windows Scale Option
>    * @sack_p: TCP Sack-Permitted Option
> @@ -186,7 +173,8 @@ struct tcp_t_opt {
>    * @end: end of options
>    */
>   struct ip_tcp_hdr_o {
> -	struct	ip_tcp_hdr hdr;
> +	struct	ip_hdr     ip_hdr;
> +	struct	tcp_hdr    tcp_hdr;
>   	struct	tcp_mss	   mss;
>   	struct	tcp_scale  scale;
>   	struct	tcp_sack_p sack_p;
> @@ -198,15 +186,17 @@ struct ip_tcp_hdr_o {
>   
>   /**
>    * struct ip_tcp_hdr_s - IP + TCP header + TCP options
> - * @hdr: IP + TCP header
> + * @ip_hdr: IP + TCP header
> + * @tcp_hdr: TCP header
>    * @t_opt: TCP Timestamp Option
>    * @sack_v: TCP SACK Option
>    * @end: end of options
>    */
>   struct ip_tcp_hdr_s {
> -	struct	ip_tcp_hdr	hdr;
> -	struct	tcp_t_opt	t_opt;
> -	struct	tcp_sack_v	sack_v;
> +	struct	ip_hdr     ip_hdr;
> +	struct	tcp_hdr    tcp_hdr;
> +	struct	tcp_t_opt  t_opt;
> +	struct	tcp_sack_v sack_v;
>   	u8	end;
>   } __packed;
>   
> @@ -303,3 +293,5 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int len);
>   
>   u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
>   			  int tcp_len, int pkt_len);
> +
> +#endif // __TCP_H__
> diff --git a/net/tcp.c b/net/tcp.c
> index a713e1dd60..10ce799814 100644
> --- a/net/tcp.c
> +++ b/net/tcp.c
> @@ -155,7 +155,7 @@ u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
>    */
>   int net_set_ack_options(union tcp_build_pkt *b)
>   {
> -	b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
> +	b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
>   
>   	b->sack.t_opt.kind = TCP_O_TS;
>   	b->sack.t_opt.len = TCP_OPT_LEN_A;
> @@ -187,12 +187,12 @@ int net_set_ack_options(union tcp_build_pkt *b)
>   			b->sack.sack_v.hill[3].r = TCP_O_NOP;
>   		}
>   
> -		b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> +		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
>   										 TCP_TSOPT_SIZE +
>   										 tcp_lost.len));
>   	} else {
>   		b->sack.sack_v.kind = 0;
> -		b->sack.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> +		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
>   										 TCP_TSOPT_SIZE));
>   	}
>   
> @@ -201,7 +201,7 @@ int net_set_ack_options(union tcp_build_pkt *b)
>   	 * TCP header to add to the total packet length
>   	 */
>   
> -	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.hdr.tcp_hlen);
> +	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.tcp_hdr.tcp_hlen);
>   }
>   
>   /**
> @@ -213,7 +213,7 @@ void net_set_syn_options(union tcp_build_pkt *b)
>   	if (IS_ENABLED(CONFIG_PROT_TCP_SACK))
>   		tcp_lost.len = 0;
>   
> -	b->ip.hdr.tcp_hlen = 0xa0;
> +	b->ip.tcp_hdr.tcp_hlen = 0xa0;
>   
>   	b->ip.mss.kind = TCP_O_MSS;
>   	b->ip.mss.len = TCP_OPT_LEN_4;
> @@ -249,9 +249,9 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   	 * Header: 5 32 bit words. 4 bits TCP header Length,
>   	 *         4 bits reserved options
>   	 */
> -	b->ip.hdr.tcp_flags = action;
> +	b->ip.tcp_hdr.tcp_flags = action;
>   	pkt_hdr_len = IP_TCP_HDR_SIZE;
> -	b->ip.hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
> +	b->ip.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
>   
>   	switch (action) {
>   	case TCP_SYN:
> @@ -274,7 +274,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   	case TCP_SYN | TCP_ACK:
>   	case TCP_ACK:
>   		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
> -		b->ip.hdr.tcp_flags = action;
> +		b->ip.tcp_hdr.tcp_flags = action;
>   		debug_cond(DEBUG_DEV_PKT,
>   			   "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
>   			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num,
> @@ -308,7 +308,7 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   		fallthrough;
>   	default:
>   		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
> -		b->ip.hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
> +		b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
>   		debug_cond(DEBUG_DEV_PKT,
>   			   "TCP Hdr:dft  (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
>   			   &net_server_ip, &net_ip,
> @@ -320,10 +320,10 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   
>   	tcp_ack_edge = tcp_ack_num;
>   	/* TCP Header */
> -	b->ip.hdr.tcp_ack = htonl(tcp_ack_edge);
> -	b->ip.hdr.tcp_src = htons(sport);
> -	b->ip.hdr.tcp_dst = htons(dport);
> -	b->ip.hdr.tcp_seq = htonl(tcp_seq_num);
> +	b->ip.tcp_hdr.tcp_ack = htonl(tcp_ack_edge);
> +	b->ip.tcp_hdr.tcp_src = htons(sport);
> +	b->ip.tcp_hdr.tcp_dst = htons(dport);
> +	b->ip.tcp_hdr.tcp_seq = htonl(tcp_seq_num);
>   
>   	/*
>   	 * TCP window size - TCP header variable tcp_win.
> @@ -340,13 +340,13 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   	 * it is, then the u-boot tftp or nfs kernel netboot should be
>   	 * considered.
>   	 */
> -	b->ip.hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
> +	b->ip.tcp_hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
>   
> -	b->ip.hdr.tcp_xsum = 0;
> -	b->ip.hdr.tcp_ugr = 0;
> +	b->ip.tcp_hdr.tcp_xsum = 0;
> +	b->ip.tcp_hdr.tcp_ugr = 0;
>   
> -	b->ip.hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
> -						   tcp_len, pkt_len);
> +	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
> +						       tcp_len, pkt_len);
>   
>   	net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip,
>   			  pkt_len, IPPROTO_TCP);
> @@ -638,7 +638,7 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
>   void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   {
>   	int tcp_len = pkt_len - IP_HDR_SIZE;
> -	u16 tcp_rx_xsum = b->ip.hdr.ip_sum;
> +	u16 tcp_rx_xsum = b->ip.ip_hdr.ip_sum;
>   	u8  tcp_action = TCP_DATA;
>   	u32 tcp_seq_num, tcp_ack_num;
>   	int tcp_hdr_len, payload_len;
> @@ -646,11 +646,11 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   	/* Verify IP header */
>   	debug_cond(DEBUG_DEV_PKT,
>   		   "TCP RX in RX Sum (to=%pI4, from=%pI4, len=%d)\n",
> -		   &b->ip.hdr.ip_src, &b->ip.hdr.ip_dst, pkt_len);
> +		   &b->ip.ip_hdr.ip_src, &b->ip.ip_hdr.ip_dst, pkt_len);
>   
> -	b->ip.hdr.ip_src = net_server_ip;
> -	b->ip.hdr.ip_dst = net_ip;
> -	b->ip.hdr.ip_sum = 0;
> +	b->ip.ip_hdr.ip_src = net_server_ip;
> +	b->ip.ip_hdr.ip_dst = net_ip;
> +	b->ip.ip_hdr.ip_sum = 0;
>   	if (tcp_rx_xsum != compute_ip_checksum(b, IP_HDR_SIZE)) {
>   		debug_cond(DEBUG_DEV_PKT,
>   			   "TCP RX IP xSum Error (%pI4, =%pI4, len=%d)\n",
> @@ -659,10 +659,10 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   	}
>   
>   	/* Build pseudo header and verify TCP header */
> -	tcp_rx_xsum = b->ip.hdr.tcp_xsum;
> -	b->ip.hdr.tcp_xsum = 0;
> -	if (tcp_rx_xsum != tcp_set_pseudo_header((uchar *)b, b->ip.hdr.ip_src,
> -						 b->ip.hdr.ip_dst, tcp_len,
> +	tcp_rx_xsum = b->ip.tcp_hdr.tcp_xsum;
> +	b->ip.tcp_hdr.tcp_xsum = 0;
> +	if (tcp_rx_xsum != tcp_set_pseudo_header((uchar *)b, b->ip.ip_hdr.ip_src,
> +						 b->ip.ip_hdr.ip_dst, tcp_len,
>   						 pkt_len)) {
>   		debug_cond(DEBUG_DEV_PKT,
>   			   "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n",
> @@ -670,7 +670,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   		return;
>   	}
>   
> -	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.hdr.tcp_hlen);
> +	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.tcp_hdr.tcp_hlen);
>   	payload_len = tcp_len - tcp_hdr_len;
>   
>   	if (tcp_hdr_len > TCP_HDR_SIZE)
> @@ -680,11 +680,11 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   	 * Incoming sequence and ack numbers are server's view of the numbers.
>   	 * The app must swap the numbers when responding.
>   	 */
> -	tcp_seq_num = ntohl(b->ip.hdr.tcp_seq);
> -	tcp_ack_num = ntohl(b->ip.hdr.tcp_ack);
> +	tcp_seq_num = ntohl(b->ip.tcp_hdr.tcp_seq);
> +	tcp_ack_num = ntohl(b->ip.tcp_hdr.tcp_ack);
>   
>   	/* Packets are not ordered. Send to app as received. */
> -	tcp_action = tcp_state_machine(b->ip.hdr.tcp_flags,
> +	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
>   				       tcp_seq_num, payload_len);
>   
>   	tcp_activity_count++;
> @@ -698,8 +698,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   			   "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
>   			   tcp_action, tcp_seq_num, tcp_ack_num, payload_len);
>   
> -		(*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.hdr.tcp_dst,
> -				       b->ip.hdr.ip_src, b->ip.hdr.tcp_src, tcp_seq_num,
> +		(*tcp_packet_handler) ((uchar *)b + pkt_len - payload_len, b->ip.tcp_hdr.tcp_dst,
> +				       b->ip.ip_hdr.ip_src, b->ip.tcp_hdr.tcp_src, tcp_seq_num,
>   				       tcp_ack_num, tcp_action, payload_len);
>   
>   	} else if (tcp_action != TCP_DATA) {
> @@ -711,8 +711,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   		 * Warning: Incoming Ack & Seq sequence numbers are transposed
>   		 * here to outgoing Seq & Ack sequence numbers
>   		 */
> -		net_send_tcp_packet(0, ntohs(b->ip.hdr.tcp_src),
> -				    ntohs(b->ip.hdr.tcp_dst),
> +		net_send_tcp_packet(0, ntohs(b->ip.tcp_hdr.tcp_src),
> +				    ntohs(b->ip.tcp_hdr.tcp_dst),
>   				    (tcp_action & (~TCP_PUSH)),
>   				    tcp_ack_num, tcp_ack_edge);
>   	}
> diff --git a/test/cmd/wget.c b/test/cmd/wget.c
> index ed83fc94a5..e2c11d3e76 100644
> --- a/test/cmd/wget.c
> +++ b/test/cmd/wget.c
> @@ -52,9 +52,11 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
>   {
>   	struct eth_sandbox_priv *priv = dev_get_priv(dev);
>   	struct ethernet_hdr *eth = packet;
> -	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
> +	struct ip_hdr *ip = packet + ETHER_HDR_SIZE;
> +	struct tcp_hdr *tcp = (void *)ip + IP_HDR_SIZE;
>   	struct ethernet_hdr *eth_send;
> -	struct ip_tcp_hdr *tcp_send;
> +	struct ip_hdr *ip_send;
> +	struct tcp_hdr *tcp_send;
>   
>   	/* Don't allow the buffer to overrun */
>   	if (priv->recv_packets >= PKTBUFSRX)
> @@ -64,7 +66,8 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
>   	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
>   	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
>   	eth_send->et_protlen = htons(PROT_IP);
> -	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
> +	ip_send = (void *)eth_send + ETHER_HDR_SIZE;
> +	tcp_send = (void *)ip_send + IP_HDR_SIZE;
>   	tcp_send->tcp_src = tcp->tcp_dst;
>   	tcp_send->tcp_dst = tcp->tcp_src;
>   	tcp_send->tcp_seq = htonl(0);
> @@ -74,14 +77,14 @@ static int sb_syn_handler(struct udevice *dev, void *packet,
>   	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
>   	tcp_send->tcp_xsum = 0;
>   	tcp_send->tcp_ugr = 0;
> -	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
> -						   tcp->ip_src,
> -						   tcp->ip_dst,
> +	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)ip_send,
> +						   ip->ip_src,
> +						   ip->ip_dst,
>   						   TCP_HDR_SIZE,
>   						   IP_TCP_HDR_SIZE);
> -	net_set_ip_header((uchar *)tcp_send,
> -			  tcp->ip_src,
> -			  tcp->ip_dst,
> +	net_set_ip_header((uchar *)ip_send,
> +			  ip->ip_src,
> +			  ip->ip_dst,
>   			  IP_TCP_HDR_SIZE,
>   			  IPPROTO_TCP);
>   
> @@ -97,9 +100,11 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
>   {
>   	struct eth_sandbox_priv *priv = dev_get_priv(dev);
>   	struct ethernet_hdr *eth = packet;
> -	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
> +	struct ip_hdr *ip = packet + ETHER_HDR_SIZE;
> +	struct tcp_hdr *tcp = (void *)ip + IP_HDR_SIZE;
>   	struct ethernet_hdr *eth_send;
> -	struct ip_tcp_hdr *tcp_send;
> +	struct ip_hdr *ip_send;
> +	struct tcp_hdr *tcp_send;
>   	void *data;
>   	int pkt_len;
>   	int payload_len = 0;
> @@ -115,10 +120,11 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
>   	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
>   	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
>   	eth_send->et_protlen = htons(PROT_IP);
> -	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
> +	ip_send = (void *)eth_send + ETHER_HDR_SIZE;
> +	tcp_send = (void *)ip_send + IP_HDR_SIZE;
> +	data = (void *)tcp_send + TCP_HDR_SIZE;
>   	tcp_send->tcp_src = tcp->tcp_dst;
>   	tcp_send->tcp_dst = tcp->tcp_src;
> -	data = (void *)tcp_send + IP_TCP_HDR_SIZE;
>   
>   	if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1) {
>   		tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
> @@ -138,14 +144,14 @@ static int sb_ack_handler(struct udevice *dev, void *packet,
>   	tcp_send->tcp_xsum = 0;
>   	tcp_send->tcp_ugr = 0;
>   	pkt_len = IP_TCP_HDR_SIZE + payload_len;
> -	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
> -						   tcp->ip_src,
> -						   tcp->ip_dst,
> +	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)ip_send,
> +						   ip->ip_src,
> +						   ip->ip_dst,
>   						   pkt_len - IP_HDR_SIZE,
>   						   pkt_len);
> -	net_set_ip_header((uchar *)tcp_send,
> -			  tcp->ip_src,
> -			  tcp->ip_dst,
> +	net_set_ip_header((uchar *)ip_send,
> +			  ip->ip_src,
> +			  ip->ip_dst,
>   			  pkt_len,
>   			  IPPROTO_TCP);
>   
> @@ -163,14 +169,14 @@ static int sb_http_handler(struct udevice *dev, void *packet,
>   {
>   	struct ethernet_hdr *eth = packet;
>   	struct ip_hdr *ip;
> -	struct ip_tcp_hdr *tcp;
> +	struct tcp_hdr *tcp;
>   
>   	if (ntohs(eth->et_protlen) == PROT_ARP) {
>   		return sb_arp_handler(dev, packet, len);
>   	} else if (ntohs(eth->et_protlen) == PROT_IP) {
>   		ip = packet + ETHER_HDR_SIZE;
>   		if (ip->ip_p == IPPROTO_TCP) {
> -			tcp = packet + ETHER_HDR_SIZE;
> +			tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE;
>   			if (tcp->tcp_flags == TCP_SYN)
>   				return sb_syn_handler(dev, packet, len);
>   			else if (tcp->tcp_flags & TCP_ACK && !(tcp->tcp_flags & TCP_SYN))

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

* Re: [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6
  2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
@ 2023-05-24 21:38   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  1 sibling, 0 replies; 21+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2023-05-24 21:38 UTC (permalink / raw)
  To: Dmitrii Merkurev, u-boot; +Cc: rammuthiah, rfried.dev, Simon Glass



On 2023/5/11 00:59, Dmitrii Merkurev wrote:
> Changes:
> 1. Separate reusable part from net_set_tcp_header to
> net_set_tcp_header_common
> 2. Make TCP signatures reusable by receiving particular
> IP agnostic TCP headers
> 3. Extract net_send_ip_packet6 from net_send_udp_packet6
> to reuse the code
> 4. Expose TCP state machine related functions
> 
> This allows us to reuse TCP logic between IP and IP6 stack.
> 
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>   include/net/tcp.h | 109 +++++++++++++--
>   net/net.c         |  18 ++-
>   net/net6.c        |  78 ++++++++---
>   net/tcp.c         | 337 ++++++++++++++++++++++++++++------------------
>   4 files changed, 372 insertions(+), 170 deletions(-)
> 
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 93ed728dfe..344b4be2a4 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -8,10 +8,20 @@
>   #ifndef __TCP_H__
>   #define __TCP_H__
>   
> +#include <net.h>
> +
>   #define TCP_ACTIVITY 127		/* Number of packets received   */
>   					/* before console progress mark */
>   
> +/*
> + * TCP lengths are stored as a rounded up number of 32 bit words.
> + * Add 3 to length round up, rounded, then divided into the
> + * length in 32 bit words.
> + */
> +#define LEN_B_TO_DW(x) ((x) >> 2)
> +#define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
>   #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
> +#define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
>   
>   /**
>    * struct tcp_hdr - TCP header
> @@ -24,7 +34,7 @@
>    * @tcp_win: TCP windows size
>    * @tcp_xsum: Checksum
>    * @tcp_ugr: Pointer to urgent data
> -*/
> + */
>   struct tcp_hdr {
>   	u16		tcp_src;
>   	u16		tcp_dst;
> @@ -163,18 +173,14 @@ struct tcp_t_opt {
>    */
>   
>   /**
> - * struct ip_tcp_hdr_o - IP + TCP header + TCP options
> - * @ip_hdr: IP + TCP header
> - * @tcp_hdr: TCP header
> + * struct tcp_hdr_o - TCP options
>    * @mss: TCP MSS Option
>    * @scale: TCP Windows Scale Option
>    * @sack_p: TCP Sack-Permitted Option
>    * @t_opt: TCP Timestamp Option
>    * @end: end of options
>    */
> -struct ip_tcp_hdr_o {
> -	struct	ip_hdr     ip_hdr;
> -	struct	tcp_hdr    tcp_hdr;
> +struct tcp_hdr_o {
>   	struct	tcp_mss	   mss;
>   	struct	tcp_scale  scale;
>   	struct	tcp_sack_p sack_p;
> @@ -182,6 +188,22 @@ struct ip_tcp_hdr_o {
>   	u8	end;
>   } __packed;
>   
> +#define TCP_O_SIZE (sizeof(struct tcp_hdr_o))
> +
> +/**
> + * struct ip_tcp_hdr_o - IP + TCP header + TCP options
> + * @ip_hdr: IP + TCP header
> + * @tcp_hdr: TCP header
> + * @tcp_o: TCP options
> + * @end: end of IP/TCP header
> + */
> +struct ip_tcp_hdr_o {
> +	struct  ip_hdr     ip_hdr;
> +	struct	tcp_hdr    tcp_hdr;
> +	struct  tcp_hdr_o  tcp_o;
> +	u8	end;
> +} __packed;
> +
>   #define IP_TCP_O_SIZE (sizeof(struct ip_tcp_hdr_o))
>   
>   /**
> @@ -209,7 +231,7 @@ struct ip_tcp_hdr_s {
>   
>   /**
>    * struct pseudo_hdr - Pseudo Header
> - * @padding: pseudo hdr size = ip_tcp hdr size
> + * @padding: pseudo hdr size = ip hdr size
>    * @p_src: Source IP address
>    * @p_dst: Destination IP address
>    * @rsvd: reserved
> @@ -236,7 +258,6 @@ struct pseudo_hdr {
>    *
>    * Build Pseudo header in packed buffer
>    * first, calculate TCP checksum, then build IP header in packed buffer.
> - *
>    */
>   union tcp_build_pkt {
>   	struct pseudo_hdr ph;
> @@ -269,9 +290,77 @@ enum tcp_state {
>   
>   enum tcp_state tcp_get_tcp_state(void);
>   void tcp_set_tcp_state(enum tcp_state new_state);
> -int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
> +
> +/**
> + * net_set_tcp_header_common() - IP version agnostic TCP header building implementation
> + *
> + * @tcp_hdr: pointer to TCP header struct
> + * @tcp_o: pointer to TCP options header struct
> + * @sack_t_opt: pointer to TCP sack options header struct
> + * @sack_v: pointer to TCP sack header struct
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: TCP payload len
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header
> + */
> +int net_set_tcp_header_common(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *tcp_o,
> +			      struct tcp_t_opt *sack_t_opt, struct tcp_sack_v *sack_v,
> +			      u16 dport, u16 sport, int payload_len, u8 action,
> +			      u32 tcp_seq_num, u32 tcp_ack_num);
> +
> +/**
> + * net_set_tcp_header() - IPv4 TCP header bulding implementation
> + *
> + * @pkt: pointer to the IP header
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: TCP payload len
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header
> + */
> +int net_set_tcp_header(uchar *pkt, u16 dport, u16 sport, int payload_len,
>   		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
>   
> +/**
> + * tcp_parse_options() - parsing TCP options
> + *
> + * @o: pointer to the option field.
> + * @o_len: length of the option field.
> + */
> +void tcp_parse_options(uchar *o, int o_len);
> +
> +/**
> + * tcp_state_machine() - update TCP state in a reaction to incoming packet
> + *
> + * @tcp_flags: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_seq_num_out: TCP sequential number we expect to answer with
> + * @tcp_ack_num_out: TCP acknowledgment number we expect to answer with
> + * @payload_len: TCP payload len
> + *
> + * returns TCP action we expect to answer with
> + */
> +u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, u32 *tcp_seq_num_out,
> +		     u32 *tcp_ack_num_out, int payload_len);
> +
> +/**
> + * tcp_sent_state_machine() - update TCP state in a reaction to outcoming packet
> + *
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP action we expect to answer with
> + */
> +u8 tcp_sent_state_machine(u8 action, u32 *tcp_seq_num, u32 *tcp_ack_num);
> +
>   /**
>    * rxhand_tcp() - An incoming packet handler.
>    * @pkt: pointer to the application packet
> diff --git a/net/net.c b/net/net.c
> index 43abbac7c3..0b68bf7b13 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -916,6 +916,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
>   {
>   	uchar *pkt;
>   	int eth_hdr_size;
> +	int ip_tcp_hdr_size;
>   	int pkt_hdr_size;
>   
>   	/* make sure the net_tx_packet is initialized (net_init() was called) */
> @@ -934,19 +935,24 @@ int net_send_ip_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_hdr_size = eth_hdr_size;
> +	pkt += eth_hdr_size;
>   
>   	switch (proto) {
>   	case IPPROTO_UDP:
> -		net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport,
> +		net_set_udp_header(pkt, dest, dport, sport,
>   				   payload_len);
> -		pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE;
> +		pkt_hdr_size += IP_UDP_HDR_SIZE;
>   		break;
>   #if defined(CONFIG_PROT_TCP)
>   	case IPPROTO_TCP:
> -		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);
> +		ip_tcp_hdr_size = IP_HDR_SIZE;
> +		ip_tcp_hdr_size += net_set_tcp_header(pkt, dport, sport,
> +						      payload_len, action, tcp_seq_num,
> +						      tcp_ack_num);
> +		net_set_ip_header(pkt, net_server_ip, net_ip,
> +				  ip_tcp_hdr_size + payload_len, IPPROTO_TCP);
> +		pkt_hdr_size += ip_tcp_hdr_size;
>   		break;
>   #endif
>   	default:
> diff --git a/net/net6.c b/net/net6.c
> index 2dd64c0e16..e395b930b0 100644
> --- a/net/net6.c
> +++ b/net/net6.c
> @@ -324,15 +324,13 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
>   	return sizeof(struct ip6_hdr);
>   }
>   
> -int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
> -			 int sport, int len)
> +int udp6_add_hdr(uchar *xip, struct in6_addr *dest, int dport, int sport,
> +		 int len)
>   {
> -	uchar *pkt;
>   	struct udp_hdr *udp;
>   	u16 csum_p;
>   
> -	udp = (struct udp_hdr *)((uchar *)net_tx_packet + net_eth_hdr_size() +
> -			IP6_HDR_SIZE);
> +	udp = (struct udp_hdr *)xip;
>   
>   	udp->udp_dst = htons(dport);
>   	udp->udp_src = htons(sport);
> @@ -344,39 +342,75 @@ int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
>   	udp->udp_xsum = csum_ipv6_magic(&net_ip6, dest, len + UDP_HDR_SIZE,
>   					IPPROTO_UDP, csum_p);
>   
> +	return sizeof(struct udp_hdr);
> +}
> +
> +int net_send_ip_packet6(uchar *ether, struct in6_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 ip_hdr_size;
> +	int udp_hdr_size;
> +	int tcp_hdr_size;
> +	int pkt_hdr_size;
> +
> +	if (!net_tx_packet)
> +		return -1;
> +
> +	pkt = (uchar *)net_tx_packet;
> +
> +	eth_hdr_size = net_set_ether(pkt, ether, PROT_IP6);
> +	pkt_hdr_size += eth_hdr_size;
> +	pkt = eth_hdr_size;
> +
> +	switch (proto) {
> +#if defined(CONFIG_PROT_UDP)
> +	case IPPROTO_UDP:
> +		ip_hdr_size = ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
> +					  payload_len + UDP_HDR_SIZE);
> +		pkt_hdr_size += ip_hdr_size;
> +		pkt += ip_hdr_size;
> +
> +		udp_hdr_size = udp6_add_hdr(pkt, dest, dport, sport, payload_len);
> +		pkt_hdr_size += udp_hdr_size;
> +		pkt += udp_hdr_size;
> +		break;
> +#endif
> +	default:
> +		return -EINVAL;
> +	}
> +
>   	/* if MAC address was not discovered yet, save the packet and do
>   	 * neighbour discovery
>   	 */
> -	if (!memcmp(ether, net_null_ethaddr, 6)) {
> +	if (memcmp(ether, net_null_ethaddr, 6) == 0) {
> +		memcpy((uchar *)net_nd_tx_packet,
> +		       (uchar *)net_tx_packet, pkt_hdr_size + payload_len);
> +		memset((uchar *)net_tx_packet, 0, pkt_hdr_size + payload_len);
> +
>   		net_copy_ip6(&net_nd_sol_packet_ip6, dest);
>   		net_nd_packet_mac = ether;
> -
> -		pkt = net_nd_tx_packet;
> -		pkt += net_set_ether(pkt, net_nd_packet_mac, PROT_IP6);
> -		pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
> -				len + UDP_HDR_SIZE);
> -		memcpy(pkt, (uchar *)udp, len + UDP_HDR_SIZE);
> -
>   		/* size of the waiting packet */
> -		net_nd_tx_packet_size = (pkt - net_nd_tx_packet) +
> -			UDP_HDR_SIZE + len;
> -
> -		/* and do the neighbor solicitation */
> +		net_nd_tx_packet_size = pkt_hdr_size + payload_len;
>   		net_nd_try = 1;
>   		net_nd_timer_start = get_timer(0);
>   		ndisc_request();
>   		return 1;	/* waiting */
>   	}
>   
> -	pkt = (uchar *)net_tx_packet;
> -	pkt += net_set_ether(pkt, ether, PROT_IP6);
> -	pkt += ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_UDP, 64,
> -			len + UDP_HDR_SIZE);
> -	(void)eth_send(net_tx_packet, pkt - net_tx_packet + UDP_HDR_SIZE + len);
> +	(void)eth_send(net_tx_packet, pkt_hdr_size + payload_len);
>   
>   	return 0;	/* transmitted */
>   }
>   
> +int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
> +			 int sport, int len)
> +{
> +	return net_send_ip_packet6(ether, dest, dport, sport, len, IPPROTO_UDP, 0, 0, 0);
> +}
> +
>   int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
>   {
>   	struct in_addr zero_ip = {.s_addr = 0 };
> diff --git a/net/tcp.c b/net/tcp.c
> index 10ce799814..483c03a595 100644
> --- a/net/tcp.c
> +++ b/net/tcp.c
> @@ -54,16 +54,6 @@ static struct sack_r edge_a[TCP_SACK];
>   static unsigned int sack_idx;
>   static unsigned int prev_len;
>   
> -/*
> - * TCP lengths are stored as a rounded up number of 32 bit words.
> - * Add 3 to length round up, rounded, then divided into the
> - * length in 32 bit words.
> - */
> -#define LEN_B_TO_DW(x) ((x) >> 2)
> -#define ROUND_TCPHDR_LEN(x) (LEN_B_TO_DW((x) + 3))
> -#define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
> -#define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
> -
>   /* TCP connection state */
>   static enum tcp_state current_tcp_state;
>   
> @@ -149,29 +139,32 @@ u16 tcp_set_pseudo_header(uchar *pkt, struct in_addr src, struct in_addr dest,
>   
>   /**
>    * net_set_ack_options() - set TCP options in acknowledge packets
> - * @b: the packet
> + * @tcp_hdr: pointer to TCP header struct
> + * @t_opt: pointer to TCP t opt header struct
> + * @sack_v: pointer to TCP sack header struct
>    *
>    * Return: TCP header length
>    */
> -int net_set_ack_options(union tcp_build_pkt *b)
> +int net_set_ack_options(struct tcp_hdr *tcp_hdr, struct tcp_t_opt *t_opt,
> +			struct tcp_sack_v *sack_v)
>   {
> -	b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
> +	tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
>   
> -	b->sack.t_opt.kind = TCP_O_TS;
> -	b->sack.t_opt.len = TCP_OPT_LEN_A;
> -	b->sack.t_opt.t_snd = htons(loc_timestamp);
> -	b->sack.t_opt.t_rcv = rmt_timestamp;
> -	b->sack.sack_v.kind = TCP_1_NOP;
> -	b->sack.sack_v.len = 0;
> +	t_opt->kind = TCP_O_TS;
> +	t_opt->len = TCP_OPT_LEN_A;
> +	t_opt->t_snd = htons(loc_timestamp);
> +	t_opt->t_rcv = rmt_timestamp;
> +	sack_v->kind = TCP_1_NOP;
> +	sack_v->len = 0;
>   
>   	if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
>   		if (tcp_lost.len > TCP_OPT_LEN_2) {
>   			debug_cond(DEBUG_DEV_PKT, "TCP ack opt lost.len %x\n",
>   				   tcp_lost.len);
> -			b->sack.sack_v.len = tcp_lost.len;
> -			b->sack.sack_v.kind = TCP_V_SACK;
> -			b->sack.sack_v.hill[0].l = htonl(tcp_lost.hill[0].l);
> -			b->sack.sack_v.hill[0].r = htonl(tcp_lost.hill[0].r);
> +			sack_v->len = tcp_lost.len;
> +			sack_v->kind = TCP_V_SACK;
> +			sack_v->hill[0].l = htonl(tcp_lost.hill[0].l);
> +			sack_v->hill[0].r = htonl(tcp_lost.hill[0].r);
>   
>   			/*
>   			 * These SACK structures are initialized with NOPs to
> @@ -179,21 +172,21 @@ int net_set_ack_options(union tcp_build_pkt *b)
>   			 * SACK structures used for both header padding and
>   			 * internally.
>   			 */
> -			b->sack.sack_v.hill[1].l = htonl(tcp_lost.hill[1].l);
> -			b->sack.sack_v.hill[1].r = htonl(tcp_lost.hill[1].r);
> -			b->sack.sack_v.hill[2].l = htonl(tcp_lost.hill[2].l);
> -			b->sack.sack_v.hill[2].r = htonl(tcp_lost.hill[2].r);
> -			b->sack.sack_v.hill[3].l = TCP_O_NOP;
> -			b->sack.sack_v.hill[3].r = TCP_O_NOP;
> +			sack_v->hill[1].l = htonl(tcp_lost.hill[1].l);
> +			sack_v->hill[1].r = htonl(tcp_lost.hill[1].r);
> +			sack_v->hill[2].l = htonl(tcp_lost.hill[2].l);
> +			sack_v->hill[2].r = htonl(tcp_lost.hill[2].r);
> +			sack_v->hill[3].l = TCP_O_NOP;
> +			sack_v->hill[3].r = TCP_O_NOP;
>   		}
>   
> -		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> -										 TCP_TSOPT_SIZE +
> -										 tcp_lost.len));
> +		tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> +									      TCP_TSOPT_SIZE +
> +									      tcp_lost.len));
>   	} else {
> -		b->sack.sack_v.kind = 0;
> -		b->sack.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> -										 TCP_TSOPT_SIZE));
> +		sack_v->kind = 0;
> +		tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(ROUND_TCPHDR_LEN(TCP_HDR_SIZE +
> +									      TCP_TSOPT_SIZE));
>   	}
>   
>   	/*
> @@ -201,69 +194,61 @@ int net_set_ack_options(union tcp_build_pkt *b)
>   	 * TCP header to add to the total packet length
>   	 */
>   
> -	return GET_TCP_HDR_LEN_IN_BYTES(b->sack.tcp_hdr.tcp_hlen);
> +	return GET_TCP_HDR_LEN_IN_BYTES(tcp_hdr->tcp_hlen);
>   }
>   
>   /**
>    * net_set_ack_options() - set TCP options in SYN packets
> - * @b: the packet
> + * @tcp_hdr: pointer to TCP header struct
> + * @options: pointer to TCP header options struct
>    */
> -void net_set_syn_options(union tcp_build_pkt *b)
> +void net_set_syn_options(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *options)
>   {
>   	if (IS_ENABLED(CONFIG_PROT_TCP_SACK))
>   		tcp_lost.len = 0;
>   
> -	b->ip.tcp_hdr.tcp_hlen = 0xa0;
> +	tcp_hdr->tcp_hlen = 0xa0;
>   
> -	b->ip.mss.kind = TCP_O_MSS;
> -	b->ip.mss.len = TCP_OPT_LEN_4;
> -	b->ip.mss.mss = htons(TCP_MSS);
> -	b->ip.scale.kind = TCP_O_SCL;
> -	b->ip.scale.scale = TCP_SCALE;
> -	b->ip.scale.len = TCP_OPT_LEN_3;
> +	options->mss.kind = TCP_O_MSS;
> +	options->mss.len = TCP_OPT_LEN_4;
> +	options->mss.mss = htons(TCP_MSS);
> +	options->scale.kind = TCP_O_SCL;
> +	options->scale.scale = TCP_SCALE;
> +	options->scale.len = TCP_OPT_LEN_3;
>   	if (IS_ENABLED(CONFIG_PROT_TCP_SACK)) {
> -		b->ip.sack_p.kind = TCP_P_SACK;
> -		b->ip.sack_p.len = TCP_OPT_LEN_2;
> +		options->sack_p.kind = TCP_P_SACK;
> +		options->sack_p.len = TCP_OPT_LEN_2;
>   	} else {
> -		b->ip.sack_p.kind = TCP_1_NOP;
> -		b->ip.sack_p.len = TCP_1_NOP;
> +		options->sack_p.kind = TCP_1_NOP;
> +		options->sack_p.len = TCP_1_NOP;
>   	}
> -	b->ip.t_opt.kind = TCP_O_TS;
> -	b->ip.t_opt.len = TCP_OPT_LEN_A;
> +	options->t_opt.kind = TCP_O_TS;
> +	options->t_opt.len = TCP_OPT_LEN_A;
>   	loc_timestamp = get_ticks();
>   	rmt_timestamp = 0;
> -	b->ip.t_opt.t_snd = 0;
> -	b->ip.t_opt.t_rcv = 0;
> -	b->ip.end = TCP_O_END;
> +
> +	options->t_opt.t_snd = 0;
> +	options->t_opt.t_rcv = 0;
>   }
>   
> -int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
> -		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
> +/**
> + * tcp_sent_state_machine() - update TCP state in a reaction to outcoming packet
> + *
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP action we expect to answer with
> + */
> +u8 tcp_sent_state_machine(u8 action, u32 *tcp_seq_num, u32 *tcp_ack_num)
>   {
> -	union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
> -	int pkt_hdr_len;
> -	int pkt_len;
> -	int tcp_len;
> -
> -	/*
> -	 * Header: 5 32 bit words. 4 bits TCP header Length,
> -	 *         4 bits reserved options
> -	 */
> -	b->ip.tcp_hdr.tcp_flags = action;
> -	pkt_hdr_len = IP_TCP_HDR_SIZE;
> -	b->ip.tcp_hdr.tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
> -
>   	switch (action) {
>   	case TCP_SYN:
>   		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:SYN (%pI4, %pI4, sq=%u, ak=%u)\n",
> -			   &net_server_ip, &net_ip,
> -			   tcp_seq_num, tcp_ack_num);
> +			   "TCP Hdr:SYN (sq=%u, ak=%u)\n", *tcp_seq_num, *tcp_ack_num);
>   		tcp_activity_count = 0;
> -		net_set_syn_options(b);
> -		tcp_seq_num = 0;
> -		tcp_ack_num = 0;
> -		pkt_hdr_len = IP_TCP_O_SIZE;
> +		*tcp_seq_num = 0;
> +		*tcp_ack_num = 0;
>   		if (current_tcp_state == TCP_SYN_SENT) {  /* Too many SYNs */
>   			action = TCP_FIN;
>   			current_tcp_state = TCP_FIN_WAIT_1;
> @@ -273,57 +258,93 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   		break;
>   	case TCP_SYN | TCP_ACK:
>   	case TCP_ACK:
> -		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
> -		b->ip.tcp_hdr.tcp_flags = action;
>   		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:ACK (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
> -			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num,
> -			   action);
> +			   "TCP Hdr:ACK (s=%u, a=%u, A=%x)\n",
> +			   *tcp_seq_num, *tcp_ack_num, action);
>   		break;
>   	case TCP_FIN:
>   		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:FIN  (%pI4, %pI4, s=%u, a=%u)\n",
> -			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num);
> -		payload_len = 0;
> -		pkt_hdr_len = IP_TCP_HDR_SIZE;
> +			   "TCP Hdr:FIN  (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
>   		current_tcp_state = TCP_FIN_WAIT_1;
>   		break;
>   	case TCP_RST | TCP_ACK:
>   	case TCP_RST:
>   		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:RST  (%pI4, %pI4, s=%u, a=%u)\n",
> -			   &net_server_ip, &net_ip, tcp_seq_num, tcp_ack_num);
> +			   "TCP Hdr:RST  (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
>   		current_tcp_state = TCP_CLOSED;
>   		break;
>   	/* Notify connection closing */
>   	case (TCP_FIN | TCP_ACK):
>   	case (TCP_FIN | TCP_ACK | TCP_PUSH):
> +		debug_cond(DEBUG_DEV_PKT,
> +			   "TCP Hdr:FIN ACK PSH(s=%u, a=%u, A=%x)\n",
> +			   *tcp_seq_num, *tcp_ack_num, action);
>   		if (current_tcp_state == TCP_CLOSE_WAIT)
>   			current_tcp_state = TCP_CLOSING;
> -
> -		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n",
> -			   &net_server_ip, &net_ip,
> -			   tcp_seq_num, tcp_ack_num, action);
>   		fallthrough;
>   	default:
> -		pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
> -		b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
> +		action = action | TCP_PUSH | TCP_ACK;
>   		debug_cond(DEBUG_DEV_PKT,
> -			   "TCP Hdr:dft  (%pI4, %pI4, s=%u, a=%u, A=%x)\n",
> -			   &net_server_ip, &net_ip,
> -			   tcp_seq_num, tcp_ack_num, action);
> +			   "TCP Hdr:dft  (s=%u, a=%u, A=%x)\n",
> +			   *tcp_seq_num, *tcp_ack_num, action);
>   	}
>   
> -	pkt_len	= pkt_hdr_len + payload_len;
> -	tcp_len	= pkt_len - IP_HDR_SIZE;
> +	return action;
> +}
> +
> +/**
> + * net_set_tcp_header_common() - IP version agnostic TCP header building implementation
> + *
> + * @tcp_hdr: pointer to TCP header struct
> + * @tcp_o: pointer to TCP options header struct
> + * @sack_t_opt: pointer to TCP sack options header struct
> + * @sack_v: pointer to TCP sack header struct
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: TCP payload len
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header size
> + */
> +int net_set_tcp_header_common(struct tcp_hdr *tcp_hdr, struct tcp_hdr_o *tcp_o,
> +			      struct tcp_t_opt *sack_t_opt, struct tcp_sack_v *sack_v,
> +			      u16 dport, u16 sport, int payload_len, u8 action,
> +			      u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> +	u8  tcp_action = TCP_DATA;
> +	int tcp_hdr_len;
> +
> +	/*
> +	 * Header: 5 32 bit words. 4 bits TCP header Length,
> +	 *         4 bits reserved options
> +	 */
> +	tcp_hdr_len = TCP_HDR_SIZE;
> +	tcp_hdr->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
> +
> +	switch (action) {
> +	case TCP_SYN:
> +		net_set_syn_options(tcp_hdr, tcp_o);
> +		tcp_hdr_len = TCP_HDR_SIZE + TCP_O_SIZE;
> +		break;
> +	case TCP_RST | TCP_ACK:
> +	case TCP_RST:
> +	case TCP_FIN:
> +		payload_len = 0;
> +		break;
> +	default:
> +		tcp_hdr_len = net_set_ack_options(tcp_hdr, sack_t_opt, sack_v);
> +	}
> +
> +	tcp_action = tcp_sent_state_machine(action, &tcp_seq_num, &tcp_ack_num);
> +	tcp_hdr->tcp_flags = tcp_action;
>   
>   	tcp_ack_edge = tcp_ack_num;
> -	/* TCP Header */
> -	b->ip.tcp_hdr.tcp_ack = htonl(tcp_ack_edge);
> -	b->ip.tcp_hdr.tcp_src = htons(sport);
> -	b->ip.tcp_hdr.tcp_dst = htons(dport);
> -	b->ip.tcp_hdr.tcp_seq = htonl(tcp_seq_num);
> +	tcp_hdr->tcp_ack = htonl(tcp_ack_edge);
> +	tcp_hdr->tcp_seq = htonl(tcp_seq_num);
> +	tcp_hdr->tcp_src = htons(sport);
> +	tcp_hdr->tcp_dst = htons(dport);
>   
>   	/*
>   	 * TCP window size - TCP header variable tcp_win.
> @@ -340,18 +361,46 @@ int tcp_set_tcp_header(uchar *pkt, int dport, int sport, int payload_len,
>   	 * it is, then the u-boot tftp or nfs kernel netboot should be
>   	 * considered.
>   	 */
> -	b->ip.tcp_hdr.tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
> +	tcp_hdr->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
>   
> -	b->ip.tcp_hdr.tcp_xsum = 0;
> -	b->ip.tcp_hdr.tcp_ugr = 0;
> +	tcp_hdr->tcp_xsum = 0;
> +	tcp_hdr->tcp_ugr = 0;
>   
> -	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
> -						       tcp_len, pkt_len);
> +	return tcp_hdr_len;
> +}
>   
> -	net_set_ip_header((uchar *)&b->ip, net_server_ip, net_ip,
> -			  pkt_len, IPPROTO_TCP);
> +/**
> + * net_set_tcp_header() - IPv4 TCP header bulding implementation
> + *
> + * @pkt: pointer to the IP header
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: TCP payload len
> + * @action: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header + payload size
> + */
> +int net_set_tcp_header(uchar *pkt, u16 dport, u16 sport, int payload_len,
> +		       u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> +	union tcp_build_pkt *b = (union tcp_build_pkt *)pkt;
> +	int tcp_hdr_len;
> +	int pkt_len;
>   
> -	return pkt_hdr_len;
> +	pkt_len = IP_HDR_SIZE;
> +	tcp_hdr_len = net_set_tcp_header_common(&b->ip.tcp_hdr, &b->ip.tcp_o,
> +						&b->sack.t_opt, &b->sack.sack_v,
> +						dport, sport, payload_len, action,
> +						tcp_seq_num, tcp_ack_num);
> +	pkt_len += tcp_hdr_len;
> +	pkt_len += payload_len;
> +
> +	b->ip.tcp_hdr.tcp_xsum = tcp_set_pseudo_header(pkt, net_ip, net_server_ip,
> +						       tcp_hdr_len + payload_len, pkt_len);
> +
> +	return tcp_hdr_len;
>   }
>   
>   /**
> @@ -500,7 +549,31 @@ void tcp_parse_options(uchar *o, int o_len)
>   	}
>   }
>   
> -static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
> +static void init_sack_options(u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> +	tcp_seq_init = tcp_seq_num;
> +	tcp_ack_edge = tcp_ack_num;
> +	sack_idx = 0;
> +	edge_a[sack_idx].se.l = tcp_ack_edge;
> +	edge_a[sack_idx].se.r = tcp_ack_edge;
> +	prev_len = 0;
> +	for (int i = 0; i < TCP_SACK; i++)
> +		edge_a[i].st = NOPKT;
> +}
> +
> +/**
> + * tcp_state_machine() - update TCP state in a reaction to incoming request
> + *
> + * @tcp_flags: TCP action (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_seq_num_out: TCP sequential number we expect to answer with
> + * @tcp_ack_num_out: TCP acknowledgment number we expect to answer with
> + * @payload_len: TCP payload len
> + *
> + * returns TCP action we expect to answer with
> + */
> +u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, u32 *tcp_seq_num_out,
> +		     u32 *tcp_ack_num_out, int payload_len)
>   {
>   	u8 tcp_fin = tcp_flags & TCP_FIN;
>   	u8 tcp_syn = tcp_flags & TCP_SYN;
> @@ -508,7 +581,6 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
>   	u8 tcp_push = tcp_flags & TCP_PUSH;
>   	u8 tcp_ack = tcp_flags & TCP_ACK;
>   	u8 action = TCP_DATA;
> -	int i;
>   
>   	/*
>   	 * tcp_flags are examined to determine TX action in a given state
> @@ -533,34 +605,29 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
>   		debug_cond(DEBUG_INT_STATE, "TCP CLOSED %x\n", tcp_flags);
>   		if (tcp_syn) {
>   			action = TCP_SYN | TCP_ACK;
> -			tcp_seq_init = tcp_seq_num;
> -			tcp_ack_edge = tcp_seq_num + 1;
> +			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
>   			current_tcp_state = TCP_SYN_RECEIVED;
>   		} else if (tcp_ack || tcp_fin) {
>   			action = TCP_DATA;
>   		}
>   		break;
>   	case TCP_SYN_RECEIVED:
> +		if (tcp_ack) {
> +			action = TCP_DATA;
> +			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
> +			current_tcp_state = TCP_ESTABLISHED;
> +		}
> +		break;
>   	case TCP_SYN_SENT:
>   		debug_cond(DEBUG_INT_STATE, "TCP_SYN_SENT | TCP_SYN_RECEIVED %x, %u\n",
>   			   tcp_flags, tcp_seq_num);
>   		if (tcp_fin) {
>   			action = action | TCP_PUSH;
>   			current_tcp_state = TCP_CLOSE_WAIT;
> -		} else if (tcp_ack || (tcp_syn && tcp_ack)) {
> -			action |= TCP_ACK;
> -			tcp_seq_init = tcp_seq_num;
> -			tcp_ack_edge = tcp_seq_num + 1;
> -			sack_idx = 0;
> -			edge_a[sack_idx].se.l = tcp_ack_edge;
> -			edge_a[sack_idx].se.r = tcp_ack_edge;
> -			prev_len = 0;
> +		} else if (tcp_syn && tcp_ack) {
> +			action |= TCP_ACK | TCP_PUSH;
> +			init_sack_options(tcp_seq_num, tcp_seq_num + 1);
>   			current_tcp_state = TCP_ESTABLISHED;
> -			for (i = 0; i < TCP_SACK; i++)
> -				edge_a[i].st = NOPKT;
> -
> -			if (tcp_syn && tcp_ack)
> -				action |= TCP_PUSH;
>   		} else {
>   			action = TCP_DATA;
>   		}
> @@ -627,6 +694,10 @@ static u8 tcp_state_machine(u8 tcp_flags, u32 tcp_seq_num, int payload_len)
>   		}
>   		break;
>   	}
> +
> +	*tcp_seq_num_out = tcp_seq_num;
> +	*tcp_ack_num_out = tcp_ack_edge;
> +
>   	return action;
>   }
>   
> @@ -641,6 +712,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   	u16 tcp_rx_xsum = b->ip.ip_hdr.ip_sum;
>   	u8  tcp_action = TCP_DATA;
>   	u32 tcp_seq_num, tcp_ack_num;
> +	u32 res_tcp_seq_num, res_tcp_ack_num;
>   	int tcp_hdr_len, payload_len;
>   
>   	/* Verify IP header */
> @@ -685,7 +757,8 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   
>   	/* Packets are not ordered. Send to app as received. */
>   	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
> -				       tcp_seq_num, payload_len);
> +				       tcp_seq_num, &res_tcp_seq_num,
> +				       &res_tcp_ack_num, payload_len);
>   
>   	tcp_activity_count++;
>   	if (tcp_activity_count > TCP_ACTIVITY) {
> @@ -705,7 +778,7 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   	} else if (tcp_action != TCP_DATA) {
>   		debug_cond(DEBUG_DEV_PKT,
>   			   "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
> -			   tcp_action, tcp_ack_num, tcp_ack_edge, payload_len);
> +			   tcp_action, res_tcp_seq_num, res_tcp_ack_num, payload_len);
>   
>   		/*
>   		 * Warning: Incoming Ack & Seq sequence numbers are transposed
> @@ -714,6 +787,6 @@ void rxhand_tcp_f(union tcp_build_pkt *b, unsigned int pkt_len)
>   		net_send_tcp_packet(0, ntohs(b->ip.tcp_hdr.tcp_src),
>   				    ntohs(b->ip.tcp_hdr.tcp_dst),
>   				    (tcp_action & (~TCP_PUSH)),
> -				    tcp_ack_num, tcp_ack_edge);
> +				    res_tcp_seq_num, res_tcp_ack_num);
>   	}
>   }

Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>

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

* Re: [PATCH v2 3/6] net: introduce TCP/IP6 support
  2023-05-10 16:59 ` [PATCH v2 3/6] net: introduce TCP/IP6 support Dmitrii Merkurev
@ 2023-05-25  4:52   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  1 sibling, 0 replies; 21+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2023-05-25  4:52 UTC (permalink / raw)
  To: Dmitrii Merkurev, u-boot; +Cc: rammuthiah, rfried.dev, Simon Glass



On 2023/5/11 00:59, Dmitrii Merkurev wrote:
> Add TCP/IP6 related headers and reuse refactored TCP/IP
> implementation
> 
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>   include/net/tcp6.h | 106 +++++++++++++++++++++++++++++++++++++++++++++
>   include/net6.h     |  14 ++++++
>   net/Makefile       |   1 +
>   net/net.c          |   6 +++
>   net/net6.c         |  72 +++++++++++++++++++++++++-----
>   net/tcp6.c         |  99 ++++++++++++++++++++++++++++++++++++++++++
>   6 files changed, 288 insertions(+), 10 deletions(-)
>   create mode 100644 include/net/tcp6.h
>   create mode 100644 net/tcp6.c
> 
> diff --git a/include/net/tcp6.h b/include/net/tcp6.h
> new file mode 100644
> index 0000000000..3db125ecc5
> --- /dev/null
> +++ b/include/net/tcp6.h
> @@ -0,0 +1,106 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2022 The Android Open Source Project
> + */
> +
> +#ifndef __TCP6_H__
> +#define __TCP6_H__
> +
> +#if defined(CONFIG_PROT_TCP)
> +
> +#include <net6.h>
> +#include <net/tcp.h>
> +
> +/**
> + * typedef rxhand_tcp6_f() - An incoming TCP IPv6 packet handler.
> + * @pkt: pointer to the application packet
> + * @dport: destination TCP port
> + * @sip: source IP6 address
> + * @sport: source TCP port
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + * @action: TCP packet type (SYN, ACK, FIN, etc)
> + */
> +typedef void rxhand_tcp6_f(uchar *pkt, u16 dport,
> +			   struct in6_addr sip, u16 sport,
> +			   u32 tcp_seq_num, u32 tcp_ack_num,
> +			   u8 action, unsigned int len);
> +
> +/**
> + * struct ip6_tcp_hdr_o - IP6 + TCP header + TCP options
> + * @ip_hdr: IP6 + TCP header
> + * @tcp_hdr: TCP header
> + * @tcp_o: TCP options
> + * @end: end of IP6/TCP header
> + */
> +struct ip6_tcp_hdr_o {
> +	struct  ip6_hdr    ip_hdr;
> +	struct  tcp_hdr    tcp_hdr;
> +	struct  tcp_hdr_o  tcp_o;
> +	u8	end;
> +} __packed;
> +
> +#define IP6_TCP_O_SIZE (sizeof(struct ip6_tcp_hdr_o))
> +
> +/**
> + * struct ip6_tcp_hdr_s - IP6 + TCP header + TCP options
> + * @ip_hdr: IP6 + TCP header
> + * @tcp_hdr: TCP header
> + * @t_opt: TCP Timestamp Option
> + * @sack_v: TCP SACK Option
> + * @end: end of options
> + */
> +struct ip6_tcp_hdr_s {
> +	struct  ip6_hdr    ip_hdr;
> +	struct  tcp_hdr    tcp_hdr;
> +	struct  tcp_t_opt  t_opt;
> +	struct  tcp_sack_v sack_v;
> +	u8	end;
> +} __packed;
> +
> +#define IP6_TCP_SACK_SIZE (sizeof(struct ip6_tcp_hdr_s))
> +
> +/**
> + * union tcp6_build_pkt - union for building TCP/IP6 packet.
> + * @ip: IP6 and TCP header plus TCP options
> + * @sack: IP6 and TCP header plus SACK options
> + * @raw: buffer
> + */
> +union tcp6_build_pkt {
> +	struct ip6_tcp_hdr_o ip;
> +	struct ip6_tcp_hdr_s sack;
> +	uchar  raw[1600];
> +} __packed;
> +
> +/**
> + * net_set_tcp6_handler6() - set application TCP6 packet handler
> + * @param f pointer to callback function
> + */
> +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> +
> +/**
> + * net_set_tcp_header6() - set
> + * @pkt: pointer to IP6/TCP headers
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: payload length
> + * @action: TCP packet type (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header size
> + */
> +int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
> +			u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
> +
> +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> +
> +/**
> + * rxhand_tcp6() - handle incoming IP6 TCP packet
> + * @param b pointer to IP6/TCP packet builder struct
> + * @param len full packet length
> + */
> +void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len);
> +
> +#endif // CONFIG_PROT_TCP
> +#endif // __TCP6_H__
> diff --git a/include/net6.h b/include/net6.h
> index beafc05338..fa926f07ac 100644
> --- a/include/net6.h
> +++ b/include/net6.h
> @@ -344,6 +344,20 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
>   int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
>   			 int sport, int len);
>   
> +/**
> + * net_send_tcp_packet6() - Make up TCP packet and send it
> + *
> + * @payload_len: TCP payload length
> + * @dport:	 destination port
> + * @sport:	 source port
> + * @action:	 TCP flag (SYN, ACL, PUSH, etc)
> + * @tcp_seq_num: TCP sequence number
> + * @tcp_ack_num: TCP ackno
> + * Return: 0 if send successfully, -1 otherwise
> + */
> +int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
> +			 u32 tcp_seq_num, u32 tcp_ack_num);
> +
>   /**
>    * net_ip6_handler() - Handle IPv6 packet
>    *
> diff --git a/net/Makefile b/net/Makefile
> index 3e2d061338..002b0f68a2 100644
> --- a/net/Makefile
> +++ b/net/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_TCP_FUNCTION_FASTBOOT)  += fastboot_tcp.o
>   obj-$(CONFIG_CMD_WOL)  += wol.o
>   obj-$(CONFIG_PROT_UDP) += udp.o
>   obj-$(CONFIG_PROT_TCP) += tcp.o
> +obj-$(CONFIG_IPV6) += tcp6.o
>   obj-$(CONFIG_CMD_WGET) += wget.o
>   
>   # Disable this warning as it is triggered by:
> diff --git a/net/net.c b/net/net.c
> index 0b68bf7b13..9ef290dc41 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -92,6 +92,7 @@
>   #include <log.h>
>   #include <net.h>
>   #include <net6.h>
> +#include <net/tcp6.h>
>   #include <ndisc.h>
>   #include <net/fastboot_udp.h>
>   #include <net/fastboot_tcp.h>
> @@ -386,6 +387,9 @@ static void net_clear_handlers(void)
>   	net_set_udp_handler(NULL);
>   	net_set_arp_handler(NULL);
>   	net_set_timeout_handler(0, NULL);
> +#if defined(CONFIG_IPV6) && defined(CONFIG_PROT_TCP)
> +	net_set_tcp_handler6(NULL);
> +#endif
>   }
>   
>   static void net_cleanup_loop(void)
> @@ -916,7 +920,9 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport,
>   {
>   	uchar *pkt;
>   	int eth_hdr_size;
> +#if defined(CONFIG_PROT_TCP)
>   	int ip_tcp_hdr_size;
> +#endif
>   	int pkt_hdr_size;
>   
>   	/* make sure the net_tx_packet is initialized (net_init() was called) */
> diff --git a/net/net6.c b/net/net6.c
> index e395b930b0..575726766e 100644
> --- a/net/net6.c
> +++ b/net/net6.c
> @@ -14,6 +14,7 @@
>   #include <malloc.h>
>   #include <net.h>
>   #include <net6.h>
> +#include <net/tcp6.h>
>   #include <ndisc.h>
>   
>   /* NULL IPv6 address */
> @@ -350,11 +351,17 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
>   			u32 tcp_ack_num)
>   {
>   	uchar *pkt;
> +	int pkt_hdr_size;
>   	int eth_hdr_size;
> +#if defined(CONFIG_PROT_UDP) || defined(CONFIG_PROT_TCP)
>   	int ip_hdr_size;
> +#endif
> +#if defined(CONFIG_PROT_UDP)
>   	int udp_hdr_size;
> +#endif
> +#if defined(CONFIG_PROT_TCP)
>   	int tcp_hdr_size;
> -	int pkt_hdr_size;
> +#endif
>   
>   	if (!net_tx_packet)
>   		return -1;
> @@ -362,8 +369,8 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
>   	pkt = (uchar *)net_tx_packet;
>   
>   	eth_hdr_size = net_set_ether(pkt, ether, PROT_IP6);
> -	pkt_hdr_size += eth_hdr_size;
> -	pkt = eth_hdr_size;
> +	pkt_hdr_size = eth_hdr_size;
> +	pkt += eth_hdr_size;
>   
>   	switch (proto) {
>   #if defined(CONFIG_PROT_UDP)
> @@ -377,6 +384,18 @@ int net_send_ip_packet6(uchar *ether, struct in6_addr *dest, int dport, int spor
>   		pkt_hdr_size += udp_hdr_size;
>   		pkt += udp_hdr_size;
>   		break;
> +#endif
> +#if defined(CONFIG_PROT_TCP)
> +	case IPPROTO_TCP:
> +		tcp_hdr_size = net_set_tcp_header6(pkt, dport, sport,
> +						   payload_len, action, tcp_seq_num,
> +						   tcp_ack_num);
> +		ip_hdr_size = ip6_add_hdr(pkt, &net_ip6, dest, IPPROTO_TCP, 64,
> +					  tcp_hdr_size + payload_len);
> +
> +		pkt_hdr_size += ip_hdr_size + tcp_hdr_size;
> +		pkt += ip_hdr_size + tcp_hdr_size;
> +		break;
>   #endif
>   	default:
>   		return -EINVAL;
> @@ -411,11 +430,25 @@ int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
>   	return net_send_ip_packet6(ether, dest, dport, sport, len, IPPROTO_UDP, 0, 0, 0);
>   }
>   
> +int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
> +			 u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> +	return net_send_ip_packet6(net_server_ethaddr, &net_server_ip6, dport,
> +				   sport, payload_len, IPPROTO_TCP, action,
> +				   tcp_seq_num, tcp_ack_num);
> +}
> +
>   int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
>   {
> -	struct in_addr zero_ip = {.s_addr = 0 };
>   	struct icmp6hdr *icmp;
> +#if defined(CONFIG_PROT_UDP)
> +	struct in_addr zero_ip = {.s_addr = 0 };
>   	struct udp_hdr *udp;
> +#endif
> +#if defined(CONFIG_PROT_TCP)
> +	union tcp6_build_pkt *tcp_headers;
> +	struct tcp_hdr *tcp;
> +#endif
>   	u16 csum;
>   	u16 csum_p;
>   	u16 hlen;
> @@ -454,6 +487,7 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
>   			break;
>   		}
>   		break;
> +#if defined(CONFIG_PROT_UDP)
>   	case IPPROTO_UDP:
>   		udp = (struct udp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
>   		csum = udp->udp_xsum;
> @@ -468,13 +502,31 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
>   			return -EINVAL;
>   
>   		/* IP header OK. Pass the packet to the current handler. */
> -		net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE +
> -					UDP_HDR_SIZE,
> -				ntohs(udp->udp_dst),
> -				zero_ip,
> -				ntohs(udp->udp_src),
> -				ntohs(udp->udp_len) - 8);
> +		net_get_udp_handler()((uchar *)ip6 + IP6_HDR_SIZE + UDP_HDR_SIZE,
> +				      ntohs(udp->udp_dst),
> +				      zero_ip,
> +				      ntohs(udp->udp_src),
> +				      ntohs(udp->udp_len) - 8);
> +		break;
> +#endif
> +#if defined(CONFIG_PROT_TCP)
> +	case IPPROTO_TCP:
> +		tcp = (struct tcp_hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
> +		csum = tcp->tcp_xsum;
> +		hlen = ntohs(ip6->payload_len);
> +		tcp->tcp_xsum = 0;
> +		/* checksum */
> +		csum_p = csum_partial((u8 *)tcp, hlen, 0);
> +		tcp->tcp_xsum = csum_ipv6_magic(&ip6->saddr, &ip6->daddr,
> +						hlen, IPPROTO_TCP, csum_p);
> +
> +		if (csum != tcp->tcp_xsum)
> +			return -EINVAL;
> +
> +		tcp_headers = (union tcp6_build_pkt *)ip6;
> +		rxhand_tcp6(tcp_headers, len);
>   		break;
> +#endif
>   	default:
>   		return -EINVAL;
>   	}
> diff --git a/net/tcp6.c b/net/tcp6.c
> new file mode 100644
> index 0000000000..09b2190db7
> --- /dev/null
> +++ b/net/tcp6.c
> @@ -0,0 +1,99 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2022 The Android Open Source Project
> + */
> +
> +#if defined(CONFIG_PROT_TCP)
> +
> +#include <common.h>
> +#include <net/tcp.h>
> +#include <net/tcp6.h>
> +#include <net6.h>
> +
> +static rxhand_tcp6_f *tcp6_packet_handler;
> +
> +static void dummy_handler(uchar *pkt, u16 dport,
> +			  struct in6_addr sip, u16 sport,
> +			  u32 tcp_seq_num, u32 tcp_ack_num,
> +			  u8 action, unsigned int len)
> +{
> +}
> +
> +void net_set_tcp_handler6(rxhand_tcp6_f *f)
> +{
> +	if (!f)
> +		tcp6_packet_handler = dummy_handler;
> +	else
> +		tcp6_packet_handler = f;
> +}
> +
> +int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
> +			u8 action, u32 tcp_seq_num, u32 tcp_ack_num)
> +{
> +	union tcp6_build_pkt *b = (union tcp6_build_pkt *)pkt;
> +	int tcp_hdr_len;
> +	int pkt_len;
> +	u16 csum;
> +
> +	pkt_len = IP6_HDR_SIZE;
> +	tcp_hdr_len = net_set_tcp_header_common(&b->ip.tcp_hdr, &b->ip.tcp_o,
> +						&b->sack.t_opt, &b->sack.sack_v,
> +						dport, sport, payload_len, action,
> +						tcp_seq_num, tcp_ack_num);
> +	pkt_len += tcp_hdr_len;
> +	pkt_len += payload_len;
> +
> +	csum = csum_partial((u8 *)&b->ip.tcp_hdr, tcp_hdr_len + payload_len, 0);
> +	b->ip.tcp_hdr.tcp_xsum = csum_ipv6_magic(&net_ip6, &net_server_ip6,
> +						 tcp_hdr_len + payload_len,
> +						 IPPROTO_TCP, csum);
> +
> +	return tcp_hdr_len;
> +}
> +
> +void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len)
> +{
> +	int tcp_len = len - IP6_HDR_SIZE;
> +	u8  tcp_action = TCP_DATA;
> +	u32 tcp_seq_num, tcp_ack_num;
> +	u32 res_tcp_seq_num, res_tcp_ack_num;
> +	int tcp_hdr_len, payload_len;
> +
> +	net_copy_ip6(&net_server_ip6, &b->ip.ip_hdr.saddr);
> +
> +	tcp_hdr_len = GET_TCP_HDR_LEN_IN_BYTES(b->ip.tcp_hdr.tcp_hlen);
> +	payload_len = tcp_len - tcp_hdr_len;
> +
> +	if (tcp_hdr_len > TCP_HDR_SIZE)
> +		tcp_parse_options((uchar *)b + IP6_HDR_SIZE + TCP_HDR_SIZE,
> +				  tcp_hdr_len - TCP_HDR_SIZE);
> +
> +	tcp_seq_num = ntohl(b->ip.tcp_hdr.tcp_seq);
> +	tcp_ack_num = ntohl(b->ip.tcp_hdr.tcp_ack);
> +
> +	tcp_action = tcp_state_machine(b->ip.tcp_hdr.tcp_flags,
> +				       tcp_seq_num, &res_tcp_seq_num, &res_tcp_ack_num,
> +				       payload_len);
> +
> +	if ((tcp_action & TCP_PUSH) || payload_len > 0) {
> +		debug_cond(DEBUG_DEV_PKT,
> +			   "TCP Notify (action=%x, Seq=%u,Ack=%u,Pay%d)\n",
> +			   tcp_action, tcp_seq_num, tcp_ack_num, payload_len);
> +
> +		(*tcp6_packet_handler) ((uchar *)b + len - payload_len, b->ip.tcp_hdr.tcp_dst,
> +					b->ip.ip_hdr.saddr, b->ip.tcp_hdr.tcp_src, tcp_seq_num,
> +					tcp_ack_num, tcp_action, payload_len);
> +
> +	} else if (tcp_action != TCP_DATA) {
> +		debug_cond(DEBUG_DEV_PKT,
> +			   "TCP Action (action=%x,Seq=%u,Ack=%u,Pay=%d)\n",
> +			   tcp_action, res_tcp_seq_num, res_tcp_ack_num, payload_len);
> +
> +		net_send_tcp_packet6(0, ntohs(b->ip.tcp_hdr.tcp_src),
> +				     ntohs(b->ip.tcp_hdr.tcp_dst),
> +				     (tcp_action & (~TCP_PUSH)),
> +				     res_tcp_seq_num, res_tcp_ack_num);
> +	}
> +}
> +
> +#endif // CONFIG_PROT_TCP

Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>

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

* Re: [PATCH v2 4/6] net: add fastboot TCP6 support
  2023-05-10 16:59 ` [PATCH v2 4/6] net: add fastboot TCP6 support Dmitrii Merkurev
@ 2023-07-03 15:48   ` Paul Liu
  2023-07-23  3:48   ` Simon Glass
  1 sibling, 0 replies; 21+ messages in thread
From: Paul Liu @ 2023-07-03 15:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Simon Glass

Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>


On Thu, 11 May 2023 at 01:00, Dmitrii Merkurev <dimorinny@google.com> wrote:

> fastboot tcp command remains the same, but started
> listening IP6 in case it's enabled.
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  include/net/fastboot_tcp.h |  2 +-
>  net/fastboot_tcp.c         | 72 ++++++++++++++++++++++++++++++++------
>  2 files changed, 62 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/fastboot_tcp.h b/include/net/fastboot_tcp.h
> index 6cf29d52e9..98986fa10a 100644
> --- a/include/net/fastboot_tcp.h
> +++ b/include/net/fastboot_tcp.h
> @@ -7,7 +7,7 @@
>  #define __NET_FASTBOOT_TCP_H__
>
>  /**
> - * Wait for incoming tcp fastboot comands.
> + * Wait for incoming TCP fastboot comands.
>   */
>  void fastboot_tcp_start_server(void);
>
> diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c
> index 2eb52ea256..d93b52ede5 100644
> --- a/net/fastboot_tcp.c
> +++ b/net/fastboot_tcp.c
> @@ -6,8 +6,10 @@
>  #include <common.h>
>  #include <fastboot.h>
>  #include <net.h>
> +#include <net6.h>
>  #include <net/fastboot_tcp.h>
>  #include <net/tcp.h>
> +#include <net/tcp6.h>
>
>  static char command[FASTBOOT_COMMAND_LEN] = {0};
>  static char response[FASTBOOT_RESPONSE_LEN] = {0};
> @@ -20,18 +22,30 @@ static u16 curr_dport;
>  static u32 curr_tcp_seq_num;
>  static u32 curr_tcp_ack_num;
>  static unsigned int curr_request_len;
> +static bool is_ipv6;
> +static size_t ip_header_size;
>  static enum fastboot_tcp_state {
>         FASTBOOT_CLOSED,
>         FASTBOOT_CONNECTED,
>         FASTBOOT_DISCONNECTING
>  } state = FASTBOOT_CLOSED;
>
> +static int command_handled_id;
> +static bool command_handled_success;
> +
>  static void fastboot_tcp_answer(u8 action, unsigned int len)
>  {
>         const u32 response_seq_num = curr_tcp_ack_num;
>         const u32 response_ack_num = curr_tcp_seq_num +
>                   (curr_request_len > 0 ? curr_request_len : 1);
>
> +#if defined(CONFIG_IPV6)
> +       if (is_ipv6) {
> +               net_send_tcp_packet6(len, htons(curr_sport),
> htons(curr_dport),
> +                                    action, response_seq_num,
> response_ack_num);
> +               return;
> +       }
> +#endif
>         net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport),
>                             action, response_seq_num, response_ack_num);
>  }
> @@ -47,7 +61,7 @@ static void fastboot_tcp_send_packet(u8 action, const
> uchar *data, unsigned int
>         uchar *pkt = net_get_async_tx_pkt_buf();
>
>         memset(pkt, '\0', PKTSIZE);
> -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE +
> TCP_TSOPT_SIZE + 2;
>         memcpy(pkt, data, len);
>         fastboot_tcp_answer(action, len);
>         memset(pkt, '\0', PKTSIZE);
> @@ -59,7 +73,7 @@ static void fastboot_tcp_send_message(const char
> *message, unsigned int len)
>         uchar *pkt = net_get_async_tx_pkt_buf();
>
>         memset(pkt, '\0', PKTSIZE);
> -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE +
> TCP_TSOPT_SIZE + 2;
>         // Put first 8 bytes as a big endian message length
>         memcpy(pkt, &len_be, 8);
>         pkt += 8;
> @@ -68,10 +82,9 @@ static void fastboot_tcp_send_message(const char
> *message, unsigned int len)
>         memset(pkt, '\0', PKTSIZE);
>  }
>
> -static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
> -                                     struct in_addr sip, u16 sport,
> -                                     u32 tcp_seq_num, u32 tcp_ack_num,
> -                                     u8 action, unsigned int len)
> +static void fastboot_tcp_handler(uchar *pkt, u16 dport, u16 sport,
> +                                u32 tcp_seq_num, u32 tcp_ack_num,
> +                                u8 action, unsigned int len)
>  {
>         int fastboot_command_id;
>         u64 command_size;
> @@ -88,7 +101,6 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt, u16
> dport,
>         case FASTBOOT_CLOSED:
>                 if (tcp_push) {
>                         if (len != handshake_length ||
> -                           strlen(pkt) != handshake_length ||
>                             memcmp(pkt, handshake, handshake_length) != 0)
> {
>                                 fastboot_tcp_reset();
>                                 break;
> @@ -111,18 +123,25 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt,
> u16 dport,
>                         pkt += 8;
>
>                         // Only single packet messages are supported ATM
> -                       if (strlen(pkt) != command_size) {
> +                       if (len != command_size) {
>                                 fastboot_tcp_reset();
>                                 break;
>                         }
>                         strlcpy(command, pkt, len + 1);
>                         fastboot_command_id =
> fastboot_handle_command(command, response);
>                         fastboot_tcp_send_message(response,
> strlen(response));
> -                       fastboot_handle_boot(fastboot_command_id,
> -                                            strncmp("OKAY", response, 4)
> == 0);
> +
> +                       command_handled_id = fastboot_command_id;
> +                       command_handled_success = strncmp("OKAY",
> response, 4) == 0;
>                 }
>                 break;
>         case FASTBOOT_DISCONNECTING:
> +               if (command_handled_success) {
> +                       fastboot_handle_boot(command_handled_id,
> command_handled_success);
> +                       command_handled_id = 0;
> +                       command_handled_success = false;
> +               }
> +
>                 if (tcp_push)
>                         state = FASTBOOT_CLOSED;
>                 break;
> @@ -137,10 +156,41 @@ static void fastboot_tcp_handler_ipv4(uchar *pkt,
> u16 dport,
>         curr_request_len = 0;
>  }
>
> +static void fastboot_tcp_handler_ipv4(uchar *pkt, u16 dport,
> +                                     struct in_addr sip, u16 sport,
> +                                     u32 tcp_seq_num, u32 tcp_ack_num,
> +                                     u8 action, unsigned int len)
> +{
> +       is_ipv6 = false;
> +       ip_header_size = IP_HDR_SIZE;
> +       fastboot_tcp_handler(pkt, dport, sport,
> +                            tcp_seq_num, tcp_ack_num,
> +                            action, len);
> +}
> +
> +#if defined(CONFIG_IPV6)
> +static void fastboot_tcp_handler_ipv6(uchar *pkt, u16 dport,
> +                                     struct in6_addr sip, u16 sport,
> +                                     u32 tcp_seq_num, u32 tcp_ack_num,
> +                                     u8 action, unsigned int len)
> +{
> +       is_ipv6 = true;
> +       ip_header_size = IP6_HDR_SIZE;
> +       fastboot_tcp_handler(pkt, dport, sport,
> +                            tcp_seq_num, tcp_ack_num,
> +                            action, len);
> +}
> +#endif
> +
>  void fastboot_tcp_start_server(void)
>  {
>         printf("Using %s device\n", eth_get_name());
> -       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
>
> +       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
>         tcp_set_tcp_handler(fastboot_tcp_handler_ipv4);
> +
> +#if defined(CONFIG_IPV6)
> +       printf("Listening for fastboot command on %pI6\n", &net_ip6);
> +       net_set_tcp_handler6(fastboot_tcp_handler_ipv6);
> +#endif
>  }
> --
> 2.40.1.606.ga4b1b128d6-goog
>
>

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

* Re: [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode
  2023-05-10 16:59 ` [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode Dmitrii Merkurev
@ 2023-07-14 15:43   ` Ying-Chun Liu (PaulLiu)
  2023-07-23  3:48   ` Simon Glass
  1 sibling, 0 replies; 21+ messages in thread
From: Ying-Chun Liu (PaulLiu) @ 2023-07-14 15:43 UTC (permalink / raw)
  To: Dmitrii Merkurev, u-boot; +Cc: rammuthiah, rfried.dev, Simon Glass

Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>


On 2023/5/11 00:59, Dmitrii Merkurev wrote:
> Command to start IP6 only TCP fastboot:
> fastboot tcp -ipv6
> 
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>   cmd/fastboot.c           | 29 +++++++++++++++++++++++++----
>   doc/android/fastboot.rst |  8 +++++++-
>   2 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/cmd/fastboot.c b/cmd/fastboot.c
> index 3d5ff951eb..36f744ae01 100644
> --- a/cmd/fastboot.c
> +++ b/cmd/fastboot.c
> @@ -12,6 +12,7 @@
>   #include <g_dnl.h>
>   #include <fastboot.h>
>   #include <net.h>
> +#include <net6.h>
>   #include <usb.h>
>   #include <watchdog.h>
>   #include <linux/stringify.h>
> @@ -121,10 +122,23 @@ static int do_fastboot(struct cmd_tbl *cmdtp, int flag, int argc,
>   {
>   	uintptr_t buf_addr = (uintptr_t)NULL;
>   	size_t buf_size = 0;
> +	bool is_ipv6_only = false;
> +	bool is_usb = false;
> +	bool is_udp = false;
> +	bool is_tcp = false;
>   
>   	if (argc < 2)
>   		return CMD_RET_USAGE;
>   
> +	if (IS_ENABLED(CONFIG_IPV6)) {
> +		use_ip6 = false;
> +		/* IPv6 parameter has to be always *last* */
> +		if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM)) {
> +			is_ipv6_only = true;
> +			--argc;
> +		}
> +	}
> +
>   	while (argc > 1 && **(argv + 1) == '-') {
>   		char *arg = *++argv;
>   
> @@ -159,11 +173,18 @@ NXTARG:
>   
>   	fastboot_init((void *)buf_addr, buf_size);
>   
> -	if (!strcmp(argv[1], "udp"))
> +	is_usb = strcmp(argv[1], "usb") == 0;
> +	is_udp = strcmp(argv[1], "udp") == 0;
> +	is_tcp = strcmp(argv[1], "tcp") == 0;
> +
> +	if (is_ipv6_only && is_tcp)
> +		use_ip6 = true;
> +
> +	if (is_udp)
>   		return do_fastboot_udp(argc, argv, buf_addr, buf_size);
> -	if (!strcmp(argv[1], "tcp"))
> +	if (is_tcp)
>   		return do_fastboot_tcp(argc, argv, buf_addr, buf_size);
> -	if (!strcmp(argv[1], "usb")) {
> +	if (is_usb) {
>   		argv++;
>   		argc--;
>   	}
> @@ -174,7 +195,7 @@ NXTARG:
>   U_BOOT_CMD(
>   	fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
>   	"run as a fastboot usb or udp device",
> -	"[-l addr] [-s size] usb <controller> | udp\n"
> +	"[-l addr] [-s size] usb <controller> | udp [-ipv6] | tcp [-ipv6]\n"
>   	"\taddr - address of buffer used during data transfers ("
>   	__stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
>   	"\tsize - size of buffer used during data transfers ("
> diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
> index 1ad8a897c8..aa6e9e5a9e 100644
> --- a/doc/android/fastboot.rst
> +++ b/doc/android/fastboot.rst
> @@ -181,13 +181,19 @@ Enter into fastboot by executing the fastboot command in U-Boot for either USB::
>   
>      => fastboot usb 0
>   
> -or UDP::
> +UDP::
>   
>      => fastboot udp
>      link up on port 0, speed 100, full duplex
>      Using ethernet@4a100000 device
>      Listening for fastboot command on 192.168.0.102
>   
> +or TCP::
> +
> +   => fastboot tcp
> +   Using ethernet@4a100000 device
> +   Listening for fastboot command on 192.168.0.102
> +
>   On the client side you can fetch the bootloader version for instance::
>   
>      $ fastboot getvar version-bootloader

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

* Re: [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers
  2023-05-24 21:19 ` [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Ying-Chun Liu (PaulLiu)
@ 2023-07-23  3:48   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Ying-Chun Liu (PaulLiu); +Cc: Dmitrii Merkurev, u-boot, rammuthiah, rfried.dev

On Wed, 24 May 2023 at 15:19, Ying-Chun Liu (PaulLiu)
<paul.liu@linaro.org> wrote:
>
> Reviewed-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
>
> On 2023/5/11 00:59, Dmitrii Merkurev wrote:
> > This allows us to reuse TCP logic between IP and IP6 stack.
> >
> > Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> > Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Сс: Joe Hershberger <joe.hershberger@ni.com>
> > Сс: Ramon Fried <rfried.dev@gmail.com>
> > ---
> >   include/net/tcp.h | 54 ++++++++++++++++--------------------
> >   net/tcp.c         | 70 +++++++++++++++++++++++------------------------
> >   test/cmd/wget.c   | 48 ++++++++++++++++++--------------
> >   3 files changed, 85 insertions(+), 87 deletions(-)
> >

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6
  2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
  2023-05-24 21:38   ` Ying-Chun Liu (PaulLiu)
@ 2023-07-23  3:48   ` Simon Glass
  2023-07-25 22:01     ` Dmitrii Merkurev
  1 sibling, 1 reply; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

Hi Dmitrii,

On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com> wrote:
>
> Changes:
> 1. Separate reusable part from net_set_tcp_header to
> net_set_tcp_header_common
> 2. Make TCP signatures reusable by receiving particular
> IP agnostic TCP headers
> 3. Extract net_send_ip_packet6 from net_send_udp_packet6
> to reuse the code
> 4. Expose TCP state machine related functions
>
> This allows us to reuse TCP logic between IP and IP6 stack.
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  include/net/tcp.h | 109 +++++++++++++--
>  net/net.c         |  18 ++-
>  net/net6.c        |  78 ++++++++---
>  net/tcp.c         | 337 ++++++++++++++++++++++++++++------------------
>  4 files changed, 372 insertions(+), 170 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

While you are here, or in a follow-up patch, can you please add full
comments to net_set_ip_header(), e,g. what is the pkt param exactly?
The whole packet, before any headers?

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

* Re: [PATCH v2 3/6] net: introduce TCP/IP6 support
  2023-05-10 16:59 ` [PATCH v2 3/6] net: introduce TCP/IP6 support Dmitrii Merkurev
  2023-05-25  4:52   ` Ying-Chun Liu (PaulLiu)
@ 2023-07-23  3:48   ` Simon Glass
  2023-07-25 22:05     ` Dmitrii Merkurev
  1 sibling, 1 reply; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

Hi Dmitrii,

On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com> wrote:
>
> Add TCP/IP6 related headers and reuse refactored TCP/IP
> implementation
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  include/net/tcp6.h | 106 +++++++++++++++++++++++++++++++++++++++++++++
>  include/net6.h     |  14 ++++++
>  net/Makefile       |   1 +
>  net/net.c          |   6 +++
>  net/net6.c         |  72 +++++++++++++++++++++++++-----
>  net/tcp6.c         |  99 ++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 288 insertions(+), 10 deletions(-)
>  create mode 100644 include/net/tcp6.h
>  create mode 100644 net/tcp6.c

Reviewed-by: Simon Glass <sjg@chromium.org>

Comments below.

>
> diff --git a/include/net/tcp6.h b/include/net/tcp6.h
> new file mode 100644
> index 0000000000..3db125ecc5
> --- /dev/null
> +++ b/include/net/tcp6.h
> @@ -0,0 +1,106 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2022 The Android Open Source Project
> + */
> +
> +#ifndef __TCP6_H__
> +#define __TCP6_H__
> +
> +#if defined(CONFIG_PROT_TCP)

Is there anything that can be done to get rid of these, at least in
the source code?

> +
> +#include <net6.h>
> +#include <net/tcp.h>
> +
> +/**
> + * typedef rxhand_tcp6_f() - An incoming TCP IPv6 packet handler.
> + * @pkt: pointer to the application packet
> + * @dport: destination TCP port
> + * @sip: source IP6 address
> + * @sport: source TCP port
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + * @action: TCP packet type (SYN, ACK, FIN, etc)
> + */
> +typedef void rxhand_tcp6_f(uchar *pkt, u16 dport,
> +                          struct in6_addr sip, u16 sport,
> +                          u32 tcp_seq_num, u32 tcp_ack_num,
> +                          u8 action, unsigned int len);
> +
> +/**
> + * struct ip6_tcp_hdr_o - IP6 + TCP header + TCP options
> + * @ip_hdr: IP6 + TCP header
> + * @tcp_hdr: TCP header
> + * @tcp_o: TCP options
> + * @end: end of IP6/TCP header
> + */
> +struct ip6_tcp_hdr_o {
> +       struct  ip6_hdr    ip_hdr;
> +       struct  tcp_hdr    tcp_hdr;
> +       struct  tcp_hdr_o  tcp_o;
> +       u8      end;
> +} __packed;
> +
> +#define IP6_TCP_O_SIZE (sizeof(struct ip6_tcp_hdr_o))
> +
> +/**
> + * struct ip6_tcp_hdr_s - IP6 + TCP header + TCP options
> + * @ip_hdr: IP6 + TCP header
> + * @tcp_hdr: TCP header
> + * @t_opt: TCP Timestamp Option
> + * @sack_v: TCP SACK Option
> + * @end: end of options
> + */
> +struct ip6_tcp_hdr_s {
> +       struct  ip6_hdr    ip_hdr;
> +       struct  tcp_hdr    tcp_hdr;
> +       struct  tcp_t_opt  t_opt;
> +       struct  tcp_sack_v sack_v;
> +       u8      end;
> +} __packed;
> +
> +#define IP6_TCP_SACK_SIZE (sizeof(struct ip6_tcp_hdr_s))
> +
> +/**
> + * union tcp6_build_pkt - union for building TCP/IP6 packet.
> + * @ip: IP6 and TCP header plus TCP options
> + * @sack: IP6 and TCP header plus SACK options
> + * @raw: buffer
> + */
> +union tcp6_build_pkt {
> +       struct ip6_tcp_hdr_o ip;
> +       struct ip6_tcp_hdr_s sack;
> +       uchar  raw[1600];
> +} __packed;
> +
> +/**
> + * net_set_tcp6_handler6() - set application TCP6 packet handler
> + * @param f pointer to callback function
> + */
> +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> +
> +/**
> + * net_set_tcp_header6() - set
> + * @pkt: pointer to IP6/TCP headers
> + * @dport: destination TCP port
> + * @sport: source TCP port
> + * @payload_len: payload length
> + * @action: TCP packet type (SYN, ACK, FIN, etc)
> + * @tcp_seq_num: TCP sequential number
> + * @tcp_ack_num: TCP acknowledgment number
> + *
> + * returns TCP header size
> + */
> +int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int payload_len,
> +                       u8 action, u32 tcp_seq_num, u32 tcp_ack_num);

Please add a full comment. We need full comments on all exported
functions and any non-trivial internal ones.

> +
> +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> +
> +/**
> + * rxhand_tcp6() - handle incoming IP6 TCP packet
> + * @param b pointer to IP6/TCP packet builder struct
> + * @param len full packet length
> + */
> +void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len);
> +
> +#endif // CONFIG_PROT_TCP
> +#endif // __TCP6_H__
> diff --git a/include/net6.h b/include/net6.h
> index beafc05338..fa926f07ac 100644
> --- a/include/net6.h
> +++ b/include/net6.h
> @@ -344,6 +344,20 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src, struct in6_addr *dest,
>  int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
>                          int sport, int len);
>
> +/**
> + * net_send_tcp_packet6() - Make up TCP packet and send it
> + *
> + * @payload_len: TCP payload length
> + * @dport:      destination port
> + * @sport:      source port
> + * @action:     TCP flag (SYN, ACL, PUSH, etc)
> + * @tcp_seq_num: TCP sequence number
> + * @tcp_ack_num: TCP ackno
> + * Return: 0 if send successfully, -1 otherwise
> + */
> +int net_send_tcp_packet6(int payload_len, int dport, int sport, u8 action,
> +                        u32 tcp_seq_num, u32 tcp_ack_num);

as you have done here

Regards,
Simon

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

* Re: [PATCH v2 4/6] net: add fastboot TCP6 support
  2023-05-10 16:59 ` [PATCH v2 4/6] net: add fastboot TCP6 support Dmitrii Merkurev
  2023-07-03 15:48   ` Paul Liu
@ 2023-07-23  3:48   ` Simon Glass
  2023-07-25 22:06     ` Dmitrii Merkurev
  1 sibling, 1 reply; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

Hi Dmitrii,

On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com> wrote:
>
> fastboot tcp command remains the same, but started
> listening IP6 in case it's enabled.
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  include/net/fastboot_tcp.h |  2 +-
>  net/fastboot_tcp.c         | 72 ++++++++++++++++++++++++++++++++------
>  2 files changed, 62 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/fastboot_tcp.h b/include/net/fastboot_tcp.h
> index 6cf29d52e9..98986fa10a 100644
> --- a/include/net/fastboot_tcp.h
> +++ b/include/net/fastboot_tcp.h
> @@ -7,7 +7,7 @@
>  #define __NET_FASTBOOT_TCP_H__
>
>  /**
> - * Wait for incoming tcp fastboot comands.
> + * Wait for incoming TCP fastboot comands.
>   */
>  void fastboot_tcp_start_server(void);
>
> diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c
> index 2eb52ea256..d93b52ede5 100644
> --- a/net/fastboot_tcp.c
> +++ b/net/fastboot_tcp.c
> @@ -6,8 +6,10 @@
>  #include <common.h>
>  #include <fastboot.h>
>  #include <net.h>
> +#include <net6.h>
>  #include <net/fastboot_tcp.h>
>  #include <net/tcp.h>
> +#include <net/tcp6.h>
>
>  static char command[FASTBOOT_COMMAND_LEN] = {0};
>  static char response[FASTBOOT_RESPONSE_LEN] = {0};
> @@ -20,18 +22,30 @@ static u16 curr_dport;
>  static u32 curr_tcp_seq_num;
>  static u32 curr_tcp_ack_num;
>  static unsigned int curr_request_len;
> +static bool is_ipv6;
> +static size_t ip_header_size;
>  static enum fastboot_tcp_state {
>         FASTBOOT_CLOSED,
>         FASTBOOT_CONNECTED,
>         FASTBOOT_DISCONNECTING
>  } state = FASTBOOT_CLOSED;
>
> +static int command_handled_id;
> +static bool command_handled_success;
> +
>  static void fastboot_tcp_answer(u8 action, unsigned int len)
>  {
>         const u32 response_seq_num = curr_tcp_ack_num;
>         const u32 response_ack_num = curr_tcp_seq_num +
>                   (curr_request_len > 0 ? curr_request_len : 1);
>
> +#if defined(CONFIG_IPV6)

Can you use if() here?

> +       if (is_ipv6) {
> +               net_send_tcp_packet6(len, htons(curr_sport), htons(curr_dport),
> +                                    action, response_seq_num, response_ack_num);
> +               return;
> +       }
> +#endif
>         net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport),
>                             action, response_seq_num, response_ack_num);
>  }
> @@ -47,7 +61,7 @@ static void fastboot_tcp_send_packet(u8 action, const uchar *data, unsigned int
>         uchar *pkt = net_get_async_tx_pkt_buf();
>
>         memset(pkt, '\0', PKTSIZE);
> -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
>         memcpy(pkt, data, len);
>         fastboot_tcp_answer(action, len);
>         memset(pkt, '\0', PKTSIZE);
> @@ -59,7 +73,7 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len)
>         uchar *pkt = net_get_async_tx_pkt_buf();
>
>         memset(pkt, '\0', PKTSIZE);
> -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
>         // Put first 8 bytes as a big endian message length
>         memcpy(pkt, &len_be, 8);
>         pkt += 8;
> @@ -68,10 +82,9 @@ static void fastboot_tcp_send_message(const char *message, unsigned int len)
>         memset(pkt, '\0', PKTSIZE);
>  }
>

[..]
 +
>  void fastboot_tcp_start_server(void)
>  {
>         printf("Using %s device\n", eth_get_name());
> -       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
>
> +       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
>         tcp_set_tcp_handler(fastboot_tcp_handler_ipv4);
> +
> +#if defined(CONFIG_IPV6)
> +       printf("Listening for fastboot command on %pI6\n", &net_ip6);
> +       net_set_tcp_handler6(fastboot_tcp_handler_ipv6);
> +#endif

and here. This needs some thought as we don't want to add #if to C
code where possible.

Regards,
Simon

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

* Re: [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode
  2023-05-10 16:59 ` [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode Dmitrii Merkurev
  2023-07-14 15:43   ` Ying-Chun Liu (PaulLiu)
@ 2023-07-23  3:48   ` Simon Glass
  2023-07-25 22:08     ` Dmitrii Merkurev
  1 sibling, 1 reply; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

Hi Dmitrii,

On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com> wrote:
>
> Command to start IP6 only TCP fastboot:
> fastboot tcp -ipv6
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  cmd/fastboot.c           | 29 +++++++++++++++++++++++++----
>  doc/android/fastboot.rst |  8 +++++++-
>  2 files changed, 32 insertions(+), 5 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Can you please add a doc/usage/cmd/fastboot.rst as well? Can be a
separate patch.

Regards,
Simon

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

* Re: [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed
  2023-05-10 16:59 ` [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed Dmitrii Merkurev
@ 2023-07-23  3:48   ` Simon Glass
  0 siblings, 0 replies; 21+ messages in thread
From: Simon Glass @ 2023-07-23  3:48 UTC (permalink / raw)
  To: Dmitrii Merkurev; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com> wrote:
>
> Current active eth device may be changed (due to ethprime), so make
> sure current net_ip6 is updated as a reaction.
>
> Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> Cc: Simon Glass <sjg@chromium.org>
> Сс: Joe Hershberger <joe.hershberger@ni.com>
> Сс: Ramon Fried <rfried.dev@gmail.com>
> ---
>  net/net.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

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

* Re: [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6
  2023-07-23  3:48   ` Simon Glass
@ 2023-07-25 22:01     ` Dmitrii Merkurev
  0 siblings, 0 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-07-25 22:01 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

>
> While you are here, or in a follow-up patch, can you please add full
> comments to net_set_ip_header(), e,g. what is the pkt param exactly?
> The whole packet, before any headers?


It's an IP header. Added comment and renamed the argument on this one and
net_set_udp_header.


On Sun, Jul 23, 2023 at 4:48 AM Simon Glass <sjg@chromium.org> wrote:

> Hi Dmitrii,
>
> On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com>
> wrote:
> >
> > Changes:
> > 1. Separate reusable part from net_set_tcp_header to
> > net_set_tcp_header_common
> > 2. Make TCP signatures reusable by receiving particular
> > IP agnostic TCP headers
> > 3. Extract net_send_ip_packet6 from net_send_udp_packet6
> > to reuse the code
> > 4. Expose TCP state machine related functions
> >
> > This allows us to reuse TCP logic between IP and IP6 stack.
> >
> > Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> > Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Сс: Joe Hershberger <joe.hershberger@ni.com>
> > Сс: Ramon Fried <rfried.dev@gmail.com>
> > ---
> >  include/net/tcp.h | 109 +++++++++++++--
> >  net/net.c         |  18 ++-
> >  net/net6.c        |  78 ++++++++---
> >  net/tcp.c         | 337 ++++++++++++++++++++++++++++------------------
> >  4 files changed, 372 insertions(+), 170 deletions(-)
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> While you are here, or in a follow-up patch, can you please add full
> comments to net_set_ip_header(), e,g. what is the pkt param exactly?
> The whole packet, before any headers?
>

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

* Re: [PATCH v2 3/6] net: introduce TCP/IP6 support
  2023-07-23  3:48   ` Simon Glass
@ 2023-07-25 22:05     ` Dmitrii Merkurev
  0 siblings, 0 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-07-25 22:05 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

>
> Is there anything that can be done to get rid of these, at least in
> the source code?


Got rid of all macro conditions across the whole patch stack. Tested it on
different configurations. Should be ok.

Please add a full comment


Added

On Sun, Jul 23, 2023 at 4:49 AM Simon Glass <sjg@chromium.org> wrote:

> Hi Dmitrii,
>
> On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com>
> wrote:
> >
> > Add TCP/IP6 related headers and reuse refactored TCP/IP
> > implementation
> >
> > Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> > Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Сс: Joe Hershberger <joe.hershberger@ni.com>
> > Сс: Ramon Fried <rfried.dev@gmail.com>
> > ---
> >  include/net/tcp6.h | 106 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/net6.h     |  14 ++++++
> >  net/Makefile       |   1 +
> >  net/net.c          |   6 +++
> >  net/net6.c         |  72 +++++++++++++++++++++++++-----
> >  net/tcp6.c         |  99 ++++++++++++++++++++++++++++++++++++++++++
> >  6 files changed, 288 insertions(+), 10 deletions(-)
> >  create mode 100644 include/net/tcp6.h
> >  create mode 100644 net/tcp6.c
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Comments below.
>
> >
> > diff --git a/include/net/tcp6.h b/include/net/tcp6.h
> > new file mode 100644
> > index 0000000000..3db125ecc5
> > --- /dev/null
> > +++ b/include/net/tcp6.h
> > @@ -0,0 +1,106 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (C) 2022 The Android Open Source Project
> > + */
> > +
> > +#ifndef __TCP6_H__
> > +#define __TCP6_H__
> > +
> > +#if defined(CONFIG_PROT_TCP)
>
> Is there anything that can be done to get rid of these, at least in
> the source code?
>
> > +
> > +#include <net6.h>
> > +#include <net/tcp.h>
> > +
> > +/**
> > + * typedef rxhand_tcp6_f() - An incoming TCP IPv6 packet handler.
> > + * @pkt: pointer to the application packet
> > + * @dport: destination TCP port
> > + * @sip: source IP6 address
> > + * @sport: source TCP port
> > + * @tcp_seq_num: TCP sequential number
> > + * @tcp_ack_num: TCP acknowledgment number
> > + * @action: TCP packet type (SYN, ACK, FIN, etc)
> > + */
> > +typedef void rxhand_tcp6_f(uchar *pkt, u16 dport,
> > +                          struct in6_addr sip, u16 sport,
> > +                          u32 tcp_seq_num, u32 tcp_ack_num,
> > +                          u8 action, unsigned int len);
> > +
> > +/**
> > + * struct ip6_tcp_hdr_o - IP6 + TCP header + TCP options
> > + * @ip_hdr: IP6 + TCP header
> > + * @tcp_hdr: TCP header
> > + * @tcp_o: TCP options
> > + * @end: end of IP6/TCP header
> > + */
> > +struct ip6_tcp_hdr_o {
> > +       struct  ip6_hdr    ip_hdr;
> > +       struct  tcp_hdr    tcp_hdr;
> > +       struct  tcp_hdr_o  tcp_o;
> > +       u8      end;
> > +} __packed;
> > +
> > +#define IP6_TCP_O_SIZE (sizeof(struct ip6_tcp_hdr_o))
> > +
> > +/**
> > + * struct ip6_tcp_hdr_s - IP6 + TCP header + TCP options
> > + * @ip_hdr: IP6 + TCP header
> > + * @tcp_hdr: TCP header
> > + * @t_opt: TCP Timestamp Option
> > + * @sack_v: TCP SACK Option
> > + * @end: end of options
> > + */
> > +struct ip6_tcp_hdr_s {
> > +       struct  ip6_hdr    ip_hdr;
> > +       struct  tcp_hdr    tcp_hdr;
> > +       struct  tcp_t_opt  t_opt;
> > +       struct  tcp_sack_v sack_v;
> > +       u8      end;
> > +} __packed;
> > +
> > +#define IP6_TCP_SACK_SIZE (sizeof(struct ip6_tcp_hdr_s))
> > +
> > +/**
> > + * union tcp6_build_pkt - union for building TCP/IP6 packet.
> > + * @ip: IP6 and TCP header plus TCP options
> > + * @sack: IP6 and TCP header plus SACK options
> > + * @raw: buffer
> > + */
> > +union tcp6_build_pkt {
> > +       struct ip6_tcp_hdr_o ip;
> > +       struct ip6_tcp_hdr_s sack;
> > +       uchar  raw[1600];
> > +} __packed;
> > +
> > +/**
> > + * net_set_tcp6_handler6() - set application TCP6 packet handler
> > + * @param f pointer to callback function
> > + */
> > +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> > +
> > +/**
> > + * net_set_tcp_header6() - set
> > + * @pkt: pointer to IP6/TCP headers
> > + * @dport: destination TCP port
> > + * @sport: source TCP port
> > + * @payload_len: payload length
> > + * @action: TCP packet type (SYN, ACK, FIN, etc)
> > + * @tcp_seq_num: TCP sequential number
> > + * @tcp_ack_num: TCP acknowledgment number
> > + *
> > + * returns TCP header size
> > + */
> > +int net_set_tcp_header6(uchar *pkt, u16 dport, u16 sport, int
> payload_len,
> > +                       u8 action, u32 tcp_seq_num, u32 tcp_ack_num);
>
> Please add a full comment. We need full comments on all exported
> functions and any non-trivial internal ones.
>
> > +
> > +void net_set_tcp_handler6(rxhand_tcp6_f *f);
> > +
> > +/**
> > + * rxhand_tcp6() - handle incoming IP6 TCP packet
> > + * @param b pointer to IP6/TCP packet builder struct
> > + * @param len full packet length
> > + */
> > +void rxhand_tcp6(union tcp6_build_pkt *b, unsigned int len);
> > +
> > +#endif // CONFIG_PROT_TCP
> > +#endif // __TCP6_H__
> > diff --git a/include/net6.h b/include/net6.h
> > index beafc05338..fa926f07ac 100644
> > --- a/include/net6.h
> > +++ b/include/net6.h
> > @@ -344,6 +344,20 @@ int ip6_add_hdr(uchar *xip, struct in6_addr *src,
> struct in6_addr *dest,
> >  int net_send_udp_packet6(uchar *ether, struct in6_addr *dest, int dport,
> >                          int sport, int len);
> >
> > +/**
> > + * net_send_tcp_packet6() - Make up TCP packet and send it
> > + *
> > + * @payload_len: TCP payload length
> > + * @dport:      destination port
> > + * @sport:      source port
> > + * @action:     TCP flag (SYN, ACL, PUSH, etc)
> > + * @tcp_seq_num: TCP sequence number
> > + * @tcp_ack_num: TCP ackno
> > + * Return: 0 if send successfully, -1 otherwise
> > + */
> > +int net_send_tcp_packet6(int payload_len, int dport, int sport, u8
> action,
> > +                        u32 tcp_seq_num, u32 tcp_ack_num);
>
> as you have done here
>
> Regards,
> Simon
>

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

* Re: [PATCH v2 4/6] net: add fastboot TCP6 support
  2023-07-23  3:48   ` Simon Glass
@ 2023-07-25 22:06     ` Dmitrii Merkurev
  0 siblings, 0 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-07-25 22:06 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

>
> Can you use if() here?


Yes, fixed

On Sun, Jul 23, 2023 at 4:48 AM Simon Glass <sjg@chromium.org> wrote:

> Hi Dmitrii,
>
> On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com>
> wrote:
> >
> > fastboot tcp command remains the same, but started
> > listening IP6 in case it's enabled.
> >
> > Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> > Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Сс: Joe Hershberger <joe.hershberger@ni.com>
> > Сс: Ramon Fried <rfried.dev@gmail.com>
> > ---
> >  include/net/fastboot_tcp.h |  2 +-
> >  net/fastboot_tcp.c         | 72 ++++++++++++++++++++++++++++++++------
> >  2 files changed, 62 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/net/fastboot_tcp.h b/include/net/fastboot_tcp.h
> > index 6cf29d52e9..98986fa10a 100644
> > --- a/include/net/fastboot_tcp.h
> > +++ b/include/net/fastboot_tcp.h
> > @@ -7,7 +7,7 @@
> >  #define __NET_FASTBOOT_TCP_H__
> >
> >  /**
> > - * Wait for incoming tcp fastboot comands.
> > + * Wait for incoming TCP fastboot comands.
> >   */
> >  void fastboot_tcp_start_server(void);
> >
> > diff --git a/net/fastboot_tcp.c b/net/fastboot_tcp.c
> > index 2eb52ea256..d93b52ede5 100644
> > --- a/net/fastboot_tcp.c
> > +++ b/net/fastboot_tcp.c
> > @@ -6,8 +6,10 @@
> >  #include <common.h>
> >  #include <fastboot.h>
> >  #include <net.h>
> > +#include <net6.h>
> >  #include <net/fastboot_tcp.h>
> >  #include <net/tcp.h>
> > +#include <net/tcp6.h>
> >
> >  static char command[FASTBOOT_COMMAND_LEN] = {0};
> >  static char response[FASTBOOT_RESPONSE_LEN] = {0};
> > @@ -20,18 +22,30 @@ static u16 curr_dport;
> >  static u32 curr_tcp_seq_num;
> >  static u32 curr_tcp_ack_num;
> >  static unsigned int curr_request_len;
> > +static bool is_ipv6;
> > +static size_t ip_header_size;
> >  static enum fastboot_tcp_state {
> >         FASTBOOT_CLOSED,
> >         FASTBOOT_CONNECTED,
> >         FASTBOOT_DISCONNECTING
> >  } state = FASTBOOT_CLOSED;
> >
> > +static int command_handled_id;
> > +static bool command_handled_success;
> > +
> >  static void fastboot_tcp_answer(u8 action, unsigned int len)
> >  {
> >         const u32 response_seq_num = curr_tcp_ack_num;
> >         const u32 response_ack_num = curr_tcp_seq_num +
> >                   (curr_request_len > 0 ? curr_request_len : 1);
> >
> > +#if defined(CONFIG_IPV6)
>
> Can you use if() here?
>
> > +       if (is_ipv6) {
> > +               net_send_tcp_packet6(len, htons(curr_sport),
> htons(curr_dport),
> > +                                    action, response_seq_num,
> response_ack_num);
> > +               return;
> > +       }
> > +#endif
> >         net_send_tcp_packet(len, htons(curr_sport), htons(curr_dport),
> >                             action, response_seq_num, response_ack_num);
> >  }
> > @@ -47,7 +61,7 @@ static void fastboot_tcp_send_packet(u8 action, const
> uchar *data, unsigned int
> >         uchar *pkt = net_get_async_tx_pkt_buf();
> >
> >         memset(pkt, '\0', PKTSIZE);
> > -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> > +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE +
> TCP_TSOPT_SIZE + 2;
> >         memcpy(pkt, data, len);
> >         fastboot_tcp_answer(action, len);
> >         memset(pkt, '\0', PKTSIZE);
> > @@ -59,7 +73,7 @@ static void fastboot_tcp_send_message(const char
> *message, unsigned int len)
> >         uchar *pkt = net_get_async_tx_pkt_buf();
> >
> >         memset(pkt, '\0', PKTSIZE);
> > -       pkt += net_eth_hdr_size() + IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
> > +       pkt += net_eth_hdr_size() + ip_header_size + TCP_HDR_SIZE +
> TCP_TSOPT_SIZE + 2;
> >         // Put first 8 bytes as a big endian message length
> >         memcpy(pkt, &len_be, 8);
> >         pkt += 8;
> > @@ -68,10 +82,9 @@ static void fastboot_tcp_send_message(const char
> *message, unsigned int len)
> >         memset(pkt, '\0', PKTSIZE);
> >  }
> >
>
> [..]
>  +
> >  void fastboot_tcp_start_server(void)
> >  {
> >         printf("Using %s device\n", eth_get_name());
> > -       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
> >
> > +       printf("Listening for fastboot command on tcp %pI4\n", &net_ip);
> >         tcp_set_tcp_handler(fastboot_tcp_handler_ipv4);
> > +
> > +#if defined(CONFIG_IPV6)
> > +       printf("Listening for fastboot command on %pI6\n", &net_ip6);
> > +       net_set_tcp_handler6(fastboot_tcp_handler_ipv6);
> > +#endif
>
> and here. This needs some thought as we don't want to add #if to C
> code where possible.
>
> Regards,
> Simon
>

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

* Re: [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode
  2023-07-23  3:48   ` Simon Glass
@ 2023-07-25 22:08     ` Dmitrii Merkurev
  0 siblings, 0 replies; 21+ messages in thread
From: Dmitrii Merkurev @ 2023-07-25 22:08 UTC (permalink / raw)
  To: Simon Glass; +Cc: u-boot, rammuthiah, rfried.dev, Ying-Chun Liu

>
> Can you please add a doc/usage/cmd/fastboot.rst as well? Can be a
> separate patch.


Added in the v3 version of this patch. Since we already have detailed
`doc/android/fastboot.rst`, I created a short version here
`doc/usage/cmd/fastboot.rst` which refers to android documentation.

On Sun, Jul 23, 2023 at 4:49 AM Simon Glass <sjg@chromium.org> wrote:

> Hi Dmitrii,
>
> On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev <dimorinny@google.com>
> wrote:
> >
> > Command to start IP6 only TCP fastboot:
> > fastboot tcp -ipv6
> >
> > Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
> > Cc: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
> > Cc: Simon Glass <sjg@chromium.org>
> > Сс: Joe Hershberger <joe.hershberger@ni.com>
> > Сс: Ramon Fried <rfried.dev@gmail.com>
> > ---
> >  cmd/fastboot.c           | 29 +++++++++++++++++++++++++----
> >  doc/android/fastboot.rst |  8 +++++++-
> >  2 files changed, 32 insertions(+), 5 deletions(-)
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Can you please add a doc/usage/cmd/fastboot.rst as well? Can be a
> separate patch.
>
> Regards,
> Simon
>

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

end of thread, other threads:[~2023-07-25 22:09 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-10 16:59 [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Dmitrii Merkurev
2023-05-10 16:59 ` [PATCH v2 2/6] net: prepare existing TCP stack to be reused by IP6 Dmitrii Merkurev
2023-05-24 21:38   ` Ying-Chun Liu (PaulLiu)
2023-07-23  3:48   ` Simon Glass
2023-07-25 22:01     ` Dmitrii Merkurev
2023-05-10 16:59 ` [PATCH v2 3/6] net: introduce TCP/IP6 support Dmitrii Merkurev
2023-05-25  4:52   ` Ying-Chun Liu (PaulLiu)
2023-07-23  3:48   ` Simon Glass
2023-07-25 22:05     ` Dmitrii Merkurev
2023-05-10 16:59 ` [PATCH v2 4/6] net: add fastboot TCP6 support Dmitrii Merkurev
2023-07-03 15:48   ` Paul Liu
2023-07-23  3:48   ` Simon Glass
2023-07-25 22:06     ` Dmitrii Merkurev
2023-05-10 16:59 ` [PATCH v2 5/6] net: add fastboot TCP documentation and IP6-only mode Dmitrii Merkurev
2023-07-14 15:43   ` Ying-Chun Liu (PaulLiu)
2023-07-23  3:48   ` Simon Glass
2023-07-25 22:08     ` Dmitrii Merkurev
2023-05-10 16:59 ` [PATCH v2 6/6] net: update net_ip6 from link_local address when eth device is changed Dmitrii Merkurev
2023-07-23  3:48   ` Simon Glass
2023-05-24 21:19 ` [PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers Ying-Chun Liu (PaulLiu)
2023-07-23  3:48   ` Simon Glass

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.