Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d55e6300 authored by Wei Wang's avatar Wei Wang Committed by Lorenzo Colitti
Browse files

BACKPORT: net/tcp-fastopen: Add new API support

This patch adds a new socket option, TCP_FASTOPEN_CONNECT, as an
alternative way to perform Fast Open on the active side (client). Prior
to this patch, a client needs to replace the connect() call with
sendto(MSG_FASTOPEN). This can be cumbersome for applications who want
to use Fast Open: these socket operations are often done in lower layer
libraries used by many other applications. Changing these libraries
and/or the socket call sequences are not trivial. A more convenient
approach is to perform Fast Open by simply enabling a socket option when
the socket is created w/o changing other socket calls sequence:
  s = socket()
    create a new socket
  setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN_CONNECT …);
    newly introduced sockopt
    If set, new functionality described below will be used.
    Return ENOTSUPP if TFO is not supported or not enabled in the
    kernel.

  connect()
    With cookie present, return 0 immediately.
    With no cookie, initiate 3WHS with TFO cookie-request option and
    return -1 with errno = EINPROGRESS.

  write()/sendmsg()
    With cookie present, send out SYN with data and return the number of
    bytes buffered.
    With no cookie, and 3WHS not yet completed, return -1 with errno =
    EINPROGRESS.
    No MSG_FASTOPEN flag is needed.

  read()
    Return -1 with errno = EWOULDBLOCK/EAGAIN if connect() is called but
    write() is not called yet.
    Return -1 with errno = EWOULDBLOCK/EAGAIN if connection is
    established but no msg is received yet.
    Return number of bytes read if socket is established and there is
    msg received.

The new API simplifies life for applications that always perform a write()
immediately after a successful connect(). Such applications can now take
advantage of Fast Open by merely making one new setsockopt() call at the time
of creating the socket. Nothing else about the application's socket call
sequence needs to change.

Backport of upstream commit 19f6d3f3c842 ("net/tcp-fastopen: Add new API
support")

Bug: 63449462
Test: Tests in https://android-review.googlesource.com/535357/

 pass
Change-Id: Icc181febd74e3117c2fc835d7ed935e107b5815e
Signed-off-by: default avatarWei Wang <weiwan@google.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarYuchung Cheng <ycheng@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
(cherry-picked from commit 19f6d3f3c8422d65b5e3d2162e30ef07c6e21ea2)
parent 9fd54650
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -219,7 +219,8 @@ struct tcp_sock {
	} rack;
	u16	advmss;		/* Advertised MSS			*/
	u8	rate_app_limited:1,  /* rate_{delivered,interval_us} limited? */
		unused:7;
		fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */
		unused:6;
	u8	nonagle     : 4,/* Disable Nagle algorithm?             */
		thin_lto    : 1,/* Use linear timeouts for thin streams */
		thin_dupack : 1,/* Fast retransmit on first dupack      */
+5 −1
Original line number Diff line number Diff line
@@ -206,7 +206,11 @@ struct inet_sock {
				transparent:1,
				mc_all:1,
				nodefrag:1;
	__u8			bind_address_no_port:1;
	__u8			bind_address_no_port:1,
				defer_connect:1; /* Indicates that fastopen_connect is set
						  * and cookie exists so we defer connect
						  * until first data frame is written
						  */
	__u8			rcv_tos;
	__u8			convert_csum;
	int			uc_index;
+1 −0
Original line number Diff line number Diff line
@@ -1509,6 +1509,7 @@ struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
void tcp_fastopen_init_key_once(bool publish);
bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
			     struct tcp_fastopen_cookie *cookie);
bool tcp_fastopen_defer_connect(struct sock *sk, int *err);
#define TCP_FASTOPEN_KEY_LENGTH 16

/* Fastopen key context */
+1 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ enum {
#define TCP_SAVE_SYN		27	/* Record SYN headers for new connections */
#define TCP_SAVED_SYN		28	/* Get SYN headers recorded for connection */
#define TCP_REPAIR_WINDOW	29	/* Get/set window parameters */
#define TCP_FASTOPEN_CONNECT	30	/* Attempt FastOpen with connect */

struct tcp_repair_opt {
	__u32	opt_code;
+24 −7
Original line number Diff line number Diff line
@@ -585,6 +585,16 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
	int err;
	long timeo;

	/*
	 * uaddr can be NULL and addr_len can be 0 if:
	 * sk is a TCP fastopen active socket and
	 * TCP_FASTOPEN_CONNECT sockopt is set and
	 * we already have a valid cookie for this socket.
	 * In this case, user can call write() after connect().
	 * write() will invoke tcp_sendmsg_fastopen() which calls
	 * __inet_stream_connect().
	 */
	if (uaddr) {
		if (addr_len < sizeof(uaddr->sa_family))
			return -EINVAL;

@@ -593,6 +603,7 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
			sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED;
			goto out;
		}
	}

	switch (sock->state) {
	default:
@@ -602,6 +613,9 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
		err = -EISCONN;
		goto out;
	case SS_CONNECTING:
		if (inet_sk(sk)->defer_connect)
			err = -EINPROGRESS;
		else
			err = -EALREADY;
		/* Fall out of switch with err, set for this state */
		break;
@@ -616,6 +630,9 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,

		sock->state = SS_CONNECTING;

		if (!err && inet_sk(sk)->defer_connect)
			goto out;

		/* Just entered SS_CONNECTING state; the only
		 * difference is that return value in non-blocking
		 * case is EINPROGRESS, rather than EALREADY.
Loading