@@ -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;
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 <dmytro@shytyi.net> ---