Skip to content

Commit 1b3e7ed

Browse files
Florian Westphaldavem330
Florian Westphal
authored andcommitted
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 <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent df00b08 commit 1b3e7ed

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

net/mptcp/sockopt.c

+106
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,90 @@ static u32 sockopt_seq_reset(const struct sock *sk)
4545
return (u32)sk->sk_state << 24u;
4646
}
4747

48+
static void sockopt_seq_inc(struct mptcp_sock *msk)
49+
{
50+
u32 seq = (msk->setsockopt_seq + 1) & 0x00ffffff;
51+
52+
msk->setsockopt_seq = sockopt_seq_reset((struct sock *)msk) + seq;
53+
}
54+
55+
static int mptcp_get_int_option(struct mptcp_sock *msk, sockptr_t optval,
56+
unsigned int optlen, int *val)
57+
{
58+
if (optlen < sizeof(int))
59+
return -EINVAL;
60+
61+
if (copy_from_sockptr(val, optval, sizeof(*val)))
62+
return -EFAULT;
63+
64+
return 0;
65+
}
66+
67+
static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, int val)
68+
{
69+
struct mptcp_subflow_context *subflow;
70+
struct sock *sk = (struct sock *)msk;
71+
72+
lock_sock(sk);
73+
sockopt_seq_inc(msk);
74+
75+
mptcp_for_each_subflow(msk, subflow) {
76+
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
77+
bool slow = lock_sock_fast(ssk);
78+
79+
switch (optname) {
80+
case SO_KEEPALIVE:
81+
if (ssk->sk_prot->keepalive)
82+
ssk->sk_prot->keepalive(ssk, !!val);
83+
sock_valbool_flag(ssk, SOCK_KEEPOPEN, !!val);
84+
break;
85+
case SO_PRIORITY:
86+
ssk->sk_priority = val;
87+
break;
88+
}
89+
90+
subflow->setsockopt_seq = msk->setsockopt_seq;
91+
unlock_sock_fast(ssk, slow);
92+
}
93+
94+
release_sock(sk);
95+
}
96+
97+
static int mptcp_sol_socket_intval(struct mptcp_sock *msk, int optname, int val)
98+
{
99+
sockptr_t optval = KERNEL_SOCKPTR(&val);
100+
struct sock *sk = (struct sock *)msk;
101+
int ret;
102+
103+
ret = sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname,
104+
optval, sizeof(val));
105+
if (ret)
106+
return ret;
107+
108+
mptcp_sol_socket_sync_intval(msk, optname, val);
109+
return 0;
110+
}
111+
112+
static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
113+
sockptr_t optval, unsigned int optlen)
114+
{
115+
int val, ret;
116+
117+
ret = mptcp_get_int_option(msk, optval, optlen, &val);
118+
if (ret)
119+
return ret;
120+
121+
switch (optname) {
122+
case SO_KEEPALIVE:
123+
mptcp_sol_socket_sync_intval(msk, optname, val);
124+
return 0;
125+
case SO_PRIORITY:
126+
return mptcp_sol_socket_intval(msk, optname, val);
127+
}
128+
129+
return -ENOPROTOOPT;
130+
}
131+
48132
static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
49133
sockptr_t optval, unsigned int optlen)
50134
{
@@ -71,6 +155,9 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
71155
}
72156
release_sock(sk);
73157
return ret;
158+
case SO_KEEPALIVE:
159+
case SO_PRIORITY:
160+
return mptcp_setsockopt_sol_socket_int(msk, optname, optval, optlen);
74161
}
75162

76163
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,
371458
return -EOPNOTSUPP;
372459
}
373460

461+
static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
462+
{
463+
struct sock *sk = (struct sock *)msk;
464+
465+
if (ssk->sk_prot->keepalive) {
466+
if (sock_flag(sk, SOCK_KEEPOPEN))
467+
ssk->sk_prot->keepalive(ssk, 1);
468+
else
469+
ssk->sk_prot->keepalive(ssk, 0);
470+
}
471+
472+
ssk->sk_priority = sk->sk_priority;
473+
}
474+
374475
static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
375476
{
477+
bool slow = lock_sock_fast(ssk);
478+
479+
sync_socket_options(msk, ssk);
480+
481+
unlock_sock_fast(ssk, slow);
376482
}
377483

378484
void mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)

0 commit comments

Comments
 (0)