All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Lobakin <alexandr.lobakin@intel.com>
To: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: <bpf@vger.kernel.org>, <netdev@vger.kernel.org>,
	Stanislav Fomichev <sdf@google.com>, <martin.lau@kernel.org>,
	<ast@kernel.org>, <daniel@iogearbox.net>,
	<yoong.siang.song@intel.com>, <anthony.l.nguyen@intel.com>,
	<intel-wired-lan@lists.osuosl.org>, <xdp-hints@xdp-project.net>
Subject: Re: [PATCH bpf-next V1] igc: enable and fix RX hash usage by netstack
Date: Tue, 14 Feb 2023 14:21:00 +0100	[thread overview]
Message-ID: <af69e040-3884-aa73-1241-99207aa577b4@intel.com> (raw)
In-Reply-To: <167604167956.1726972.7266620647404438534.stgit@firesoul>

From: Jesper Dangaard Brouer <brouer@redhat.com>
Date: Fri, 10 Feb 2023 16:07:59 +0100

> When function igc_rx_hash() was introduced in v4.20 via commit 0507ef8a0372
> ("igc: Add transmit and receive fastpath and interrupt handlers"), the
> hardware wasn't configured to provide RSS hash, thus it made sense to not
> enable net_device NETIF_F_RXHASH feature bit.

[...]

> @@ -311,6 +311,58 @@ extern char igc_driver_name[];
>  #define IGC_MRQC_RSS_FIELD_IPV4_UDP	0x00400000
>  #define IGC_MRQC_RSS_FIELD_IPV6_UDP	0x00800000
>  
> +/* RX-desc Write-Back format RSS Type's */
> +enum igc_rss_type_num {
> +	IGC_RSS_TYPE_NO_HASH		= 0,
> +	IGC_RSS_TYPE_HASH_TCP_IPV4	= 1,
> +	IGC_RSS_TYPE_HASH_IPV4		= 2,
> +	IGC_RSS_TYPE_HASH_TCP_IPV6	= 3,
> +	IGC_RSS_TYPE_HASH_IPV6_EX	= 4,
> +	IGC_RSS_TYPE_HASH_IPV6		= 5,
> +	IGC_RSS_TYPE_HASH_TCP_IPV6_EX	= 6,
> +	IGC_RSS_TYPE_HASH_UDP_IPV4	= 7,
> +	IGC_RSS_TYPE_HASH_UDP_IPV6	= 8,
> +	IGC_RSS_TYPE_HASH_UDP_IPV6_EX	= 9,
> +	IGC_RSS_TYPE_MAX		= 10,
> +};
> +#define IGC_RSS_TYPE_MAX_TABLE		16
> +#define IGC_RSS_TYPE_MASK		0xF

GENMASK()?

> +
> +/* igc_rss_type - Rx descriptor RSS type field */
> +static inline u8 igc_rss_type(union igc_adv_rx_desc *rx_desc)

Why use types shorter than u32 on the stack?
Why this union is not const here, since there are no modifications?

> +{
> +	/* RSS Type 4-bit number: 0-9 (above 9 is reserved) */
> +	return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info & IGC_RSS_TYPE_MASK;

The most important I wanted to mention: doesn't this function make the
CPU read the uncached field again, while you could just read it once
onto the stack and then extract all such data from there?

> +}
> +
> +/* Packet header type identified by hardware (when BIT(11) is zero).
> + * Even when UDP ports are not part of RSS hash HW still parse and mark UDP bits
> + */
> +enum igc_pkt_type_bits {
> +	IGC_PKT_TYPE_HDR_IPV4	=	BIT(0),
> +	IGC_PKT_TYPE_HDR_IPV4_WITH_OPT=	BIT(1), /* IPv4 Hdr includes IP options */
> +	IGC_PKT_TYPE_HDR_IPV6	=	BIT(2),
> +	IGC_PKT_TYPE_HDR_IPV6_WITH_EXT=	BIT(3), /* IPv6 Hdr includes extensions */
> +	IGC_PKT_TYPE_HDR_L4_TCP	=	BIT(4),
> +	IGC_PKT_TYPE_HDR_L4_UDP	=	BIT(5),
> +	IGC_PKT_TYPE_HDR_L4_SCTP=	BIT(6),
> +	IGC_PKT_TYPE_HDR_NFS	=	BIT(7),
> +	/* Above only valid when BIT(11) is zero */
> +	IGC_PKT_TYPE_L2		=	BIT(11),
> +	IGC_PKT_TYPE_VLAN	=	BIT(12),
> +	IGC_PKT_TYPE_MASK	=	0x1FFF, /* 13-bits */

Also GENMASK().

> +};
> +
> +/* igc_pkt_type - Rx descriptor Packet type field */
> +static inline u16 igc_pkt_type(union igc_adv_rx_desc *rx_desc)

Also short types and consts.

> +{
> +	u32 data = le32_to_cpu(rx_desc->wb.lower.lo_dword.data);
> +	/* Packet type is 13-bits - as bits (16:4) in lower.lo_dword*/
> +	u16 pkt_type = (data >> 4) & IGC_PKT_TYPE_MASK;

Perfect candidate for FIELD_GET(). No, even for le32_get_bits().

Also my note above about excessive expensive reads.

> +
> +	return pkt_type;
> +}
> +
>  /* Interrupt defines */
>  #define IGC_START_ITR			648 /* ~6000 ints/sec */
>  #define IGC_4K_ITR			980
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
> index 8b572cd2c350..42a072509d2a 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -1677,14 +1677,40 @@ static void igc_rx_checksum(struct igc_ring *ring,
>  		   le32_to_cpu(rx_desc->wb.upper.status_error));
>  }
>  
> +/* Mapping HW RSS Type to enum pkt_hash_types */
> +struct igc_rss_type {
> +	u8 hash_type; /* can contain enum pkt_hash_types */

Why make a struct for one field? + short type note

> +} igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = {
> +	[IGC_RSS_TYPE_NO_HASH].hash_type	  = PKT_HASH_TYPE_L2,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV4].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_IPV4].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV6].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_IPV6_EX].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_IPV6].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV6_EX].hash_type = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV4].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV6].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV6_EX].hash_type = PKT_HASH_TYPE_L4,
> +	[10].hash_type = PKT_HASH_TYPE_L2, /* RSS Type above 9 "Reserved" by HW */
> +	[11].hash_type = PKT_HASH_TYPE_L2,
> +	[12].hash_type = PKT_HASH_TYPE_L2,
> +	[13].hash_type = PKT_HASH_TYPE_L2,
> +	[14].hash_type = PKT_HASH_TYPE_L2,
> +	[15].hash_type = PKT_HASH_TYPE_L2,

Why define those empty if you could do a bound check in the code
instead? E.g. `if (unlikely(bigger_than_9)) return PKT_HASH_TYPE_L2`.

> +};
> +
>  static inline void igc_rx_hash(struct igc_ring *ring,
>  			       union igc_adv_rx_desc *rx_desc,
>  			       struct sk_buff *skb)
>  {
> -	if (ring->netdev->features & NETIF_F_RXHASH)
> -		skb_set_hash(skb,
> -			     le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
> -			     PKT_HASH_TYPE_L3);
> +	if (ring->netdev->features & NETIF_F_RXHASH) {

	if (!(feature & HASH))
		return;

and -1 indent level?

> +		u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
> +		u8  rss_type = igc_rss_type(rx_desc);
> +		enum pkt_hash_types hash_type;
> +
> +		hash_type = igc_rss_type_table[rss_type].hash_type;
> +		skb_set_hash(skb, rss_hash, hash_type);
> +	}
>  }

[...]

Thanks,
Olek

WARNING: multiple messages have this Message-ID (diff)
From: Alexander Lobakin <alexandr.lobakin@intel.com>
To: Jesper Dangaard Brouer <brouer@redhat.com>
Cc: xdp-hints@xdp-project.net, martin.lau@kernel.org,
	daniel@iogearbox.net, netdev@vger.kernel.org, ast@kernel.org,
	anthony.l.nguyen@intel.com, Stanislav Fomichev <sdf@google.com>,
	yoong.siang.song@intel.com, intel-wired-lan@lists.osuosl.org,
	bpf@vger.kernel.org
Subject: Re: [Intel-wired-lan] [PATCH bpf-next V1] igc: enable and fix RX hash usage by netstack
Date: Tue, 14 Feb 2023 14:21:00 +0100	[thread overview]
Message-ID: <af69e040-3884-aa73-1241-99207aa577b4@intel.com> (raw)
In-Reply-To: <167604167956.1726972.7266620647404438534.stgit@firesoul>

From: Jesper Dangaard Brouer <brouer@redhat.com>
Date: Fri, 10 Feb 2023 16:07:59 +0100

> When function igc_rx_hash() was introduced in v4.20 via commit 0507ef8a0372
> ("igc: Add transmit and receive fastpath and interrupt handlers"), the
> hardware wasn't configured to provide RSS hash, thus it made sense to not
> enable net_device NETIF_F_RXHASH feature bit.

[...]

> @@ -311,6 +311,58 @@ extern char igc_driver_name[];
>  #define IGC_MRQC_RSS_FIELD_IPV4_UDP	0x00400000
>  #define IGC_MRQC_RSS_FIELD_IPV6_UDP	0x00800000
>  
> +/* RX-desc Write-Back format RSS Type's */
> +enum igc_rss_type_num {
> +	IGC_RSS_TYPE_NO_HASH		= 0,
> +	IGC_RSS_TYPE_HASH_TCP_IPV4	= 1,
> +	IGC_RSS_TYPE_HASH_IPV4		= 2,
> +	IGC_RSS_TYPE_HASH_TCP_IPV6	= 3,
> +	IGC_RSS_TYPE_HASH_IPV6_EX	= 4,
> +	IGC_RSS_TYPE_HASH_IPV6		= 5,
> +	IGC_RSS_TYPE_HASH_TCP_IPV6_EX	= 6,
> +	IGC_RSS_TYPE_HASH_UDP_IPV4	= 7,
> +	IGC_RSS_TYPE_HASH_UDP_IPV6	= 8,
> +	IGC_RSS_TYPE_HASH_UDP_IPV6_EX	= 9,
> +	IGC_RSS_TYPE_MAX		= 10,
> +};
> +#define IGC_RSS_TYPE_MAX_TABLE		16
> +#define IGC_RSS_TYPE_MASK		0xF

GENMASK()?

> +
> +/* igc_rss_type - Rx descriptor RSS type field */
> +static inline u8 igc_rss_type(union igc_adv_rx_desc *rx_desc)

Why use types shorter than u32 on the stack?
Why this union is not const here, since there are no modifications?

> +{
> +	/* RSS Type 4-bit number: 0-9 (above 9 is reserved) */
> +	return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info & IGC_RSS_TYPE_MASK;

The most important I wanted to mention: doesn't this function make the
CPU read the uncached field again, while you could just read it once
onto the stack and then extract all such data from there?

> +}
> +
> +/* Packet header type identified by hardware (when BIT(11) is zero).
> + * Even when UDP ports are not part of RSS hash HW still parse and mark UDP bits
> + */
> +enum igc_pkt_type_bits {
> +	IGC_PKT_TYPE_HDR_IPV4	=	BIT(0),
> +	IGC_PKT_TYPE_HDR_IPV4_WITH_OPT=	BIT(1), /* IPv4 Hdr includes IP options */
> +	IGC_PKT_TYPE_HDR_IPV6	=	BIT(2),
> +	IGC_PKT_TYPE_HDR_IPV6_WITH_EXT=	BIT(3), /* IPv6 Hdr includes extensions */
> +	IGC_PKT_TYPE_HDR_L4_TCP	=	BIT(4),
> +	IGC_PKT_TYPE_HDR_L4_UDP	=	BIT(5),
> +	IGC_PKT_TYPE_HDR_L4_SCTP=	BIT(6),
> +	IGC_PKT_TYPE_HDR_NFS	=	BIT(7),
> +	/* Above only valid when BIT(11) is zero */
> +	IGC_PKT_TYPE_L2		=	BIT(11),
> +	IGC_PKT_TYPE_VLAN	=	BIT(12),
> +	IGC_PKT_TYPE_MASK	=	0x1FFF, /* 13-bits */

Also GENMASK().

> +};
> +
> +/* igc_pkt_type - Rx descriptor Packet type field */
> +static inline u16 igc_pkt_type(union igc_adv_rx_desc *rx_desc)

Also short types and consts.

> +{
> +	u32 data = le32_to_cpu(rx_desc->wb.lower.lo_dword.data);
> +	/* Packet type is 13-bits - as bits (16:4) in lower.lo_dword*/
> +	u16 pkt_type = (data >> 4) & IGC_PKT_TYPE_MASK;

Perfect candidate for FIELD_GET(). No, even for le32_get_bits().

Also my note above about excessive expensive reads.

> +
> +	return pkt_type;
> +}
> +
>  /* Interrupt defines */
>  #define IGC_START_ITR			648 /* ~6000 ints/sec */
>  #define IGC_4K_ITR			980
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
> index 8b572cd2c350..42a072509d2a 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -1677,14 +1677,40 @@ static void igc_rx_checksum(struct igc_ring *ring,
>  		   le32_to_cpu(rx_desc->wb.upper.status_error));
>  }
>  
> +/* Mapping HW RSS Type to enum pkt_hash_types */
> +struct igc_rss_type {
> +	u8 hash_type; /* can contain enum pkt_hash_types */

Why make a struct for one field? + short type note

> +} igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = {
> +	[IGC_RSS_TYPE_NO_HASH].hash_type	  = PKT_HASH_TYPE_L2,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV4].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_IPV4].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV6].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_IPV6_EX].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_IPV6].hash_type	  = PKT_HASH_TYPE_L3,
> +	[IGC_RSS_TYPE_HASH_TCP_IPV6_EX].hash_type = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV4].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV6].hash_type	  = PKT_HASH_TYPE_L4,
> +	[IGC_RSS_TYPE_HASH_UDP_IPV6_EX].hash_type = PKT_HASH_TYPE_L4,
> +	[10].hash_type = PKT_HASH_TYPE_L2, /* RSS Type above 9 "Reserved" by HW */
> +	[11].hash_type = PKT_HASH_TYPE_L2,
> +	[12].hash_type = PKT_HASH_TYPE_L2,
> +	[13].hash_type = PKT_HASH_TYPE_L2,
> +	[14].hash_type = PKT_HASH_TYPE_L2,
> +	[15].hash_type = PKT_HASH_TYPE_L2,

Why define those empty if you could do a bound check in the code
instead? E.g. `if (unlikely(bigger_than_9)) return PKT_HASH_TYPE_L2`.

> +};
> +
>  static inline void igc_rx_hash(struct igc_ring *ring,
>  			       union igc_adv_rx_desc *rx_desc,
>  			       struct sk_buff *skb)
>  {
> -	if (ring->netdev->features & NETIF_F_RXHASH)
> -		skb_set_hash(skb,
> -			     le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
> -			     PKT_HASH_TYPE_L3);
> +	if (ring->netdev->features & NETIF_F_RXHASH) {

	if (!(feature & HASH))
		return;

and -1 indent level?

> +		u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
> +		u8  rss_type = igc_rss_type(rx_desc);
> +		enum pkt_hash_types hash_type;
> +
> +		hash_type = igc_rss_type_table[rss_type].hash_type;
> +		skb_set_hash(skb, rss_hash, hash_type);
> +	}
>  }

[...]

Thanks,
Olek
_______________________________________________
Intel-wired-lan mailing list
Intel-wired-lan@osuosl.org
https://lists.osuosl.org/mailman/listinfo/intel-wired-lan

  parent reply	other threads:[~2023-02-14 13:22 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-10 15:07 [PATCH bpf-next V1] igc: enable and fix RX hash usage by netstack Jesper Dangaard Brouer
2023-02-10 15:07 ` [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-10 15:23 ` Jesper Dangaard Brouer
2023-02-10 15:23   ` [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-14 13:21 ` Alexander Lobakin [this message]
2023-02-14 13:21   ` Alexander Lobakin
2023-02-16 16:46   ` Jesper Dangaard Brouer
2023-02-16 16:46     ` [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-20 15:39     ` Alexander Lobakin
2023-02-20 15:39       ` [Intel-wired-lan] " Alexander Lobakin
2023-02-22 15:00       ` Jesper Dangaard Brouer
2023-02-22 15:00         ` [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-24 16:41         ` Alexander Lobakin
2023-02-24 16:41           ` [Intel-wired-lan] " Alexander Lobakin
2023-02-27 14:24           ` Alexander Lobakin
2023-02-27 14:24             ` [Intel-wired-lan] " Alexander Lobakin
2023-02-14 15:00 ` Paul Menzel
2023-02-14 15:00   ` Paul Menzel
2023-02-14 15:13   ` [xdp-hints] " Alexander Lobakin
2023-02-14 15:13     ` [Intel-wired-lan] [xdp-hints] " Alexander Lobakin
2023-02-16 15:17     ` [xdp-hints] Re: [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-16 15:17       ` [Intel-wired-lan] [xdp-hints] " Jesper Dangaard Brouer
2023-02-16 15:43       ` [xdp-hints] Re: [Intel-wired-lan] " Alexander Lobakin
2023-02-16 15:43         ` [Intel-wired-lan] [xdp-hints] " Alexander Lobakin
2023-02-27 14:53         ` [xdp-hints] Re: [Intel-wired-lan] " Alexander Lobakin
2023-02-27 14:53           ` [Intel-wired-lan] [xdp-hints] " Alexander Lobakin
2023-02-16 13:29   ` [xdp-hints] Re: [Intel-wired-lan] " Jesper Dangaard Brouer
2023-02-16 13:29     ` [Intel-wired-lan] [xdp-hints] " Jesper Dangaard Brouer
2023-02-16 15:34     ` [xdp-hints] Re: [Intel-wired-lan] " Alexander Lobakin
2023-02-16 15:34       ` [Intel-wired-lan] [xdp-hints] " Alexander Lobakin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=af69e040-3884-aa73-1241-99207aa577b4@intel.com \
    --to=alexandr.lobakin@intel.com \
    --cc=anthony.l.nguyen@intel.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brouer@redhat.com \
    --cc=daniel@iogearbox.net \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=martin.lau@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=sdf@google.com \
    --cc=xdp-hints@xdp-project.net \
    --cc=yoong.siang.song@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.