lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <6b1b61d0-1306-49e3-aed7-3787d1c2f96f@molgen.mpg.de>
Date: Sat, 13 Sep 2025 06:41:27 +0200
From: Paul Menzel <pmenzel@...gen.mpg.de>
To: Aleksandr Loktionov <aleksandr.loktionov@...el.com>
Cc: intel-wired-lan@...ts.osuosl.org, anthony.l.nguyen@...el.com,
 netdev@...r.kernel.org, Przemek Kitszel <przemyslaw.kitszel@...el.com>,
 Qi Zhang <qi.z.zhang@...el.com>, Dan Nowlin <dan.nowlin@...el.com>
Subject: Re: [Intel-wired-lan] [PATCH iwl-next v4 2/5] ice: add virtchnl and
 VF context support for GTP RSS

Dear Aleksandr,


Thank you for the patch.

Am 29.08.25 um 12:18 schrieb Aleksandr Loktionov:
> Introduce infrastructure to support GTP-specific RSS configuration
> in the ICE driver, enabling flexible and programmable flow hashing
> on virtual functions (VFs).

Mention the datasheet name, revision, and section?

> 
>   - Define new virtchnl protocol header and field types for GTPC, GTPU,
>     L2TPv2, ECPRI, PPP, GRE, and IP fragment headers.
>   - Extend virtchnl.h to support additional RSS fields including checksums,
>     TEID, QFI, and IPv6 prefix matching.
>   - Add VF-side hash context structures for IPv4/IPv6 and GTPU flows.
>   - Implement context tracking and rule ordering logic for TCAM-based
>     RSS configuration.
>   - Introduce symmetric hashing support for raw and tunnel flows.
>   - Update ice_vf_lib.h and virt/rss.c to handle advanced RSS
>     configuration via virtchnl messages.

Why can’t the patch be split into smaller pieces, for example, roughly 
one patch for each item?

> VFs can express RSS configuration for GTP flows
> using ethtool and virtchnl, laying the foundation for tunnel-aware
> RSS offloads in virtualized environments.

Please re-flow.

Also, please add a paragraph how to test this patch.

> Co-developed-by: Dan Nowlin <dan.nowlin@...el.com>
> Signed-off-by: Dan Nowlin <dan.nowlin@...el.com>
> Co-developed-by: Jie Wang <jie1x.wang@...el.com>
> Signed-off-by: Jie Wang <jie1x.wang@...el.com>
> Co-developed-by: Junfeng Guo <junfeng.guo@...el.com>
> Signed-off-by: Junfeng Guo <junfeng.guo@...el.com>
> Co-developed-by: Qi Zhang <qi.z.zhang@...el.com>
> Signed-off-by: Qi Zhang <qi.z.zhang@...el.com>
> Co-developed-by: Ting Xu <ting.xu@...el.com>
> Signed-off-by: Ting Xu <ting.xu@...el.com>
> Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@...el.com>
> Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@...el.com>
> ---
>   drivers/net/ethernet/intel/ice/ice_vf_lib.h |   48 +
>   drivers/net/ethernet/intel/ice/virt/rss.c   | 1307 ++++++++++++++++++-
>   include/linux/avf/virtchnl.h                |   50 +
>   3 files changed, 1350 insertions(+), 55 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
> index b007089..7a9c75d 100644
> --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h
> +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h
> @@ -53,6 +53,46 @@ struct ice_mdd_vf_events {
>   	u16 last_printed;
>   };
>   
> +enum ice_hash_ip_ctx_type {
> +	ICE_HASH_IP_CTX_IP = 0,
> +	ICE_HASH_IP_CTX_IP_ESP,
> +	ICE_HASH_IP_CTX_IP_UDP_ESP,
> +	ICE_HASH_IP_CTX_IP_AH,
> +	ICE_HASH_IP_CTX_IP_PFCP,
> +	ICE_HASH_IP_CTX_IP_UDP,
> +	ICE_HASH_IP_CTX_IP_TCP,
> +	ICE_HASH_IP_CTX_IP_SCTP,
> +	ICE_HASH_IP_CTX_MAX,
> +};
> +
> +struct ice_vf_hash_ip_ctx {
> +	struct ice_rss_hash_cfg ctx[ICE_HASH_IP_CTX_MAX];
> +};
> +
> +enum ice_hash_gtpu_ctx_type {
> +	ICE_HASH_GTPU_CTX_EH_IP = 0,
> +	ICE_HASH_GTPU_CTX_EH_IP_UDP,
> +	ICE_HASH_GTPU_CTX_EH_IP_TCP,
> +	ICE_HASH_GTPU_CTX_UP_IP,
> +	ICE_HASH_GTPU_CTX_UP_IP_UDP,
> +	ICE_HASH_GTPU_CTX_UP_IP_TCP,
> +	ICE_HASH_GTPU_CTX_DW_IP,
> +	ICE_HASH_GTPU_CTX_DW_IP_UDP,
> +	ICE_HASH_GTPU_CTX_DW_IP_TCP,
> +	ICE_HASH_GTPU_CTX_MAX,
> +};
> +
> +struct ice_vf_hash_gtpu_ctx {
> +	struct ice_rss_hash_cfg ctx[ICE_HASH_GTPU_CTX_MAX];
> +};
> +
> +struct ice_vf_hash_ctx {
> +	struct ice_vf_hash_ip_ctx v4;
> +	struct ice_vf_hash_ip_ctx v6;
> +	struct ice_vf_hash_gtpu_ctx ipv4;
> +	struct ice_vf_hash_gtpu_ctx ipv6;
> +};
> +
>   /* Structure to store fdir fv entry */
>   struct ice_fdir_prof_info {
>   	struct ice_parser_profile prof;
> @@ -66,6 +106,12 @@ struct ice_vf_qs_bw {
>   	u8 tc;
>   };
>   
> +/* Structure to store RSS field vector entry */
> +struct ice_rss_prof_info {
> +	struct ice_parser_profile prof;
> +	bool symm;
> +};
> +
>   /* VF operations */
>   struct ice_vf_ops {
>   	enum ice_disq_rst_src reset_type;
> @@ -106,6 +152,8 @@ struct ice_vf {
>   	u16 ctrl_vsi_idx;
>   	struct ice_vf_fdir fdir;
>   	struct ice_fdir_prof_info fdir_prof_info[ICE_MAX_PTGS];
> +	struct ice_rss_prof_info rss_prof_info[ICE_MAX_PTGS];
> +	struct ice_vf_hash_ctx hash_ctx;
>   	u64 rss_hashcfg;		/* RSS hash configuration */
>   	struct ice_sw *vf_sw_id;	/* switch ID the VF VSIs connect to */
>   	struct virtchnl_version_info vf_ver;
> diff --git a/drivers/net/ethernet/intel/ice/virt/rss.c b/drivers/net/ethernet/intel/ice/virt/rss.c
> index cbdbb32..1f3bed9 100644
> --- a/drivers/net/ethernet/intel/ice/virt/rss.c
> +++ b/drivers/net/ethernet/intel/ice/virt/rss.c
> @@ -36,6 +36,11 @@ static const struct ice_vc_hdr_match_type ice_vc_hdr_list[] = {
>   	{VIRTCHNL_PROTO_HDR_ESP,	ICE_FLOW_SEG_HDR_ESP},
>   	{VIRTCHNL_PROTO_HDR_AH,		ICE_FLOW_SEG_HDR_AH},
>   	{VIRTCHNL_PROTO_HDR_PFCP,	ICE_FLOW_SEG_HDR_PFCP_SESSION},
> +	{VIRTCHNL_PROTO_HDR_GTPC,	ICE_FLOW_SEG_HDR_GTPC},
> +	{VIRTCHNL_PROTO_HDR_L2TPV2,	ICE_FLOW_SEG_HDR_L2TPV2},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,	ICE_FLOW_SEG_HDR_IPV_FRAG},
> +	{VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,	ICE_FLOW_SEG_HDR_IPV_FRAG},
> +	{VIRTCHNL_PROTO_HDR_GRE,        ICE_FLOW_SEG_HDR_GRE},
>   };
>   
>   struct ice_vc_hash_field_match_type {
> @@ -87,8 +92,125 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
>   		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> -	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +	{VIRTCHNL_PROTO_HDR_IPV4,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID)},
> +	{VIRTCHNL_PROTO_HDR_IPV4,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
> +		ICE_FLOW_HASH_IPV4},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
>   	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)},
>   	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
> @@ -110,6 +232,35 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		ICE_FLOW_HASH_IPV6 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
>   	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_ID)},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST),
> +		ICE_FLOW_HASH_IPV6_PRE64},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA)},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA)},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
> +		ICE_FLOW_HASH_IPV6_PRE64 |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
> +	{VIRTCHNL_PROTO_HDR_IPV6,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
>   	{VIRTCHNL_PROTO_HDR_TCP,
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)},
> @@ -120,6 +271,25 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
>   		ICE_FLOW_HASH_TCP_PORT},
> +	{VIRTCHNL_PROTO_HDR_TCP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_TCP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_TCP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_TCP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
> +		ICE_FLOW_HASH_TCP_PORT |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
>   	{VIRTCHNL_PROTO_HDR_UDP,
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)},
> @@ -130,6 +300,25 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
>   		ICE_FLOW_HASH_UDP_PORT},
> +	{VIRTCHNL_PROTO_HDR_UDP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_UDP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_UDP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_UDP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
> +		ICE_FLOW_HASH_UDP_PORT |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
>   	{VIRTCHNL_PROTO_HDR_SCTP,
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)},
> @@ -140,6 +329,25 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
>   		ICE_FLOW_HASH_SCTP_PORT},
> +	{VIRTCHNL_PROTO_HDR_SCTP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_SCTP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_SCTP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT) |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
> +	{VIRTCHNL_PROTO_HDR_SCTP,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT) |
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
> +		ICE_FLOW_HASH_SCTP_PORT |
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
>   	{VIRTCHNL_PROTO_HDR_PPPOE,
>   		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID)},
> @@ -155,8 +363,56 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_AH_SPI)},
>   	{VIRTCHNL_PROTO_HDR_PFCP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID),
>   		BIT_ULL(ICE_FLOW_FIELD_IDX_PFCP_SEID)},
> +	{VIRTCHNL_PROTO_HDR_GTPC,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPC_TEID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_GTPC_TEID)},
> +	{VIRTCHNL_PROTO_HDR_L2TPV2,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV2_SESS_ID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID)},
> +	{VIRTCHNL_PROTO_HDR_L2TPV2,
> +		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV2_LEN_SESS_ID),
> +		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV2_LEN_SESS_ID)},
>   };
>   
> +static enum virtchnl_status_code
> +ice_vc_rss_hash_update(struct ice_hw *hw, struct ice_vsi *vsi, u8 hash_type)
> +{
> +	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
> +	struct ice_vsi_ctx *ctx;
> +	int ret;
> +
> +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +
> +	/* clear previous hash_type */
> +	ctx->info.q_opt_rss = vsi->info.q_opt_rss &
> +		~ICE_AQ_VSI_Q_OPT_RSS_HASH_M;
> +	/* hash_type is passed in as ICE_AQ_VSI_Q_OPT_RSS_<XOR|TPLZ|SYM_TPLZ */

Missing closing >?

> +	ctx->info.q_opt_rss |= FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M,
> +					  hash_type);
> +
> +	/* Preserve existing queueing option setting */
> +	ctx->info.q_opt_tc = vsi->info.q_opt_tc;
> +	ctx->info.q_opt_flags = vsi->info.q_opt_flags;
> +
> +	ctx->info.valid_sections =
> +			cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
> +
> +	ret = ice_update_vsi(hw, vsi->idx, ctx, NULL);
> +	if (ret) {
> +		dev_err(ice_hw_to_dev(hw), "update VSI for RSS failed, err %d aq_err %s\n",
> +			ret, libie_aq_str(hw->adminq.sq_last_status));
> +		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
> +	} else {
> +		vsi->info.q_opt_rss = ctx->info.q_opt_rss;
> +	}
> +
> +	kfree(ctx);
> +
> +	return v_ret;
> +}
> +
>   /**
>    * ice_vc_validate_pattern
>    * @vf: pointer to the VF info
> @@ -271,6 +527,11 @@ static bool ice_vc_parse_rss_cfg(struct ice_hw *hw,
>   	const struct ice_vc_hash_field_match_type *hf_list;
>   	const struct ice_vc_hdr_match_type *hdr_list;
>   	int i, hf_list_len, hdr_list_len;
> +	bool outer_ipv4 = false;
> +	bool outer_ipv6 = false;
> +	bool inner_hdr = false;
> +	bool has_gre = false;
> +
>   	u32 *addl_hdrs = &hash_cfg->addl_hdrs;
>   	u64 *hash_flds = &hash_cfg->hash_flds;
>   
> @@ -290,17 +551,17 @@ static bool ice_vc_parse_rss_cfg(struct ice_hw *hw,
>   	for (i = 0; i < rss_cfg->proto_hdrs.count; i++) {
>   		struct virtchnl_proto_hdr *proto_hdr =
>   					&rss_cfg->proto_hdrs.proto_hdr[i];
> -		bool hdr_found = false;
> +		u32 hdr_found = 0;

Should it be renamed too? The naming suggests it to be a boolean type.

>   		int j;
>   
> -		/* Find matched ice headers according to virtchnl headers. */
> +		/* Find matched ice headers according to virtchnl headers.
> +		 * Also figure out the outer type of GTPU headers.

Could enums be introduced for the different types?

> +		 */
>   		for (j = 0; j < hdr_list_len; j++) {
>   			struct ice_vc_hdr_match_type hdr_map = hdr_list[j];
>   
> -			if (proto_hdr->type == hdr_map.vc_hdr) {
> -				*addl_hdrs |= hdr_map.ice_hdr;
> -				hdr_found = true;
> -			}
> +			if (proto_hdr->type == hdr_map.vc_hdr)
> +				hdr_found = hdr_map.ice_hdr;
>   		}
>   
>   		if (!hdr_found)
> @@ -318,8 +579,98 @@ static bool ice_vc_parse_rss_cfg(struct ice_hw *hw,
>   				break;
>   			}
>   		}
> +
> +		if (proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV4 && !inner_hdr)
> +			outer_ipv4 = true;
> +		else if (proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV6 &&
> +			 !inner_hdr)
> +			outer_ipv6 = true;
> +		/* for GRE and L2TPv2, take inner header as input set if no

What is “input set”?

> +		 * any field is selected from outer headers.

“no any” sounds wrong.

> +		 * for GTPU, take inner header and GTPU teid as input set.

*For* GTPU, …

> +		 */
> +		else if ((proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_IP ||
> +			  proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_EH ||
> +			  proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN ||
> +			  proto_hdr->type ==
> +				VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP) ||
> +			 ((proto_hdr->type == VIRTCHNL_PROTO_HDR_L2TPV2 ||
> +			   proto_hdr->type == VIRTCHNL_PROTO_HDR_GRE) &&
> +			   *hash_flds == 0)) {
> +			/* set inner_hdr flag, and clean up outer header */
> +			inner_hdr = true;
> +
> +			/* clear outer headers */
> +			*addl_hdrs = 0;
> +
> +			if (outer_ipv4 && outer_ipv6)
> +				return false;
> +
> +			if (outer_ipv4)
> +				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
> +			else if (outer_ipv6)
> +				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
> +			else
> +				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS;

Use ternary operator, so it’s easier understandable, that it’s only 
about setting that one variable?

> +
> +			if (has_gre && outer_ipv4)
> +				hash_cfg->hdr_type =
> +					ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE;
> +			if (has_gre && outer_ipv6)
> +				hash_cfg->hdr_type =
> +					ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE;
> +
> +			if (proto_hdr->type == VIRTCHNL_PROTO_HDR_GRE)
> +				has_gre = true;
> +		}
> +
> +		*addl_hdrs |= hdr_found;

Excuse my ignorance: Is `hdr_found` used as a bitmap?

> +
> +		/* refine hash hdrs and fields for IP fragment */

The comment does not help me. Maybe add, why this is done?

> +		if (VIRTCHNL_TEST_PROTO_HDR_FIELD(proto_hdr,
> +						  VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID) &&
> +		    proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV4_FRAG) {
> +			*addl_hdrs |= ICE_FLOW_SEG_HDR_IPV_FRAG;
> +			*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_IPV_OTHER);
> +			*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID);
> +			VIRTCHNL_DEL_PROTO_HDR_FIELD(proto_hdr,
> +						     VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID);
> +		}
> +		if (VIRTCHNL_TEST_PROTO_HDR_FIELD(proto_hdr,
> +						  VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID) &&
> +		    proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG) {
> +			*addl_hdrs |= ICE_FLOW_SEG_HDR_IPV_FRAG;
> +			*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_IPV_OTHER);

These seem to be the same as above.

> +			*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_ID);
> +			VIRTCHNL_DEL_PROTO_HDR_FIELD(proto_hdr,
> +						     VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID);
> +		}
> +	}
> +
> +	/* refine gtpu header if we take outer as input set for a no inner

Consistently capitalize GTPU in comments?

> +	 * ip gtpu flow.

Ditto.

> +	 */
> +	if (hash_cfg->hdr_type == ICE_RSS_OUTER_HEADERS &&
> +	    *addl_hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
> +		*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_GTPU_IP);
> +		*addl_hdrs |= ICE_FLOW_SEG_HDR_GTPU_NON_IP;
> +	}
> +
> +	/* refine hash field for esp and nat-t-esp. */

Ditto regarding comment’s usefulness.

> +	if ((*addl_hdrs & ICE_FLOW_SEG_HDR_UDP) &&
> +	    (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP)) {
> +		*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_UDP);
> +		*addl_hdrs |= ICE_FLOW_SEG_HDR_NAT_T_ESP;
> +		*hash_flds &= ~(BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI));
> +		*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI);
>   	}
>   
> +	/* refine hash hdrs for L4 udp/tcp/sctp. */
> +	if (*addl_hdrs & (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP |
> +			  ICE_FLOW_SEG_HDR_SCTP) &&
> +	    *addl_hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)
> +		*addl_hdrs &= ~ICE_FLOW_SEG_HDR_IPV_OTHER;
> +
>   	return true;
>   }
>   
> @@ -336,6 +687,871 @@ static bool ice_vf_adv_rss_offload_ena(u32 caps)
>   	return !!(caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF);
>   }
>   
> +/**
> + * ice_is_hash_cfg_valid - Check whether an RSS hash context is valid
> + * @cfg: RSS hash configuration to test
> + *
> + * Return: true if both @cfg->hash_flds and @cfg->addl_hdrs are non-zero; false otherwise.
> + */
> +static bool ice_is_hash_cfg_valid(struct ice_rss_hash_cfg *cfg)
> +{
> +	return cfg->hash_flds && cfg->addl_hdrs;
> +}
> +
> +/**
> + * ice_hash_cfg_reset - Reset an RSS hash context
> + * @cfg: RSS hash configuration to reset
> + *
> + * Reset fields of @cfg that store the active rule information.
> + */
> +static void ice_hash_cfg_reset(struct ice_rss_hash_cfg *cfg)
> +{
> +	cfg->hash_flds = 0;
> +	cfg->addl_hdrs = 0;
> +	cfg->hdr_type = ICE_RSS_OUTER_HEADERS;
> +	cfg->symm = 0;
> +}
> +
> +/**
> + * ice_hash_cfg_record - Record an RSS hash context
> + * @ctx: destination (global) RSS hash configuration
> + * @cfg: source RSS hash configuration to record
> + *
> + * Copy the active rule information from @cfg into @ctx.
> + */
> +static void ice_hash_cfg_record(struct ice_rss_hash_cfg *ctx,
> +				struct ice_rss_hash_cfg *cfg)
> +{
> +	ctx->hash_flds = cfg->hash_flds;
> +	ctx->addl_hdrs = cfg->addl_hdrs;
> +	ctx->hdr_type = cfg->hdr_type;
> +	ctx->symm = cfg->symm;
> +}
> +
> +/**
> + * ice_hash_moveout - Delete an RSS configuration (keep context)
> + * @vf: VF pointer
> + * @cfg: RSS hash configuration
> + *
> + * Return: 0 on success (including when already absent); -ENOENT if @cfg is
> + * invalid or VSI is missing; -EBUSY on hardware removal failure.

Should the return types be formatted as in the next function documentation?

> + */
> +static int
> +ice_hash_moveout(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int ret;
> +
> +	if (!ice_is_hash_cfg_valid(cfg) || !vsi)
> +		return -ENOENT;
> +
> +	ret = ice_rem_rss_cfg(hw, vsi->idx, cfg);
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "ice_rem_rss_cfg failed for VF %d, VSI %d, error:%d\n",
> +			vf->vf_id, vf->lan_vsi_idx, ret);
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_hash_moveback - Add an RSS hash configuration for a VF
> + * @vf: VF pointer
> + * @cfg: RSS hash configuration to apply
> + *
> + * Add @cfg to @vf if the context is valid and VSI exists; programs HW.
> + *
> + * Return:
> + * * 0 on success
> + * * -ENOENT if @cfg is invalid or VSI is missing
> + * * -EBUSY if hardware programming fails

Use - as list bullets?

> + */
> +static int
> +ice_hash_moveback(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int ret;
> +
> +	if (!ice_is_hash_cfg_valid(cfg) || !vsi)
> +		return -ENOENT;
> +
> +	ret = ice_add_rss_cfg(hw, vsi, cfg);
> +	if (ret) {
> +		dev_err(dev, "ice_add_rss_cfg failed for VF %d, VSI %d, error:%d\n",
> +			vf->vf_id, vf->lan_vsi_idx, ret);

What should users do reading that error in their logs? As an admin, I’d 
always like to see such a statement.

> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_hash_remove - remove a RSS configuration

1.  *R*emove
2.  a*n* RSS

> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS hash configuration
> + *
> + * This function will delete a RSS hash configuration and also delete the

a*n*

> + * hash context which stores the rule info.
> + */
> +static int
> +ice_hash_remove(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	int ret;
> +
> +	ret = ice_hash_moveout(vf, cfg);
> +	if (ret && (ret != -ENOENT))
> +		return ret;
> +
> +	ice_hash_cfg_reset(cfg);
> +
> +	return 0;
> +}
> +
> +struct ice_gtpu_ctx_action {
> +	u32 ctx_idx;
> +	const u32 *remove_list;
> +	int remove_count;
> +	const u32 *moveout_list;
> +	int moveout_count;
> +};
> +
> +/**
> + * ice_add_rss_cfg_pre_gtpu - Pre-process the GTPU RSS configuration
> + * @vf: pointer to the VF info
> + * @ctx: pointer to the context of the GTPU hash
> + * @ctx_idx: index of the hash context
> + *
> + * Pre-processes the GTPU hash configuration before adding a new
> + * hash context. It removes or reorders existing hash configurations that may
> + * conflict with the new one. For example, if a GTPU_UP or GTPU_DWN rule is
> + * configured after a GTPU_EH rule, the GTPU_EH hash will be matched first due
> + * to TCAM write and match order (top-down). In such cases, the GTPU_EH rule
> + * must be moved after the GTPU_UP/DWN rule. Conversely, if a GTPU_EH rule is
> + * configured after a GTPU_UP/DWN rule, the UP/DWN rules should be removed to
> + * avoid conflict.
> + *
> + * Return: 0 on success or a negative error code on failure
> + */
> +static int ice_add_rss_cfg_pre_gtpu(struct ice_vf *vf,
> +				    struct ice_vf_hash_gtpu_ctx *ctx,
> +				    u32 ctx_idx)
> +{
> +	int ret, i;

size_t as it’s compared with `ARRAY_SIZE()`?

> +
> +	static const u32 remove_eh_ip[] = {
> +		ICE_HASH_GTPU_CTX_EH_IP_UDP, ICE_HASH_GTPU_CTX_EH_IP_TCP,
> +		ICE_HASH_GTPU_CTX_UP_IP,     ICE_HASH_GTPU_CTX_UP_IP_UDP,
> +		ICE_HASH_GTPU_CTX_UP_IP_TCP, ICE_HASH_GTPU_CTX_DW_IP,
> +		ICE_HASH_GTPU_CTX_DW_IP_UDP, ICE_HASH_GTPU_CTX_DW_IP_TCP,
> +	};
> +
> +	static const u32 remove_eh_ip_udp[] = {
> +		ICE_HASH_GTPU_CTX_UP_IP_UDP,
> +		ICE_HASH_GTPU_CTX_DW_IP_UDP,
> +	};
> +	static const u32 moveout_eh_ip_udp[] = {
> +		ICE_HASH_GTPU_CTX_UP_IP,
> +		ICE_HASH_GTPU_CTX_UP_IP_TCP,
> +		ICE_HASH_GTPU_CTX_DW_IP,
> +		ICE_HASH_GTPU_CTX_DW_IP_TCP,
> +	};
> +
> +	static const u32 remove_eh_ip_tcp[] = {
> +		ICE_HASH_GTPU_CTX_UP_IP_TCP,
> +		ICE_HASH_GTPU_CTX_DW_IP_TCP,
> +	};
> +	static const u32 moveout_eh_ip_tcp[] = {
> +		ICE_HASH_GTPU_CTX_UP_IP,
> +		ICE_HASH_GTPU_CTX_UP_IP_UDP,
> +		ICE_HASH_GTPU_CTX_DW_IP,
> +		ICE_HASH_GTPU_CTX_DW_IP_UDP,
> +	};
> +
> +	static const u32 remove_up_ip[] = {
> +		ICE_HASH_GTPU_CTX_UP_IP_UDP,
> +		ICE_HASH_GTPU_CTX_UP_IP_TCP,
> +	};
> +	static const u32 moveout_up_ip[] = {
> +		ICE_HASH_GTPU_CTX_EH_IP,
> +		ICE_HASH_GTPU_CTX_EH_IP_UDP,
> +		ICE_HASH_GTPU_CTX_EH_IP_TCP,
> +	};
> +
> +	static const u32 moveout_up_ip_udp_tcp[] = {
> +		ICE_HASH_GTPU_CTX_EH_IP,
> +		ICE_HASH_GTPU_CTX_EH_IP_UDP,
> +		ICE_HASH_GTPU_CTX_EH_IP_TCP,
> +	};
> +
> +	static const u32 remove_dw_ip[] = {
> +		ICE_HASH_GTPU_CTX_DW_IP_UDP,
> +		ICE_HASH_GTPU_CTX_DW_IP_TCP,
> +	};
> +	static const u32 moveout_dw_ip[] = {
> +		ICE_HASH_GTPU_CTX_EH_IP,
> +		ICE_HASH_GTPU_CTX_EH_IP_UDP,
> +		ICE_HASH_GTPU_CTX_EH_IP_TCP,
> +	};
> +
> +	static const struct ice_gtpu_ctx_action actions[] = {
> +		{ ICE_HASH_GTPU_CTX_EH_IP, remove_eh_ip,
> +		  ARRAY_SIZE(remove_eh_ip), NULL, 0 },
> +		{ ICE_HASH_GTPU_CTX_EH_IP_UDP, remove_eh_ip_udp,
> +		  ARRAY_SIZE(remove_eh_ip_udp), moveout_eh_ip_udp,
> +		  ARRAY_SIZE(moveout_eh_ip_udp) },
> +		{ ICE_HASH_GTPU_CTX_EH_IP_TCP, remove_eh_ip_tcp,
> +		  ARRAY_SIZE(remove_eh_ip_tcp), moveout_eh_ip_tcp,
> +		  ARRAY_SIZE(moveout_eh_ip_tcp) },
> +		{ ICE_HASH_GTPU_CTX_UP_IP, remove_up_ip,
> +		  ARRAY_SIZE(remove_up_ip), moveout_up_ip,
> +		  ARRAY_SIZE(moveout_up_ip) },
> +		{ ICE_HASH_GTPU_CTX_UP_IP_UDP, NULL, 0, moveout_up_ip_udp_tcp,
> +		  ARRAY_SIZE(moveout_up_ip_udp_tcp) },
> +		{ ICE_HASH_GTPU_CTX_UP_IP_TCP, NULL, 0, moveout_up_ip_udp_tcp,
> +		  ARRAY_SIZE(moveout_up_ip_udp_tcp) },
> +		{ ICE_HASH_GTPU_CTX_DW_IP, remove_dw_ip,
> +		  ARRAY_SIZE(remove_dw_ip), moveout_dw_ip,
> +		  ARRAY_SIZE(moveout_dw_ip) },
> +		{ ICE_HASH_GTPU_CTX_DW_IP_UDP, NULL, 0, moveout_dw_ip,
> +		  ARRAY_SIZE(moveout_dw_ip) },
> +		{ ICE_HASH_GTPU_CTX_DW_IP_TCP, NULL, 0, moveout_dw_ip,
> +		  ARRAY_SIZE(moveout_dw_ip) },
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(actions); i++) {
> +		if (actions[i].ctx_idx != ctx_idx)
> +			continue;
> +
> +		if (actions[i].remove_list) {
> +			for (int j = 0; j < actions[i].remove_count; j++) {

Declare `j` at the top for consistency?

> +				u16 rm = actions[i].remove_list[j];

Why limit the length of the variable?

> +
> +				ret = ice_hash_remove(vf, &ctx->ctx[rm]);
> +				if (ret && ret != -ENOENT)
> +					return ret;
> +			}
> +		}
> +
> +		if (actions[i].moveout_list) {
> +			for (int j = 0; j < actions[i].moveout_count; j++) {
> +				u16 mv = actions[i].moveout_list[j];
> +
> +				ret = ice_hash_moveout(vf, &ctx->ctx[mv]);
> +				if (ret && ret != -ENOENT)
> +					return ret;
> +			}
> +		}
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_add_rss_cfg_pre_ip - Pre-process IP-layer RSS configuration
> + * @vf: VF pointer
> + * @ctx: IP L4 hash context (ESP/UDP-ESP/AH/PFCP and UDP/TCP/SCTP)
> + *
> + * Remove covered/recorded IP RSS configurations prior to adding a new one.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_add_rss_cfg_pre_ip(struct ice_vf *vf, struct ice_vf_hash_ip_ctx *ctx)
> +{
> +	int i, ret;
> +
> +	for (i = 1; i < ICE_HASH_IP_CTX_MAX; i++)
> +		if (ice_is_hash_cfg_valid(&ctx->ctx[i])) {
> +			ret = ice_hash_remove(vf, &ctx->ctx[i]);
> +
> +			if (ret)
> +				return ret;
> +		}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_calc_gtpu_ctx_idx - Calculate GTPU hash context index
> + * @hdrs: Bitmask of protocol headers prefixed with ICE_FLOW_SEG_HDR_*
> + *
> + * Determine the GTPU hash context index based on the combination of
> + * encapsulation headers (GTPU_EH, GTPU_UP, GTPU_DWN) and transport
> + * protocols (UDP, TCP) within IPv4 or IPv6 flows.
> + *
> + * Return: A valid context index (0-8) if the header combination is supported,
> + *         or ICE_HASH_GTPU_CTX_MAX if the combination is invalid.
> + */
> +static enum ice_hash_gtpu_ctx_type ice_calc_gtpu_ctx_idx(u32 hdrs)
> +{
> +	u32 eh_idx, ip_idx;
> +
> +	if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH)
> +		eh_idx = 0;
> +	else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP)
> +		eh_idx = 1;
> +	else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN)
> +		eh_idx = 2;
> +	else
> +		return ICE_HASH_GTPU_CTX_MAX;
> +
> +	ip_idx = 0;
> +	if (hdrs & ICE_FLOW_SEG_HDR_UDP)
> +		ip_idx = 1;
> +	else if (hdrs & ICE_FLOW_SEG_HDR_TCP)
> +		ip_idx = 2;

Use ternary operator?

> +
> +	if (hdrs & (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6))
> +		return eh_idx * 3 + ip_idx;

How would this be easily converted to `ice_hash_gtpu_ctx_type` members?

> +	else
> +		return ICE_HASH_GTPU_CTX_MAX;

Use ternary operator?


I am stopping my review here due to time constraints. Nice work, overall.


Kind regards,

Paul


> +}
> +
> +/**
> + * ice_map_ip_ctx_idx - map the index of the IP L4 hash context
> + * @hdrs: protocol headers prefix with ICE_FLOW_SEG_HDR_XXX.
> + *
> + * The IP L4 hash context use the index to classify for IPv4/IPv6 with
> + * ESP/UDP_ESP/AH/PFCP and non-tunnel UDP/TCP/SCTP
> + * this function map the index based on the protocol headers.
> + */
> +static u8 ice_map_ip_ctx_idx(u32 hdrs)
> +{
> +	u8 i;
> +
> +	static struct {
> +		u32 hdrs;
> +		u8 ctx_idx;
> +	} ip_ctx_idx_map[] = {
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_ESP,
> +			ICE_HASH_IP_CTX_IP_ESP },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_NAT_T_ESP,
> +			ICE_HASH_IP_CTX_IP_UDP_ESP },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_AH,
> +			ICE_HASH_IP_CTX_IP_AH },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_PFCP_SESSION,
> +			ICE_HASH_IP_CTX_IP_PFCP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_UDP,
> +			ICE_HASH_IP_CTX_IP_UDP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_TCP,
> +			ICE_HASH_IP_CTX_IP_TCP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_SCTP,
> +			ICE_HASH_IP_CTX_IP_SCTP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER,
> +			ICE_HASH_IP_CTX_IP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_ESP,
> +			ICE_HASH_IP_CTX_IP_ESP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_NAT_T_ESP,
> +			ICE_HASH_IP_CTX_IP_UDP_ESP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_AH,
> +			ICE_HASH_IP_CTX_IP_AH },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
> +			ICE_FLOW_SEG_HDR_PFCP_SESSION,
> +			ICE_HASH_IP_CTX_IP_PFCP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_UDP,
> +			ICE_HASH_IP_CTX_IP_UDP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_TCP,
> +			ICE_HASH_IP_CTX_IP_TCP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP,
> +			ICE_HASH_IP_CTX_IP_SCTP },
> +		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
> +			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER,
> +			ICE_HASH_IP_CTX_IP },
> +		/* the remaining mappings are used for default RSS */
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_UDP,
> +			ICE_HASH_IP_CTX_IP_UDP },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_TCP,
> +			ICE_HASH_IP_CTX_IP_TCP },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_SCTP,
> +			ICE_HASH_IP_CTX_IP_SCTP },
> +		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER,
> +			ICE_HASH_IP_CTX_IP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_UDP,
> +			ICE_HASH_IP_CTX_IP_UDP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_TCP,
> +			ICE_HASH_IP_CTX_IP_TCP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP,
> +			ICE_HASH_IP_CTX_IP_SCTP },
> +		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER,
> +			ICE_HASH_IP_CTX_IP },
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(ip_ctx_idx_map); i++) {
> +		if (hdrs == ip_ctx_idx_map[i].hdrs)
> +			return ip_ctx_idx_map[i].ctx_idx;
> +	}
> +
> +	return ICE_HASH_IP_CTX_MAX;
> +}
> +
> +/**
> + * ice_add_rss_cfg_pre - Prepare RSS configuration context for a VF
> + * @vf: pointer to the VF structure
> + * @cfg: pointer to the RSS hash configuration
> + *
> + * Prepare the RSS hash context for a given VF based on the additional
> + * protocol headers specified in @cfg. This includes pre-configuration
> + * for IP and GTPU-based flows.
> + *
> + * If the configuration matches a known IP context, the function sets up
> + * the appropriate IP hash context. If the configuration includes GTPU
> + * headers, it prepares the GTPU-specific context accordingly.
> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +static int
> +ice_add_rss_cfg_pre(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
> +	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
> +
> +	if (ip_ctx_idx == ICE_HASH_IP_CTX_IP) {
> +		int ret = 0;
> +
> +		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
> +			ret = ice_add_rss_cfg_pre_ip(vf, &vf->hash_ctx.v4);
> +		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
> +			ret = ice_add_rss_cfg_pre_ip(vf, &vf->hash_ctx.v6);
> +
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4) {
> +		return ice_add_rss_cfg_pre_gtpu(vf, &vf->hash_ctx.ipv4,
> +						ice_gtpu_ctx_idx);
> +	} else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6) {
> +		return ice_add_rss_cfg_pre_gtpu(vf, &vf->hash_ctx.ipv6,
> +						ice_gtpu_ctx_idx);
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_add_rss_cfg_post_gtpu - Post-process GTPU RSS configuration
> + * @vf: pointer to the VF info
> + * @ctx: pointer to the context of the GTPU hash
> + * @cfg: pointer to the RSS hash configuration
> + * @ctx_idx: index of the hash context
> + *
> + * Post-processes the GTPU hash configuration after a new hash
> + * context has been successfully added. It updates the context with the new
> + * configuration and restores any previously removed hash contexts that need
> + * to be re-applied. This ensures proper TCAM rule ordering and avoids
> + * conflicts between overlapping GTPU rules.
> + *
> + * Return: 0 on success or a negative error code on failure
> + */
> +static int ice_add_rss_cfg_post_gtpu(struct ice_vf *vf,
> +				     struct ice_vf_hash_gtpu_ctx *ctx,
> +				     struct ice_rss_hash_cfg *cfg, u32 ctx_idx)
> +{
> +	/*
> +	 * GTPU hash moveback lookup table indexed by context ID.
> +	 * Each entry is a bitmap indicating which contexts need moveback
> +	 * operations when the corresponding context index is processed.
> +	 */
> +	static const unsigned long
> +		ice_gtpu_moveback_tbl[ICE_HASH_GTPU_CTX_MAX] = {
> +			[ICE_HASH_GTPU_CTX_EH_IP] = 0,
> +			[ICE_HASH_GTPU_CTX_EH_IP_UDP] =
> +				BIT(ICE_HASH_GTPU_CTX_UP_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_UP_IP_TCP) |
> +				BIT(ICE_HASH_GTPU_CTX_DW_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_DW_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_EH_IP_TCP] =
> +				BIT(ICE_HASH_GTPU_CTX_UP_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_UP_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_DW_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_DW_IP_UDP),
> +			[ICE_HASH_GTPU_CTX_UP_IP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_UP_IP_UDP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_UP_IP_TCP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_DW_IP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_DW_IP_UDP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +			[ICE_HASH_GTPU_CTX_DW_IP_TCP] =
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
> +				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
> +		};
> +	unsigned long moveback_mask;
> +	int ret;
> +	int i;
> +
> +	if (unlikely(ctx_idx >= ICE_HASH_GTPU_CTX_MAX))
> +		return 0;
> +
> +	ctx->ctx[ctx_idx].addl_hdrs = cfg->addl_hdrs;
> +	ctx->ctx[ctx_idx].hash_flds = cfg->hash_flds;
> +	ctx->ctx[ctx_idx].hdr_type = cfg->hdr_type;
> +	ctx->ctx[ctx_idx].symm = cfg->symm;
> +
> +	moveback_mask = ice_gtpu_moveback_tbl[ctx_idx];
> +	for_each_set_bit(i, &moveback_mask, ICE_HASH_GTPU_CTX_MAX) {
> +		ret = ice_hash_moveback(vf, &ctx->ctx[i]);
> +		if (ret && ret != -ENOENT)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +ice_add_rss_cfg_post(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
> +	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
> +
> +	if (ip_ctx_idx && ip_ctx_idx < ICE_HASH_IP_CTX_MAX) {
> +		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
> +			ice_hash_cfg_record(&vf->hash_ctx.v4.ctx[ip_ctx_idx], cfg);
> +		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
> +			ice_hash_cfg_record(&vf->hash_ctx.v6.ctx[ip_ctx_idx], cfg);
> +	}
> +
> +	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4) {
> +		return ice_add_rss_cfg_post_gtpu(vf, &vf->hash_ctx.ipv4,
> +						 cfg, ice_gtpu_ctx_idx);
> +	} else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6) {
> +		return ice_add_rss_cfg_post_gtpu(vf, &vf->hash_ctx.ipv6,
> +						 cfg, ice_gtpu_ctx_idx);
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_rem_rss_cfg_post - post-process the RSS configuration
> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS hash configuration
> + *
> + * Post process the RSS hash configuration after deleting a hash
> + * config. Such as, it will reset the hash context for the GTPU hash.
> + */
> +static void
> +ice_rem_rss_cfg_post(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
> +	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
> +
> +	if (ip_ctx_idx && ip_ctx_idx < ICE_HASH_IP_CTX_MAX) {
> +		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
> +			ice_hash_cfg_reset(&vf->hash_ctx.v4.ctx[ip_ctx_idx]);
> +		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
> +			ice_hash_cfg_reset(&vf->hash_ctx.v6.ctx[ip_ctx_idx]);
> +	}
> +
> +	if (ice_gtpu_ctx_idx >= ICE_HASH_GTPU_CTX_MAX)
> +		return;
> +
> +	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
> +		ice_hash_cfg_reset(&vf->hash_ctx.ipv4.ctx[ice_gtpu_ctx_idx]);
> +	else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
> +		ice_hash_cfg_reset(&vf->hash_ctx.ipv6.ctx[ice_gtpu_ctx_idx]);
> +}
> +
> +/**
> + * ice_rem_rss_cfg_wrap - Wrapper for deleting an RSS configuration
> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS hash configuration
> + *
> + * Wrapper function to delete a flow profile base on an RSS configuration,
> + * and also post process the hash context base on the rollback mechanism
> + * which handle some rules conflict by ice_add_rss_cfg_wrap.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_rem_rss_cfg_wrap(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int ret;
> +
> +	ret = ice_rem_rss_cfg(hw, vsi->idx, cfg);
> +	/* We just ignore -ENOENT, because if two configurations share the same
> +	 * profile remove one of them actually removes both, since the
> +	 * profile is deleted.
> +	 */
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "ice_rem_rss_cfg failed for VF %d, VSI %d, error:%d\n",
> +			vf->vf_id, vf->lan_vsi_idx, ret);
> +		return ret;
> +	}
> +
> +	ice_rem_rss_cfg_post(vf, cfg);
> +
> +	return 0;
> +}
> +
> +/**
> + * ice_add_rss_cfg_wrap - Wrapper for adding an RSS configuration
> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS hash configuration
> + *
> + * Add a flow profile based on an RSS configuration. Use a rollback
> + * mechanism to handle rule conflicts due to TCAM
> + * write sequence from top to down.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_add_rss_cfg_wrap(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
> +{
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int ret;
> +
> +	if (ice_add_rss_cfg_pre(vf, cfg))
> +		return -EINVAL;
> +
> +	ret = ice_add_rss_cfg(hw, vsi, cfg);
> +	if (ret) {
> +		dev_err(dev, "ice_add_rss_cfg failed for VF %d, VSI %d, error:%d\n",
> +			vf->vf_id, vf->lan_vsi_idx, ret);
> +		return ret;
> +	}
> +
> +	if (ice_add_rss_cfg_post(vf, cfg))
> +		ret = -EINVAL;
> +
> +	return ret;
> +}
> +
> +/**
> + * ice_parse_raw_rss_pattern - Parse raw pattern spec and mask for RSS
> + * @vf: pointer to the VF info
> + * @proto: pointer to the virtchnl protocol header
> + * @raw_cfg: pointer to the RSS raw pattern configuration
> + *
> + * Parser function to get spec and mask from virtchnl message, and parse
> + * them to get the corresponding profile and offset. The profile is used
> + * to add RSS configuration.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_parse_raw_rss_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto,
> +			  struct ice_rss_raw_cfg *raw_cfg)
> +{
> +	struct ice_parser_result pkt_parsed;
> +	struct ice_hw *hw = &vf->pf->hw;
> +	struct ice_parser_profile prof;
> +	u16 pkt_len;
> +	struct ice_parser *psr;
> +	u8 *pkt_buf, *msk_buf;
> +	int ret = 0;
> +
> +	pkt_len = proto->raw.pkt_len;
> +	if (!pkt_len)
> +		return -EINVAL;
> +	if (pkt_len > VIRTCHNL_MAX_SIZE_RAW_PACKET)
> +		pkt_len = VIRTCHNL_MAX_SIZE_RAW_PACKET;
> +
> +	pkt_buf = kzalloc(pkt_len, GFP_KERNEL);
> +	msk_buf = kzalloc(pkt_len, GFP_KERNEL);
> +	if (!pkt_buf || !msk_buf) {
> +		ret = -ENOMEM;
> +		goto free_alloc;
> +	}
> +
> +	memcpy(pkt_buf, proto->raw.spec, pkt_len);
> +	memcpy(msk_buf, proto->raw.mask, pkt_len);
> +
> +	psr = ice_parser_create(hw);
> +	if (IS_ERR(psr)) {
> +		ret = PTR_ERR(psr);
> +		goto parser_destroy;
> +	}
> +
> +	ret = ice_parser_run(psr, pkt_buf, pkt_len, &pkt_parsed);
> +	if (ret)
> +		goto parser_destroy;
> +
> +	ret = ice_parser_profile_init(&pkt_parsed, pkt_buf, msk_buf,
> +				      pkt_len, ICE_BLK_RSS, &prof);
> +	if (ret)
> +		goto parser_destroy;
> +
> +	memcpy(&raw_cfg->prof, &prof, sizeof(prof));
> +
> +parser_destroy:
> +	ice_parser_destroy(psr);
> +free_alloc:
> +	kfree(pkt_buf);
> +	kfree(msk_buf);
> +	return ret;
> +}
> +
> +/**
> + * ice_add_raw_rss_cfg - add RSS configuration for raw pattern
> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS raw pattern configuration
> + *
> + * This function adds the RSS configuration for raw pattern.
> + * Check if current profile is matched. If not, remove the old
> + * one and add the new profile to HW directly. Update the symmetric
> + * hash configuration as well.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_add_raw_rss_cfg(struct ice_vf *vf, struct ice_rss_raw_cfg *cfg)
> +{
> +	struct ice_parser_profile *prof = &cfg->prof;
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_rss_prof_info *rss_prof;
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int i, ptg, ret = 0;
> +	u16 vsi_handle;
> +	u64 id;
> +
> +	vsi_handle = vf->lan_vsi_idx;
> +	id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
> +
> +	ptg = hw->blk[ICE_BLK_RSS].xlt1.t[id];
> +	rss_prof = &vf->rss_prof_info[ptg];
> +
> +	/* check if ptg already has a profile */
> +	if (rss_prof->prof.fv_num) {
> +		for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
> +			if (rss_prof->prof.fv[i].proto_id !=
> +			    prof->fv[i].proto_id ||
> +			    rss_prof->prof.fv[i].offset !=
> +			    prof->fv[i].offset)
> +				break;
> +		}
> +
> +		/* current profile is matched, check symmetric hash */
> +		if (i == ICE_MAX_FV_WORDS) {
> +			if (rss_prof->symm != cfg->symm)
> +				goto update_symm;
> +			return ret;
> +		}
> +
> +		/* current profile is not matched, remove it */
> +		ret =
> +		ice_rem_prof_id_flow(hw, ICE_BLK_RSS,
> +				     ice_get_hw_vsi_num(hw, vsi_handle),
> +				     id);
> +		if (ret) {
> +			dev_err(dev, "remove RSS flow failed\n");
> +			return ret;
> +		}
> +
> +		ret = ice_rem_prof(hw, ICE_BLK_RSS, id);
> +		if (ret) {
> +			dev_err(dev, "remove RSS profile failed\n");
> +			return ret;
> +		}
> +	}
> +
> +	/* add new profile */
> +	ret = ice_flow_set_parser_prof(hw, vsi_handle, 0, prof, ICE_BLK_RSS);
> +	if (ret) {
> +		dev_err(dev, "HW profile add failed\n");
> +		return ret;
> +	}
> +
> +	memcpy(&rss_prof->prof, prof, sizeof(struct ice_parser_profile));
> +
> +update_symm:
> +	rss_prof->symm = cfg->symm;
> +	ice_rss_update_raw_symm(hw, cfg, id);
> +	return ret;
> +}
> +
> +/**
> + * ice_rem_raw_rss_cfg - remove RSS configuration for raw pattern
> + * @vf: pointer to the VF info
> + * @cfg: pointer to the RSS raw pattern configuration
> + *
> + * This function removes the RSS configuration for raw pattern.
> + * Check if vsi group is already removed first. If not, remove the
> + * profile.
> + *
> + * Return: 0 on success; negative error code on failure.
> + */
> +static int
> +ice_rem_raw_rss_cfg(struct ice_vf *vf, struct ice_rss_raw_cfg *cfg)
> +{
> +	struct ice_parser_profile *prof = &cfg->prof;
> +	struct device *dev = ice_pf_to_dev(vf->pf);
> +	struct ice_hw *hw = &vf->pf->hw;
> +	int ptg, ret = 0;
> +	u16 vsig, vsi;
> +	u64 id;
> +
> +	id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
> +
> +	ptg = hw->blk[ICE_BLK_RSS].xlt1.t[id];
> +
> +	memset(&vf->rss_prof_info[ptg], 0,
> +	       sizeof(struct ice_rss_prof_info));
> +
> +	/* check if vsig is already removed */
> +	vsi = ice_get_hw_vsi_num(hw, vf->lan_vsi_idx);
> +	if (vsi >= ICE_MAX_VSI) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	vsig = hw->blk[ICE_BLK_RSS].xlt2.vsis[vsi].vsig;
> +	if (vsig) {
> +		ret = ice_rem_prof_id_flow(hw, ICE_BLK_RSS, vsi, id);
> +		if (ret)
> +			goto err;
> +
> +		ret = ice_rem_prof(hw, ICE_BLK_RSS, id);
> +		if (ret)
> +			goto err;
> +	}
> +
> +	return ret;
> +
> +err:
> +	dev_err(dev, "HW profile remove failed\n");
> +	return ret;
> +}
> +
>   /**
>    * ice_vc_handle_rss_cfg
>    * @vf: pointer to the VF info
> @@ -352,6 +1568,8 @@ int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
>   	struct device *dev = ice_pf_to_dev(vf->pf);
>   	struct ice_hw *hw = &vf->pf->hw;
>   	struct ice_vsi *vsi;
> +	u8 hash_type;
> +	bool symm;
>   
>   	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
>   		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS is not supported by the PF\n",
> @@ -387,49 +1605,40 @@ int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
>   		goto error_param;
>   	}
>   
> -	if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) {
> -		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
> +	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) {
> +		hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR :
> +				  ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
> +
> +		v_ret = ice_vc_rss_hash_update(hw, vsi, hash_type);
>   		goto error_param;
>   	}
>   
> -	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) {
> -		struct ice_vsi_ctx *ctx;
> -		u8 lut_type, hash_type;
> -		int status;
> +	hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ :
> +			  ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
> +	v_ret = ice_vc_rss_hash_update(hw, vsi, hash_type);
> +	if (v_ret)
> +		goto error_param;
>   
> -		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
> -		hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR :
> -				ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
> +	symm = rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
> +	/* Configure RSS hash for raw pattern */
> +	if (rss_cfg->proto_hdrs.tunnel_level == 0 &&
> +	    rss_cfg->proto_hdrs.count == 0) {
> +		struct ice_rss_raw_cfg raw_cfg;
>   
> -		ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> -		if (!ctx) {
> -			v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +		if (ice_parse_raw_rss_pattern(vf, &rss_cfg->proto_hdrs,
> +					      &raw_cfg)) {
> +			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
>   			goto error_param;
>   		}
>   
> -		ctx->info.q_opt_rss =
> -			FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_LUT_M, lut_type) |
> -			FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hash_type);
> -
> -		/* Preserve existing queueing option setting */
> -		ctx->info.q_opt_rss |= (vsi->info.q_opt_rss &
> -					  ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M);
> -		ctx->info.q_opt_tc = vsi->info.q_opt_tc;
> -		ctx->info.q_opt_flags = vsi->info.q_opt_rss;
> -
> -		ctx->info.valid_sections =
> -				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
> -
> -		status = ice_update_vsi(hw, vsi->idx, ctx, NULL);
> -		if (status) {
> -			dev_err(dev, "update VSI for RSS failed, err %d aq_err %s\n",
> -				status, libie_aq_str(hw->adminq.sq_last_status));
> -			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
> +		if (add) {
> +			raw_cfg.symm = symm;
> +			if (ice_add_raw_rss_cfg(vf, &raw_cfg))
> +				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
>   		} else {
> -			vsi->info.q_opt_rss = ctx->info.q_opt_rss;
> +			if (ice_rem_raw_rss_cfg(vf, &raw_cfg))
> +				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
>   		}
> -
> -		kfree(ctx);
>   	} else {
>   		struct ice_rss_hash_cfg cfg;
>   
> @@ -448,24 +1657,12 @@ int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
>   		}
>   
>   		if (add) {
> -			if (ice_add_rss_cfg(hw, vsi, &cfg)) {
> +			cfg.symm = symm;
> +			if (ice_add_rss_cfg_wrap(vf, &cfg))
>   				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
> -				dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n",
> -					vsi->vsi_num, v_ret);
> -			}
>   		} else {
> -			int status;
> -
> -			status = ice_rem_rss_cfg(hw, vsi->idx, &cfg);
> -			/* We just ignore -ENOENT, because if two configurations
> -			 * share the same profile remove one of them actually
> -			 * removes both, since the profile is deleted.
> -			 */
> -			if (status && status != -ENOENT) {
> +			if (ice_rem_rss_cfg_wrap(vf, &cfg))
>   				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
> -				dev_err(dev, "ice_rem_rss_cfg failed for VF ID:%d, error:%d\n",
> -					vf->vf_id, status);
> -			}
>   		}
>   	}
>   
> diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h
> index 5be1881..11bdab5 100644
> --- a/include/linux/avf/virtchnl.h
> +++ b/include/linux/avf/virtchnl.h
> @@ -1253,6 +1253,17 @@ enum virtchnl_proto_hdr_type {
>   	VIRTCHNL_PROTO_HDR_ESP,
>   	VIRTCHNL_PROTO_HDR_AH,
>   	VIRTCHNL_PROTO_HDR_PFCP,
> +	VIRTCHNL_PROTO_HDR_GTPC,
> +	VIRTCHNL_PROTO_HDR_ECPRI,
> +	VIRTCHNL_PROTO_HDR_L2TPV2,
> +	VIRTCHNL_PROTO_HDR_PPP,
> +	/* IPv4 and IPv6 Fragment header types are only associated to
> +	 * VIRTCHNL_PROTO_HDR_IPV4 and VIRTCHNL_PROTO_HDR_IPV6 respectively,
> +	 * cannot be used independently.
> +	 */
> +	VIRTCHNL_PROTO_HDR_IPV4_FRAG,
> +	VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,
> +	VIRTCHNL_PROTO_HDR_GRE,
>   };
>   
>   /* Protocol header field within a protocol header. */
> @@ -1275,6 +1286,7 @@ enum virtchnl_proto_hdr_field {
>   	VIRTCHNL_PROTO_HDR_IPV4_DSCP,
>   	VIRTCHNL_PROTO_HDR_IPV4_TTL,
>   	VIRTCHNL_PROTO_HDR_IPV4_PROT,
> +	VIRTCHNL_PROTO_HDR_IPV4_CHKSUM,
>   	/* IPV6 */
>   	VIRTCHNL_PROTO_HDR_IPV6_SRC =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6),
> @@ -1282,18 +1294,34 @@ enum virtchnl_proto_hdr_field {
>   	VIRTCHNL_PROTO_HDR_IPV6_TC,
>   	VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT,
>   	VIRTCHNL_PROTO_HDR_IPV6_PROT,
> +	/* IPV6 Prefix */
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX32_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX32_DST,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX40_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX40_DST,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX48_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX48_DST,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX56_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX56_DST,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX96_SRC,
> +	VIRTCHNL_PROTO_HDR_IPV6_PREFIX96_DST,
>   	/* TCP */
>   	VIRTCHNL_PROTO_HDR_TCP_SRC_PORT =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_TCP),
>   	VIRTCHNL_PROTO_HDR_TCP_DST_PORT,
> +	VIRTCHNL_PROTO_HDR_TCP_CHKSUM,
>   	/* UDP */
>   	VIRTCHNL_PROTO_HDR_UDP_SRC_PORT =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_UDP),
>   	VIRTCHNL_PROTO_HDR_UDP_DST_PORT,
> +	VIRTCHNL_PROTO_HDR_UDP_CHKSUM,
>   	/* SCTP */
>   	VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_SCTP),
>   	VIRTCHNL_PROTO_HDR_SCTP_DST_PORT,
> +	VIRTCHNL_PROTO_HDR_SCTP_CHKSUM,
>   	/* GTPU_IP */
>   	VIRTCHNL_PROTO_HDR_GTPU_IP_TEID =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_IP),
> @@ -1317,6 +1345,28 @@ enum virtchnl_proto_hdr_field {
>   	VIRTCHNL_PROTO_HDR_PFCP_S_FIELD =
>   		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_PFCP),
>   	VIRTCHNL_PROTO_HDR_PFCP_SEID,
> +	/* GTPC */
> +	VIRTCHNL_PROTO_HDR_GTPC_TEID =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPC),
> +	/* ECPRI */
> +	VIRTCHNL_PROTO_HDR_ECPRI_MSG_TYPE =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_ECPRI),
> +	VIRTCHNL_PROTO_HDR_ECPRI_PC_RTC_ID,
> +	/* IPv4 Dummy Fragment */
> +	VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV4_FRAG),
> +	/* IPv6 Extension Fragment */
> +	VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG),
> +	/* GTPU_DWN/UP */
> +	VIRTCHNL_PROTO_HDR_GTPU_DWN_QFI =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN),
> +	VIRTCHNL_PROTO_HDR_GTPU_UP_QFI =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP),
> +	/* L2TPv2 */
> +	VIRTCHNL_PROTO_HDR_L2TPV2_SESS_ID =
> +		PROTO_HDR_FIELD_START(VIRTCHNL_PROTO_HDR_L2TPV2),
> +	VIRTCHNL_PROTO_HDR_L2TPV2_LEN_SESS_ID,
>   };
>   
>   struct virtchnl_proto_hdr {


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ