diff mbox series

[net] udp: fix l4 hash after reconnect

Message ID 4761e466ab9f7542c68cdc95f248987d127044d2.1733499715.git.pabeni@redhat.com (mailing list archive)
State Accepted
Commit 51a00be6a0994da2ba6b4ace3b7a0d9373b4b25e
Delegated to: Netdev Maintainers
Headers show
Series [net] udp: fix l4 hash after reconnect | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 8 of 9 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1 this patch: 1
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 20 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-12-06--18-00 (tests: 764)

Commit Message

Paolo Abeni Dec. 6, 2024, 3:49 p.m. UTC
After the blamed commit below, udp_rehash() is supposed to be called
with both local and remote addresses set.

Currently that is already the case for IPv6 sockets, but for IPv4 the
destination address is updated after rehashing.

Address the issue moving the destination address and port initialization
before rehashing.

Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/ipv4/datagram.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Eric Dumazet Dec. 6, 2024, 3:57 p.m. UTC | #1
On Fri, Dec 6, 2024 at 4:50 PM Paolo Abeni <pabeni@redhat.com> wrote:
>
> After the blamed commit below, udp_rehash() is supposed to be called
> with both local and remote addresses set.
>
> Currently that is already the case for IPv6 sockets, but for IPv4 the
> destination address is updated after rehashing.
>
> Address the issue moving the destination address and port initialization
> before rehashing.
>
> Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Nice catch, thanks !

Reviewed-by: Eric Dumazet <edumazet@google.com>
Eric Dumazet Dec. 6, 2024, 4:01 p.m. UTC | #2
On Fri, Dec 6, 2024 at 4:57 PM Eric Dumazet <edumazet@google.com> wrote:
>
> On Fri, Dec 6, 2024 at 4:50 PM Paolo Abeni <pabeni@redhat.com> wrote:
> >
> > After the blamed commit below, udp_rehash() is supposed to be called
> > with both local and remote addresses set.
> >
> > Currently that is already the case for IPv6 sockets, but for IPv4 the
> > destination address is updated after rehashing.
> >
> > Address the issue moving the destination address and port initialization
> > before rehashing.
> >
> > Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
> > Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>
> Nice catch, thanks !
>
> Reviewed-by: Eric Dumazet <edumazet@google.com>

BTW, it seems that udp_lib_rehash() does the udp_rehash4()
only if the hash2 has changed.
Paolo Abeni Dec. 6, 2024, 4:23 p.m. UTC | #3
On 12/6/24 17:01, Eric Dumazet wrote:
> On Fri, Dec 6, 2024 at 4:57 PM Eric Dumazet <edumazet@google.com> wrote:
>> On Fri, Dec 6, 2024 at 4:50 PM Paolo Abeni <pabeni@redhat.com> wrote:
>>>
>>> After the blamed commit below, udp_rehash() is supposed to be called
>>> with both local and remote addresses set.
>>>
>>> Currently that is already the case for IPv6 sockets, but for IPv4 the
>>> destination address is updated after rehashing.
>>>
>>> Address the issue moving the destination address and port initialization
>>> before rehashing.
>>>
>>> Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
>>> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>>
>> Nice catch, thanks !
>>
>> Reviewed-by: Eric Dumazet <edumazet@google.com>
> 
> BTW, it seems that udp_lib_rehash() does the udp_rehash4()
> only if the hash2 has changed.

Oh, you are right, that requires a separate fix.

@Philo: could you please have a look at that? basically you need to
check separately for hash2 and hash4 changes.

Thanks!

Paolo
Philo Lu Dec. 7, 2024, 2:34 a.m. UTC | #4
On 2024/12/7 00:23, Paolo Abeni wrote:
> On 12/6/24 17:01, Eric Dumazet wrote:
>> On Fri, Dec 6, 2024 at 4:57 PM Eric Dumazet <edumazet@google.com> wrote:
>>> On Fri, Dec 6, 2024 at 4:50 PM Paolo Abeni <pabeni@redhat.com> wrote:
>>>>
>>>> After the blamed commit below, udp_rehash() is supposed to be called
>>>> with both local and remote addresses set.
>>>>
>>>> Currently that is already the case for IPv6 sockets, but for IPv4 the
>>>> destination address is updated after rehashing.
>>>>
>>>> Address the issue moving the destination address and port initialization
>>>> before rehashing.
>>>>
>>>> Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
>>>> Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Thank you for this fix :)

>>>
>>> Nice catch, thanks !
>>>
>>> Reviewed-by: Eric Dumazet <edumazet@google.com>
>>
>> BTW, it seems that udp_lib_rehash() does the udp_rehash4()
>> only if the hash2 has changed.
> 
> Oh, you are right, that requires a separate fix.
> 
> @Philo: could you please have a look at that? basically you need to
> check separately for hash2 and hash4 changes.

This is a good question. IIUC, the only affected case is when trying to 
re-connect another remote address with the same local address (i.e., 
hash2 unchanged). And this will be handled by udp_lib_hash4(). So in 
udp_lib_rehash() I put rehash4() inside hash2 checking, which means a 
passive rehash4 following rehash2.

So I think it's more about the convention for rehash. We can choose the 
better one.

Thanks.
Paolo Abeni Dec. 10, 2024, 8:32 a.m. UTC | #5
On 12/7/24 03:34, Philo Lu wrote:
> On 2024/12/7 00:23, Paolo Abeni wrote:
>> On 12/6/24 17:01, Eric Dumazet wrote:
>>> BTW, it seems that udp_lib_rehash() does the udp_rehash4()
>>> only if the hash2 has changed.
>>
>> Oh, you are right, that requires a separate fix.
>>
>> @Philo: could you please have a look at that? basically you need to
>> check separately for hash2 and hash4 changes.
> 
> This is a good question. IIUC, the only affected case is when trying to 
> re-connect another remote address with the same local address 

AFAICS, there is also another case: when re-connection using a different
local addresses with the same l2 hash...

> (i.e., 
> hash2 unchanged). And this will be handled by udp_lib_hash4(). So in 
> udp_lib_rehash() I put rehash4() inside hash2 checking, which means a 
> passive rehash4 following rehash2.

... but even the latter case should be covered from the above.

> So I think it's more about the convention for rehash. We can choose the 
> better one.

IIRC a related question raised during code review for the udp L4 hash
patches. Perhaps refactoring the code slightly to let udp_rehash()
really doing the re-hashing and udp_hash really doing only the hashing
could be worth.

Cheers,

Paolo
Philo Lu Dec. 10, 2024, 10:45 a.m. UTC | #6
On 2024/12/10 16:32, Paolo Abeni wrote:
> On 12/7/24 03:34, Philo Lu wrote:
>> On 2024/12/7 00:23, Paolo Abeni wrote:
>>> On 12/6/24 17:01, Eric Dumazet wrote:
>>>> BTW, it seems that udp_lib_rehash() does the udp_rehash4()
>>>> only if the hash2 has changed.
>>>
>>> Oh, you are right, that requires a separate fix.
>>>
>>> @Philo: could you please have a look at that? basically you need to
>>> check separately for hash2 and hash4 changes.
>>
>> This is a good question. IIUC, the only affected case is when trying to
>> re-connect another remote address with the same local address
> 
> AFAICS, there is also another case: when re-connection using a different
> local addresses with the same l2 hash...
> 

Yes, you're right. I missed this case... Thank you for pointing out it.

>> (i.e.,
>> hash2 unchanged). And this will be handled by udp_lib_hash4(). So in
>> udp_lib_rehash() I put rehash4() inside hash2 checking, which means a
>> passive rehash4 following rehash2.
> 
> ... but even the latter case should be covered from the above.
> 
>> So I think it's more about the convention for rehash. We can choose the
>> better one.
> 
> IIRC a related question raised during code review for the udp L4 hash
> patches. Perhaps refactoring the code slightly to let udp_rehash()
> really doing the re-hashing and udp_hash really doing only the hashing
> could be worth.

Agreed. I'd appreciate it if someone helps to refactor it, or I can do 
this later myself.
patchwork-bot+netdevbpf@kernel.org Dec. 10, 2024, 2:40 p.m. UTC | #7
Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Fri,  6 Dec 2024 16:49:14 +0100 you wrote:
> After the blamed commit below, udp_rehash() is supposed to be called
> with both local and remote addresses set.
> 
> Currently that is already the case for IPv6 sockets, but for IPv4 the
> destination address is updated after rehashing.
> 
> Address the issue moving the destination address and port initialization
> before rehashing.
> 
> [...]

Here is the summary with links:
  - [net] udp: fix l4 hash after reconnect
    https://git.kernel.org/netdev/net/c/51a00be6a099

You are awesome, thank you!
Jakub Kicinski Dec. 11, 2024, 12:59 a.m. UTC | #8
On Fri,  6 Dec 2024 16:49:14 +0100 Paolo Abeni wrote:
> After the blamed commit below, udp_rehash() is supposed to be called
> with both local and remote addresses set.
> 
> Currently that is already the case for IPv6 sockets, but for IPv4 the
> destination address is updated after rehashing.
> 
> Address the issue moving the destination address and port initialization
> before rehashing.
> 
> Fixes: 1b29a730ef8b ("ipv6/udp: Add 4-tuple hash for connected socket")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>

I feel obliged to point out a lack of selftest both here and the series
under Fixes :(
diff mbox series

Patch

diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index cc6d0bd7b0a9..4aca1f05edd3 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -61,15 +61,17 @@  int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
 		err = -EACCES;
 		goto out;
 	}
+
+	/* Update addresses before rehashing */
+	inet->inet_daddr = fl4->daddr;
+	inet->inet_dport = usin->sin_port;
 	if (!inet->inet_saddr)
-		inet->inet_saddr = fl4->saddr;	/* Update source address */
+		inet->inet_saddr = fl4->saddr;
 	if (!inet->inet_rcv_saddr) {
 		inet->inet_rcv_saddr = fl4->saddr;
 		if (sk->sk_prot->rehash)
 			sk->sk_prot->rehash(sk);
 	}
-	inet->inet_daddr = fl4->daddr;
-	inet->inet_dport = usin->sin_port;
 	reuseport_has_conns_set(sk);
 	sk->sk_state = TCP_ESTABLISHED;
 	sk_set_txhash(sk);