[PATCH net-next v1] net: mptcp, Fast Open Mechanism
From: Dmytro Shytyi <hidden>
Date: 2021-10-22 05:15:54
This set of patches will bring "Fast Open" Option support to MPTCP. The aim of Fast Open Mechanism is to eliminate one round trip time from a TCP conversation by allowing data to be included as part of the SYN segment that initiates the connection. IETF RFC 8684: Appendix B. TCP Fast Open and MPTCP. [PATCH v1] includes "client" partial support for : 1. send request for cookie; 2. send syn+data+cookie. Signed-off-by: Dmytro Shytyi <redacted> ---
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index cd6b11c9b54d..1f9ef060e980 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c@@ -1686,6 +1686,68 @@ static void mptcp_set_nospace(struct sock *sk) set_bit(MPTCP_NOSPACE, &mptcp_sk(sk)->flags); } +static int mptcp_sendmsg_fastopen_cookie_req(struct sock *sk, struct msghdr *msg, + size_t *copied, size_t size, + struct ubuf_info *uarg) +{ + struct mptcp_sock *msk = mptcp_sk(sk); + struct socket *ssk = __mptcp_nmpc_socket(msk); + struct tcp_sock *tp = tcp_sk(ssk->sk); + struct sockaddr *uaddr = msg->msg_name; + struct tcp_fastopen_context *ctx; + const struct iphdr *iph; + struct sk_buff *skb; + int err; + + skb = sk_stream_alloc_skb(ssk->sk, 0, ssk->sk->sk_allocation, true); + iph = ip_hdr(skb); + tcp_fastopen_init_key_once(sock_net(ssk->sk)); + ctx = tcp_fastopen_get_ctx(ssk->sk); + tp->fastopen_req = kzalloc(sizeof(*tp->fatopen_req), + ssk->sk->sk_allocation); + tp->fastopen_req->data = msg; + tp->fastopen_req->size = size; + tp->fastopen_req->uarg = uarg; + err = mptcp_stream_connect(sk->sk_socket, uaddr, msg->msg_namelen, msg->msg_flags); + return err; +} + +static int mptcp_sendmsg_fastopen_cookie_send(struct sock *sk, struct msghdr *msg, + size_t *copied, size_t size, + struct ubuf_info *uarg) +{ + struct tcp_fastopen_cookie *fastopen_cookie = kmalloc(sizeof(*fastopen_cookie), + GFP_KERNEL); + struct mptcp_sock *msk = mptcp_sk(sk); + struct socket *ssk = __mptcp_nmpc_socket(msk); + struct tcp_sock *tp = tcp_sk(ssk->sk); + struct sockaddr *uaddr = msg->msg_name; + struct tcp_fastopen_context *ctx; + const struct iphdr *iph; + struct sk_buff *skb; + int err; + + skb = sk_stream_alloc_skb(ssk->sk, 0, ssk->sk->sk_allocation, true); + iph = ip_hdr(skb); + tcp_fastopen_init_key_once(sock_net(ssk->sk)); + ctx = tcp_fastopen_get_ctx(ssk->sk); + + fastopen_cookie->val[0] = cpu_to_le64(siphash(&iph->saddr, + sizeof(iph->saddr) + + sizeof(iph->daddr), + &ctx->key[0])); + fastopen_cookie->len = TCP_FASTOPEN_COOKIE_SIZE; + + tp->fastopen_req = kzalloc(sizeof(*tp->fastopen_req), + ssk->sk->sk_allocation); + tp->fastopen_req->data = msg; + tp->fastopen_req->size = size; + tp->fastopen_req->uarg = uarg; + memcpy(&tp->fastopen_req->cookie, fastopen_cookie, sizeof(tp->fastopen_req->cookie)); + err = mptcp_stream_connect(sk->sk_socket, uaddr, msg->msg_namelen, msg->msg_flags); + return err; +} + static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) { struct mptcp_sock *msk = mptcp_sk(sk);
@@ -1694,9 +1756,22 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) int ret = 0; long timeo; - /* we don't support FASTOPEN yet */ - if (msg->msg_flags & MSG_FASTOPEN) - return -EOPNOTSUPP; + /* we don't fully support FASTOPEN yet */ + + if (msg->msg_flags & MSG_FASTOPEN) { + struct socket *ssk = __mptcp_nmpc_socket(msk); + struct tcp_sock *tp = tcp_sk(ssk->sk); + + if (tp && tp->fastopen_req && tp->fastopen_req->cookie.len != 0) { + // send cookie + ret = mptcp_sendmsg_fastopen_cookie_send(sk, msg, &copied, len, uarg); + } else { + struct tcp_fastopen_request *fastopen = tp->fastopen_req; + //requests a cookie + ret = mptcp_sendmsg_fastopen_cookie_req(sk, msg, &copied, len, uarg); + } + return ret; + } /* silently ignore everything else */ msg->msg_flags &= MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL;