mptcp: support TCP_CORK and TCP_NODELAY
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>
This commit is contained in:
parent
8b38217a2a
commit
4f6e14bd19
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user