tcp: add TCP_MAXSEG support
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
bd4d7a1b76
commit
93c3b8f19e
@ -137,6 +137,12 @@
|
||||
#define TCP_DEFAULT_IPv4_MSS 536
|
||||
#define TCP_DEFAULT_IPv6_MSS 1220
|
||||
|
||||
/* Minimal accepted MSS. It is (60+60+8) - (20+20).
|
||||
* (MAX_IP_HDR + MAX_TCP_HDR + MIN_IP_FRAG) - (MIN_IP_HDR + MIN_TCP_HDR)
|
||||
*/
|
||||
|
||||
#define TCP_MIN_MSS 88
|
||||
|
||||
/* However, we do need to make allowance for certain links such as SLIP that
|
||||
* have unusually small MTUs.
|
||||
*/
|
||||
|
@ -43,7 +43,7 @@ config NET_SOCKOPTS
|
||||
Enable or disable support for socket options
|
||||
|
||||
config NET_TCPPROTO_OPTIONS
|
||||
bool
|
||||
bool "TCP proto socket options"
|
||||
default n
|
||||
---help---
|
||||
Enable or disable support for TCP protocol level socket options.
|
||||
|
@ -229,6 +229,10 @@ struct tcp_conn_s
|
||||
uint16_t rport; /* The remoteTCP port, in network byte order */
|
||||
uint16_t mss; /* Current maximum segment size for the
|
||||
* connection */
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
uint16_t user_mss; /* Configured maximum segment size for the
|
||||
* connection */
|
||||
#endif
|
||||
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
|
||||
|
@ -754,6 +754,28 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain)
|
||||
|
||||
nxsem_init(&conn->snd_sem, 0, 0);
|
||||
#endif
|
||||
|
||||
/* Set the default value of mss to max, this field will changed when
|
||||
* receive SYN.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (domain == PF_INET)
|
||||
#endif
|
||||
{
|
||||
conn->mss = MIN_IPv4_TCP_INITIAL_MSS;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
conn->mss = MIN_IPv6_TCP_INITIAL_MSS;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
}
|
||||
|
||||
return conn;
|
||||
@ -1293,9 +1315,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
FAR const struct sockaddr_in *inaddr =
|
||||
(FAR const struct sockaddr_in *)addr;
|
||||
|
||||
/* Save MSS and the port from the sockaddr (already in network order) */
|
||||
|
||||
conn->mss = MIN_IPv4_TCP_INITIAL_MSS;
|
||||
conn->rport = inaddr->sin_port;
|
||||
|
||||
/* The sockaddr address is 32-bits in network order.
|
||||
@ -1327,9 +1346,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
FAR const struct sockaddr_in6 *inaddr =
|
||||
(FAR const struct sockaddr_in6 *)addr;
|
||||
|
||||
/* Save MSS and the port from the sockaddr (already in network order) */
|
||||
|
||||
conn->mss = MIN_IPv6_TCP_INITIAL_MSS;
|
||||
conn->rport = inaddr->sin6_port;
|
||||
|
||||
/* The sockaddr address is 128-bits in network order.
|
||||
|
@ -82,11 +82,6 @@
|
||||
int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* Keep alive options are the only TCP protocol socket option currently
|
||||
* supported.
|
||||
*/
|
||||
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int ret;
|
||||
|
||||
@ -118,6 +113,7 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
if (*value_len < sizeof(int))
|
||||
@ -221,6 +217,26 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
|
||||
case TCP_MAXSEG: /* The maximum segment size */
|
||||
if (*value_len < sizeof(int))
|
||||
{
|
||||
/* REVISIT: POSIX says that we should truncate the value if it
|
||||
* is larger than value_len. That just doesn't make sense
|
||||
* to me in this case.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR int *mss = (FAR int *)value;
|
||||
*mss = conn->mss;
|
||||
*value_len = sizeof(int);
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized TCP option: %d\n", option);
|
||||
@ -229,9 +245,6 @@ int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_TCPPROTO_OPTIONS */
|
||||
|
@ -586,6 +586,13 @@ static void tcp_parse_option(FAR struct net_driver_s *dev,
|
||||
|
||||
tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) |
|
||||
(uint16_t)IPDATA(tcpiplen + 3 + i);
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
if (conn->user_mss > 0 && conn->user_mss < tcp_mss)
|
||||
{
|
||||
tcp_mss = conn->user_mss;
|
||||
}
|
||||
#endif
|
||||
|
||||
conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16;
|
||||
}
|
||||
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
|
||||
|
@ -585,7 +585,16 @@ void tcp_synack(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
|
||||
/* Set the packet length for the TCP Maximum Segment Size */
|
||||
|
||||
tcp_mss = tcp_rx_mss(dev);
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
if (conn->user_mss != 0 && conn->user_mss < tcp_rx_mss(dev))
|
||||
{
|
||||
tcp_mss = conn->user_mss;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
tcp_mss = tcp_rx_mss(dev);
|
||||
}
|
||||
|
||||
/* Save the ACK bits */
|
||||
|
||||
|
@ -72,11 +72,6 @@
|
||||
int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* Keep alive options are the only TCP protocol socket option currently
|
||||
* supported.
|
||||
*/
|
||||
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int ret = OK;
|
||||
|
||||
@ -107,6 +102,7 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
if (value_len != sizeof(int))
|
||||
@ -233,6 +229,35 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
|
||||
case TCP_MAXSEG: /* The maximum segment size */
|
||||
if (value_len != sizeof(int))
|
||||
{
|
||||
ret = -EFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
int mss = *(FAR int *)value;
|
||||
|
||||
if (conn->tcpstateflags != TCP_ALLOCATED)
|
||||
{
|
||||
/* Set TCP_MAXSEG in the wrong state, direct return success */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
if (mss < TCP_MIN_MSS || mss > UINT16_MAX)
|
||||
{
|
||||
nerr("ERROR: TCP_MAXSEG value out of range: %d\n", mss);
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->user_mss = mss;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized TCP option: %d\n", option);
|
||||
@ -241,9 +266,6 @@ int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_TCPPROTO_OPTIONS */
|
||||
|
Loading…
Reference in New Issue
Block a user