diff mbox series

[net] sfc: check hash is valid before using it

Message ID 35c28344-605a-009b-70a0-6030cf88ed02@solarflare.com
State Accepted
Delegated to: David Miller
Headers show
Series [net] sfc: check hash is valid before using it | expand

Commit Message

Edward Cree Aug. 14, 2020, 12:26 p.m. UTC
On EF100, the RX hash field in the packet prefix may not be valid (e.g.
 if the header parse failed), and this is indicated by a one-bit flag
 elsewhere in the packet prefix.  Only call skb_set_hash() if the
 RSS_HASH_VALID bit is set.

Signed-off-by: Edward Cree <ecree@solarflare.com>
---
 drivers/net/ethernet/sfc/ef100_rx.c   | 5 +++++
 drivers/net/ethernet/sfc/ef100_rx.h   | 1 +
 drivers/net/ethernet/sfc/efx.h        | 8 ++++++++
 drivers/net/ethernet/sfc/net_driver.h | 2 ++
 drivers/net/ethernet/sfc/rx_common.c  | 3 ++-
 5 files changed, 18 insertions(+), 1 deletion(-)

Comments

David Miller Aug. 14, 2020, 9:07 p.m. UTC | #1
From: Edward Cree <ecree@solarflare.com>
Date: Fri, 14 Aug 2020 13:26:22 +0100

> On EF100, the RX hash field in the packet prefix may not be valid (e.g.
>  if the header parse failed), and this is indicated by a one-bit flag
>  elsewhere in the packet prefix.  Only call skb_set_hash() if the
>  RSS_HASH_VALID bit is set.
> 
> Signed-off-by: Edward Cree <ecree@solarflare.com>

Applied.
Martin Habets Aug. 18, 2020, 8:35 a.m. UTC | #2
Hi Ed,

On Fri, Aug 14, 2020 at 01:26:22PM +0100, Edward Cree wrote:
> On EF100, the RX hash field in the packet prefix may not be valid (e.g.
>  if the header parse failed), and this is indicated by a one-bit flag
>  elsewhere in the packet prefix.  Only call skb_set_hash() if the
>  RSS_HASH_VALID bit is set.
> 
> Signed-off-by: Edward Cree <ecree@solarflare.com>
> ---
>  drivers/net/ethernet/sfc/ef100_rx.c   | 5 +++++
>  drivers/net/ethernet/sfc/ef100_rx.h   | 1 +
>  drivers/net/ethernet/sfc/efx.h        | 8 ++++++++
>  drivers/net/ethernet/sfc/net_driver.h | 2 ++
>  drivers/net/ethernet/sfc/rx_common.c  | 3 ++-
>  5 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c
> index 13ba1a4f66fc..012925e878f4 100644
> --- a/drivers/net/ethernet/sfc/ef100_rx.c
> +++ b/drivers/net/ethernet/sfc/ef100_rx.c
> @@ -31,6 +31,11 @@
>  #define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_WIDTH	\
>  		ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_WIDTH
>  
> +bool ef100_rx_buf_hash_valid(const u8 *prefix)
> +{
> +	return PREFIX_FIELD(prefix, RSS_HASH_VALID);
> +}
> +
>  static bool check_fcs(struct efx_channel *channel, u32 *prefix)
>  {
>  	u16 rxclass;
> diff --git a/drivers/net/ethernet/sfc/ef100_rx.h b/drivers/net/ethernet/sfc/ef100_rx.h
> index f2f266863966..fe45b36458d1 100644
> --- a/drivers/net/ethernet/sfc/ef100_rx.h
> +++ b/drivers/net/ethernet/sfc/ef100_rx.h
> @@ -14,6 +14,7 @@
>  
>  #include "net_driver.h"
>  
> +bool ef100_rx_buf_hash_valid(const u8 *prefix);
>  void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event);
>  void ef100_rx_write(struct efx_rx_queue *rx_queue);
>  void __ef100_rx_packet(struct efx_channel *channel);
> diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
> index a9808e86068d..daf0c00c1242 100644
> --- a/drivers/net/ethernet/sfc/efx.h
> +++ b/drivers/net/ethernet/sfc/efx.h
> @@ -45,6 +45,14 @@ static inline void efx_rx_flush_packet(struct efx_channel *channel)
>  				__ef100_rx_packet, __efx_rx_packet,
>  				channel);
>  }
> +static inline bool efx_rx_buf_hash_valid(struct efx_nic *efx, const u8 *prefix)
> +{
> +	if (efx->type->rx_buf_hash_valid)

For this to take effect you still need to hook up efx->type->rx_buf_hash_valid
in the ef100_nic.c efx_nic_type structs.

Martin

> +		return INDIRECT_CALL_1(efx->type->rx_buf_hash_valid,
> +				       ef100_rx_buf_hash_valid,
> +				       prefix);
> +	return true;
> +}
>  
>  /* Maximum number of TCP segments we support for soft-TSO */
>  #define EFX_TSO_MAX_SEGS	100
> diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
> index 7bb7ecb480ae..dcb741d8bd11 100644
> --- a/drivers/net/ethernet/sfc/net_driver.h
> +++ b/drivers/net/ethernet/sfc/net_driver.h
> @@ -1265,6 +1265,7 @@ struct efx_udp_tunnel {
>   * @rx_write: Write RX descriptors and doorbell
>   * @rx_defer_refill: Generate a refill reminder event
>   * @rx_packet: Receive the queued RX buffer on a channel
> + * @rx_buf_hash_valid: Determine whether the RX prefix contains a valid hash
>   * @ev_probe: Allocate resources for event queue
>   * @ev_init: Initialise event queue on the NIC
>   * @ev_fini: Deinitialise event queue on the NIC
> @@ -1409,6 +1410,7 @@ struct efx_nic_type {
>  	void (*rx_write)(struct efx_rx_queue *rx_queue);
>  	void (*rx_defer_refill)(struct efx_rx_queue *rx_queue);
>  	void (*rx_packet)(struct efx_channel *channel);
> +	bool (*rx_buf_hash_valid)(const u8 *prefix);
>  	int (*ev_probe)(struct efx_channel *channel);
>  	int (*ev_init)(struct efx_channel *channel);
>  	void (*ev_fini)(struct efx_channel *channel);
> diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c
> index fb77c7bbe4af..ef9bca92b0b7 100644
> --- a/drivers/net/ethernet/sfc/rx_common.c
> +++ b/drivers/net/ethernet/sfc/rx_common.c
> @@ -525,7 +525,8 @@ efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
>  		return;
>  	}
>  
> -	if (efx->net_dev->features & NETIF_F_RXHASH)
> +	if (efx->net_dev->features & NETIF_F_RXHASH &&
> +	    efx_rx_buf_hash_valid(efx, eh))
>  		skb_set_hash(skb, efx_rx_buf_hash(efx, eh),
>  			     PKT_HASH_TYPE_L3);
>  	if (csum) {
diff mbox series

Patch

diff --git a/drivers/net/ethernet/sfc/ef100_rx.c b/drivers/net/ethernet/sfc/ef100_rx.c
index 13ba1a4f66fc..012925e878f4 100644
--- a/drivers/net/ethernet/sfc/ef100_rx.c
+++ b/drivers/net/ethernet/sfc/ef100_rx.c
@@ -31,6 +31,11 @@ 
 #define ESF_GZ_RX_PREFIX_NT_OR_INNER_L3_CLASS_WIDTH	\
 		ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS_WIDTH
 
+bool ef100_rx_buf_hash_valid(const u8 *prefix)
+{
+	return PREFIX_FIELD(prefix, RSS_HASH_VALID);
+}
+
 static bool check_fcs(struct efx_channel *channel, u32 *prefix)
 {
 	u16 rxclass;
diff --git a/drivers/net/ethernet/sfc/ef100_rx.h b/drivers/net/ethernet/sfc/ef100_rx.h
index f2f266863966..fe45b36458d1 100644
--- a/drivers/net/ethernet/sfc/ef100_rx.h
+++ b/drivers/net/ethernet/sfc/ef100_rx.h
@@ -14,6 +14,7 @@ 
 
 #include "net_driver.h"
 
+bool ef100_rx_buf_hash_valid(const u8 *prefix);
 void efx_ef100_ev_rx(struct efx_channel *channel, const efx_qword_t *p_event);
 void ef100_rx_write(struct efx_rx_queue *rx_queue);
 void __ef100_rx_packet(struct efx_channel *channel);
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index a9808e86068d..daf0c00c1242 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -45,6 +45,14 @@  static inline void efx_rx_flush_packet(struct efx_channel *channel)
 				__ef100_rx_packet, __efx_rx_packet,
 				channel);
 }
+static inline bool efx_rx_buf_hash_valid(struct efx_nic *efx, const u8 *prefix)
+{
+	if (efx->type->rx_buf_hash_valid)
+		return INDIRECT_CALL_1(efx->type->rx_buf_hash_valid,
+				       ef100_rx_buf_hash_valid,
+				       prefix);
+	return true;
+}
 
 /* Maximum number of TCP segments we support for soft-TSO */
 #define EFX_TSO_MAX_SEGS	100
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 7bb7ecb480ae..dcb741d8bd11 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -1265,6 +1265,7 @@  struct efx_udp_tunnel {
  * @rx_write: Write RX descriptors and doorbell
  * @rx_defer_refill: Generate a refill reminder event
  * @rx_packet: Receive the queued RX buffer on a channel
+ * @rx_buf_hash_valid: Determine whether the RX prefix contains a valid hash
  * @ev_probe: Allocate resources for event queue
  * @ev_init: Initialise event queue on the NIC
  * @ev_fini: Deinitialise event queue on the NIC
@@ -1409,6 +1410,7 @@  struct efx_nic_type {
 	void (*rx_write)(struct efx_rx_queue *rx_queue);
 	void (*rx_defer_refill)(struct efx_rx_queue *rx_queue);
 	void (*rx_packet)(struct efx_channel *channel);
+	bool (*rx_buf_hash_valid)(const u8 *prefix);
 	int (*ev_probe)(struct efx_channel *channel);
 	int (*ev_init)(struct efx_channel *channel);
 	void (*ev_fini)(struct efx_channel *channel);
diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c
index fb77c7bbe4af..ef9bca92b0b7 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -525,7 +525,8 @@  efx_rx_packet_gro(struct efx_channel *channel, struct efx_rx_buffer *rx_buf,
 		return;
 	}
 
-	if (efx->net_dev->features & NETIF_F_RXHASH)
+	if (efx->net_dev->features & NETIF_F_RXHASH &&
+	    efx_rx_buf_hash_valid(efx, eh))
 		skb_set_hash(skb, efx_rx_buf_hash(efx, eh),
 			     PKT_HASH_TYPE_L3);
 	if (csum) {