Skip to content

Commit

Permalink
mptcp: support TCP_CORK and TCP_NODELAY
Browse files Browse the repository at this point in the history
First, add cork and nodelay fields to the mptcp_sock structure
so they can be used in sync_socket_options(), and fill them on setsockopt
while holding the msk socket lock.

Then, on setsockopt set proper tcp_sk(ssk)->nonagle values for subflows
by calling __tcp_sock_set_cork() or __tcp_sock_set_nodelay() on the ssk
while holding the ssk socket lock.

tcp_push_pending_frames() will be invoked on the ssk if a cork was cleared
or nodelay was set. Also set MPTCP_PUSH_PENDING bit by calling
mptcp_check_and_set_pending(). This will lead to __mptcp_push_pending()
being called inside mptcp_release_cb() with new tcp_sk(ssk)->nonagle.

Also add getsockopt support for TCP_CORK and TCP_NODELAY.

Acked-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Maxim Galaganov <max@internet.ru>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
darkwrat authored and kuba-moo committed Dec 7, 2021
1 parent 8b38217 commit 4f6e14b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
4 changes: 3 additions & 1 deletion net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ struct mptcp_sock {
bool rcv_fastclose;
bool use_64bit_ack; /* Set when we received a 64-bit DSN */
bool csum_enabled;
u8 recvmsg_inq:1;
u8 recvmsg_inq:1,
cork:1,
nodelay:1;
spinlock_t join_list_lock;
struct work_struct work;
struct sk_buff *ooo_last_skb;
Expand Down
70 changes: 70 additions & 0 deletions net/mptcp/sockopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,66 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
return ret;
}

static int mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, sockptr_t optval,
unsigned int optlen)
{
struct mptcp_subflow_context *subflow;
struct sock *sk = (struct sock *)msk;
int val;

if (optlen < sizeof(int))
return -EINVAL;

if (copy_from_sockptr(&val, optval, sizeof(val)))
return -EFAULT;

lock_sock(sk);
sockopt_seq_inc(msk);
msk->cork = !!val;
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);

lock_sock(ssk);
__tcp_sock_set_cork(ssk, !!val);
release_sock(ssk);
}
if (!val)
mptcp_check_and_set_pending(sk);
release_sock(sk);

return 0;
}

static int mptcp_setsockopt_sol_tcp_nodelay(struct mptcp_sock *msk, sockptr_t optval,
unsigned int optlen)
{
struct mptcp_subflow_context *subflow;
struct sock *sk = (struct sock *)msk;
int val;

if (optlen < sizeof(int))
return -EINVAL;

if (copy_from_sockptr(&val, optval, sizeof(val)))
return -EFAULT;

lock_sock(sk);
sockopt_seq_inc(msk);
msk->nodelay = !!val;
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);

lock_sock(ssk);
__tcp_sock_set_nodelay(ssk, !!val);
release_sock(ssk);
}
if (val)
mptcp_check_and_set_pending(sk);
release_sock(sk);

return 0;
}

static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int optname,
sockptr_t optval, unsigned int optlen)
{
Expand Down Expand Up @@ -717,6 +777,10 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
return -EOPNOTSUPP;
case TCP_CONGESTION:
return mptcp_setsockopt_sol_tcp_congestion(msk, optval, optlen);
case TCP_CORK:
return mptcp_setsockopt_sol_tcp_cork(msk, optval, optlen);
case TCP_NODELAY:
return mptcp_setsockopt_sol_tcp_nodelay(msk, optval, optlen);
}

return -EOPNOTSUPP;
Expand Down Expand Up @@ -1087,6 +1151,10 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
optval, optlen);
case TCP_INQ:
return mptcp_put_int_option(msk, optval, optlen, msk->recvmsg_inq);
case TCP_CORK:
return mptcp_put_int_option(msk, optval, optlen, msk->cork);
case TCP_NODELAY:
return mptcp_put_int_option(msk, optval, optlen, msk->nodelay);
}
return -EOPNOTSUPP;
}
Expand Down Expand Up @@ -1189,6 +1257,8 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)

if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops)
tcp_set_congestion_control(ssk, msk->ca_name, false, true);
__tcp_sock_set_cork(ssk, !!msk->cork);
__tcp_sock_set_nodelay(ssk, !!msk->nodelay);

inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
inet_sk(ssk)->freebind = inet_sk(sk)->freebind;
Expand Down

0 comments on commit 4f6e14b

Please sign in to comment.