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 | ||||
| #include <net/mptcp.h> | ||||
| #include <net/xfrm.h> | ||||
| #include <asm/ioctls.h> | ||||
| #include "protocol.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; | ||||
| } | ||||
| 
 | ||||
| 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 = { | ||||
| 	.name		= "MPTCP", | ||||
| 	.owner		= THIS_MODULE, | ||||
|  | @ -3223,6 +3275,7 @@ static struct proto mptcp_prot = { | |||
| 	.shutdown	= mptcp_shutdown, | ||||
| 	.destroy	= mptcp_destroy, | ||||
| 	.sendmsg	= mptcp_sendmsg, | ||||
| 	.ioctl		= mptcp_ioctl, | ||||
| 	.recvmsg	= mptcp_recvmsg, | ||||
| 	.release_cb	= mptcp_release_cb, | ||||
| 	.hash		= mptcp_hash, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Florian Westphal
						Florian Westphal