mptcp: setsockopt: handle SO_KEEPALIVE and SO_PRIORITY
start with something simple: both take an integer value, both need to be mirrored to all subflows. Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
df00b087da
commit
1b3e7ede13
@ -45,6 +45,90 @@ static u32 sockopt_seq_reset(const struct sock *sk)
|
||||
return (u32)sk->sk_state << 24u;
|
||||
}
|
||||
|
||||
static void sockopt_seq_inc(struct mptcp_sock *msk)
|
||||
{
|
||||
u32 seq = (msk->setsockopt_seq + 1) & 0x00ffffff;
|
||||
|
||||
msk->setsockopt_seq = sockopt_seq_reset((struct sock *)msk) + seq;
|
||||
}
|
||||
|
||||
static int mptcp_get_int_option(struct mptcp_sock *msk, sockptr_t optval,
|
||||
unsigned int optlen, int *val)
|
||||
{
|
||||
if (optlen < sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_sockptr(val, optval, sizeof(*val)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, int val)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
|
||||
lock_sock(sk);
|
||||
sockopt_seq_inc(msk);
|
||||
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
bool slow = lock_sock_fast(ssk);
|
||||
|
||||
switch (optname) {
|
||||
case SO_KEEPALIVE:
|
||||
if (ssk->sk_prot->keepalive)
|
||||
ssk->sk_prot->keepalive(ssk, !!val);
|
||||
sock_valbool_flag(ssk, SOCK_KEEPOPEN, !!val);
|
||||
break;
|
||||
case SO_PRIORITY:
|
||||
ssk->sk_priority = val;
|
||||
break;
|
||||
}
|
||||
|
||||
subflow->setsockopt_seq = msk->setsockopt_seq;
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
}
|
||||
|
||||
static int mptcp_sol_socket_intval(struct mptcp_sock *msk, int optname, int val)
|
||||
{
|
||||
sockptr_t optval = KERNEL_SOCKPTR(&val);
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
int ret;
|
||||
|
||||
ret = sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname,
|
||||
optval, sizeof(val));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mptcp_sol_socket_sync_intval(msk, optname, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
|
||||
sockptr_t optval, unsigned int optlen)
|
||||
{
|
||||
int val, ret;
|
||||
|
||||
ret = mptcp_get_int_option(msk, optval, optlen, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (optname) {
|
||||
case SO_KEEPALIVE:
|
||||
mptcp_sol_socket_sync_intval(msk, optname, val);
|
||||
return 0;
|
||||
case SO_PRIORITY:
|
||||
return mptcp_sol_socket_intval(msk, optname, val);
|
||||
}
|
||||
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
|
||||
sockptr_t optval, unsigned int optlen)
|
||||
{
|
||||
@ -71,6 +155,9 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
|
||||
}
|
||||
release_sock(sk);
|
||||
return ret;
|
||||
case SO_KEEPALIVE:
|
||||
case SO_PRIORITY:
|
||||
return mptcp_setsockopt_sol_socket_int(msk, optname, optval, optlen);
|
||||
}
|
||||
|
||||
return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, optval, optlen);
|
||||
@ -371,8 +458,27 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
|
||||
{
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
|
||||
if (ssk->sk_prot->keepalive) {
|
||||
if (sock_flag(sk, SOCK_KEEPOPEN))
|
||||
ssk->sk_prot->keepalive(ssk, 1);
|
||||
else
|
||||
ssk->sk_prot->keepalive(ssk, 0);
|
||||
}
|
||||
|
||||
ssk->sk_priority = sk->sk_priority;
|
||||
}
|
||||
|
||||
static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
|
||||
{
|
||||
bool slow = lock_sock_fast(ssk);
|
||||
|
||||
sync_socket_options(msk, ssk);
|
||||
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
|
||||
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
|
||||
|
Loading…
Reference in New Issue
Block a user