net/tcp: Support initial sequence number described in RFC 6528
Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
5096a2c9fd
commit
d1c73b6ed6
@ -158,6 +158,17 @@ config NET_TCP_CC_NEWRENO
|
|||||||
The TCP Congestion Control defines four congestion control algorithms,
|
The TCP Congestion Control defines four congestion control algorithms,
|
||||||
slow start, congestion avoidance, fast retransmit, and fast recovery.
|
slow start, congestion avoidance, fast retransmit, and fast recovery.
|
||||||
|
|
||||||
|
config NET_TCP_ISN_RFC6528
|
||||||
|
bool "Use Initial Sequence Number Algorithm from RFC 6528"
|
||||||
|
default n
|
||||||
|
depends on CRYPTO
|
||||||
|
---help---
|
||||||
|
Initial Sequence Number Generation Algorithm from RFC 6528:
|
||||||
|
ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||||
|
|
||||||
|
M is the 4 microsecond timer, and F() is a pseudorandom
|
||||||
|
function (PRF) which is MD5 (suggested by RFC 6528).
|
||||||
|
|
||||||
config NET_TCP_WINDOW_SCALE
|
config NET_TCP_WINDOW_SCALE
|
||||||
bool "Enable TCP/IP Window Scale Option"
|
bool "Enable TCP/IP Window Scale Option"
|
||||||
default n
|
default n
|
||||||
|
@ -896,7 +896,7 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len);
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void tcp_initsequence(FAR uint8_t *seqno);
|
void tcp_initsequence(FAR struct tcp_conn_s *conn);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: tcp_nextsequence
|
* Name: tcp_nextsequence
|
||||||
|
@ -1200,7 +1200,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||||||
conn->rport = tcp->srcport;
|
conn->rport = tcp->srcport;
|
||||||
conn->tcpstateflags = TCP_SYN_RCVD;
|
conn->tcpstateflags = TCP_SYN_RCVD;
|
||||||
|
|
||||||
tcp_initsequence(conn->sndseq);
|
tcp_initsequence(conn);
|
||||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||||
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
||||||
#endif
|
#endif
|
||||||
@ -1506,13 +1506,6 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
conn->tcpstateflags = TCP_SYN_SENT;
|
conn->tcpstateflags = TCP_SYN_SENT;
|
||||||
tcp_initsequence(conn->sndseq);
|
|
||||||
|
|
||||||
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
|
|
||||||
|
|
||||||
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
|
||||||
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
conn->tx_unacked = 1; /* TCP length of the SYN is one. */
|
conn->tx_unacked = 1; /* TCP length of the SYN is one. */
|
||||||
conn->nrtx = 0;
|
conn->nrtx = 0;
|
||||||
@ -1528,6 +1521,16 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
|||||||
conn->sndseq_max = 0;
|
conn->sndseq_max = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set initial sndseq when we have both local/remote addr and port */
|
||||||
|
|
||||||
|
tcp_initsequence(conn);
|
||||||
|
|
||||||
|
/* Save initial sndseq to rexmit_seq, otherwise it will be zero */
|
||||||
|
|
||||||
|
#if !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
|
||||||
|
conn->rexmit_seq = tcp_getsequence(conn->sndseq);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_TCP_CC_NEWRENO
|
#ifdef CONFIG_NET_TCP_CC_NEWRENO
|
||||||
/* Initialize the variables of congestion control. */
|
/* Initialize the variables of congestion control. */
|
||||||
|
|
||||||
|
@ -43,23 +43,84 @@
|
|||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP)
|
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP)
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <crypto/md5.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
#include <nuttx/net/netconfig.h>
|
#include <nuttx/net/netconfig.h>
|
||||||
#include <nuttx/net/netdev.h>
|
#include <nuttx/net/netdev.h>
|
||||||
|
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
|
#include "tcp/tcp.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* g_tcpsequence is used to generate initial TCP sequence numbers */
|
/* These fields are used to generate initial TCP sequence numbers */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||||
|
/* RFC 6528, Section 3: Key lengths of 128 bits should be adequate. */
|
||||||
|
|
||||||
|
static uint32_t g_tcp_isnkey[4];
|
||||||
|
#else
|
||||||
static uint32_t g_tcpsequence;
|
static uint32_t g_tcpsequence;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: tcp_isn_rfc6528
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Calculate the initial sequence number described in RFC 6528.
|
||||||
|
* ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||||
|
static uint32_t tcp_isn_rfc6528(FAR struct tcp_conn_s *conn)
|
||||||
|
{
|
||||||
|
const size_t addrlen = net_ip_domain_select(conn->domain,
|
||||||
|
sizeof(in_addr_t), sizeof(net_ipv6addr_t));
|
||||||
|
MD5_CTX ctx;
|
||||||
|
uint32_t digest[MD5_DIGEST_LENGTH / 4];
|
||||||
|
uint32_t m;
|
||||||
|
|
||||||
|
/* Make sure we have a secret key */
|
||||||
|
|
||||||
|
if (g_tcp_isnkey[0] == 0)
|
||||||
|
{
|
||||||
|
net_getrandom(g_tcp_isnkey, sizeof(g_tcp_isnkey));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* M is the 4 microsecond timer */
|
||||||
|
|
||||||
|
m = TICK2USEC(clock_systime_ticks()) / 4;
|
||||||
|
|
||||||
|
/* F() is suggested to be MD5 */
|
||||||
|
|
||||||
|
md5init(&ctx);
|
||||||
|
|
||||||
|
/* Calculate F(localip, localport, remoteip, remoteport, secretkey) */
|
||||||
|
|
||||||
|
md5update(&ctx, net_ip_binding_laddr(&conn->u, conn->domain), addrlen);
|
||||||
|
md5update(&ctx, &conn->lport, sizeof(conn->lport));
|
||||||
|
md5update(&ctx, net_ip_binding_raddr(&conn->u, conn->domain), addrlen);
|
||||||
|
md5update(&ctx, &conn->rport, sizeof(conn->rport));
|
||||||
|
md5update(&ctx, g_tcp_isnkey, sizeof(g_tcp_isnkey));
|
||||||
|
|
||||||
|
md5final((FAR uint8_t *)digest, &ctx);
|
||||||
|
|
||||||
|
/* ISN = M + F(localip, localport, remoteip, remoteport, secretkey) */
|
||||||
|
|
||||||
|
return m + digest[0];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -142,8 +203,11 @@ uint32_t tcp_addsequence(FAR uint8_t *seqno, uint16_t len)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void tcp_initsequence(FAR uint8_t *seqno)
|
void tcp_initsequence(FAR struct tcp_conn_s *conn)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_NET_TCP_ISN_RFC6528
|
||||||
|
tcp_setsequence(conn->sndseq, tcp_isn_rfc6528(conn));
|
||||||
|
#else
|
||||||
/* If g_tcpsequence is already initialized, just copy it */
|
/* If g_tcpsequence is already initialized, just copy it */
|
||||||
|
|
||||||
if (g_tcpsequence == 0)
|
if (g_tcpsequence == 0)
|
||||||
@ -164,7 +228,8 @@ void tcp_initsequence(FAR uint8_t *seqno)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp_setsequence(seqno, g_tcpsequence);
|
tcp_setsequence(conn->sndseq, g_tcpsequence);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -180,7 +245,9 @@ void tcp_initsequence(FAR uint8_t *seqno)
|
|||||||
|
|
||||||
void tcp_nextsequence(void)
|
void tcp_nextsequence(void)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_NET_TCP_ISN_RFC6528
|
||||||
g_tcpsequence++;
|
g_tcpsequence++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET && CONFIG_NET_TCP */
|
#endif /* CONFIG_NET && CONFIG_NET_TCP */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user