diff mbox series

[net-next,v2,2/2] net/smc: support ipv4 mapped ipv6 addr client for smc-r v2

Message ID 20241202125203.48821-3-guangguan.wang@linux.alibaba.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series net/smc: Two features for smc-r | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 3 this patch: 3
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 12 of 12 maintainers
netdev/build_clang success Errors and warnings before: 3 this patch: 3
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 No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 304 this patch: 304
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 12 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-02--15-00 (tests: 760)

Commit Message

Guangguan Wang Dec. 2, 2024, 12:52 p.m. UTC
AF_INET6 is not supported for smc-r v2 client before, event if the
ipv6 addr is ipv4 mapped. Thus, when using AF_INET6, smc-r connection
will fallback to tcp, especially for java applications running smc-r.
This patch support ipv4 mapped ipv6 addr client for smc-r v2. Clients
using real global ipv6 addr is still not supported yet.

Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
Reviewed-by: Wen Gu <guwen@linux.alibaba.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Reviewed-by: D. Wythe <alibuda@linux.alibaba.com>
---
 net/smc/af_smc.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Wenjia Zhang Dec. 5, 2024, 10:16 a.m. UTC | #1
On 02.12.24 13:52, Guangguan Wang wrote:
> AF_INET6 is not supported for smc-r v2 client before, event if the
%s/event/even/g

> ipv6 addr is ipv4 mapped. Thus, when using AF_INET6, smc-r connection
> will fallback to tcp, especially for java applications running smc-r.
> This patch support ipv4 mapped ipv6 addr client for smc-r v2. Clients
> using real global ipv6 addr is still not supported yet.
> 
> Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
> Reviewed-by: Wen Gu <guwen@linux.alibaba.com>
> Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
> Reviewed-by: D. Wythe <alibuda@linux.alibaba.com>
> ---
>   net/smc/af_smc.c | 5 +++++
>   1 file changed, 5 insertions(+)
> 
> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
> index 9d76e902fd77..5b13dd759766 100644
> --- a/net/smc/af_smc.c
> +++ b/net/smc/af_smc.c
> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
>   	ini->check_smcrv2 = true;
>   	ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>   	if (!(ini->smcr_version & SMC_V2) ||
> +#if IS_ENABLED(CONFIG_IPV6)
> +	    (smc->clcsock->sk->sk_family != AF_INET &&
> +	     !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET && 
ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If it 
is, the negativ form of the logical operation (a&&b) is (!a)||(!b), i.e. 
here should be:
(smc->clcsock->sk->sk_family != AF_INET)|| 
(!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))

> +#else
>   	    smc->clcsock->sk->sk_family != AF_INET ||
> +#endif
>   	    !smc_clc_ueid_count() ||
>   	    smc_find_rdma_device(smc, ini))
>   		ini->smcr_version &= ~SMC_V2;
Guangguan Wang Dec. 5, 2024, 12:02 p.m. UTC | #2
On 2024/12/5 18:16, Wenjia Zhang wrote:
> 
> 
> On 02.12.24 13:52, Guangguan Wang wrote:
>> AF_INET6 is not supported for smc-r v2 client before, event if the
> %s/event/even/g
> 

I will fix it in the next version.

>> ipv6 addr is ipv4 mapped. Thus, when using AF_INET6, smc-r connection
>> will fallback to tcp, especially for java applications running smc-r.
>> This patch support ipv4 mapped ipv6 addr client for smc-r v2. Clients
>> using real global ipv6 addr is still not supported yet.
>>
>> Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
>> Reviewed-by: Wen Gu <guwen@linux.alibaba.com>
>> Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
>> Reviewed-by: D. Wythe <alibuda@linux.alibaba.com>
>> ---
>>   net/smc/af_smc.c | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
>> index 9d76e902fd77..5b13dd759766 100644
>> --- a/net/smc/af_smc.c
>> +++ b/net/smc/af_smc.c
>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
>>       ini->check_smcrv2 = true;
>>       ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>       if (!(ini->smcr_version & SMC_V2) ||
>> +#if IS_ENABLED(CONFIG_IPV6)
>> +        (smc->clcsock->sk->sk_family != AF_INET &&
>> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If it is, the negativ form of the logical operation (a&&b) is (!a)||(!b), i.e. here should be:
> (smc->clcsock->sk->sk_family != AF_INET)|| (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
> 

(smc->clcsock->sk->sk_family != AF_INET && !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) not equls to !(smc->clcsock->sk->sk_family == AF_INET && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))

Following your logic, here also can be: 
!(smc->clcsock->sk->sk_family == AF_INET || ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))

I think both is acceptable. But in order to keep consistent with the code when IPV6 is not enabled, I prefer (smc->clcsock->sk->sk_family != AF_INET && !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)).

>> +#else
>>           smc->clcsock->sk->sk_family != AF_INET ||
>> +#endif
>>           !smc_clc_ueid_count() ||
>>           smc_find_rdma_device(smc, ini))
>>           ini->smcr_version &= ~SMC_V2;
Halil Pasic Dec. 5, 2024, 12:58 p.m. UTC | #3
On Thu, 5 Dec 2024 11:16:27 +0100
Wenjia Zhang <wenjia@linux.ibm.com> wrote:

> > --- a/net/smc/af_smc.c
> > +++ b/net/smc/af_smc.c
> > @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
> > smc_sock *smc, ini->check_smcrv2 = true;
> >   	ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
> >   	if (!(ini->smcr_version & SMC_V2) ||
> > +#if IS_ENABLED(CONFIG_IPV6)
> > +	    (smc->clcsock->sk->sk_family != AF_INET &&
> > +
> > !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||  
> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
> i.e. here should be:
> (smc->clcsock->sk->sk_family != AF_INET)|| 
> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))

Wenjia, I think you happen to confuse something here. The condition
of this if statement is supposed to evaluate as true iff we don't want
to propose SMCRv2 because the situation is such that SMCRv2 is not
supported.

We have a bunch of conditions we need to meet for SMCRv2 so
logically we have (A && B && C && D). Now since the if is
about when SMCRv2 is not supported we have a super structure
that looks like !A || !B || !C || !D. With this patch, if
CONFIG_IPV6 is not enabled, the sub-condition remains the same:
if smc->clcsock->sk->sk_family is something else that AF_INET
the we do not do SMCRv2!

But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
AF_INET6 sockets too if the addresses used are actually
v4 mapped addresses.

Now this is where the cognitive dissonance starts on my end. I
think the author assumes sk_family == AF_INET || sk_family == AF_INET6
is a tautology in this context. That may be a reasonable thing to
assume. Under that assumption 
sk_family != AF_INET &&	!ipv6_addr_v4mapped(addr) (shortened for
convenience)
becomes equivalent to
sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
which means in words if the socket is an IPv6 sockeet and the addr is not
a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
the aforementioned assumption.

But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
the #else does not make any sense, because I guess with IPv6 not
available AF_INET6 is not available ant thus the else is always
guaranteed to evaluate to false under the assumption made.

Thus I conclude, that I am certainly missing something here. Guangguan,
do you care to explain?

Regards,
Halil
Guangguan Wang Dec. 6, 2024, 6:06 a.m. UTC | #4
On 2024/12/5 20:58, Halil Pasic wrote:
> On Thu, 5 Dec 2024 11:16:27 +0100
> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
> 
>>> --- a/net/smc/af_smc.c
>>> +++ b/net/smc/af_smc.c
>>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
>>> smc_sock *smc, ini->check_smcrv2 = true;
>>>   	ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>>   	if (!(ini->smcr_version & SMC_V2) ||
>>> +#if IS_ENABLED(CONFIG_IPV6)
>>> +	    (smc->clcsock->sk->sk_family != AF_INET &&
>>> +
>>> !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||  
>> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
>> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
>> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
>> i.e. here should be:
>> (smc->clcsock->sk->sk_family != AF_INET)|| 
>> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
> 
> Wenjia, I think you happen to confuse something here. The condition
> of this if statement is supposed to evaluate as true iff we don't want
> to propose SMCRv2 because the situation is such that SMCRv2 is not
> supported.
> 
> We have a bunch of conditions we need to meet for SMCRv2 so
> logically we have (A && B && C && D). Now since the if is
> about when SMCRv2 is not supported we have a super structure
> that looks like !A || !B || !C || !D. With this patch, if
> CONFIG_IPV6 is not enabled, the sub-condition remains the same:
> if smc->clcsock->sk->sk_family is something else that AF_INET
> the we do not do SMCRv2!
> 
> But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
> AF_INET6 sockets too if the addresses used are actually
> v4 mapped addresses.
> 
> Now this is where the cognitive dissonance starts on my end. I
> think the author assumes sk_family == AF_INET || sk_family == AF_INET6
> is a tautology in this context. That may be a reasonable thing to
> assume. Under that assumption 
> sk_family != AF_INET &&	!ipv6_addr_v4mapped(addr) (shortened for
> convenience)
> becomes equivalent to
> sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
> which means in words if the socket is an IPv6 sockeet and the addr is not
> a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
> when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
> is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
> the aforementioned assumption.

Hi, Halil

Thank you for such a detailed derivation. 

Yes, here assume that sk_family == AF_INET || sk_family == AF_INET6. Indeed,
many codes in SMC have already made this assumption, for example,
static int __smc_create(struct net *net, struct socket *sock, int protocol,
			int kern, struct socket *clcsock)
{
	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
	...
}
And I also believe it is reasonable.

Before this patch, for SMCR client, only an IPV4 socket can do SMCRv2. This patch
introduce an IPV6 socket with v4 mapped v6 address for SMCRv2. It is equivalen
to sk_family == AF_INET || ipv6_addr_v4mapped(addr) as you described.

> 
> But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
> the #else does not make any sense, because I guess with IPv6 not
> available AF_INET6 is not available ant thus the else is always
> guaranteed to evaluate to false under the assumption made.
> 
You are right. The #else here does not make any sense. It's my mistake.

The condition is easier to understand and read should be like this:
 	if (!(ini->smcr_version & SMC_V2) ||
+#if IS_ENABLED(CONFIG_IPV6)
+	    (smc->clcsock->sk->sk_family == AF_INET6 &&
+	     !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
+#endif
 	    !smc_clc_ueid_count() ||
 	    smc_find_rdma_device(smc, ini))
 		ini->smcr_version &= ~SMC_V2;

Thanks,
Guangguan Wang


> Thus I conclude, that I am certainly missing something here. Guangguan,
> do you care to explain?
> 
> Regards,
> Halil
>
Wenjia Zhang Dec. 6, 2024, 10:51 a.m. UTC | #5
On 06.12.24 07:06, Guangguan Wang wrote:
> 
> 
> On 2024/12/5 20:58, Halil Pasic wrote:
>> On Thu, 5 Dec 2024 11:16:27 +0100
>> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
>>
>>>> --- a/net/smc/af_smc.c
>>>> +++ b/net/smc/af_smc.c
>>>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
>>>> smc_sock *smc, ini->check_smcrv2 = true;
>>>>    	ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>>>    	if (!(ini->smcr_version & SMC_V2) ||
>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>> +	    (smc->clcsock->sk->sk_family != AF_INET &&
>>>> +
>>>> !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
>>> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
>>> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
>>> i.e. here should be:
>>> (smc->clcsock->sk->sk_family != AF_INET)||
>>> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
>>
>> Wenjia, I think you happen to confuse something here. The condition
>> of this if statement is supposed to evaluate as true iff we don't want
>> to propose SMCRv2 because the situation is such that SMCRv2 is not
>> supported.
>>
>> We have a bunch of conditions we need to meet for SMCRv2 so
>> logically we have (A && B && C && D). Now since the if is
>> about when SMCRv2 is not supported we have a super structure
>> that looks like !A || !B || !C || !D. With this patch, if
>> CONFIG_IPV6 is not enabled, the sub-condition remains the same:
>> if smc->clcsock->sk->sk_family is something else that AF_INET
>> the we do not do SMCRv2!
>>
>> But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
>> AF_INET6 sockets too if the addresses used are actually
>> v4 mapped addresses.
>>
>> Now this is where the cognitive dissonance starts on my end. I
>> think the author assumes sk_family == AF_INET || sk_family == AF_INET6
>> is a tautology in this context. That may be a reasonable thing to
>> assume. Under that assumption
>> sk_family != AF_INET &&	!ipv6_addr_v4mapped(addr) (shortened for
>> convenience)
>> becomes equivalent to
>> sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
>> which means in words if the socket is an IPv6 sockeet and the addr is not
>> a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
>> when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
>> is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
>> the aforementioned assumption.
> 
> Hi, Halil
> 
> Thank you for such a detailed derivation.
> 
> Yes, here assume that sk_family == AF_INET || sk_family == AF_INET6. Indeed,
> many codes in SMC have already made this assumption, for example,
> static int __smc_create(struct net *net, struct socket *sock, int protocol,
> 			int kern, struct socket *clcsock)
> {
> 	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
> 	...
> }
> And I also believe it is reasonable.
> 
> Before this patch, for SMCR client, only an IPV4 socket can do SMCRv2. This patch
> introduce an IPV6 socket with v4 mapped v6 address for SMCRv2. It is equivalen
> to sk_family == AF_INET || ipv6_addr_v4mapped(addr) as you described.
> 
>>
>> But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
>> the #else does not make any sense, because I guess with IPv6 not
>> available AF_INET6 is not available ant thus the else is always
>> guaranteed to evaluate to false under the assumption made.
>>
> You are right. The #else here does not make any sense. It's my mistake.
> 
> The condition is easier to understand and read should be like this:
>   	if (!(ini->smcr_version & SMC_V2) ||
> +#if IS_ENABLED(CONFIG_IPV6)
> +	    (smc->clcsock->sk->sk_family == AF_INET6 &&
> +	     !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
> +#endif
>   	    !smc_clc_ueid_count() ||
>   	    smc_find_rdma_device(smc, ini))
>   		ini->smcr_version &= ~SMC_V2;
> 

sorry, I still don't agree on this version. You removed the condition
"
smc->clcsock->sk->sk_family != AF_INET ||
"
completely. What about the socket with neither AF_INET nor AF_INET6 family?

Thanks,
Wenjia
Wenjia Zhang Dec. 6, 2024, 7:49 p.m. UTC | #6
On 06.12.24 11:51, Wenjia Zhang wrote:
> 
> 
> On 06.12.24 07:06, Guangguan Wang wrote:
>>
>>
>> On 2024/12/5 20:58, Halil Pasic wrote:
>>> On Thu, 5 Dec 2024 11:16:27 +0100
>>> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
>>>
>>>>> --- a/net/smc/af_smc.c
>>>>> +++ b/net/smc/af_smc.c
>>>>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
>>>>> smc_sock *smc, ini->check_smcrv2 = true;
>>>>>        ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>>>>        if (!(ini->smcr_version & SMC_V2) ||
>>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>>> +        (smc->clcsock->sk->sk_family != AF_INET &&
>>>>> +
>>>>> !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>>> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
>>>> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
>>>> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
>>>> i.e. here should be:
>>>> (smc->clcsock->sk->sk_family != AF_INET)||
>>>> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
>>>
>>> Wenjia, I think you happen to confuse something here. The condition
>>> of this if statement is supposed to evaluate as true iff we don't want
>>> to propose SMCRv2 because the situation is such that SMCRv2 is not
>>> supported.
>>>
>>> We have a bunch of conditions we need to meet for SMCRv2 so
>>> logically we have (A && B && C && D). Now since the if is
>>> about when SMCRv2 is not supported we have a super structure
>>> that looks like !A || !B || !C || !D. With this patch, if
>>> CONFIG_IPV6 is not enabled, the sub-condition remains the same:
>>> if smc->clcsock->sk->sk_family is something else that AF_INET
>>> the we do not do SMCRv2!
>>>
>>> But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
>>> AF_INET6 sockets too if the addresses used are actually
>>> v4 mapped addresses.
>>>
>>> Now this is where the cognitive dissonance starts on my end. I
>>> think the author assumes sk_family == AF_INET || sk_family == AF_INET6
>>> is a tautology in this context. That may be a reasonable thing to
>>> assume. Under that assumption
>>> sk_family != AF_INET &&    !ipv6_addr_v4mapped(addr) (shortened for
>>> convenience)
>>> becomes equivalent to
>>> sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
>>> which means in words if the socket is an IPv6 sockeet and the addr is 
>>> not
>>> a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
>>> when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
>>> is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
>>> the aforementioned assumption.
>>
>> Hi, Halil
>>
>> Thank you for such a detailed derivation.
>>
>> Yes, here assume that sk_family == AF_INET || sk_family == AF_INET6. 
>> Indeed,
>> many codes in SMC have already made this assumption, for example,
>> static int __smc_create(struct net *net, struct socket *sock, int 
>> protocol,
>>             int kern, struct socket *clcsock)
>> {
>>     int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
>>     ...
>> }
>> And I also believe it is reasonable.
>>
>> Before this patch, for SMCR client, only an IPV4 socket can do SMCRv2. 
>> This patch
>> introduce an IPV6 socket with v4 mapped v6 address for SMCRv2. It is 
>> equivalen
>> to sk_family == AF_INET || ipv6_addr_v4mapped(addr) as you described.
>>
>>>
>>> But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
>>> the #else does not make any sense, because I guess with IPv6 not
>>> available AF_INET6 is not available ant thus the else is always
>>> guaranteed to evaluate to false under the assumption made.
>>>
>> You are right. The #else here does not make any sense. It's my mistake.
>>
>> The condition is easier to understand and read should be like this:
>>       if (!(ini->smcr_version & SMC_V2) ||
>> +#if IS_ENABLED(CONFIG_IPV6)
>> +        (smc->clcsock->sk->sk_family == AF_INET6 &&
>> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>> +#endif
>>           !smc_clc_ueid_count() ||
>>           smc_find_rdma_device(smc, ini))
>>           ini->smcr_version &= ~SMC_V2;
>>
> 
> sorry, I still don't agree on this version. You removed the condition
> "
> smc->clcsock->sk->sk_family != AF_INET ||
> "
> completely. What about the socket with neither AF_INET nor AF_INET6 family?
> 
> Thanks,
> Wenjia
> 
I think the main problem in the original version was that
(sk_family != AF_INET) is not equivalent to (sk_family == AF_INET6).
Since you already in the new version above used sk_family == AF_INET6,
the else condition could stay as it is. My suggestion:

diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 8e3093938cd2..5f205a41fc48 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct 
smc_sock *smc,
         ini->check_smcrv2 = true;
         ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
         if (!(ini->smcr_version & SMC_V2) ||
+#if IS_ENABLED(CONFIG_IPV6)
+           (smc->clcsock->sk->sk_family == AF_INET6 &&
+            !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
+#else
             smc->clcsock->sk->sk_family != AF_INET ||
+#endif
             !smc_clc_ueid_count() ||
             smc_find_rdma_device(smc, ini))
                 ini->smcr_version &= ~SMC_V2;

Thanks,
Wenjia
Guangguan Wang Dec. 9, 2024, 6:04 a.m. UTC | #7
On 2024/12/7 03:49, Wenjia Zhang wrote:
> 
> 
> On 06.12.24 11:51, Wenjia Zhang wrote:
>>
>>
>> On 06.12.24 07:06, Guangguan Wang wrote:
>>>
>>>
>>> On 2024/12/5 20:58, Halil Pasic wrote:
>>>> On Thu, 5 Dec 2024 11:16:27 +0100
>>>> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
>>>>
>>>>>> --- a/net/smc/af_smc.c
>>>>>> +++ b/net/smc/af_smc.c
>>>>>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
>>>>>> smc_sock *smc, ini->check_smcrv2 = true;
>>>>>>        ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>>>>>        if (!(ini->smcr_version & SMC_V2) ||
>>>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>>>> +        (smc->clcsock->sk->sk_family != AF_INET &&
>>>>>> +
>>>>>> !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>>>> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
>>>>> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
>>>>> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
>>>>> i.e. here should be:
>>>>> (smc->clcsock->sk->sk_family != AF_INET)||
>>>>> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
>>>>
>>>> Wenjia, I think you happen to confuse something here. The condition
>>>> of this if statement is supposed to evaluate as true iff we don't want
>>>> to propose SMCRv2 because the situation is such that SMCRv2 is not
>>>> supported.
>>>>
>>>> We have a bunch of conditions we need to meet for SMCRv2 so
>>>> logically we have (A && B && C && D). Now since the if is
>>>> about when SMCRv2 is not supported we have a super structure
>>>> that looks like !A || !B || !C || !D. With this patch, if
>>>> CONFIG_IPV6 is not enabled, the sub-condition remains the same:
>>>> if smc->clcsock->sk->sk_family is something else that AF_INET
>>>> the we do not do SMCRv2!
>>>>
>>>> But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
>>>> AF_INET6 sockets too if the addresses used are actually
>>>> v4 mapped addresses.
>>>>
>>>> Now this is where the cognitive dissonance starts on my end. I
>>>> think the author assumes sk_family == AF_INET || sk_family == AF_INET6
>>>> is a tautology in this context. That may be a reasonable thing to
>>>> assume. Under that assumption
>>>> sk_family != AF_INET &&    !ipv6_addr_v4mapped(addr) (shortened for
>>>> convenience)
>>>> becomes equivalent to
>>>> sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
>>>> which means in words if the socket is an IPv6 sockeet and the addr is not
>>>> a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
>>>> when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
>>>> is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
>>>> the aforementioned assumption.
>>>
>>> Hi, Halil
>>>
>>> Thank you for such a detailed derivation.
>>>
>>> Yes, here assume that sk_family == AF_INET || sk_family == AF_INET6. Indeed,
>>> many codes in SMC have already made this assumption, for example,
>>> static int __smc_create(struct net *net, struct socket *sock, int protocol,
>>>             int kern, struct socket *clcsock)
>>> {
>>>     int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
>>>     ...
>>> }
>>> And I also believe it is reasonable.
>>>
>>> Before this patch, for SMCR client, only an IPV4 socket can do SMCRv2. This patch
>>> introduce an IPV6 socket with v4 mapped v6 address for SMCRv2. It is equivalen
>>> to sk_family == AF_INET || ipv6_addr_v4mapped(addr) as you described.
>>>
>>>>
>>>> But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
>>>> the #else does not make any sense, because I guess with IPv6 not
>>>> available AF_INET6 is not available ant thus the else is always
>>>> guaranteed to evaluate to false under the assumption made.
>>>>
>>> You are right. The #else here does not make any sense. It's my mistake.
>>>
>>> The condition is easier to understand and read should be like this:
>>>       if (!(ini->smcr_version & SMC_V2) ||
>>> +#if IS_ENABLED(CONFIG_IPV6)
>>> +        (smc->clcsock->sk->sk_family == AF_INET6 &&
>>> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>> +#endif
>>>           !smc_clc_ueid_count() ||
>>>           smc_find_rdma_device(smc, ini))
>>>           ini->smcr_version &= ~SMC_V2;
>>>
>>
>> sorry, I still don't agree on this version. You removed the condition
>> "
>> smc->clcsock->sk->sk_family != AF_INET ||
>> "
>> completely. What about the socket with neither AF_INET nor AF_INET6 family?
>>
>> Thanks,
>> Wenjia
>>
> I think the main problem in the original version was that
> (sk_family != AF_INET) is not equivalent to (sk_family == AF_INET6).
> Since you already in the new version above used sk_family == AF_INET6,
> the else condition could stay as it is. My suggestion:
> 
> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
> index 8e3093938cd2..5f205a41fc48 100644
> --- a/net/smc/af_smc.c
> +++ b/net/smc/af_smc.c
> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
>         ini->check_smcrv2 = true;
>         ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>         if (!(ini->smcr_version & SMC_V2) ||
> +#if IS_ENABLED(CONFIG_IPV6)
> +           (smc->clcsock->sk->sk_family == AF_INET6 &&
> +            !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
> +#else
>             smc->clcsock->sk->sk_family != AF_INET ||
> +#endif
>             !smc_clc_ueid_count() ||
>             smc_find_rdma_device(smc, ini))
>                 ini->smcr_version &= ~SMC_V2;
> 
> Thanks,
> Wenjia

The RFC7609 have confined SMC to socket applications using stream (i.e., TCP) sockets over IPv4 or IPv6.
https://datatracker.ietf.org/doc/html/rfc7609#page-26:~:text=It%20is%20confined%20to%20socket%20applications%20using%20stream%0A%20%20%20(i.e.%2C%20TCP)%20sockets%20over%20IPv4%20or%20IPv6

Both in the smc-tools and in smc kernel module, we can see codes that the sk_family is either AF_INET or AF_INET6.
The codes here:
https://raw.githubusercontent.com/ibm-s390-linux/smc-tools/refs/heads/main/smc-preload.c#:~:text=if%20((domain%20%3D%3D%20AF_INET%20%7C%7C%20domain%20%3D%3D%20AF_INET6)%20%26%26
and
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=(sk%2D%3Esk_family%20!%3D%20AF_INET%20%26%26%20sk%2D%3Esk_family%20!%3D%20AF_INET6))
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=int%20family%20%3D%20(protocol%20%3D%3D%20SMCPROTO_SMC6)%20%3F%20PF_INET6%20%3A%20PF_INET%3B 
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=%2D%3Esin_family%20!%3D-,AF_INET,-%26%26%0A%09%20%20%20%20addr%2D%3E
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=%2D%3Esa_family%20!%3D-,AF_INET6,-)%0A%09%09goto%20out_err
...

I wonder if SMC-R can support other address famliy rather than AF_INET AF_INET6 in design?
And IBM has any plan to support other address family in future?  Wenjia, can you help explain
this?

If the answer is positive, the code should be like this:
        if (!(ini->smcr_version & SMC_V2) ||
+#if IS_ENABLED(CONFIG_IPV6)
+           !(smc->clcsock->sk->sk_family == AF_INET || (smc->clcsock->sk->sk_family == AF_INET6 &&
+            ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))) ||
+#else
             smc->clcsock->sk->sk_family != AF_INET ||
+#endif
             !smc_clc_ueid_count() ||
             smc_find_rdma_device(smc, ini))
                 ini->smcr_version &= ~SMC_V2;

Otherwise, the code below is reasonable.
      if (!(ini->smcr_version & SMC_V2) ||
+#if IS_ENABLED(CONFIG_IPV6)
+        (smc->clcsock->sk->sk_family == AF_INET6 &&
+         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
+#endif
          !smc_clc_ueid_count() ||
          smc_find_rdma_device(smc, ini))
          ini->smcr_version &= ~SMC_V2;

Thanks,
Guangguan Wang
Wenjia Zhang Dec. 9, 2024, 8:49 a.m. UTC | #8
On 09.12.24 07:04, Guangguan Wang wrote:
> 
> 
> On 2024/12/7 03:49, Wenjia Zhang wrote:
>>
>>
>> On 06.12.24 11:51, Wenjia Zhang wrote:
>>>
>>>
>>> On 06.12.24 07:06, Guangguan Wang wrote:
>>>>
>>>>
>>>> On 2024/12/5 20:58, Halil Pasic wrote:
>>>>> On Thu, 5 Dec 2024 11:16:27 +0100
>>>>> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
>>>>>
>>>>>>> --- a/net/smc/af_smc.c
>>>>>>> +++ b/net/smc/af_smc.c
>>>>>>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct
>>>>>>> smc_sock *smc, ini->check_smcrv2 = true;
>>>>>>>         ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>>>>>>         if (!(ini->smcr_version & SMC_V2) ||
>>>>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>>>>> +        (smc->clcsock->sk->sk_family != AF_INET &&
>>>>>>> +
>>>>>>> !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>>>>> I think here you want to say !(smc->clcsock->sk->sk_family == AF_INET
>>>>>> && ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)), right? If
>>>>>> it is, the negativ form of the logical operation (a&&b) is (!a)||(!b),
>>>>>> i.e. here should be:
>>>>>> (smc->clcsock->sk->sk_family != AF_INET)||
>>>>>> (!ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))
>>>>>
>>>>> Wenjia, I think you happen to confuse something here. The condition
>>>>> of this if statement is supposed to evaluate as true iff we don't want
>>>>> to propose SMCRv2 because the situation is such that SMCRv2 is not
>>>>> supported.
>>>>>
>>>>> We have a bunch of conditions we need to meet for SMCRv2 so
>>>>> logically we have (A && B && C && D). Now since the if is
>>>>> about when SMCRv2 is not supported we have a super structure
>>>>> that looks like !A || !B || !C || !D. With this patch, if
>>>>> CONFIG_IPV6 is not enabled, the sub-condition remains the same:
>>>>> if smc->clcsock->sk->sk_family is something else that AF_INET
>>>>> the we do not do SMCRv2!
>>>>>
>>>>> But when we do have CONFIG_IPV6 then we want to do SMCRv2 for
>>>>> AF_INET6 sockets too if the addresses used are actually
>>>>> v4 mapped addresses.
>>>>>
>>>>> Now this is where the cognitive dissonance starts on my end. I
>>>>> think the author assumes sk_family == AF_INET || sk_family == AF_INET6
>>>>> is a tautology in this context. That may be a reasonable thing to
>>>>> assume. Under that assumption
>>>>> sk_family != AF_INET &&    !ipv6_addr_v4mapped(addr) (shortened for
>>>>> convenience)
>>>>> becomes equivalent to
>>>>> sk_family == AF_INET6 && !ipv6_addr_v4mapped(addr)
>>>>> which means in words if the socket is an IPv6 sockeet and the addr is not
>>>>> a v4 mapped v6 address then we *can not* do SMCRv2. And the condition
>>>>> when we can is sk_family != AF_INET6 || ipv6_addr_v4mapped(addr) which
>>>>> is equivalen to sk_family == AF_INET || ipv6_addr_v4mapped(addr) under
>>>>> the aforementioned assumption.
>>>>
>>>> Hi, Halil
>>>>
>>>> Thank you for such a detailed derivation.
>>>>
>>>> Yes, here assume that sk_family == AF_INET || sk_family == AF_INET6. Indeed,
>>>> many codes in SMC have already made this assumption, for example,
>>>> static int __smc_create(struct net *net, struct socket *sock, int protocol,
>>>>              int kern, struct socket *clcsock)
>>>> {
>>>>      int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
>>>>      ...
>>>> }
>>>> And I also believe it is reasonable.
>>>>
>>>> Before this patch, for SMCR client, only an IPV4 socket can do SMCRv2. This patch
>>>> introduce an IPV6 socket with v4 mapped v6 address for SMCRv2. It is equivalen
>>>> to sk_family == AF_INET || ipv6_addr_v4mapped(addr) as you described.
>>>>
>>>>>
>>>>> But if we assume sk_family == AF_INET || sk_family == AF_INET6 then
>>>>> the #else does not make any sense, because I guess with IPv6 not
>>>>> available AF_INET6 is not available ant thus the else is always
>>>>> guaranteed to evaluate to false under the assumption made.
>>>>>
>>>> You are right. The #else here does not make any sense. It's my mistake.
>>>>
>>>> The condition is easier to understand and read should be like this:
>>>>        if (!(ini->smcr_version & SMC_V2) ||
>>>> +#if IS_ENABLED(CONFIG_IPV6)
>>>> +        (smc->clcsock->sk->sk_family == AF_INET6 &&
>>>> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>>> +#endif
>>>>            !smc_clc_ueid_count() ||
>>>>            smc_find_rdma_device(smc, ini))
>>>>            ini->smcr_version &= ~SMC_V2;
>>>>
>>>
>>> sorry, I still don't agree on this version. You removed the condition
>>> "
>>> smc->clcsock->sk->sk_family != AF_INET ||
>>> "
>>> completely. What about the socket with neither AF_INET nor AF_INET6 family?
>>>
>>> Thanks,
>>> Wenjia
>>>
>> I think the main problem in the original version was that
>> (sk_family != AF_INET) is not equivalent to (sk_family == AF_INET6).
>> Since you already in the new version above used sk_family == AF_INET6,
>> the else condition could stay as it is. My suggestion:
>>
>> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
>> index 8e3093938cd2..5f205a41fc48 100644
>> --- a/net/smc/af_smc.c
>> +++ b/net/smc/af_smc.c
>> @@ -1116,7 +1116,12 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
>>          ini->check_smcrv2 = true;
>>          ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
>>          if (!(ini->smcr_version & SMC_V2) ||
>> +#if IS_ENABLED(CONFIG_IPV6)
>> +           (smc->clcsock->sk->sk_family == AF_INET6 &&
>> +            !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>> +#else
>>              smc->clcsock->sk->sk_family != AF_INET ||
>> +#endif
>>              !smc_clc_ueid_count() ||
>>              smc_find_rdma_device(smc, ini))
>>                  ini->smcr_version &= ~SMC_V2;
>>
>> Thanks,
>> Wenjia
> 
> The RFC7609 have confined SMC to socket applications using stream (i.e., TCP) sockets over IPv4 or IPv6.
> https://datatracker.ietf.org/doc/html/rfc7609#page-26:~:text=It%20is%20confined%20to%20socket%20applications%20using%20stream%0A%20%20%20(i.e.%2C%20TCP)%20sockets%20over%20IPv4%20or%20IPv6
> 
> Both in the smc-tools and in smc kernel module, we can see codes that the sk_family is either AF_INET or AF_INET6.
> The codes here:
> https://raw.githubusercontent.com/ibm-s390-linux/smc-tools/refs/heads/main/smc-preload.c#:~:text=if%20((domain%20%3D%3D%20AF_INET%20%7C%7C%20domain%20%3D%3D%20AF_INET6)%20%26%26
> and
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=(sk%2D%3Esk_family%20!%3D%20AF_INET%20%26%26%20sk%2D%3Esk_family%20!%3D%20AF_INET6))
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=int%20family%20%3D%20(protocol%20%3D%3D%20SMCPROTO_SMC6)%20%3F%20PF_INET6%20%3A%20PF_INET%3B
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=%2D%3Esin_family%20!%3D-,AF_INET,-%26%26%0A%09%20%20%20%20addr%2D%3E
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/smc/af_smc.c#:~:text=%2D%3Esa_family%20!%3D-,AF_INET6,-)%0A%09%09goto%20out_err
> ...
> 
> I wonder if SMC-R can support other address famliy rather than AF_INET AF_INET6 in design?
> And IBM has any plan to support other address family in future?  Wenjia, can you help explain
> this?
> 
The answer is no, at least in the near future. As you might be already 
aware, it depends on the implementation on z/OS.

> If the answer is positive, the code should be like this:
>          if (!(ini->smcr_version & SMC_V2) ||
> +#if IS_ENABLED(CONFIG_IPV6)
> +           !(smc->clcsock->sk->sk_family == AF_INET || (smc->clcsock->sk->sk_family == AF_INET6 &&
> +            ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr))) ||
> +#else
>               smc->clcsock->sk->sk_family != AF_INET ||
> +#endif
>               !smc_clc_ueid_count() ||
>               smc_find_rdma_device(smc, ini))
>                   ini->smcr_version &= ~SMC_V2;
> 
> Otherwise, the code below is reasonable.
>        if (!(ini->smcr_version & SMC_V2) ||
> +#if IS_ENABLED(CONFIG_IPV6)
> +        (smc->clcsock->sk->sk_family == AF_INET6 &&
> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
> +#endif
>            !smc_clc_ueid_count() ||
>            smc_find_rdma_device(smc, ini))
>            ini->smcr_version &= ~SMC_V2;
> 
Ok, I got your point, a socket with an address family other than AF_INET 
and AF_INET6 is already pre-filtered, so that such extra condition 
checking for the smc->clcsock->sk->sk_family != AF_INET is not 
necessary, right?

Would you like to send a new version? And feel free to use this in the 
new version:

Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>

Thanks,
Wenjia
Halil Pasic Dec. 9, 2024, 9:46 a.m. UTC | #9
On Mon, 9 Dec 2024 09:49:23 +0100
Wenjia Zhang <wenjia@linux.ibm.com> wrote:

> > Otherwise, the code below is reasonable.
> >        if (!(ini->smcr_version & SMC_V2) ||
> > +#if IS_ENABLED(CONFIG_IPV6)
> > +        (smc->clcsock->sk->sk_family == AF_INET6 &&
> > +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
> > +#endif
> >            !smc_clc_ueid_count() ||
> >            smc_find_rdma_device(smc, ini))
> >            ini->smcr_version &= ~SMC_V2;
> >   
> Ok, I got your point, a socket with an address family other than AF_INET 
> and AF_INET6 is already pre-filtered, so that such extra condition 
> checking for the smc->clcsock->sk->sk_family != AF_INET is not 
> necessary, right?
> 
> Would you like to send a new version? And feel free to use this in the 
> new version:
> 
> Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>

I believe we would like to have a v3 here. Also I'm not sure
checking on saddr is sufficient, but I didn't do my research on
that question yet.

Regards,
Halil
Guangguan Wang Dec. 9, 2024, 12:36 p.m. UTC | #10
On 2024/12/9 17:46, Halil Pasic wrote:
> On Mon, 9 Dec 2024 09:49:23 +0100
> Wenjia Zhang <wenjia@linux.ibm.com> wrote:
> 
>>> Otherwise, the code below is reasonable.
>>>        if (!(ini->smcr_version & SMC_V2) ||
>>> +#if IS_ENABLED(CONFIG_IPV6)
>>> +        (smc->clcsock->sk->sk_family == AF_INET6 &&
>>> +         !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
>>> +#endif
>>>            !smc_clc_ueid_count() ||
>>>            smc_find_rdma_device(smc, ini))
>>>            ini->smcr_version &= ~SMC_V2;
>>>   
>> Ok, I got your point, a socket with an address family other than AF_INET 
>> and AF_INET6 is already pre-filtered, so that such extra condition 
>> checking for the smc->clcsock->sk->sk_family != AF_INET is not 
>> necessary, right?
>>
>> Would you like to send a new version? And feel free to use this in the 
>> new version:
>>
>> Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
> 
> I believe we would like to have a v3 here. Also I'm not sure
> checking on saddr is sufficient, but I didn't do my research on
> that question yet.
> 
> Regards,
> Halil

Did you mean to research whether the daddr should be checked too?

Thanks,
Guangguan Wang
Halil Pasic Dec. 9, 2024, 8:44 p.m. UTC | #11
On Mon, 9 Dec 2024 20:36:45 +0800
Guangguan Wang <guangguan.wang@linux.alibaba.com> wrote:

> > I believe we would like to have a v3 here. Also I'm not sure
> > checking on saddr is sufficient, but I didn't do my research on
> > that question yet.
> > 
> > Regards,
> > Halil  
> 
> Did you mean to research whether the daddr should be checked too?

Right! Or is it implied that if saddr is a ipv4 mapped ipv6 addr
then the daddr must be ipv4 mapped ipv6 addr as well?

Regards,
Halil
Guangguan Wang Dec. 10, 2024, 7:07 a.m. UTC | #12
On 2024/12/10 04:44, Halil Pasic wrote:
> On Mon, 9 Dec 2024 20:36:45 +0800
> Guangguan Wang <guangguan.wang@linux.alibaba.com> wrote:
> 
>>> I believe we would like to have a v3 here. Also I'm not sure
>>> checking on saddr is sufficient, but I didn't do my research on
>>> that question yet.
>>>
>>> Regards,
>>> Halil  
>>
>> Did you mean to research whether the daddr should be checked too?
> 
> Right! Or is it implied that if saddr is a ipv4 mapped ipv6 addr
> then the daddr must be ipv4 mapped ipv6 addr as well?
> 
> Regards,
> Halil

I did a test by iperf3:
A server with IPV4 addr 11.213.5.33/24 and real IPV6 addr 2012::1/64.
A client with IPV4 addr 11.213.5.5/24 and real IPV6 addr 2012::2/64.
iperf3 fails to run when server listen on IPV6 addr and client connect
to server using IPV4 mapped IPV6 addr. commands show below:
server: smc_run iperf3 -s -6 -B 2012::1
client: smc_run iperf3 -t 10 -c 2012::1 -6 -B ::ffff:11.213.5.5

Failure happened due to the connect() function got the errno -EAFNOSUPPORT,
I also located the kernel code where the -EAFNOSUPPORT is returned
(https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/ipv6/ip6_output.c#:~:text=err%20%3D%20%2DEAFNOSUPPORT%3B).
The call stack is:
ip6_dst_lookup_tail+1
ip6_dst_lookup_flow+55
tcp_v6_connect+743
__inet_stream_connect+181
inet_stream_connect+59
kernel_connect+109
smc_connect+239
__sys_connect+179
__x64_sys_connect+26
do_syscall_64+112
entry_SYSCALL_64_after_hwframe+118

The kernel code mentioned above restricts that when the saddr is ipv4
mapped ipv6 addr, the daddr should be either ipv4 mapped ipv6 addr or
ipv6_addr_any(::). As far as I know, the ipv6_addr_any daddr is used
to connect to a server listen on ipv6_addr_any(::) by loopback connection.

Thus, based on the test and the code, I think it has the restrict that for
SMC-Rv2 if saddr is a ipv4 mapped ipv6 addr then the daddr must be
ipv4 mapped ipv6 addr as well.

Thanks,
Guangguan Wang
Halil Pasic Dec. 10, 2024, 9:59 a.m. UTC | #13
On Tue, 10 Dec 2024 15:07:04 +0800
Guangguan Wang <guangguan.wang@linux.alibaba.com> wrote:

> On 2024/12/10 04:44, Halil Pasic wrote:
> > On Mon, 9 Dec 2024 20:36:45 +0800
> > Guangguan Wang <guangguan.wang@linux.alibaba.com> wrote:
> >   
> >>> I believe we would like to have a v3 here. Also I'm not sure
> >>> checking on saddr is sufficient, but I didn't do my research on
> >>> that question yet.
> >>>
> >>> Regards,
> >>> Halil    
> >>
> >> Did you mean to research whether the daddr should be checked too?  
> > 
> > Right! Or is it implied that if saddr is a ipv4 mapped ipv6 addr
> > then the daddr must be ipv4 mapped ipv6 addr as well?
> > 
> > Regards,
> > Halil  
> 
> I did a test by iperf3:
> A server with IPV4 addr 11.213.5.33/24 and real IPV6 addr 2012::1/64.
> A client with IPV4 addr 11.213.5.5/24 and real IPV6 addr 2012::2/64.
> iperf3 fails to run when server listen on IPV6 addr and client connect
> to server using IPV4 mapped IPV6 addr. commands show below:
> server: smc_run iperf3 -s -6 -B 2012::1
> client: smc_run iperf3 -t 10 -c 2012::1 -6 -B ::ffff:11.213.5.5
> 
> Failure happened due to the connect() function got the errno -EAFNOSUPPORT,
> I also located the kernel code where the -EAFNOSUPPORT is returned
> (https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/ipv6/ip6_output.c#:~:text=err%20%3D%20%2DEAFNOSUPPORT%3B).

Thanks! That is enough for me!
diff mbox series

Patch

diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 9d76e902fd77..5b13dd759766 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1116,7 +1116,12 @@  static int smc_find_proposal_devices(struct smc_sock *smc,
 	ini->check_smcrv2 = true;
 	ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
 	if (!(ini->smcr_version & SMC_V2) ||
+#if IS_ENABLED(CONFIG_IPV6)
+	    (smc->clcsock->sk->sk_family != AF_INET &&
+	     !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
+#else
 	    smc->clcsock->sk->sk_family != AF_INET ||
+#endif
 	    !smc_clc_ueid_count() ||
 	    smc_find_rdma_device(smc, ini))
 		ini->smcr_version &= ~SMC_V2;