* [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.