mptcp: add SIOCINQ, OUTQ and OUTQNSD ioctls
Allows to query in-sequence data ready for read(), total bytes in write queue and total bytes in write queue that have not yet been sent. v2: remove unneeded READ_ONCE() (Paolo Abeni) v3: check for new data unconditionally in SIOCINQ ioctl (Mat Martineau) Signed-off-by: Florian Westphal <fw@strlen.de> 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
5cbd886ce2
commit
644807e3e4
1 changed files with 53 additions and 0 deletions
|
@ -22,6 +22,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include <net/mptcp.h>
|
#include <net/mptcp.h>
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
|
#include <asm/ioctls.h>
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "mib.h"
|
#include "mib.h"
|
||||||
|
|
||||||
|
@ -3211,6 +3212,57 @@ static int mptcp_forward_alloc_get(const struct sock *sk)
|
||||||
return sk->sk_forward_alloc + mptcp_sk(sk)->rmem_fwd_alloc;
|
return sk->sk_forward_alloc + mptcp_sk(sk)->rmem_fwd_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mptcp_ioctl_outq(const struct mptcp_sock *msk, u64 v)
|
||||||
|
{
|
||||||
|
const struct sock *sk = (void *)msk;
|
||||||
|
u64 delta;
|
||||||
|
|
||||||
|
if (sk->sk_state == TCP_LISTEN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
delta = msk->write_seq - v;
|
||||||
|
if (delta > INT_MAX)
|
||||||
|
delta = INT_MAX;
|
||||||
|
|
||||||
|
return (int)delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct mptcp_sock *msk = mptcp_sk(sk);
|
||||||
|
bool slow;
|
||||||
|
int answ;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SIOCINQ:
|
||||||
|
if (sk->sk_state == TCP_LISTEN)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
lock_sock(sk);
|
||||||
|
__mptcp_move_skbs(msk);
|
||||||
|
answ = mptcp_inq_hint(sk);
|
||||||
|
release_sock(sk);
|
||||||
|
break;
|
||||||
|
case SIOCOUTQ:
|
||||||
|
slow = lock_sock_fast(sk);
|
||||||
|
answ = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una));
|
||||||
|
unlock_sock_fast(sk, slow);
|
||||||
|
break;
|
||||||
|
case SIOCOUTQNSD:
|
||||||
|
slow = lock_sock_fast(sk);
|
||||||
|
answ = mptcp_ioctl_outq(msk, msk->snd_nxt);
|
||||||
|
unlock_sock_fast(sk, slow);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return put_user(answ, (int __user *)arg);
|
||||||
|
}
|
||||||
|
|
||||||
static struct proto mptcp_prot = {
|
static struct proto mptcp_prot = {
|
||||||
.name = "MPTCP",
|
.name = "MPTCP",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
|
@ -3223,6 +3275,7 @@ static struct proto mptcp_prot = {
|
||||||
.shutdown = mptcp_shutdown,
|
.shutdown = mptcp_shutdown,
|
||||||
.destroy = mptcp_destroy,
|
.destroy = mptcp_destroy,
|
||||||
.sendmsg = mptcp_sendmsg,
|
.sendmsg = mptcp_sendmsg,
|
||||||
|
.ioctl = mptcp_ioctl,
|
||||||
.recvmsg = mptcp_recvmsg,
|
.recvmsg = mptcp_recvmsg,
|
||||||
.release_cb = mptcp_release_cb,
|
.release_cb = mptcp_release_cb,
|
||||||
.hash = mptcp_hash,
|
.hash = mptcp_hash,
|
||||||
|
|
Loading…
Add table
Reference in a new issue