[PATCH v2 1/6] net: split IP_TCP header into separate IP/IP6 and TCP headers

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))

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); } }

On 2023/5/11 00:59, Dmitrii Merkurev wrote:
Changes:
- 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;
break; #if defined(CONFIG_PROT_TCP) case IPPROTO_TCP:pkt_hdr_size += IP_UDP_HDR_SIZE;
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);
break; #endif default:pkt_hdr_size += ip_tcp_hdr_size;
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_try = 1; net_nd_timer_start = get_timer(0); ndisc_request(); return 1; /* waiting */ }net_nd_tx_packet_size = pkt_hdr_size + payload_len;
- 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 +
} else {tcp_lost.len));
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;
} else {options->sack_p.len = TCP_OPT_LEN_2;
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_activity_count = 0;"TCP Hdr:SYN (sq=%u, ak=%u)\n", *tcp_seq_num, *tcp_ack_num);
net_set_syn_options(b);
tcp_seq_num = 0;
tcp_ack_num = 0;
pkt_hdr_len = IP_TCP_O_SIZE;
*tcp_seq_num = 0;
if (current_tcp_state == TCP_SYN_SENT) { /* Too many SYNs */ action = TCP_FIN; current_tcp_state = TCP_FIN_WAIT_1;*tcp_ack_num = 0;
@@ -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);
debug_cond(DEBUG_DEV_PKT,b->ip.tcp_hdr.tcp_flags = action;
"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",
break; case TCP_FIN: debug_cond(DEBUG_DEV_PKT,*tcp_seq_num, *tcp_ack_num, action);
"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;
current_tcp_state = TCP_FIN_WAIT_1; break; case TCP_RST | TCP_ACK: case TCP_RST: debug_cond(DEBUG_DEV_PKT,"TCP Hdr:FIN (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
"TCP Hdr:RST (%pI4, %pI4, s=%u, a=%u)\n",
&net_server_ip, &net_ip, 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):"TCP Hdr:RST (s=%u, a=%u)\n", *tcp_seq_num, *tcp_ack_num);
debug_cond(DEBUG_DEV_PKT,
"TCP Hdr:FIN ACK PSH(s=%u, a=%u, A=%x)\n",
if (current_tcp_state == TCP_CLOSE_WAIT) current_tcp_state = TCP_CLOSING;*tcp_seq_num, *tcp_ack_num, action);
debug_cond(DEBUG_DEV_PKT,
"TCP Hdr:FIN ACK PSH(%pI4, %pI4, s=%u, a=%u, A=%x)\n",
&net_server_ip, &net_ip,
fallthrough; default:tcp_seq_num, tcp_ack_num, action);
pkt_hdr_len = IP_HDR_SIZE + net_set_ack_options(b);
b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
debug_cond(DEBUG_DEV_PKT,action = action | TCP_PUSH | TCP_ACK;
"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,
{ u8 tcp_fin = tcp_flags & TCP_FIN; u8 tcp_syn = tcp_flags & TCP_SYN;u32 *tcp_ack_num_out, int payload_len)
@@ -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;
} else if (tcp_ack || tcp_fin) { action = TCP_DATA; } break; case TCP_SYN_RECEIVED:init_sack_options(tcp_seq_num, tcp_seq_num + 1); current_tcp_state = TCP_SYN_RECEIVED;
if (tcp_ack) {
action = TCP_DATA;
init_sack_options(tcp_seq_num, tcp_seq_num + 1);
current_tcp_state = TCP_ESTABLISHED;
}
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;break;
} 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)
} else { action = TCP_DATA; }action |= TCP_PUSH;
@@ -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

Hi Dmitrii,
On Wed, 10 May 2023 at 11:00, Dmitrii Merkurev dimorinny@google.com wrote:
Changes:
- 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?

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:
- 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?

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

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;
#endif default: return -EINVAL;break;
@@ -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;
break;rxhand_tcp6(tcp_headers, len);
+#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

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

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

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 }

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

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

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

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

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

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

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

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

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

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
*/ struct ip_tcp_hdr_s {
- @tcp_hdr: TCP header
- @t_opt: TCP Timestamp Option
- @sack_v: TCP SACK Option
- @end: end of options
- 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 +
} 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 + tcp_lost.len));
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;
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,b->ip.tcp_hdr.tcp_flags = action;
@@ -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;
debug_cond(DEBUG_DEV_PKT, "TCP Hdr:dft (%pI4, %pI4, s=%u, a=%u, A=%x)\n", &net_server_ip, &net_ip,b->ip.tcp_hdr.tcp_flags = action | TCP_PUSH | TCP_ACK;
@@ -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,
debug_cond(DEBUG_DEV_PKT, "TCP RX TCP xSum Error (%pI4, %pI4, len=%d)\n",b->ip.ip_hdr.ip_dst, tcp_len, pkt_len)) {
@@ -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))

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
participants (4)
-
Dmitrii Merkurev
-
Paul Liu
-
Simon Glass
-
Ying-Chun Liu (PaulLiu)