mirror of
https://github.com/apache/nuttx.git
synced 2026-09-22 14:41:29 +08:00
net/tcp: add window scale support
Reference here: https://tools.ietf.org/html/rfc1323 Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
@@ -76,8 +76,11 @@
|
||||
#define TCP_OPT_END 0 /* End of TCP options list */
|
||||
#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
|
||||
#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
|
||||
#define TCP_OPT_WS 3 /* Window size scaling factor */
|
||||
|
||||
#define TCP_OPT_NOOP_LEN 1 /* Length of TCP NOOP option. */
|
||||
#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
|
||||
#define TCP_OPT_WS_LEN 3 /* Length of TCP WS option. */
|
||||
|
||||
/* The TCP states used in the struct tcp_conn_s tcpstateflags field */
|
||||
|
||||
|
||||
@@ -106,6 +106,27 @@ config NET_TCP_FAST_RETRANSMIT_WATERMARK
|
||||
missing segment, without waiting for a retransmission timer to
|
||||
expire.
|
||||
|
||||
config NET_TCP_WINDOW_SCALE
|
||||
bool "Enable TCP/IP Window Scale Option"
|
||||
default n
|
||||
---help---
|
||||
RFC1323:
|
||||
2. TCP WINDOW SCALE OPTION
|
||||
The window scale extension expands the definition of the TCP
|
||||
window to 32 bits and then uses a scale factor to carry this 32-
|
||||
bit value in the 16-bit Window field of the TCP header (SEG.WND in
|
||||
RFC-793).
|
||||
|
||||
if NET_TCP_WINDOW_SCALE
|
||||
|
||||
config NET_TCP_WINDOW_SCALE_FACTOR
|
||||
int "TCP/IP Window Scale Factor"
|
||||
default 0
|
||||
---help---
|
||||
This is the default value for window scale factor.
|
||||
|
||||
endif # NET_TCP_WINDOW_SCALE
|
||||
|
||||
config NET_TCP_NOTIFIER
|
||||
bool "Support TCP notifications"
|
||||
default n
|
||||
|
||||
+13
-1
@@ -96,6 +96,10 @@
|
||||
#define TCP_SEQ_ADD(a, b) ((uint32_t)((a) + (b)))
|
||||
#define TCP_SEQ_SUB(a, b) ((uint32_t)((a) - (b)))
|
||||
|
||||
/* The TCP options flags */
|
||||
|
||||
#define TCP_WSCALE 0x01U /* Window Scale option enabled */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
@@ -187,9 +191,16 @@ struct tcp_conn_s
|
||||
uint16_t rport; /* The remoteTCP port, in network byte order */
|
||||
uint16_t mss; /* Current maximum segment size for the
|
||||
* connection */
|
||||
uint32_t rcv_adv; /* The right edge of the recv window advertized */
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
uint32_t snd_wnd; /* Sequence and acknowledgement numbers of last
|
||||
* window update */
|
||||
uint8_t snd_scale; /* Sender window scale factor */
|
||||
uint8_t rcv_scale; /* Receiver windows scale factor */
|
||||
#else
|
||||
uint16_t snd_wnd; /* Sequence and acknowledgement numbers of last
|
||||
* window update */
|
||||
uint32_t rcv_adv; /* The right edge of the recv window advertized */
|
||||
#endif
|
||||
#if CONFIG_NET_RECV_BUFSIZE > 0
|
||||
int32_t rcv_bufs; /* Maximum amount of bytes queued in recv */
|
||||
#endif
|
||||
@@ -198,6 +209,7 @@ struct tcp_conn_s
|
||||
#else
|
||||
uint16_t tx_unacked; /* Number bytes sent but not yet ACKed */
|
||||
#endif
|
||||
uint16_t flags; /* Flags of TCP-specific options */
|
||||
|
||||
/* If the TCP socket is bound to a local address, then this is
|
||||
* a reference to the device that routes traffic on the corresponding
|
||||
|
||||
+24
-2
@@ -388,6 +388,15 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
(uint16_t)dev->d_buf[hdrlen + 3 + i];
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
else if (opt == TCP_OPT_WS &&
|
||||
dev->d_buf[hdrlen + 1 + i] == TCP_OPT_WS_LEN)
|
||||
{
|
||||
conn->snd_scale = dev->d_buf[hdrlen + 2 + i];
|
||||
conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
conn->flags |= TCP_WSCALE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* All other options have a length field, so that we
|
||||
@@ -440,7 +449,12 @@ found:
|
||||
|
||||
/* Update the connection's window size */
|
||||
|
||||
conn->snd_wnd = ((uint16_t)tcp->wnd[0] << 8) + (uint16_t)tcp->wnd[1];
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
conn->snd_wnd = (((uint32_t)tcp->wnd[0] << 8) + (uint32_t)tcp->wnd[1]) <<
|
||||
conn->snd_scale;
|
||||
#else
|
||||
conn->snd_wnd = (((uint16_t)tcp->wnd[0] << 8) + (uint16_t)tcp->wnd[1]);
|
||||
#endif
|
||||
|
||||
flags = 0;
|
||||
|
||||
@@ -783,6 +797,15 @@ found:
|
||||
dev->d_buf[hdrlen + 3 + i];
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
else if (opt == TCP_OPT_WS &&
|
||||
dev->d_buf[hdrlen + 1 + i] == TCP_OPT_WS_LEN)
|
||||
{
|
||||
conn->snd_scale = dev->d_buf[hdrlen + 2 + i];
|
||||
conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
conn->flags |= TCP_WSCALE;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* All other options have a length field, so that we
|
||||
@@ -797,7 +820,6 @@ found:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i += dev->d_buf[hdrlen + 1 + i];
|
||||
|
||||
+20
-4
@@ -365,14 +365,18 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
|
||||
uint32_t rcvseq = tcp_getsequence(conn->rcvseq);
|
||||
uint16_t recvwndo = tcp_get_recvwindow(dev, conn);
|
||||
|
||||
/* Update the Receiver Window */
|
||||
|
||||
conn->rcv_adv = rcvseq + recvwndo;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
recvwndo >>= conn->rcv_scale;
|
||||
#endif
|
||||
|
||||
/* Set the TCP Window */
|
||||
|
||||
tcp->wnd[0] = recvwndo >> 8;
|
||||
tcp->wnd[1] = recvwndo & 0xff;
|
||||
|
||||
/* Update the Receiver Window */
|
||||
|
||||
conn->rcv_adv = rcvseq + recvwndo;
|
||||
}
|
||||
|
||||
/* Finish the IP portion of the message and calculate checksums */
|
||||
@@ -674,6 +678,18 @@ void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
tcp->optdata[optlen++] = TCP_OPT_MSS_LEN;
|
||||
tcp->optdata[optlen++] = tcp_mss >> 8;
|
||||
tcp->optdata[optlen++] = tcp_mss & 0xff;
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
if (tcp->flags == TCP_SYN ||
|
||||
((tcp->flags == (TCP_ACK | TCP_SYN)) && (conn->flags & TCP_WSCALE)))
|
||||
{
|
||||
tcp->optdata[optlen++] = TCP_OPT_NOOP;
|
||||
tcp->optdata[optlen++] = TCP_OPT_WS;
|
||||
tcp->optdata[optlen++] = TCP_OPT_WS_LEN;
|
||||
tcp->optdata[optlen++] = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp->tcpoffset = ((TCP_HDRLEN + optlen) / 4) << 4;
|
||||
dev->d_len += optlen;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user