forked from mirrors/linux
		
	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…
	
		Reference in a new issue
	
	 Florian Westphal
						Florian Westphal