netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
@ 2023-04-07 21:08 Tony Nguyen
  2023-04-09 10:45 ` Leon Romanovsky
  0 siblings, 1 reply; 6+ messages in thread
From: Tony Nguyen @ 2023-04-07 21:08 UTC (permalink / raw)
  To: davem, kuba, pabeni, edumazet, netdev
  Cc: Ahmed Zaki, anthony.l.nguyen, Arpana Arland

From: Ahmed Zaki <ahmed.zaki@intel.com>

The flow ID passed to ice_rx_flow_steer() is computed like this:

    flow_id = skb_get_hash(skb) & flow_table->mask;

With smaller aRFS tables (for example, size 256) and higher number of
flows, there is a good chance of flow ID collisions where two or more
different flows are using the same flow ID. This results in the aRFS
destination queue constantly changing for all flows sharing that ID.

Use the full L3/L4 flow dissector info to identify the steered flow
instead of the passed flow ID.

Fixes: 28bf26724fdb ("ice: Implement aRFS")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
index fba178e07600..d7ae64d21e01 100644
--- a/drivers/net/ethernet/intel/ice/ice_arfs.c
+++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
@@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
 	return arfs_entry;
 }
 
+/**
+ * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
+ * @fltr_info: filter info of the saved ARFS entry
+ * @fk: flow dissector keys
+ *
+ * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
+ */
+static bool
+ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)
+{
+	bool is_ipv4;
+
+	if (!fltr_info || !fk)
+		return false;
+
+	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
+		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
+
+	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
+		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
+			fltr_info->ip.v4.src_port == fk->ports.src &&
+			fltr_info->ip.v4.dst_port == fk->ports.dst &&
+			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
+			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);
+	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
+		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
+			fltr_info->ip.v6.src_port == fk->ports.src &&
+			fltr_info->ip.v6.dst_port == fk->ports.dst &&
+			!memcmp(&fltr_info->ip.v6.src_ip,
+				&fk->addrs.v6addrs.src,
+				sizeof(struct in6_addr)) &&
+			!memcmp(&fltr_info->ip.v6.dst_ip,
+				&fk->addrs.v6addrs.dst,
+				sizeof(struct in6_addr)));
+
+	return false;
+}
+
 /**
  * ice_arfs_is_perfect_flow_set - Check to see if perfect flow is set
  * @hw: pointer to HW structure
@@ -436,17 +474,17 @@ ice_rx_flow_steer(struct net_device *netdev, const struct sk_buff *skb,
 
 	/* choose the aRFS list bucket based on skb hash */
 	idx = skb_get_hash_raw(skb) & ICE_ARFS_LST_MASK;
+
 	/* search for entry in the bucket */
 	spin_lock_bh(&vsi->arfs_lock);
 	hlist_for_each_entry(arfs_entry, &vsi->arfs_fltr_list[idx],
 			     list_entry) {
-		struct ice_fdir_fltr *fltr_info;
+		struct ice_fdir_fltr *fltr_info = &arfs_entry->fltr_info;
 
 		/* keep searching for the already existing arfs_entry flow */
-		if (arfs_entry->flow_id != flow_id)
+		if (!ice_arfs_cmp(fltr_info, &fk))
 			continue;
 
-		fltr_info = &arfs_entry->fltr_info;
 		ret = fltr_info->fltr_id;
 
 		if (fltr_info->q_index == rxq_idx ||
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
  2023-04-07 21:08 [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info Tony Nguyen
@ 2023-04-09 10:45 ` Leon Romanovsky
  2023-04-10 18:54   ` Ahmed Zaki
  0 siblings, 1 reply; 6+ messages in thread
From: Leon Romanovsky @ 2023-04-09 10:45 UTC (permalink / raw)
  To: Tony Nguyen
  Cc: davem, kuba, pabeni, edumazet, netdev, Ahmed Zaki, Arpana Arland

On Fri, Apr 07, 2023 at 02:08:20PM -0700, Tony Nguyen wrote:
> From: Ahmed Zaki <ahmed.zaki@intel.com>
> 
> The flow ID passed to ice_rx_flow_steer() is computed like this:
> 
>     flow_id = skb_get_hash(skb) & flow_table->mask;
> 
> With smaller aRFS tables (for example, size 256) and higher number of
> flows, there is a good chance of flow ID collisions where two or more
> different flows are using the same flow ID. This results in the aRFS
> destination queue constantly changing for all flows sharing that ID.
> 
> Use the full L3/L4 flow dissector info to identify the steered flow
> instead of the passed flow ID.
> 
> Fixes: 28bf26724fdb ("ice: Implement aRFS")
> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
> Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
> ---
>  drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
>  1 file changed, 41 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
> index fba178e07600..d7ae64d21e01 100644
> --- a/drivers/net/ethernet/intel/ice/ice_arfs.c
> +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
> @@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
>  	return arfs_entry;
>  }
>  
> +/**
> + * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
> + * @fltr_info: filter info of the saved ARFS entry
> + * @fk: flow dissector keys
> + *
> + * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
> + */
> +static bool
> +ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)
> +{
> +	bool is_ipv4;
> +
> +	if (!fltr_info || !fk)
> +		return false;
> +
> +	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
> +		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
> +
> +	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
> +		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
> +			fltr_info->ip.v4.src_port == fk->ports.src &&
> +			fltr_info->ip.v4.dst_port == fk->ports.dst &&
> +			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
> +			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);
> +	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
> +		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
> +			fltr_info->ip.v6.src_port == fk->ports.src &&
> +			fltr_info->ip.v6.dst_port == fk->ports.dst &&
> +			!memcmp(&fltr_info->ip.v6.src_ip,
> +				&fk->addrs.v6addrs.src,
> +				sizeof(struct in6_addr)) &&
> +			!memcmp(&fltr_info->ip.v6.dst_ip,
> +				&fk->addrs.v6addrs.dst,
> +				sizeof(struct in6_addr)));

I'm confident that you can write this function more clear with
comparisons in one "return ..." instruction.

Thanks

> +
> +	return false;
> +}
> +
>  /**
>   * ice_arfs_is_perfect_flow_set - Check to see if perfect flow is set
>   * @hw: pointer to HW structure
> @@ -436,17 +474,17 @@ ice_rx_flow_steer(struct net_device *netdev, const struct sk_buff *skb,
>  
>  	/* choose the aRFS list bucket based on skb hash */
>  	idx = skb_get_hash_raw(skb) & ICE_ARFS_LST_MASK;
> +
>  	/* search for entry in the bucket */
>  	spin_lock_bh(&vsi->arfs_lock);
>  	hlist_for_each_entry(arfs_entry, &vsi->arfs_fltr_list[idx],
>  			     list_entry) {
> -		struct ice_fdir_fltr *fltr_info;
> +		struct ice_fdir_fltr *fltr_info = &arfs_entry->fltr_info;
>  
>  		/* keep searching for the already existing arfs_entry flow */
> -		if (arfs_entry->flow_id != flow_id)
> +		if (!ice_arfs_cmp(fltr_info, &fk))
>  			continue;
>  
> -		fltr_info = &arfs_entry->fltr_info;
>  		ret = fltr_info->fltr_id;
>  
>  		if (fltr_info->q_index == rxq_idx ||
> -- 
> 2.38.1
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
  2023-04-09 10:45 ` Leon Romanovsky
@ 2023-04-10 18:54   ` Ahmed Zaki
  2023-04-13 17:27     ` Jacob Keller
  0 siblings, 1 reply; 6+ messages in thread
From: Ahmed Zaki @ 2023-04-10 18:54 UTC (permalink / raw)
  To: Leon Romanovsky, Tony Nguyen
  Cc: davem, kuba, pabeni, edumazet, netdev, Arpana Arland


On 2023-04-09 04:45, Leon Romanovsky wrote:
> On Fri, Apr 07, 2023 at 02:08:20PM -0700, Tony Nguyen wrote:
>> From: Ahmed Zaki <ahmed.zaki@intel.com>
>>
>> The flow ID passed to ice_rx_flow_steer() is computed like this:
>>
>>      flow_id = skb_get_hash(skb) & flow_table->mask;
>>
>> With smaller aRFS tables (for example, size 256) and higher number of
>> flows, there is a good chance of flow ID collisions where two or more
>> different flows are using the same flow ID. This results in the aRFS
>> destination queue constantly changing for all flows sharing that ID.
>>
>> Use the full L3/L4 flow dissector info to identify the steered flow
>> instead of the passed flow ID.
>>
>> Fixes: 28bf26724fdb ("ice: Implement aRFS")
>> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
>> Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
>> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
>> ---
>>   drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
>>   1 file changed, 41 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
>> index fba178e07600..d7ae64d21e01 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_arfs.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
>> @@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
>>   	return arfs_entry;
>>   }
>>   
>> +/**
>> + * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
>> + * @fltr_info: filter info of the saved ARFS entry
>> + * @fk: flow dissector keys
>> + *
>> + * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
>> + */
>> +static bool
>> +ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)
>> +{
>> +	bool is_ipv4;
>> +
>> +	if (!fltr_info || !fk)
>> +		return false;
>> +
>> +	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
>> +		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
>> +
>> +	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
>> +		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
>> +			fltr_info->ip.v4.src_port == fk->ports.src &&
>> +			fltr_info->ip.v4.dst_port == fk->ports.dst &&
>> +			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
>> +			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);
>> +	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
>> +		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
>> +			fltr_info->ip.v6.src_port == fk->ports.src &&
>> +			fltr_info->ip.v6.dst_port == fk->ports.dst &&
>> +			!memcmp(&fltr_info->ip.v6.src_ip,
>> +				&fk->addrs.v6addrs.src,
>> +				sizeof(struct in6_addr)) &&
>> +			!memcmp(&fltr_info->ip.v6.dst_ip,
>> +				&fk->addrs.v6addrs.dst,
>> +				sizeof(struct in6_addr)));
> I'm confident that you can write this function more clear with
> comparisons in one "return ..." instruction.
>
> Thanks

Do you mean remove the "if condition"? how?

I wrote it this way to match how I'd think:

If (IPv4 and V4 flows), test IPv4 flow keys, else if (IPv6 and V6 
flows), test IPv6 keys, else false.

I m not sure how can I make it more clearer.

Thanks.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
  2023-04-10 18:54   ` Ahmed Zaki
@ 2023-04-13 17:27     ` Jacob Keller
  2023-04-14  8:54       ` Leon Romanovsky
  0 siblings, 1 reply; 6+ messages in thread
From: Jacob Keller @ 2023-04-13 17:27 UTC (permalink / raw)
  To: Ahmed Zaki, Leon Romanovsky, Tony Nguyen
  Cc: davem, kuba, pabeni, edumazet, netdev, Arpana Arland



On 4/10/2023 11:54 AM, Ahmed Zaki wrote:
> 
> On 2023-04-09 04:45, Leon Romanovsky wrote:
>> On Fri, Apr 07, 2023 at 02:08:20PM -0700, Tony Nguyen wrote:
>>> From: Ahmed Zaki <ahmed.zaki@intel.com>
>>>
>>> The flow ID passed to ice_rx_flow_steer() is computed like this:
>>>
>>>      flow_id = skb_get_hash(skb) & flow_table->mask;
>>>
>>> With smaller aRFS tables (for example, size 256) and higher number of
>>> flows, there is a good chance of flow ID collisions where two or more
>>> different flows are using the same flow ID. This results in the aRFS
>>> destination queue constantly changing for all flows sharing that ID.
>>>
>>> Use the full L3/L4 flow dissector info to identify the steered flow
>>> instead of the passed flow ID.
>>>
>>> Fixes: 28bf26724fdb ("ice: Implement aRFS")
>>> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
>>> Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
>>> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
>>> ---
>>>   drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
>>>   1 file changed, 41 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
>>> index fba178e07600..d7ae64d21e01 100644
>>> --- a/drivers/net/ethernet/intel/ice/ice_arfs.c
>>> +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
>>> @@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
>>>   	return arfs_entry;
>>>   }
>>>   
>>> +/**
>>> + * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
>>> + * @fltr_info: filter info of the saved ARFS entry
>>> + * @fk: flow dissector keys
>>> + *
>>> + * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
>>> + */
>>> +static bool
>>> +ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)
>>> +{
>>> +	bool is_ipv4;
>>> +
>>> +	if (!fltr_info || !fk)
>>> +		return false;
>>> +
>>> +	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
>>> +		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
>>> +
>>> +	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
>>> +		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
>>> +			fltr_info->ip.v4.src_port == fk->ports.src &&
>>> +			fltr_info->ip.v4.dst_port == fk->ports.dst &&
>>> +			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
>>> +			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);
>>> +	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
>>> +		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
>>> +			fltr_info->ip.v6.src_port == fk->ports.src &&
>>> +			fltr_info->ip.v6.dst_port == fk->ports.dst &&
>>> +			!memcmp(&fltr_info->ip.v6.src_ip,
>>> +				&fk->addrs.v6addrs.src,
>>> +				sizeof(struct in6_addr)) &&
>>> +			!memcmp(&fltr_info->ip.v6.dst_ip,
>>> +				&fk->addrs.v6addrs.dst,
>>> +				sizeof(struct in6_addr)));
>> I'm confident that you can write this function more clear with
>> comparisons in one "return ..." instruction.
>>>> Thanks
> 
> Do you mean remove the "if condition"? how?
> 
> I wrote it this way to match how I'd think:
> 
> If (IPv4 and V4 flows), test IPv4 flow keys, else if (IPv6 and V6 
> flows), test IPv6 keys, else false.
> 

You can use a || chain, something like:

return (is_ipv4 && (<check ipv4 fields)) || (!is_ipv4 && (<check ip6
fields>)

There might be other ways to simplify the conditional. You could
possibly combine the n_proto check with the is_ipv4 check above as well.


> I m not sure how can I make it more clearer.
> 
> Thanks.
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
  2023-04-13 17:27     ` Jacob Keller
@ 2023-04-14  8:54       ` Leon Romanovsky
  2023-04-14 16:07         ` Alexander Lobakin
  0 siblings, 1 reply; 6+ messages in thread
From: Leon Romanovsky @ 2023-04-14  8:54 UTC (permalink / raw)
  To: Jacob Keller
  Cc: Ahmed Zaki, Tony Nguyen, davem, kuba, pabeni, edumazet, netdev,
	Arpana Arland

On Thu, Apr 13, 2023 at 10:27:56AM -0700, Jacob Keller wrote:
> 
> 
> On 4/10/2023 11:54 AM, Ahmed Zaki wrote:
> > 
> > On 2023-04-09 04:45, Leon Romanovsky wrote:
> >> On Fri, Apr 07, 2023 at 02:08:20PM -0700, Tony Nguyen wrote:
> >>> From: Ahmed Zaki <ahmed.zaki@intel.com>
> >>>
> >>> The flow ID passed to ice_rx_flow_steer() is computed like this:
> >>>
> >>>      flow_id = skb_get_hash(skb) & flow_table->mask;
> >>>
> >>> With smaller aRFS tables (for example, size 256) and higher number of
> >>> flows, there is a good chance of flow ID collisions where two or more
> >>> different flows are using the same flow ID. This results in the aRFS
> >>> destination queue constantly changing for all flows sharing that ID.
> >>>
> >>> Use the full L3/L4 flow dissector info to identify the steered flow
> >>> instead of the passed flow ID.
> >>>
> >>> Fixes: 28bf26724fdb ("ice: Implement aRFS")
> >>> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
> >>> Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
> >>> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
> >>> ---
> >>>   drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
> >>>   1 file changed, 41 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
> >>> index fba178e07600..d7ae64d21e01 100644
> >>> --- a/drivers/net/ethernet/intel/ice/ice_arfs.c
> >>> +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
> >>> @@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
> >>>   	return arfs_entry;
> >>>   }
> >>>   
> >>> +/**
> >>> + * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
> >>> + * @fltr_info: filter info of the saved ARFS entry
> >>> + * @fk: flow dissector keys
> >>> + *
> >>> + * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
> >>> + */
> >>> +static bool
> >>> +ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)
> >>> +{
> >>> +	bool is_ipv4;
> >>> +
> >>> +	if (!fltr_info || !fk)
> >>> +		return false;
> >>> +
> >>> +	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
> >>> +		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
> >>> +
> >>> +	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
> >>> +		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
> >>> +			fltr_info->ip.v4.src_port == fk->ports.src &&
> >>> +			fltr_info->ip.v4.dst_port == fk->ports.dst &&
> >>> +			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
> >>> +			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);
> >>> +	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
> >>> +		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
> >>> +			fltr_info->ip.v6.src_port == fk->ports.src &&
> >>> +			fltr_info->ip.v6.dst_port == fk->ports.dst &&
> >>> +			!memcmp(&fltr_info->ip.v6.src_ip,
> >>> +				&fk->addrs.v6addrs.src,
> >>> +				sizeof(struct in6_addr)) &&
> >>> +			!memcmp(&fltr_info->ip.v6.dst_ip,
> >>> +				&fk->addrs.v6addrs.dst,
> >>> +				sizeof(struct in6_addr)));
> >> I'm confident that you can write this function more clear with
> >> comparisons in one "return ..." instruction.
> >>>> Thanks
> > 
> > Do you mean remove the "if condition"? how?
> > 
> > I wrote it this way to match how I'd think:
> > 
> > If (IPv4 and V4 flows), test IPv4 flow keys, else if (IPv6 and V6 
> > flows), test IPv6 keys, else false.
> > 
> 
> You can use a || chain, something like:
> 
> return (is_ipv4 && (<check ipv4 fields)) || (!is_ipv4 && (<check ip6
> fields>)
> 
> There might be other ways to simplify the conditional. You could
> possibly combine the n_proto check with the is_ipv4 check above as well.

Another possible option is to use variable to store intermediate result.

Thanks

> 
> 
> > I m not sure how can I make it more clearer.
> > 
> > Thanks.
> > 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info
  2023-04-14  8:54       ` Leon Romanovsky
@ 2023-04-14 16:07         ` Alexander Lobakin
  0 siblings, 0 replies; 6+ messages in thread
From: Alexander Lobakin @ 2023-04-14 16:07 UTC (permalink / raw)
  To: Ahmed Zaki
  Cc: Leon Romanovsky, Jacob Keller, Tony Nguyen, davem, kuba, pabeni,
	edumazet, netdev, Arpana Arland

From: Leon Romanovsky <leon@kernel.org>
Date: Fri, 14 Apr 2023 11:54:05 +0300

> On Thu, Apr 13, 2023 at 10:27:56AM -0700, Jacob Keller wrote:
>>
>>
>> On 4/10/2023 11:54 AM, Ahmed Zaki wrote:
>>>
>>> On 2023-04-09 04:45, Leon Romanovsky wrote:
>>>> On Fri, Apr 07, 2023 at 02:08:20PM -0700, Tony Nguyen wrote:
>>>>> From: Ahmed Zaki <ahmed.zaki@intel.com>
>>>>>
>>>>> The flow ID passed to ice_rx_flow_steer() is computed like this:
>>>>>
>>>>>      flow_id = skb_get_hash(skb) & flow_table->mask;
>>>>>
>>>>> With smaller aRFS tables (for example, size 256) and higher number of
>>>>> flows, there is a good chance of flow ID collisions where two or more
>>>>> different flows are using the same flow ID. This results in the aRFS
>>>>> destination queue constantly changing for all flows sharing that ID.
>>>>>
>>>>> Use the full L3/L4 flow dissector info to identify the steered flow
>>>>> instead of the passed flow ID.
>>>>>
>>>>> Fixes: 28bf26724fdb ("ice: Implement aRFS")
>>>>> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
>>>>> Tested-by: Arpana Arland <arpanax.arland@intel.com> (A Contingent worker at Intel)
>>>>> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
>>>>> ---
>>>>>   drivers/net/ethernet/intel/ice/ice_arfs.c | 44 +++++++++++++++++++++--
>>>>>   1 file changed, 41 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c
>>>>> index fba178e07600..d7ae64d21e01 100644
>>>>> --- a/drivers/net/ethernet/intel/ice/ice_arfs.c
>>>>> +++ b/drivers/net/ethernet/intel/ice/ice_arfs.c
>>>>> @@ -345,6 +345,44 @@ ice_arfs_build_entry(struct ice_vsi *vsi, const struct flow_keys *fk,
>>>>>   	return arfs_entry;
>>>>>   }
>>>>>   
>>>>> +/**
>>>>> + * ice_arfs_cmp - compare flow to a saved ARFS entry's filter info
>>>>> + * @fltr_info: filter info of the saved ARFS entry
>>>>> + * @fk: flow dissector keys
>>>>> + *
>>>>> + * Caller must hold arfs_lock if @fltr_info belongs to arfs_fltr_list
>>>>> + */
>>>>> +static bool
>>>>> +ice_arfs_cmp(struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk)

@fltr_info can be const BTW.

>>>>> +{
>>>>> +	bool is_ipv4;
>>>>> +
>>>>> +	if (!fltr_info || !fk)
>>>>> +		return false;
>>>>> +
>>>>> +	is_ipv4 = (fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
>>>>> +		fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);

	is_v4 = fk->basic.n_proto == htons(ETH_P_IP) &&
		(fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
		 fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP);
	if (!is_v4 && fk->basic.n_proto != htons(ETH_P_IPV6))
		return;

That's -1 indent level.

(your statements have too many braces BTW, at least half of them are not
needed)

>>>>> +
>>>>> +	if (fk->basic.n_proto == htons(ETH_P_IP) && is_ipv4)
>>>>> +		return (fltr_info->ip.v4.proto == fk->basic.ip_proto &&
>>>>> +			fltr_info->ip.v4.src_port == fk->ports.src &&
>>>>> +			fltr_info->ip.v4.dst_port == fk->ports.dst &&
>>>>> +			fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src &&
>>>>> +			fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst);

	const struct ice_fdir_v4 *v4 = &fltr_info->ip.v4;

	return v4->proto == fk->basic.ip_proto && ...

That removes 13 chars from each comparison.
return with IP ver check would then look like:

	return (is_v4 && v4->proto == ...) ||
	       (!is_v4 && v6->proto == ...);

But honestly I would split those branches into separate small static
functions, compilers will combine them later as well:

	return is_v4 ? ice_arfs_cmp_v4(&fltr_info->ip.v4, fk) :
		       ice_arfs_cmp_v6(&fltr_info->ip.v6, fk);

>>>>> +	else if (fk->basic.n_proto == htons(ETH_P_IPV6) && !is_ipv4)
>>>>> +		return (fltr_info->ip.v6.proto == fk->basic.ip_proto &&
>>>>> +			fltr_info->ip.v6.src_port == fk->ports.src &&
>>>>> +			fltr_info->ip.v6.dst_port == fk->ports.dst &&
>>>>> +			!memcmp(&fltr_info->ip.v6.src_ip,
>>>>> +				&fk->addrs.v6addrs.src,
>>>>> +				sizeof(struct in6_addr)) &&
>>>>> +			!memcmp(&fltr_info->ip.v6.dst_ip,
>>>>> +				&fk->addrs.v6addrs.dst,
>>>>> +				sizeof(struct in6_addr)));

Or you can reorder src and dst IPs in &ice_fdir_v6 and then do that in
one memcmp():

	return ... &&
	       !memcmp(&v6->dst_ip, &fk->addrs.v6addrs.dst,
		       2 * sizeof(v6->dst_ip));

OR what I'd do is I'd use Flow Dissector's structures in ice_fdir_v{4,6}
so that it would be much easier to compare them. The layout won't even
change, not counting dst/src IP reorder:

struct ice_fdir_v6 {
	struct flow_dissector_key_ipv6_addrs addrs;
	struct flow_dissector_key_ports ports;
	__be32 l4_header;
	...
};

I know those structures probably come from OS-independent code or so,
but folks know I never sacrifice convenience in favor of some OOT
compatibility :p

Also, note that &flow_dissector_key_ports unionize src + dst ports into
one `__be32` nicely, so that they could be compared in one 32-bit value
cmp instruction. &ice_fdir_v{4,6} lack those and you need to use more
instructions and shorter types (even more instructions).

>>>> I'm confident that you can write this function more clear with
>>>> comparisons in one "return ..." instruction.
>>>>>> Thanks
>>>
>>> Do you mean remove the "if condition"? how?
>>>
>>> I wrote it this way to match how I'd think:
>>>
>>> If (IPv4 and V4 flows), test IPv4 flow keys, else if (IPv6 and V6 
>>> flows), test IPv6 keys, else false.
>>>
>>
>> You can use a || chain, something like:
>>
>> return (is_ipv4 && (<check ipv4 fields)) || (!is_ipv4 && (<check ip6
>> fields>)
>>
>> There might be other ways to simplify the conditional. You could
>> possibly combine the n_proto check with the is_ipv4 check above as well.
> 
> Another possible option is to use variable to store intermediate result.

Billion of different options here to me <_<

> 
> Thanks
> 
>>
>>
>>> I m not sure how can I make it more clearer.
>>>
>>> Thanks.
>>>
> 

Thanks,
Olek

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-04-14 16:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-07 21:08 [PATCH net 1/1] ice: identify aRFS flows using L3/L4 dissector info Tony Nguyen
2023-04-09 10:45 ` Leon Romanovsky
2023-04-10 18:54   ` Ahmed Zaki
2023-04-13 17:27     ` Jacob Keller
2023-04-14  8:54       ` Leon Romanovsky
2023-04-14 16:07         ` Alexander Lobakin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).