diff mbox series

[v2,mptcp-next,2/3] mptcp: sockopt: support IP_LOCAL_PORT_RANGE and IP_BIND_ADDRESS_NO_PORT

Message ID 20231129113403.157953-3-max@internet.ru (mailing list archive)
State Superseded, archived
Delegated to: Mat Martineau
Headers show
Series more sockopts for ephemeral ports | expand

Checks

Context Check Description
matttbe/build success Build and static analysis OK
matttbe/checkpatch success total: 0 errors, 0 warnings, 0 checks, 75 lines checked
matttbe/KVM_Validation__normal__except_selftest_mptcp_join_ success Success! ✅
matttbe/KVM_Validation__normal__only_selftest_mptcp_join_ success Success! ✅
matttbe/KVM_Validation__debug__except_selftest_mptcp_join_ success Success! ✅
matttbe/KVM_Validation__debug__only_selftest_mptcp_join_ success Success! ✅

Commit Message

Maxim Galaganov Nov. 29, 2023, 11:34 a.m. UTC
Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
Recently [2] allowed its value to be accessed without locking the
socket.

Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
In the same series a selftest was added in [4]. This selftest also
covers the IP_BIND_ADDRESS_NO_PORT sockopt.

This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
socket options, syncing set values to subflows in sync_socket_options().
Ephemeral port range is synced to subflows, enabling NAT usecase
described in [3].

[1] commit 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
bind(0) limitations")
[2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
inet->inet_flags")
[3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
[4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
socket option")

Signed-off-by: Maxim Galaganov <max@internet.ru>
---
 net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

Comments

Mat Martineau Nov. 29, 2023, 6:07 p.m. UTC | #1
On Wed, 29 Nov 2023, Maxim Galaganov wrote:

> Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
> Recently [2] allowed its value to be accessed without locking the
> socket.
>
> Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
> In the same series a selftest was added in [4]. This selftest also
> covers the IP_BIND_ADDRESS_NO_PORT sockopt.
>
> This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
> socket options, syncing set values to subflows in sync_socket_options().
> Ephemeral port range is synced to subflows, enabling NAT usecase
> described in [3].
>
> [1] commit 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
> bind(0) limitations")
> [2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
> inet->inet_flags")
> [3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
> [4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
> socket option")
>
> Signed-off-by: Maxim Galaganov <max@internet.ru>

Thanks for the v2 Maxim, looks good to me:

Reviewed-by: Mat Martineau <martineau@kernel.org>

> ---
> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++-
> 1 file changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
> index a4bf337e6f77..a164a3e21be4 100644
> --- a/net/mptcp/sockopt.c
> +++ b/net/mptcp/sockopt.c
> @@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int optname)
> 		/* should work fine */
> 		case IP_FREEBIND:
> 		case IP_TRANSPARENT:
> +		case IP_BIND_ADDRESS_NO_PORT:
> +		case IP_LOCAL_PORT_RANGE:
>
> 		/* the following are control cmsg related */
> 		case IP_PKTINFO:
> @@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int optname)
> 		/* common stuff that need some love */
> 		case IP_TOS:
> 		case IP_TTL:
> -		case IP_BIND_ADDRESS_NO_PORT:
> 		case IP_MTU_DISCOVER:
> 		case IP_RECVERR:
>
> @@ -688,6 +689,7 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
> {
> 	struct sock *sk = (struct sock *)msk;
> 	struct sock *ssk;
> +	bool slow;
> 	int err;
>
> 	err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
> @@ -710,6 +712,16 @@ static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
> 		inet_assign_bit(TRANSPARENT, ssk,
> 				inet_test_bit(TRANSPARENT, sk));
> 		break;
> +	case IP_BIND_ADDRESS_NO_PORT:
> +		inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
> +				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> +		break;
> +	case IP_LOCAL_PORT_RANGE:
> +		slow = lock_sock_fast(ssk);
> +		inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
> +		inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
> +		unlock_sock_fast(ssk, slow);
> +		break;
> 	default:
> 		release_sock(sk);
> 		WARN_ON_ONCE(1);
> @@ -755,6 +767,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
> 	switch (optname) {
> 	case IP_FREEBIND:
> 	case IP_TRANSPARENT:
> +	case IP_BIND_ADDRESS_NO_PORT:
> +	case IP_LOCAL_PORT_RANGE:
> 		return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen);
> 	case IP_TOS:
> 		return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen);
> @@ -1346,10 +1360,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
> 			       char __user *optval, int __user *optlen)
> {
> 	struct sock *sk = (void *)msk;
> +	bool slow;
> +	int val;
>
> 	switch (optname) {
> 	case IP_TOS:
> 		return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->tos));
> +	case IP_BIND_ADDRESS_NO_PORT:
> +		return mptcp_put_int_option(msk, optval, optlen,
> +				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> +	case IP_LOCAL_PORT_RANGE:
> +		slow = lock_sock_fast(sk);
> +		val = inet_sk(sk)->local_port_range.hi << 16 | inet_sk(sk)->local_port_range.lo;
> +		unlock_sock_fast(sk, slow);
> +		return mptcp_put_int_option(msk, optval, optlen, val);
> 	}
>
> 	return -EOPNOTSUPP;
> @@ -1450,6 +1474,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
>
> 	inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
> 	inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
> +	inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> +	inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
> +	inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
> }
>
> void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
> -- 
> 2.43.0
>
>
>
Mat Martineau Dec. 1, 2023, 11:59 p.m. UTC | #2
On Wed, 29 Nov 2023, Mat Martineau wrote:

> On Wed, 29 Nov 2023, Maxim Galaganov wrote:
>
>> Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
>> Recently [2] allowed its value to be accessed without locking the
>> socket.
>> 
>> Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
>> In the same series a selftest was added in [4]. This selftest also
>> covers the IP_BIND_ADDRESS_NO_PORT sockopt.
>> 
>> This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
>> socket options, syncing set values to subflows in sync_socket_options().
>> Ephemeral port range is synced to subflows, enabling NAT usecase
>> described in [3].
>> 
>> [1] commit 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
>> bind(0) limitations")
>> [2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
>> inet->inet_flags")
>> [3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
>> [4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
>> socket option")
>> 
>> Signed-off-by: Maxim Galaganov <max@internet.ru>
>
> Thanks for the v2 Maxim, looks good to me:
>
> Reviewed-by: Mat Martineau <martineau@kernel.org>
>

Now that I've signed off on this, I see that there's work going on to 
change the implementation of local_port_range:

https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/

I think it makes sense to do a v3 of this series if a version of David's 
patch gets merged soon (I expect a v2 as he got some feedback from me and 
some others). I'll watch for progress with his patch on netdev.


- Mat

>> ---
>> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++-
>> 1 file changed, 28 insertions(+), 1 deletion(-)
>> 
>> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
>> index a4bf337e6f77..a164a3e21be4 100644
>> --- a/net/mptcp/sockopt.c
>> +++ b/net/mptcp/sockopt.c
>> @@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int 
>> optname)
>> 		/* should work fine */
>> 		case IP_FREEBIND:
>> 		case IP_TRANSPARENT:
>> +		case IP_BIND_ADDRESS_NO_PORT:
>> +		case IP_LOCAL_PORT_RANGE:
>>
>> 		/* the following are control cmsg related */
>> 		case IP_PKTINFO:
>> @@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int 
>> optname)
>> 		/* common stuff that need some love */
>> 		case IP_TOS:
>> 		case IP_TTL:
>> -		case IP_BIND_ADDRESS_NO_PORT:
>> 		case IP_MTU_DISCOVER:
>> 		case IP_RECVERR:
>> 
>> @@ -688,6 +689,7 @@ static int mptcp_setsockopt_sol_ip_set(struct 
>> mptcp_sock *msk, int optname,
>> {
>> 	struct sock *sk = (struct sock *)msk;
>> 	struct sock *ssk;
>> +	bool slow;
>> 	int err;
>>
>> 	err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
>> @@ -710,6 +712,16 @@ static int mptcp_setsockopt_sol_ip_set(struct 
>> mptcp_sock *msk, int optname,
>> 		inet_assign_bit(TRANSPARENT, ssk,
>> 				inet_test_bit(TRANSPARENT, sk));
>> 		break;
>> +	case IP_BIND_ADDRESS_NO_PORT:
>> +		inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
>> +				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>> +		break;
>> +	case IP_LOCAL_PORT_RANGE:
>> +		slow = lock_sock_fast(ssk);
>> +		inet_sk(ssk)->local_port_range.lo = 
>> inet_sk(sk)->local_port_range.lo;
>> +		inet_sk(ssk)->local_port_range.hi = 
>> inet_sk(sk)->local_port_range.hi;
>> +		unlock_sock_fast(ssk, slow);
>> +		break;
>> 	default:
>> 		release_sock(sk);
>> 		WARN_ON_ONCE(1);
>> @@ -755,6 +767,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, 
>> int optname,
>> 	switch (optname) {
>> 	case IP_FREEBIND:
>> 	case IP_TRANSPARENT:
>> +	case IP_BIND_ADDRESS_NO_PORT:
>> +	case IP_LOCAL_PORT_RANGE:
>> 		return mptcp_setsockopt_sol_ip_set(msk, optname, optval, 
>> optlen);
>> 	case IP_TOS:
>> 		return mptcp_setsockopt_v4_set_tos(msk, optname, optval, 
>> optlen);
>> @@ -1346,10 +1360,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock 
>> *msk, int optname,
>> 			       char __user *optval, int __user *optlen)
>> {
>> 	struct sock *sk = (void *)msk;
>> +	bool slow;
>> +	int val;
>>
>> 	switch (optname) {
>> 	case IP_TOS:
>> 		return mptcp_put_int_option(msk, optval, optlen, 
>> READ_ONCE(inet_sk(sk)->tos));
>> +	case IP_BIND_ADDRESS_NO_PORT:
>> +		return mptcp_put_int_option(msk, optval, optlen,
>> +				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>> +	case IP_LOCAL_PORT_RANGE:
>> +		slow = lock_sock_fast(sk);
>> +		val = inet_sk(sk)->local_port_range.hi << 16 | 
>> inet_sk(sk)->local_port_range.lo;
>> +		unlock_sock_fast(sk, slow);
>> +		return mptcp_put_int_option(msk, optval, optlen, val);
>> 	}
>>
>> 	return -EOPNOTSUPP;
>> @@ -1450,6 +1474,9 @@ static void sync_socket_options(struct mptcp_sock 
>> *msk, struct sock *ssk)
>>
>> 	inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
>> 	inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
>> +	inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, 
>> inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>> +	inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
>> +	inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
>> }
>> 
>> void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
>> -- 
>> 2.43.0
>> 
>> 
>> 
>
Mat Martineau Dec. 8, 2023, 12:24 a.m. UTC | #3
On Fri, Dec 1, 2023 at 3:59 PM Mat Martineau <martineau@kernel.org> wrote:
>
> On Wed, 29 Nov 2023, Mat Martineau wrote:
>
> > On Wed, 29 Nov 2023, Maxim Galaganov wrote:
> >
> >> Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
> >> Recently [2] allowed its value to be accessed without locking the
> >> socket.
> >>
> >> Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
> >> In the same series a selftest was added in [4]. This selftest also
> >> covers the IP_BIND_ADDRESS_NO_PORT sockopt.
> >>
> >> This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
> >> socket options, syncing set values to subflows in sync_socket_options().
> >> Ephemeral port range is synced to subflows, enabling NAT usecase
> >> described in [3].
> >>
> >> [1] commit 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
> >> bind(0) limitations")
> >> [2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
> >> inet->inet_flags")
> >> [3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
> >> [4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
> >> socket option")
> >>
> >> Signed-off-by: Maxim Galaganov <max@internet.ru>
> >
> > Thanks for the v2 Maxim, looks good to me:
> >
> > Reviewed-by: Mat Martineau <martineau@kernel.org>
> >
>
> Now that I've signed off on this, I see that there's work going on to
> change the implementation of local_port_range:
>
> https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/
>
> I think it makes sense to do a v3 of this series if a version of David's
> patch gets merged soon (I expect a v2 as he got some feedback from me and
> some others). I'll watch for progress with his patch on netdev.

Maxim -

It looks like this patch will be merged to net-next soon:

https://lore.kernel.org/netdev/4e505d4198e946a8be03fb1b4c3072b0@AcuMS.aculab.com/

Please cherry-pick that and update your IP_LOCAL_PORT_RANGE patch to
fit the new implementation.

Thanks!

- Mat


>
> >> ---
> >> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++-
> >> 1 file changed, 28 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
> >> index a4bf337e6f77..a164a3e21be4 100644
> >> --- a/net/mptcp/sockopt.c
> >> +++ b/net/mptcp/sockopt.c
> >> @@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int
> >> optname)
> >>              /* should work fine */
> >>              case IP_FREEBIND:
> >>              case IP_TRANSPARENT:
> >> +            case IP_BIND_ADDRESS_NO_PORT:
> >> +            case IP_LOCAL_PORT_RANGE:
> >>
> >>              /* the following are control cmsg related */
> >>              case IP_PKTINFO:
> >> @@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int
> >> optname)
> >>              /* common stuff that need some love */
> >>              case IP_TOS:
> >>              case IP_TTL:
> >> -            case IP_BIND_ADDRESS_NO_PORT:
> >>              case IP_MTU_DISCOVER:
> >>              case IP_RECVERR:
> >>
> >> @@ -688,6 +689,7 @@ static int mptcp_setsockopt_sol_ip_set(struct
> >> mptcp_sock *msk, int optname,
> >> {
> >>      struct sock *sk = (struct sock *)msk;
> >>      struct sock *ssk;
> >> +    bool slow;
> >>      int err;
> >>
> >>      err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
> >> @@ -710,6 +712,16 @@ static int mptcp_setsockopt_sol_ip_set(struct
> >> mptcp_sock *msk, int optname,
> >>              inet_assign_bit(TRANSPARENT, ssk,
> >>                              inet_test_bit(TRANSPARENT, sk));
> >>              break;
> >> +    case IP_BIND_ADDRESS_NO_PORT:
> >> +            inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
> >> +                            inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> >> +            break;
> >> +    case IP_LOCAL_PORT_RANGE:
> >> +            slow = lock_sock_fast(ssk);
> >> +            inet_sk(ssk)->local_port_range.lo =
> >> inet_sk(sk)->local_port_range.lo;
> >> +            inet_sk(ssk)->local_port_range.hi =
> >> inet_sk(sk)->local_port_range.hi;
> >> +            unlock_sock_fast(ssk, slow);
> >> +            break;
> >>      default:
> >>              release_sock(sk);
> >>              WARN_ON_ONCE(1);
> >> @@ -755,6 +767,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk,
> >> int optname,
> >>      switch (optname) {
> >>      case IP_FREEBIND:
> >>      case IP_TRANSPARENT:
> >> +    case IP_BIND_ADDRESS_NO_PORT:
> >> +    case IP_LOCAL_PORT_RANGE:
> >>              return mptcp_setsockopt_sol_ip_set(msk, optname, optval,
> >> optlen);
> >>      case IP_TOS:
> >>              return mptcp_setsockopt_v4_set_tos(msk, optname, optval,
> >> optlen);
> >> @@ -1346,10 +1360,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock
> >> *msk, int optname,
> >>                             char __user *optval, int __user *optlen)
> >> {
> >>      struct sock *sk = (void *)msk;
> >> +    bool slow;
> >> +    int val;
> >>
> >>      switch (optname) {
> >>      case IP_TOS:
> >>              return mptcp_put_int_option(msk, optval, optlen,
> >> READ_ONCE(inet_sk(sk)->tos));
> >> +    case IP_BIND_ADDRESS_NO_PORT:
> >> +            return mptcp_put_int_option(msk, optval, optlen,
> >> +                            inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> >> +    case IP_LOCAL_PORT_RANGE:
> >> +            slow = lock_sock_fast(sk);
> >> +            val = inet_sk(sk)->local_port_range.hi << 16 |
> >> inet_sk(sk)->local_port_range.lo;
> >> +            unlock_sock_fast(sk, slow);
> >> +            return mptcp_put_int_option(msk, optval, optlen, val);
> >>      }
> >>
> >>      return -EOPNOTSUPP;
> >> @@ -1450,6 +1474,9 @@ static void sync_socket_options(struct mptcp_sock
> >> *msk, struct sock *ssk)
> >>
> >>      inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
> >>      inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
> >> +    inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
> >> inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
> >> +    inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
> >> +    inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
> >> }
> >>
> >> void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
> >> --
> >> 2.43.0
> >>
> >>
> >>
> >
Maxim Galaganov Dec. 8, 2023, 6:04 p.m. UTC | #4
On 08.12.2023 03:24, Mat Martineau wrote:
> On Fri, Dec 1, 2023 at 3:59 PM Mat Martineau <martineau@kernel.org> wrote:
>>
>> On Wed, 29 Nov 2023, Mat Martineau wrote:
>>
>>> On Wed, 29 Nov 2023, Maxim Galaganov wrote:
>>>
>>>> Support for IP_BIND_ADDRESS_NO_PORT sockopt was introduced in [1].
>>>> Recently [2] allowed its value to be accessed without locking the
>>>> socket.
>>>>
>>>> Support for (newer) IP_LOCAL_PORT_RANGE sockopt was introduced in [3].
>>>> In the same series a selftest was added in [4]. This selftest also
>>>> covers the IP_BIND_ADDRESS_NO_PORT sockopt.
>>>>
>>>> This patch enables getsockopt()/setsockopt() on MPTCP sockets for these
>>>> socket options, syncing set values to subflows in sync_socket_options().
>>>> Ephemeral port range is synced to subflows, enabling NAT usecase
>>>> described in [3].
>>>>
>>>> [1] commit 90c337da1524 ("inet: add IP_BIND_ADDRESS_NO_PORT to overcome
>>>> bind(0) limitations")
>>>> [2] commit ca571e2eb7eb ("inet: move inet->bind_address_no_port to
>>>> inet->inet_flags")
>>>> [3] commit 91d0b78c5177 ("inet: Add IP_LOCAL_PORT_RANGE socket option")
>>>> [4] commit ae5439658cce ("selftests/net: Cover the IP_LOCAL_PORT_RANGE
>>>> socket option")
>>>>
>>>> Signed-off-by: Maxim Galaganov <max@internet.ru>
>>>
>>> Thanks for the v2 Maxim, looks good to me:
>>>
>>> Reviewed-by: Mat Martineau <martineau@kernel.org>
>>>
>>
>> Now that I've signed off on this, I see that there's work going on to
>> change the implementation of local_port_range:
>>
>> https://lore.kernel.org/netdev/a4f5b61c9cd44eada41d8f09d3848806@AcuMS.aculab.com/
>>
>> I think it makes sense to do a v3 of this series if a version of David's
>> patch gets merged soon (I expect a v2 as he got some feedback from me and
>> some others). I'll watch for progress with his patch on netdev.
> 
> Maxim -
> 
> It looks like this patch will be merged to net-next soon:
> 
> https://lore.kernel.org/netdev/4e505d4198e946a8be03fb1b4c3072b0@AcuMS.aculab.com/
> 
> Please cherry-pick that and update your IP_LOCAL_PORT_RANGE patch to
> fit the new implementation.

Hi Mat,

I'd prefer posting v3 once the mentioned patch gets to net-next and then 
export branch, otherwise bots will probably complain about build errors. 
Tell me if I should just post them now.

Thank you for spotting and tracking this.

Max

> 
> Thanks!
> 
> - Mat
> 
> 
>>
>>>> ---
>>>> net/mptcp/sockopt.c | 29 ++++++++++++++++++++++++++++-
>>>> 1 file changed, 28 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
>>>> index a4bf337e6f77..a164a3e21be4 100644
>>>> --- a/net/mptcp/sockopt.c
>>>> +++ b/net/mptcp/sockopt.c
>>>> @@ -440,6 +440,8 @@ static bool mptcp_supported_sockopt(int level, int
>>>> optname)
>>>>               /* should work fine */
>>>>               case IP_FREEBIND:
>>>>               case IP_TRANSPARENT:
>>>> +            case IP_BIND_ADDRESS_NO_PORT:
>>>> +            case IP_LOCAL_PORT_RANGE:
>>>>
>>>>               /* the following are control cmsg related */
>>>>               case IP_PKTINFO:
>>>> @@ -455,7 +457,6 @@ static bool mptcp_supported_sockopt(int level, int
>>>> optname)
>>>>               /* common stuff that need some love */
>>>>               case IP_TOS:
>>>>               case IP_TTL:
>>>> -            case IP_BIND_ADDRESS_NO_PORT:
>>>>               case IP_MTU_DISCOVER:
>>>>               case IP_RECVERR:
>>>>
>>>> @@ -688,6 +689,7 @@ static int mptcp_setsockopt_sol_ip_set(struct
>>>> mptcp_sock *msk, int optname,
>>>> {
>>>>       struct sock *sk = (struct sock *)msk;
>>>>       struct sock *ssk;
>>>> +    bool slow;
>>>>       int err;
>>>>
>>>>       err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
>>>> @@ -710,6 +712,16 @@ static int mptcp_setsockopt_sol_ip_set(struct
>>>> mptcp_sock *msk, int optname,
>>>>               inet_assign_bit(TRANSPARENT, ssk,
>>>>                               inet_test_bit(TRANSPARENT, sk));
>>>>               break;
>>>> +    case IP_BIND_ADDRESS_NO_PORT:
>>>> +            inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
>>>> +                            inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>>>> +            break;
>>>> +    case IP_LOCAL_PORT_RANGE:
>>>> +            slow = lock_sock_fast(ssk);
>>>> +            inet_sk(ssk)->local_port_range.lo =
>>>> inet_sk(sk)->local_port_range.lo;
>>>> +            inet_sk(ssk)->local_port_range.hi =
>>>> inet_sk(sk)->local_port_range.hi;
>>>> +            unlock_sock_fast(ssk, slow);
>>>> +            break;
>>>>       default:
>>>>               release_sock(sk);
>>>>               WARN_ON_ONCE(1);
>>>> @@ -755,6 +767,8 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk,
>>>> int optname,
>>>>       switch (optname) {
>>>>       case IP_FREEBIND:
>>>>       case IP_TRANSPARENT:
>>>> +    case IP_BIND_ADDRESS_NO_PORT:
>>>> +    case IP_LOCAL_PORT_RANGE:
>>>>               return mptcp_setsockopt_sol_ip_set(msk, optname, optval,
>>>> optlen);
>>>>       case IP_TOS:
>>>>               return mptcp_setsockopt_v4_set_tos(msk, optname, optval,
>>>> optlen);
>>>> @@ -1346,10 +1360,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock
>>>> *msk, int optname,
>>>>                              char __user *optval, int __user *optlen)
>>>> {
>>>>       struct sock *sk = (void *)msk;
>>>> +    bool slow;
>>>> +    int val;
>>>>
>>>>       switch (optname) {
>>>>       case IP_TOS:
>>>>               return mptcp_put_int_option(msk, optval, optlen,
>>>> READ_ONCE(inet_sk(sk)->tos));
>>>> +    case IP_BIND_ADDRESS_NO_PORT:
>>>> +            return mptcp_put_int_option(msk, optval, optlen,
>>>> +                            inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>>>> +    case IP_LOCAL_PORT_RANGE:
>>>> +            slow = lock_sock_fast(sk);
>>>> +            val = inet_sk(sk)->local_port_range.hi << 16 |
>>>> inet_sk(sk)->local_port_range.lo;
>>>> +            unlock_sock_fast(sk, slow);
>>>> +            return mptcp_put_int_option(msk, optval, optlen, val);
>>>>       }
>>>>
>>>>       return -EOPNOTSUPP;
>>>> @@ -1450,6 +1474,9 @@ static void sync_socket_options(struct mptcp_sock
>>>> *msk, struct sock *ssk)
>>>>
>>>>       inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
>>>>       inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
>>>> +    inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
>>>> inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
>>>> +    inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
>>>> +    inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
>>>> }
>>>>
>>>> void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)
>>>> --
>>>> 2.43.0
>>>>
>>>>
>>>>
>>>
diff mbox series

Patch

diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index a4bf337e6f77..a164a3e21be4 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -440,6 +440,8 @@  static bool mptcp_supported_sockopt(int level, int optname)
 		/* should work fine */
 		case IP_FREEBIND:
 		case IP_TRANSPARENT:
+		case IP_BIND_ADDRESS_NO_PORT:
+		case IP_LOCAL_PORT_RANGE:
 
 		/* the following are control cmsg related */
 		case IP_PKTINFO:
@@ -455,7 +457,6 @@  static bool mptcp_supported_sockopt(int level, int optname)
 		/* common stuff that need some love */
 		case IP_TOS:
 		case IP_TTL:
-		case IP_BIND_ADDRESS_NO_PORT:
 		case IP_MTU_DISCOVER:
 		case IP_RECVERR:
 
@@ -688,6 +689,7 @@  static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
 {
 	struct sock *sk = (struct sock *)msk;
 	struct sock *ssk;
+	bool slow;
 	int err;
 
 	err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
@@ -710,6 +712,16 @@  static int mptcp_setsockopt_sol_ip_set(struct mptcp_sock *msk, int optname,
 		inet_assign_bit(TRANSPARENT, ssk,
 				inet_test_bit(TRANSPARENT, sk));
 		break;
+	case IP_BIND_ADDRESS_NO_PORT:
+		inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk,
+				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
+		break;
+	case IP_LOCAL_PORT_RANGE:
+		slow = lock_sock_fast(ssk);
+		inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
+		inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
+		unlock_sock_fast(ssk, slow);
+		break;
 	default:
 		release_sock(sk);
 		WARN_ON_ONCE(1);
@@ -755,6 +767,8 @@  static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
 	switch (optname) {
 	case IP_FREEBIND:
 	case IP_TRANSPARENT:
+	case IP_BIND_ADDRESS_NO_PORT:
+	case IP_LOCAL_PORT_RANGE:
 		return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen);
 	case IP_TOS:
 		return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen);
@@ -1346,10 +1360,20 @@  static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
 			       char __user *optval, int __user *optlen)
 {
 	struct sock *sk = (void *)msk;
+	bool slow;
+	int val;
 
 	switch (optname) {
 	case IP_TOS:
 		return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->tos));
+	case IP_BIND_ADDRESS_NO_PORT:
+		return mptcp_put_int_option(msk, optval, optlen,
+				inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
+	case IP_LOCAL_PORT_RANGE:
+		slow = lock_sock_fast(sk);
+		val = inet_sk(sk)->local_port_range.hi << 16 | inet_sk(sk)->local_port_range.lo;
+		unlock_sock_fast(sk, slow);
+		return mptcp_put_int_option(msk, optval, optlen, val);
 	}
 
 	return -EOPNOTSUPP;
@@ -1450,6 +1474,9 @@  static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
 
 	inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
 	inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
+	inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, inet_test_bit(BIND_ADDRESS_NO_PORT, sk));
+	inet_sk(ssk)->local_port_range.lo = inet_sk(sk)->local_port_range.lo;
+	inet_sk(ssk)->local_port_range.hi = inet_sk(sk)->local_port_range.hi;
 }
 
 void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk)