Skip to content

Commit

Permalink
net: tcp2: Send our MSS to peer
Browse files Browse the repository at this point in the history
Send our MSS to peer when sending SYN or SYN-ACK.

Fixes zephyrproject-rtos#30367

Signed-off-by: Jukka Rissanen <[email protected]>
  • Loading branch information
jukkar authored and nashif committed Oct 14, 2021
1 parent 3fff255 commit fc5d460
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
48 changes: 47 additions & 1 deletion subsys/net/ip/tcp2.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt);

int (*tcp_send_cb)(struct net_pkt *pkt) = NULL;
size_t (*tcp_recv_cb)(struct tcp *conn, struct net_pkt *pkt) = NULL;
uint16_t net_tcp_get_recv_mss(const struct tcp *conn);

static uint32_t tcp_get_seq(struct net_buf *buf)
{
Expand Down Expand Up @@ -771,6 +772,11 @@ static int tcp_header_add(struct tcp *conn, struct net_pkt *pkt, uint8_t flags,
UNALIGNED_PUT(conn->src.sin.sin_port, &th->th_sport);
UNALIGNED_PUT(conn->dst.sin.sin_port, &th->th_dport);
th->th_off = 5;

if (conn->send_options.mss_found) {
th->th_off++;
}

UNALIGNED_PUT(flags, &th->th_flags);
UNALIGNED_PUT(htons(conn->recv_win), &th->th_win);
UNALIGNED_PUT(htonl(seq), &th->th_seq);
Expand Down Expand Up @@ -799,13 +805,40 @@ static int ip_header_add(struct tcp *conn, struct net_pkt *pkt)
return -EINVAL;
}

static int net_tcp_set_mss_opt(struct tcp *conn, struct net_pkt *pkt)
{
struct mss_option {
uint32_t option;
};
NET_PKT_DATA_ACCESS_DEFINE(mss_option, struct mss_option);
struct mss_option *mss;
uint32_t recv_mss;

mss = net_pkt_get_data(pkt, &mss_option);
if (!mss) {
return -ENOBUFS;
}

recv_mss = net_tcp_get_recv_mss(conn);
recv_mss |= (NET_TCP_MSS_OPT << 24) | (NET_TCP_MSS_SIZE << 16);

UNALIGNED_PUT(htonl(recv_mss), (uint32_t *)mss);

return net_pkt_set_data(pkt, &mss_option);
}

static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data,
uint32_t seq)
{
size_t alloc_len = sizeof(struct tcphdr);
struct net_pkt *pkt;
int ret = 0;

pkt = tcp_pkt_alloc(conn, sizeof(struct tcphdr));
if (conn->send_options.mss_found) {
alloc_len += sizeof(uint32_t);
}

pkt = tcp_pkt_alloc(conn, alloc_len);
if (!pkt) {
ret = -ENOBUFS;
goto out;
Expand All @@ -829,6 +862,14 @@ static int tcp_out_ext(struct tcp *conn, uint8_t flags, struct net_pkt *data,
goto out;
}

if (conn->send_options.mss_found) {
ret = net_tcp_set_mss_opt(conn, pkt);
if (ret < 0) {
tcp_pkt_unref(pkt);
goto out;
}
}

ret = tcp_finalize_pkt(pkt);
if (ret < 0) {
tcp_pkt_unref(pkt);
Expand Down Expand Up @@ -1710,8 +1751,11 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
switch (conn->state) {
case TCP_LISTEN:
if (FL(&fl, ==, SYN)) {
/* Make sure our MSS is also sent in the ACK */
conn->send_options.mss_found = true;
conn_ack(conn, th_seq(th) + 1); /* capture peer's isn */
tcp_out(conn, SYN | ACK);
conn->send_options.mss_found = false;
conn_seq(conn, + 1);
next = TCP_SYN_RECEIVED;

Expand All @@ -1721,7 +1765,9 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
&conn->establish_timer,
ACK_TIMEOUT);
} else {
conn->send_options.mss_found = true;
tcp_out(conn, SYN);
conn->send_options.mss_found = false;
conn_seq(conn, + 1);
next = TCP_SYN_SENT;
}
Expand Down
13 changes: 13 additions & 0 deletions subsys/net/ip/tcp2_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,18 @@ union tcp_endpoint {
struct sockaddr_in6 sin6;
};

/* TCP Option codes */
#define NET_TCP_END_OPT 0
#define NET_TCP_NOP_OPT 1
#define NET_TCP_MSS_OPT 2
#define NET_TCP_WINDOW_SCALE_OPT 3

/* TCP Option sizes */
#define NET_TCP_END_SIZE 1
#define NET_TCP_NOP_SIZE 1
#define NET_TCP_MSS_SIZE 4
#define NET_TCP_WINDOW_SCALE_SIZE 3

struct tcp_options {
uint16_t mss;
uint16_t window;
Expand All @@ -225,6 +237,7 @@ struct tcp { /* TCP connection */
struct k_sem connect_sem; /* semaphore for blocking connect */
struct k_fifo recv_data; /* temp queue before passing data to app */
struct tcp_options recv_options;
struct tcp_options send_options;
struct k_work_delayable send_timer;
struct k_work_delayable recv_queue_timer;
struct k_work_delayable send_data_timer;
Expand Down

0 comments on commit fc5d460

Please sign in to comment.