From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============8118605917548709924==" MIME-Version: 1.0 From: Peter Krystad To: mptcp at lists.01.org Subject: Re: [MPTCP] [PATCH v3 08/10] mptcp: Add handling of outgoing MP_JOIN requests Date: Mon, 12 Aug 2019 15:36:46 -0700 Message-ID: In-Reply-To: alpine.OSX.2.21.1908121116420.4973@mjmartin-mac01.local X-Status: X-Keywords: X-UID: 1629 --===============8118605917548709924== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable On Mon, 2019-08-12 at 11:33 -0700, Mat Martineau wrote: > On Wed, 7 Aug 2019, Peter Krystad wrote: > = > > Subflow creation may be initiated by the path manager when > > the primary connection is fully established and a remote > > address has been received via ADD_ADDR. > > = > > Create an in-kernel sock and use kernel_connect() to > > initiate connection. When a valid SYN-ACK is received the > > new sock is added to the tail of the mptcp sock conn_list > > where it will not interfere with data flow on the original > > connection. > > = > > Data flow and connection failover not addressed by this commit. > > = > > Signed-off-by: Peter Krystad > > --- > > include/net/mptcp.h | 2 ++ > > net/mptcp/options.c | 51 ++++++++++++++++++++++++++++++--- > > net/mptcp/protocol.c | 1 + > > net/mptcp/protocol.h | 11 +++++++ > > net/mptcp/subflow.c | 68 +++++++++++++++++++++++++++++++++++++++++++- > > net/mptcp/token.c | 48 +++++++++++++++++++++++++++++++ > > 6 files changed, 176 insertions(+), 5 deletions(-) > > = > > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > > index bb2dd193c0c5..50cd1b31ebdd 100644 > > --- a/include/net/mptcp.h > > +++ b/include/net/mptcp.h > > @@ -40,6 +40,8 @@ struct mptcp_out_options { > > u8 backup; > > u32 nonce; > > u64 thmac; > > + u32 token; > > + u8 hmac[20]; > > struct mptcp_ext ext_copy; > > #endif > > }; > > diff --git a/net/mptcp/options.c b/net/mptcp/options.c > > index 01f59ad629e5..be7afa5aac6a 100644 > > --- a/net/mptcp/options.c > > +++ b/net/mptcp/options.c > > @@ -300,6 +300,16 @@ bool mptcp_syn_options(struct sock *sk, unsigned i= nt *size, > > opts->sndr_key =3D subflow->local_key; > > *size =3D TCPOLEN_MPTCP_MPC_SYN; > > return true; > > + } else if (subflow->request_join) { > > + pr_debug("remote_token=3D%u, nonce=3D%u", subflow->remote_token, > > + subflow->local_nonce); > > + opts->suboptions =3D OPTION_MPTCP_MPJ_SYN; > > + opts->join_id =3D subflow->remote_id; > > + opts->token =3D subflow->remote_token; > > + opts->nonce =3D subflow->local_nonce; > > + opts->backup =3D subflow->request_bkup; > > + *size =3D TCPOLEN_MPTCP_MPJ_SYN; > > + return true; > > } > > return false; > > } > > @@ -309,10 +319,17 @@ void mptcp_rcv_synsent(struct sock *sk) > > struct tcp_sock *tp =3D tcp_sk(sk); > > struct subflow_context *subflow =3D subflow_ctx(sk); > > = > > - pr_debug("subflow=3D%p", subflow); > > if (subflow->request_mptcp && tp->rx_opt.mptcp.mp_capable) { > > subflow->mp_capable =3D 1; > > subflow->remote_key =3D tp->rx_opt.mptcp.sndr_key; > > + pr_debug("subflow=3D%p, remote_key=3D%llu", subflow, > > + subflow->remote_key); > > + } else if (subflow->request_join && tp->rx_opt.mptcp.mp_join) { > > + subflow->mp_join =3D 1; > > + subflow->thmac =3D tp->rx_opt.mptcp.thmac; > > + subflow->remote_nonce =3D tp->rx_opt.mptcp.nonce; > > + pr_debug("subflow=3D%p, thmac=3D%llu, remote_nonce=3D%u", subflow, > > + subflow->thmac, subflow->remote_nonce); > > } > > } > > = > > @@ -322,7 +339,8 @@ static bool mptcp_established_options_mp(struct soc= k *sk, unsigned int *size, > > { > > struct subflow_context *subflow =3D subflow_ctx(sk); > > = > > - if (!subflow->fourth_ack && remaining >=3D TCPOLEN_MPTCP_MPC_ACK) { > > + if (subflow->mp_capable && !subflow->fourth_ack && > > + remaining >=3D TCPOLEN_MPTCP_MPC_ACK) { > > opts->suboptions =3D OPTION_MPTCP_MPC_ACK; > > opts->sndr_key =3D subflow->local_key; > > opts->rcvr_key =3D subflow->remote_key; > > @@ -331,6 +349,14 @@ static bool mptcp_established_options_mp(struct so= ck *sk, unsigned int *size, > > pr_debug("subflow=3D%p, local_key=3D%llu, remote_key=3D%llu", > > subflow, subflow->local_key, subflow->remote_key); > > return true; > > + } else if (subflow->mp_join && !subflow->fourth_ack && > > + remaining >=3D TCPOLEN_MPTCP_MPJ_ACK) { > > + opts->suboptions =3D OPTION_MPTCP_MPJ_ACK; > > + memcpy(opts->hmac, subflow->hmac, MPTCPOPT_HMAC_LEN); > > + *size =3D TCPOLEN_MPTCP_MPJ_ACK; > > + subflow->fourth_ack =3D 1; > > + pr_debug("subflow=3D%p", subflow); > > + return true; > > } > > return false; > > } > > @@ -443,10 +469,11 @@ bool mptcp_established_options(struct sock *sk, s= truct sk_buff *skb, > > unsigned int *size, unsigned int remaining, > > struct mptcp_out_options *opts) > > { > > + struct subflow_context *subflow =3D subflow_ctx(sk); > > unsigned int opt_size =3D 0; > > bool ret =3D false; > > = > > - if (!subflow_ctx(sk)->mp_capable) > > + if (!subflow->mp_capable && !subflow->mp_join) > > return false; > > = > > opts->suboptions =3D 0; > > @@ -546,7 +573,6 @@ void mptcp_incoming_options(struct sock *sk, struct= sk_buff *skb, > > = > > if (msk) > > pm_fully_established(msk); > > - > > } > > = > > void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts) > > @@ -595,6 +621,16 @@ void mptcp_write_options(__be32 *ptr, struct mptcp= _out_options *opts) > > 0, opts->addr_id); > > } > > = > > + if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > > + *ptr++ =3D mptcp_option(MPTCPOPT_MP_JOIN, > > + TCPOLEN_MPTCP_MPJ_SYN, > > + opts->backup, opts->join_id); > > + put_unaligned_be32(opts->token, ptr); > > + ptr +=3D 1; > > + put_unaligned_be32(opts->nonce, ptr); > > + ptr +=3D 1; > > + } > > + > > if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > > *ptr++ =3D mptcp_option(MPTCPOPT_MP_JOIN, > > TCPOLEN_MPTCP_MPJ_SYNACK, > > @@ -605,6 +641,13 @@ void mptcp_write_options(__be32 *ptr, struct mptcp= _out_options *opts) > > ptr +=3D 1; > > } > > = > > + if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > > + *ptr++ =3D mptcp_option(MPTCPOPT_MP_JOIN, > > + TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > > + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > > + ptr +=3D 5; > > + } > > + > > if (opts->ext_copy.use_ack || opts->ext_copy.use_map) { > > struct mptcp_ext *mpext =3D &opts->ext_copy; > > u8 len =3D TCPOLEN_MPTCP_DSS_BASE; > > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c > > index fce5eea729ba..80a8c7e5a3e7 100644 > > --- a/net/mptcp/protocol.c > > +++ b/net/mptcp/protocol.c > > @@ -797,6 +797,7 @@ void mptcp_finish_connect(struct sock *sk, int mp_c= apable) > > msk->local_key =3D subflow->local_key; > > msk->token =3D subflow->token; > > pr_debug("msk=3D%p, token=3D%u", msk, msk->token); > > + msk->dport =3D ntohs(inet_sk(msk->subflow->sk)->inet_dport); > > = > > pm_new_connection(msk, 0); > > = > > diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h > > index 9774ff5a5481..243d896d9e42 100644 > > --- a/net/mptcp/protocol.h > > +++ b/net/mptcp/protocol.h > > @@ -49,8 +49,10 @@ > > #define TCPOLEN_MPTCP_ADD_ADDR6 20 > > #define TCPOLEN_MPTCP_RM_ADDR 4 > > = > > +/* MPTCP MP_JOIN flags */ > > #define MPTCPOPT_BACKUP BIT(0) > > #define MPTCPOPT_HMAC_LEN 20 > > +#define MPTCPOPT_THMAC_LEN 8 > > = > > /* MPTCP MP_CAPABLE flags */ > > #define MPTCP_VERSION_MASK (0x0F) > > @@ -115,6 +117,7 @@ struct mptcp_sock { > > u64 write_seq; > > u64 ack_seq; > > u32 token; > > + u16 dport; > > struct list_head conn_list; > > struct socket *subflow; /* outgoing connect/listener/!mp_capable */ > > struct mptcp_pm_data pm; > > @@ -167,7 +170,9 @@ struct subflow_context { > > u32 ssn_offset; > > u16 map_data_len; > > u16 request_mptcp : 1, /* send MP_CAPABLE */ > > + request_join : 1, /* send MP_JOIN */ > > request_cksum : 1, > > + request_bkup : 1, > > request_version : 4, > > mp_capable : 1, /* remote is MPTCP capable */ > > mp_join : 1, /* remote is JOINing */ > > @@ -179,6 +184,8 @@ struct subflow_context { > > u32 remote_nonce; > > u64 thmac; > > u32 local_nonce; > > + u32 remote_token; > > + u8 hmac[MPTCPOPT_HMAC_LEN]; > > u8 local_id; > > u8 remote_id; > > = > > @@ -202,6 +209,8 @@ mptcp_subflow_tcp_socket(const struct subflow_conte= xt *subflow) > > } > > = > > void subflow_init(void); > > +int subflow_connect(struct sock *sk, struct sockaddr_in *local, > > + struct sockaddr_in *remote, u8 remote_id); > > int subflow_create_socket(struct sock *sk, struct socket **new_sock); > > = > > extern const struct inet_connection_sock_af_ops ipv4_specific; > > @@ -215,10 +224,12 @@ void mptcp_finish_join(struct sock *sk); > > void token_init(void); > > void token_new_request(struct request_sock *req, const struct sk_buff *= skb); > > int token_join_request(struct request_sock *req, const struct sk_buff *= skb); > > +int token_join_response(struct sock *sk); > > int token_join_valid(struct request_sock *req, > > struct tcp_options_received *rx_opt); > > void token_destroy_request(u32 token); > > void token_new_connect(struct sock *sk); > > +void token_new_subflow(struct sock *sk); > > void token_new_accept(struct sock *sk); > > int token_new_join(struct sock *sk); > > void token_update_accept(struct sock *sk, struct sock *conn); > > diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c > > index 678fca99c23a..448c9e7f567a 100644 > > --- a/net/mptcp/subflow.c > > +++ b/net/mptcp/subflow.c > > @@ -22,6 +22,9 @@ static int subflow_rebuild_header(struct sock *sk) > > if (subflow->request_mptcp && !subflow->token) { > > pr_debug("subflow=3D%p", sk); > > token_new_connect(sk); > > + } else if (subflow->request_join && !subflow->local_nonce) { > > + pr_debug("subflow=3D%p", sk); > > + token_new_subflow(sk); > > } > > = > > return inet_sk_rebuild_header(sk); > > @@ -95,7 +98,10 @@ static void subflow_finish_connect(struct sock *sk, = const struct sk_buff *skb) > > = > > inet_sk_rx_dst_set(sk, skb); > > = > > - if (subflow->conn && !subflow->conn_finished) { > > + if (!subflow->conn) > > + return; > > + > > + if (subflow->mp_capable && !subflow->conn_finished) { > > pr_debug("subflow=3D%p, remote_key=3D%llu", subflow_ctx(sk), > > subflow->remote_key); > > mptcp_finish_connect(subflow->conn, subflow->mp_capable); > > @@ -105,6 +111,17 @@ static void subflow_finish_connect(struct sock *sk= , const struct sk_buff *skb) > > pr_debug("synack seq=3D%u", TCP_SKB_CB(skb)->seq); > > subflow->ssn_offset =3D TCP_SKB_CB(skb)->seq; > > } > > + } else if (subflow->mp_join && !subflow->conn_finished) { > > + pr_debug("subflow=3D%p, thmac=3D%llu, remote_nonce=3D%u", > > + subflow_ctx(sk), subflow->thmac, > > + subflow->remote_nonce); > > + if (token_join_response(sk)) { > > + subflow->mp_join =3D 0; > > + // @@ need to trigger RST > > + } else { > > + mptcp_finish_join(sk); > > + subflow->conn_finished =3D 1; > > + } > > } > > } > > = > > @@ -195,6 +212,55 @@ static void subflow_data_ready(struct sock *sk) > > } > > } > > = > > +int subflow_connect(struct sock *sk, struct sockaddr_in *local, > > + struct sockaddr_in *remote, u8 remote_id) > > +{ > > + struct mptcp_sock *msk =3D mptcp_sk(sk); > > + struct subflow_context *subflow; > > + struct socket *sf; > > + u32 remote_token; > > + int err; > > + > > + lock_sock(sk); > > + err =3D subflow_create_socket(sk, &sf); > > + if (err) { > > + release_sock(sk); > > + return err; > > + } > > + > > + subflow =3D subflow_ctx(sf->sk); > > + subflow->remote_key =3D msk->remote_key; > > + subflow->local_key =3D msk->local_key; > > + subflow->token =3D msk->token; > > + > > + sock_hold(sf->sk); > > + release_sock(sk); > > + > > + err =3D kernel_bind(sf, (struct sockaddr *)local, > > + sizeof(struct sockaddr_in)); > > + if (err) > > + goto failed; > > + > > + crypto_key_sha1(subflow->remote_key, &remote_token, NULL); > > + pr_debug("msk=3D%p remote_token=3D%u", msk, remote_token); > > + subflow->remote_token =3D remote_token; > > + subflow->remote_id =3D remote_id; > > + subflow->request_join =3D 1; > > + subflow->request_bkup =3D 1; > > + > > + err =3D kernel_connect(sf, (struct sockaddr *)remote, > > + sizeof(struct sockaddr_in), O_NONBLOCK); > > + if (err && err !=3D -EINPROGRESS) > > + goto failed; > > + > > + sock_put(sf->sk); > > + return err; > > + > > +failed: > > + sock_release(sf); > = > Should there be a sock_put(sf->sk) on this path too? Looks like = > sock_release() will free the subflow context but not the struct sock = > itself. > = Yes. Since this is already merged I'll submit a separate patch. Peter. > Mat > = > = > > + return err; > > +} > > + > > int subflow_create_socket(struct sock *sk, struct socket **new_sock) > > { > > struct subflow_context *subflow; > > diff --git a/net/mptcp/token.c b/net/mptcp/token.c > > index ef03ef19af98..d7cf40b40beb 100644 > > --- a/net/mptcp/token.c > > +++ b/net/mptcp/token.c > > @@ -93,6 +93,28 @@ static void new_req_join(struct request_sock *req, s= truct sock *sk, > > subflow_req->thmac); > > } > > = > > +static int new_rsp_join(struct sock *sk) > > +{ > > + struct subflow_context *subflow =3D subflow_ctx(sk); > > + u8 hmac[MPTCPOPT_HMAC_LEN]; > > + u64 thmac; > > + > > + crypto_hmac_sha1(subflow->remote_key, subflow->local_key, > > + subflow->remote_nonce, subflow->local_nonce, > > + (u32 *)hmac); > > + > > + thmac =3D get_unaligned_be64(hmac); > > + pr_debug("thmac=3D%llu", thmac); > > + if (thmac !=3D subflow->thmac) > > + return -1; > > + > > + crypto_hmac_sha1(subflow->local_key, subflow->remote_key, > > + subflow->local_nonce, subflow->remote_nonce, > > + (u32 *)subflow->hmac); > > + > > + return 0; > > +} > > + > > static int new_join_valid(struct request_sock *req, struct sock *sk, > > struct tcp_options_received *rx_opt) > > { > > @@ -210,6 +232,15 @@ int token_join_request(struct request_sock *req, c= onst struct sk_buff *skb) > > return -1; > > } > > = > > +/* validate received truncated hmac and create hmac for third ACK */ > > +int token_join_response(struct sock *sk) > > +{ > > + struct subflow_context *subflow =3D subflow_ctx(sk); > > + > > + pr_debug("subflow=3D%p, token=3D%u", subflow, subflow->token); > > + return new_rsp_join(sk); > > +} > > + > > /* validate hmac received in third ACK */ > > int token_join_valid(struct request_sock *req, > > struct tcp_options_received *rx_opt) > > @@ -247,6 +278,23 @@ void token_new_connect(struct sock *sk) > > spin_unlock_bh(&token_tree_lock); > > } > > = > > +/* take reference to connection and create nonce for secondary subflow= */ > > +void token_new_subflow(struct sock *sk) > > +{ > > + struct subflow_context *subflow =3D subflow_ctx(sk); > > + struct sock *conn; > > + > > + pr_debug("subflow=3D%p", subflow); > > + > > + spin_lock_bh(&token_tree_lock); > > + conn =3D lookup_token(subflow->token); > > + if (conn) > > + sock_hold(conn); > > + spin_unlock_bh(&token_tree_lock); > > + > > + get_random_bytes(&subflow->local_nonce, sizeof(u32)); > > +} > > + > > void token_new_accept(struct sock *sk) > > { > > struct subflow_context *subflow =3D subflow_ctx(sk); > > -- = > > 2.17.2 > > = > > _______________________________________________ > > mptcp mailing list > > mptcp(a)lists.01.org > > https://lists.01.org/mailman/listinfo/mptcp > > = > = > -- > Mat Martineau > Intel --===============8118605917548709924==--