forked from mirrors/linux
		
	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
					
				
					 1 changed files with 106 additions and 0 deletions
				
			
		|  | @ -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 a new issue
	
	 Florian Westphal
						Florian Westphal