[PATCH 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 | 50 ++++++++++++++------------------- net/tcp.c | 70 +++++++++++++++++++++++------------------------ test/cmd/wget.c | 16 +++++------ 3 files changed, 64 insertions(+), 72 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h index c29d4ce24a..5ab1127d8b 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,13 +186,15 @@ 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 ip_hdr ip_hdr; + struct tcp_hdr tcp_hdr; struct tcp_t_opt t_opt; struct tcp_sack_v sack_v; u8 end; @@ -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..fd6ed26e8a 100644 --- a/test/cmd/wget.c +++ b/test/cmd/wget.c @@ -52,9 +52,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send; - struct ip_tcp_hdr *tcp_send; + struct tcp_hdr *tcp_send;
/* Don't allow the buffer to overrun */ if (priv->recv_packets >= PKTBUFSRX) @@ -64,7 +64,7 @@ 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; + tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; tcp_send->tcp_seq = htonl(0); @@ -97,9 +97,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send; - struct ip_tcp_hdr *tcp_send; + struct tcp_hdr *tcp_send; void *data; int pkt_len; int payload_len = 0; @@ -115,7 +115,7 @@ 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; + tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; data = (void *)tcp_send + IP_TCP_HDR_SIZE; @@ -163,14 +163,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 = ip + 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 5ab1127d8b..1332f19153 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); } }

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 | 103 +++++++++++++++++++++++++++++++++++++++++++++ include/net6.h | 14 ++++++ net/Makefile | 1 + net/net.c | 6 +++ net/net6.c | 43 ++++++++++++++++++- net/tcp6.c | 95 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 260 insertions(+), 2 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..102f5a240a --- /dev/null +++ b/include/net/tcp6.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2022 The Android Open Source Project + */ + +#ifndef __TCP6_H__ +#define __TCP6_H__ + +#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 // __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..3fc6681898 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) + 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..6418611403 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 */ @@ -362,8 +363,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 +378,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 +424,21 @@ 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) { + union tcp6_build_pkt *tcp_headers; struct in_addr zero_ip = {.s_addr = 0 }; struct icmp6hdr *icmp; struct udp_hdr *udp; + struct tcp_hdr *tcp; u16 csum; u16 csum_p; u16 hlen; @@ -475,6 +498,22 @@ int net_ip6_handler(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) ntohs(udp->udp_src), ntohs(udp->udp_len) - 8); break; + 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; default: return -EINVAL; } diff --git a/net/tcp6.c b/net/tcp6.c new file mode 100644 index 0000000000..9add8cddab --- /dev/null +++ b/net/tcp6.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 The Android Open Source Project + */ + +#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); + } +}

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 }

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

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 3fc6681898..a52c110d93 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

Hi Dmitrii,
It seems to me that this series of patches breaks the unittest of TCP stack in sandbox.
I'll see if I have some time to fix the unittest too.
The unittest can be built by the following commands. 1. "make sandbox64_defconfig" 2. turn on the options that need to be tested. For example, CMD_WGET 3. "make" 4. "sudo ./u-boot -D" 5. "ut lib net_test_wget" in the U-boot prompt.
Yours, Paul
On Tue, 9 May 2023 at 01:15, Dmitrii Merkurev dimorinny@google.com 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 | 50 ++++++++++++++------------------- net/tcp.c | 70 +++++++++++++++++++++++------------------------ test/cmd/wget.c | 16 +++++------ 3 files changed, 64 insertions(+), 72 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h index c29d4ce24a..5ab1127d8b 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,13 +186,15 @@ 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 ip_hdr ip_hdr;
struct tcp_hdr tcp_hdr; struct tcp_t_opt t_opt; struct tcp_sack_v sack_v; u8 end;
@@ -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..fd6ed26e8a 100644 --- a/test/cmd/wget.c +++ b/test/cmd/wget.c @@ -52,9 +52,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send;
struct ip_tcp_hdr *tcp_send;
struct tcp_hdr *tcp_send; /* Don't allow the buffer to overrun */ if (priv->recv_packets >= PKTBUFSRX)
@@ -64,7 +64,7 @@ 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;
tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; tcp_send->tcp_seq = htonl(0);
@@ -97,9 +97,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send;
struct ip_tcp_hdr *tcp_send;
struct tcp_hdr *tcp_send; void *data; int pkt_len; int payload_len = 0;
@@ -115,7 +115,7 @@ 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;
tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; data = (void *)tcp_send + IP_TCP_HDR_SIZE;
@@ -163,14 +163,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 = ip + IP_HDR_SIZE; if (tcp->tcp_flags == TCP_SYN) return sb_syn_handler(dev, packet, len); else if (tcp->tcp_flags & TCP_ACK &&
!(tcp->tcp_flags & TCP_SYN))
2.40.1.521.gf1e218fcd8-goog

Hey Paul,
Huge thanks for pointing this out. Uploaded v2 with a couple of fixes (including wget test on 1/6).
On Mon, May 8, 2023 at 10:18 PM Paul Liu paul.liu@linaro.org wrote:
Hi Dmitrii,
It seems to me that this series of patches breaks the unittest of TCP stack in sandbox.
I'll see if I have some time to fix the unittest too.
The unittest can be built by the following commands.
- "make sandbox64_defconfig"
- turn on the options that need to be tested. For example, CMD_WGET
- "make"
- "sudo ./u-boot -D"
- "ut lib net_test_wget" in the U-boot prompt.
Yours, Paul
On Tue, 9 May 2023 at 01:15, Dmitrii Merkurev dimorinny@google.com 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 | 50 ++++++++++++++------------------- net/tcp.c | 70 +++++++++++++++++++++++------------------------ test/cmd/wget.c | 16 +++++------ 3 files changed, 64 insertions(+), 72 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h index c29d4ce24a..5ab1127d8b 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,13 +186,15 @@ 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 ip_hdr ip_hdr;
struct tcp_hdr tcp_hdr; struct tcp_t_opt t_opt; struct tcp_sack_v sack_v; u8 end;
@@ -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..fd6ed26e8a 100644 --- a/test/cmd/wget.c +++ b/test/cmd/wget.c @@ -52,9 +52,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send;
struct ip_tcp_hdr *tcp_send;
struct tcp_hdr *tcp_send; /* Don't allow the buffer to overrun */ if (priv->recv_packets >= PKTBUFSRX)
@@ -64,7 +64,7 @@ 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;
tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; tcp_send->tcp_seq = htonl(0);
@@ -97,9 +97,9 @@ 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 tcp_hdr *tcp = packet + ETHER_HDR_SIZE + IP_HDR_SIZE; struct ethernet_hdr *eth_send;
struct ip_tcp_hdr *tcp_send;
struct tcp_hdr *tcp_send; void *data; int pkt_len; int payload_len = 0;
@@ -115,7 +115,7 @@ 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;
tcp_send = (void *)eth_send + ETHER_HDR_SIZE + IP_HDR_SIZE; tcp_send->tcp_src = tcp->tcp_dst; tcp_send->tcp_dst = tcp->tcp_src; data = (void *)tcp_send + IP_TCP_HDR_SIZE;
@@ -163,14 +163,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 = ip + IP_HDR_SIZE; if (tcp->tcp_flags == TCP_SYN) return sb_syn_handler(dev, packet, len); else if (tcp->tcp_flags & TCP_ACK && !(tcp->tcp_flags & TCP_SYN))
-- 2.40.1.521.gf1e218fcd8-goog
participants (2)
-
Dmitrii Merkurev
-
Paul Liu