From patchwork Thu Sep 19 05:15:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simei Su X-Patchwork-Id: 59352 X-Patchwork-Delegate: xiaolong.ye@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id EF2941E89B; Thu, 19 Sep 2019 07:15:37 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 91FA61E880 for ; Thu, 19 Sep 2019 07:15:35 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Sep 2019 22:15:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,522,1559545200"; d="scan'208";a="199279704" Received: from npg-dpdk-cvl-simeisu-118d193.sh.intel.com ([10.67.110.189]) by orsmga002.jf.intel.com with ESMTP; 18 Sep 2019 22:15:31 -0700 From: Simei Su To: xiaolong.ye@intel.com, qi.z.zhang@intel.com, beilei.xing@intel.com, qiming.yang@intel.com, wenzhuo.lu@intel.com Cc: dev@dpdk.org, simei.su@intel.com Date: Thu, 19 Sep 2019 13:15:29 +0800 Message-Id: <1568870129-154706-1-git-send-email-simei.su@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1568041014-341418-1-git-send-email-simei.su@intel.com> References: <1568041014-341418-1-git-send-email-simei.su@intel.com> Subject: [dpdk-dev] [PATCH v3] net/ice: enable advanced RSS X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The v3 patch adds configuration for pppoe/pppod with input set Source MAC and Session ID in the initialization. It also updates release notes and Makefile/meson.build. This patch supports the following features: (1)inner header hash for tunnel packets, including comms package. (2)symmetric hash by rte_flow RSS action. (3)input set change by rte_flow RSS action. Signed-off-by: Simei Su This patch depends on the following patches on patchwork: (1)net/ice: rework for generic flow enabling (2)https://patchwork.dpdk.org/patch/57137/ [v2,1/2] ethdev: add symmetric toeplitz hash support (3)https://patchwork.dpdk.org/patch/57138/ [v2,2/2] app/testpmd: add symmetric toeplitz hash support (4)https://patchwork.dpdk.org/patch/57601/ [1/2] ethdev: extend RSS offload types (5)https://patchwork.dpdk.org/patch/57602/ [2/2] app/testpmd: add RSS offload types extending support --- doc/guides/rel_notes/release_19_11.rst | 1 + drivers/net/ice/Makefile | 1 + drivers/net/ice/ice_ethdev.c | 17 + drivers/net/ice/ice_hash.c | 556 +++++++++++++++++++++++++++++++++ drivers/net/ice/meson.build | 1 + 5 files changed, 576 insertions(+) create mode 100644 drivers/net/ice/ice_hash.c diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 7dc4f00..4352a9e 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -63,6 +63,7 @@ New Features * Supported device-specific DDP package loading. * Generic filter enhancement - Supported pipeline mode. + * Supported input set change and symmetric hash by rte_flow RSS action. Removed Items ------------- diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile index ae53c26..7c7bbb0 100644 --- a/drivers/net/ice/Makefile +++ b/drivers/net/ice/Makefile @@ -62,6 +62,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_rxtx_vec_sse.c endif SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_switch_filter.c +SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_hash.c ifeq ($(findstring RTE_MACHINE_CPUFLAG_AVX2,$(CFLAGS)),RTE_MACHINE_CPUFLAG_AVX2) CC_AVX2_SUPPORT=1 else diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c index 480a5ce..6cce68c 100644 --- a/drivers/net/ice/ice_ethdev.c +++ b/drivers/net/ice/ice_ethdev.c @@ -1870,6 +1870,7 @@ static int ice_init_rss(struct ice_pf *pf) uint16_t i, nb_q; int ret = 0; bool is_safe_mode = pf->adapter->is_safe_mode; + uint32_t reg; rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf; nb_q = dev->data->nb_rx_queues; @@ -1913,6 +1914,12 @@ static int ice_init_rss(struct ice_pf *pf) if (ret) return -EINVAL; + /* Enable registers for symmetric_toeplitz function. */ + reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id)); + reg = (reg & (~VSIQF_HASH_CTL_HASH_SCHEME_M)) | + (1 << VSIQF_HASH_CTL_HASH_SCHEME_S); + ICE_WRITE_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id), reg); + /* configure RSS for IPv4 with input set IPv4 src/dst */ ret = ice_add_rss_cfg(hw, vsi->idx, ICE_FLOW_HASH_IPV4, ICE_FLOW_SEG_HDR_IPV4, 0); @@ -1962,6 +1969,16 @@ static int ice_init_rss(struct ice_pf *pf) PMD_DRV_LOG(ERR, "%s SCTP_IPV4 rss flow fail %d", __func__, ret); + /** + * configure RSS for pppoe/pppod with input set + * Source MAC and Session ID + */ + ret = ice_add_rss_cfg(hw, vsi->idx, ICE_FLOW_HASH_PPPOE_SESS_ID_ETH, + ICE_FLOW_SEG_HDR_PPPOE, 0); + if (ret) + PMD_DRV_LOG(ERR, "%s PPPoE/PPPoD rss flow fail %d", + __func__, ret); + return 0; } diff --git a/drivers/net/ice/ice_hash.c b/drivers/net/ice/ice_hash.c new file mode 100644 index 0000000..15105c5 --- /dev/null +++ b/drivers/net/ice/ice_hash.c @@ -0,0 +1,556 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ice_logs.h" +#include "base/ice_type.h" +#include "base/ice_flow.h" +#include "ice_ethdev.h" +#include "ice_generic_flow.h" + +#define ICE_ACTION_RSS_MAX_QUEUE_NUM 32 + +struct rss_type_match_hdr { + uint32_t hdr_mask; + uint64_t eth_rss_hint; +}; + +struct ice_hash_match_type { + uint64_t hash_type; + uint64_t hash_flds; +}; + +struct rss_meta { + uint32_t pkt_hdr; + uint64_t hash_flds; + uint8_t hash_function; +}; + +static int +ice_hash_init(struct ice_adapter *ad); + +static int +ice_hash_create(struct ice_adapter *ad, + struct rte_flow *flow, + void *meta, + struct rte_flow_error *error); + +static int +ice_hash_destroy(struct ice_adapter *ad, + struct rte_flow *flow, + struct rte_flow_error *error); + +static void +ice_hash_uninit(struct ice_adapter *ad); + +static void +ice_hash_free(struct rte_flow *flow); + +static int +ice_hash_parse_pattern_action(struct ice_adapter *ad, + struct ice_pattern_match_item *array, + uint32_t array_len, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + void **meta, + struct rte_flow_error *error); + +/* The first member is protocol header, the second member is ETH_RSS_*. */ +const struct rss_type_match_hdr hint_0 = { + ICE_FLOW_SEG_HDR_NONE, 0}; +const struct rss_type_match_hdr hint_1 = { + ICE_FLOW_SEG_HDR_IPV4, ETH_RSS_IPV4}; +const struct rss_type_match_hdr hint_2 = { + ICE_FLOW_SEG_HDR_IPV4|ICE_FLOW_SEG_HDR_UDP, ETH_RSS_NONFRAG_IPV4_UDP}; +const struct rss_type_match_hdr hint_3 = { + ICE_FLOW_SEG_HDR_IPV4|ICE_FLOW_SEG_HDR_TCP, ETH_RSS_NONFRAG_IPV4_TCP}; +const struct rss_type_match_hdr hint_4 = { + ICE_FLOW_SEG_HDR_IPV4|ICE_FLOW_SEG_HDR_SCTP, ETH_RSS_NONFRAG_IPV4_SCTP}; +const struct rss_type_match_hdr hint_5 = { + ICE_FLOW_SEG_HDR_IPV6, ETH_RSS_IPV6}; +const struct rss_type_match_hdr hint_6 = { + ICE_FLOW_SEG_HDR_IPV6|ICE_FLOW_SEG_HDR_UDP, ETH_RSS_NONFRAG_IPV6_UDP}; +const struct rss_type_match_hdr hint_7 = { + ICE_FLOW_SEG_HDR_IPV6|ICE_FLOW_SEG_HDR_TCP, ETH_RSS_NONFRAG_IPV6_TCP}; +const struct rss_type_match_hdr hint_8 = { + ICE_FLOW_SEG_HDR_IPV6|ICE_FLOW_SEG_HDR_SCTP, ETH_RSS_NONFRAG_IPV6_SCTP}; +const struct rss_type_match_hdr hint_9 = { + ICE_FLOW_SEG_HDR_GTPU_IP, ETH_RSS_IPV4}; +const struct rss_type_match_hdr hint_10 = { + ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_IPV4}; +const struct rss_type_match_hdr hint_11 = { + ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_UDP}; +const struct rss_type_match_hdr hint_12 = { + ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_TCP}; +const struct rss_type_match_hdr hint_13 = { + ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_SCTP}; + +/* Supported pattern for os default package. */ +static struct ice_pattern_match_item ice_hash_pattern_list_os[] = { + {pattern_eth_ipv4, ICE_INSET_NONE, (uint64_t)(&hint_1)}, + {pattern_eth_ipv4_udp, ICE_INSET_NONE, (uint64_t)(&hint_2)}, + {pattern_eth_ipv4_tcp, ICE_INSET_NONE, (uint64_t)(&hint_3)}, + {pattern_eth_ipv4_sctp, ICE_INSET_NONE, (uint64_t)(&hint_4)}, + {pattern_eth_ipv6, ICE_INSET_NONE, (uint64_t)(&hint_5)}, + {pattern_eth_ipv6_udp, ICE_INSET_NONE, (uint64_t)(&hint_6)}, + {pattern_eth_ipv6_tcp, ICE_INSET_NONE, (uint64_t)(&hint_7)}, + {pattern_eth_ipv6_sctp, ICE_INSET_NONE, (uint64_t)(&hint_8)}, + {pattern_empty, ICE_INSET_NONE, (uint64_t)(&hint_0)}, +}; + +/* Supported pattern for comms package. */ +static struct ice_pattern_match_item ice_hash_pattern_list_comms[] = { + {pattern_eth_ipv4, ICE_INSET_NONE, (uint64_t)(&hint_1)}, + {pattern_eth_ipv4_udp, ICE_INSET_NONE, (uint64_t)(&hint_2)}, + {pattern_eth_ipv4_tcp, ICE_INSET_NONE, (uint64_t)(&hint_3)}, + {pattern_eth_ipv4_sctp, ICE_INSET_NONE, (uint64_t)(&hint_4)}, + {pattern_eth_ipv6, ICE_INSET_NONE, (uint64_t)(&hint_5)}, + {pattern_eth_ipv6_udp, ICE_INSET_NONE, (uint64_t)(&hint_6)}, + {pattern_eth_ipv6_tcp, ICE_INSET_NONE, (uint64_t)(&hint_7)}, + {pattern_eth_ipv6_sctp, ICE_INSET_NONE, (uint64_t)(&hint_8)}, + {pattern_empty, ICE_INSET_NONE, (uint64_t)(&hint_0)}, + {pattern_eth_ipv4_gtpu_ipv4, ICE_INSET_NONE, (uint64_t)(&hint_9)}, + {pattern_eth_ipv4_gtpu_ipv4_udp, ICE_INSET_NONE, (uint64_t)(&hint_9)}, + {pattern_eth_ipv4_gtpu_ipv4_tcp, ICE_INSET_NONE, (uint64_t)(&hint_9)}, + {pattern_eth_pppoes_ipv4, ICE_INSET_NONE, (uint64_t)(&hint_10)}, + {pattern_eth_pppoes_ipv4_udp, ICE_INSET_NONE, (uint64_t)(&hint_11)}, + {pattern_eth_pppoes_ipv4_tcp, ICE_INSET_NONE, (uint64_t)(&hint_12)}, + {pattern_eth_pppoes_ipv4_sctp, ICE_INSET_NONE, (uint64_t)(&hint_13)}, +}; + +/** + * The first member is input set combination, + * the second member is hash fields. + */ +struct ice_hash_match_type ice_hash_type_list[] = { + {ETH_RSS_IPV4|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, + {ETH_RSS_IPV4|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, + {ETH_RSS_IPV4, ICE_FLOW_HASH_IPV4}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|ICE_FLOW_HASH_UDP_PORT}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|ICE_FLOW_HASH_UDP_PORT}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_UDP, ICE_HASH_UDP_IPV4}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|ICE_FLOW_HASH_TCP_PORT}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|ICE_FLOW_HASH_TCP_PORT}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_TCP, ICE_HASH_TCP_IPV4}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)|ICE_FLOW_HASH_SCTP_PORT}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)|ICE_FLOW_HASH_SCTP_PORT}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV4|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV4_SCTP, ICE_HASH_SCTP_IPV4}, + {ETH_RSS_IPV6|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, + {ETH_RSS_IPV6|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, + {ETH_RSS_IPV6, ICE_FLOW_HASH_IPV6}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|ICE_FLOW_HASH_UDP_PORT}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|ICE_FLOW_HASH_UDP_PORT}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_UDP, ICE_HASH_UDP_IPV6}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|ICE_FLOW_HASH_TCP_PORT}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|ICE_FLOW_HASH_TCP_PORT}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_TCP, ICE_HASH_TCP_IPV6}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_SRC_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)|ICE_FLOW_HASH_SCTP_PORT}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_DST_ONLY|ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)|ICE_FLOW_HASH_SCTP_PORT}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L4_SRC_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP|ETH_RSS_L4_DST_ONLY, ICE_FLOW_HASH_IPV6|BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, + {ETH_RSS_NONFRAG_IPV6_SCTP, ICE_HASH_SCTP_IPV6}, +}; + +static struct ice_flow_engine ice_hash_engine = { + .init = ice_hash_init, + .create = ice_hash_create, + .destroy = ice_hash_destroy, + .uninit = ice_hash_uninit, + .free = ice_hash_free, + .type = ICE_FLOW_ENGINE_HASH, +}; + +/* Register parser for os package. */ +static struct ice_flow_parser ice_hash_parser_os = { + .engine = &ice_hash_engine, + .array = ice_hash_pattern_list_os, + .array_len = RTE_DIM(ice_hash_pattern_list_os), + .parse_pattern_action = ice_hash_parse_pattern_action, + .stage = ICE_FLOW_STAGE_RSS, +}; + +/* Register parser for comms package. */ +static struct ice_flow_parser ice_hash_parser_comms = { + .engine = &ice_hash_engine, + .array = ice_hash_pattern_list_comms, + .array_len = RTE_DIM(ice_hash_pattern_list_comms), + .parse_pattern_action = ice_hash_parse_pattern_action, + .stage = ICE_FLOW_STAGE_RSS, +}; + +RTE_INIT(ice_hash_engine_init) +{ + struct ice_flow_engine *engine = &ice_hash_engine; + ice_register_flow_engine(engine); +} + +static int +ice_hash_init(struct ice_adapter *ad) +{ + struct ice_flow_parser *parser = NULL; + + if (ad->active_pkg_type == ICE_PKG_TYPE_OS_DEFAULT) + parser = &ice_hash_parser_os; + else if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) + parser = &ice_hash_parser_comms; + + return ice_register_parser(parser, ad); +} + +static int +ice_hash_check_inset(const struct rte_flow_item pattern[], + struct rte_flow_error *error) +{ + const struct rte_flow_item *item = pattern; + + for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { + if (item->last) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Not support range"); + return -rte_errno; + } + + /* Ignore spec and mask. */ + if (item->spec || item->mask) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Invalid spec/mask."); + return -rte_errno; + } + } + + return 0; +} + +static int +ice_hash_parse_action(struct ice_pattern_match_item *pattern_match_item, + const struct rte_flow_action actions[], + void **meta, + struct rte_flow_error *error) +{ + const struct rte_flow_action *action; + enum rte_flow_action_type action_type; + const struct rte_flow_action_rss *rss; + struct rss_type_match_hdr *m = (struct rss_type_match_hdr *) + (pattern_match_item->meta); + uint32_t type_list_len = RTE_DIM(ice_hash_type_list); + struct ice_hash_match_type *type_match_item; + + /* Supported action is RSS. */ + for (action = actions; action->type != + RTE_FLOW_ACTION_TYPE_END; action++) { + action_type = action->type; + switch (action_type) { + case RTE_FLOW_ACTION_TYPE_RSS: + rss = action->conf; + uint16_t i; + + /* Check if pattern is empty. */ + if (((pattern_match_item->pattern_list) != + pattern_empty) && (rss->func == + RTE_ETH_HASH_FUNCTION_SIMPLE_XOR)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "Not supported flow"); + + /* Check if rss types match pattern. */ + if (rss->func != RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { + if (((rss->types & ETH_RSS_IPV4) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV4_UDP) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV4_TCP) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV4_SCTP) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_IPV6) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV6_UDP) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV6_TCP) != m->eth_rss_hint) || + ((rss->types & ETH_RSS_NONFRAG_IPV6_SCTP) != m->eth_rss_hint)) + return rte_flow_error_set(error, + ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, + action, "Not supported RSS types"); + } + + if (rss->level) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "a nonzero RSS encapsulation level is not supported"); + + if (rss->key_len == 0) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "RSS hash key_len mustn't be 0"); + + if ((rss->queue_num) > ICE_ACTION_RSS_MAX_QUEUE_NUM) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "too many queues for RSS context"); + + /* Check hash function and save it to rss_meta. */ + if (rss->func == + RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) + ((struct rss_meta *)*meta)->hash_function = + RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; + + if (rss->func == + RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) + ((struct rss_meta *)*meta)->hash_function = + RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; + + type_match_item = rte_zmalloc("ice_type_match_item", + sizeof(struct ice_hash_match_type), 0); + if (!type_match_item) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "No memory for type_match_item"); + return -ENOMEM; + } + + /* Find matched hash fields according to hash type. */ + for (i = 0; i < type_list_len; i++) { + if (rss->types == + ice_hash_type_list[i].hash_type) { + type_match_item->hash_type = + ice_hash_type_list[i].hash_type; + type_match_item->hash_flds = + ice_hash_type_list[i].hash_flds; + } + } + + /* Save hash fileds to rss_meta. */ + ((struct rss_meta *)*meta)->hash_flds = + type_match_item->hash_flds; + + rte_free(type_match_item); + break; + + case RTE_FLOW_ACTION_TYPE_END: + return 0; + break; + + default: + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, action, + "Invalid action."); + return -rte_errno; + } + } + + return 0; +} + +static int +ice_hash_parse_pattern_action(__rte_unused struct ice_adapter *ad, + struct ice_pattern_match_item *array, + uint32_t array_len, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + void **meta, + struct rte_flow_error *error) +{ + int ret = 0; + struct ice_pattern_match_item *pattern_match_item; + struct rss_meta *rss_meta_ptr; + + rss_meta_ptr = rte_zmalloc(NULL, sizeof(*rss_meta_ptr), 0); + if (!rss_meta_ptr) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "No memory for rss_meta_ptr"); + return -ENOMEM; + } + + /* Check rss supported pattern and find matched pattern. */ + pattern_match_item = ice_search_pattern_match_item(pattern, + array, array_len, error); + if (!pattern_match_item) + return -rte_errno; + + ret = ice_hash_check_inset(pattern, error); + if (ret) + return -rte_errno; + + /* Save protocol header to rss_meta. */ + *meta = rss_meta_ptr; + ((struct rss_meta *)*meta)->pkt_hdr = ((struct rss_type_match_hdr *) + (pattern_match_item->meta))->hdr_mask; + + /* Check rss action. */ + ret = ice_hash_parse_action(pattern_match_item, actions, meta, error); + if (ret) + return -rte_errno; + + rte_free(pattern_match_item); + + return 0; +} + +static int +ice_hash_create(struct ice_adapter *ad, + struct rte_flow *flow, + void *meta, + struct rte_flow_error *error) +{ + struct ice_pf *pf = &ad->pf; + struct ice_hw *hw = ICE_PF_TO_HW(pf); + struct ice_vsi *vsi = pf->main_vsi; + int ret; + uint32_t reg; + struct ice_rss_cfg *filter_ptr; + + uint32_t headermask = ((struct rss_meta *)meta)->pkt_hdr; + uint64_t hash_field = ((struct rss_meta *)meta)->hash_flds; + uint8_t hash_function = ((struct rss_meta *)meta)->hash_function; + + filter_ptr = rte_zmalloc("ice_rss_filter", + sizeof(struct ice_rss_cfg), 0); + if (!filter_ptr) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "No memory for filter_ptr"); + return -ENOMEM; + } + + if (hash_function == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { + /* Enable registers for simple_xor hash function. */ + reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id)); + reg = (reg & (~VSIQF_HASH_CTL_HASH_SCHEME_M)) | + (2 << VSIQF_HASH_CTL_HASH_SCHEME_S); + ICE_WRITE_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id), reg); + + filter_ptr->symm = hash_function; + + goto out; + } else if (hash_function == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) { + ret = ice_add_rss_cfg(hw, vsi->idx, hash_field, headermask, 1); + if (ret) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "rss flow create fail"); + goto error; + } + } else { + ret = ice_add_rss_cfg(hw, vsi->idx, hash_field, headermask, 0); + if (ret) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "rss flow create fail"); + goto error; + } + } + + filter_ptr->packet_hdr = headermask; + filter_ptr->hashed_flds = hash_field; + +out: + flow->rule = filter_ptr; + rte_free(meta); + return 0; + +error: + rte_free(filter_ptr); + rte_free(meta); + return -rte_errno; +} + +static int +ice_hash_destroy(struct ice_adapter *ad, + struct rte_flow *flow, + struct rte_flow_error *error) +{ + struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(ad); + struct ice_hw *hw = ICE_PF_TO_HW(pf); + struct ice_vsi *vsi = pf->main_vsi; + int ret; + uint32_t reg; + struct ice_rss_cfg *filter_ptr; + + filter_ptr = (struct ice_rss_cfg *)flow->rule; + + if (filter_ptr->symm == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { + /* Return to symmetric_toeplitz state. */ + reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id)); + reg = (reg & (~VSIQF_HASH_CTL_HASH_SCHEME_M)) | + (1 << VSIQF_HASH_CTL_HASH_SCHEME_S); + ICE_WRITE_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id), reg); + } else { + ret = ice_rem_vsi_rss_cfg(hw, vsi->idx); + if (ret) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_HANDLE, NULL, + "rss flow destroy fail"); + goto error; + } + } + + rte_free(filter_ptr); + return 0; + +error: + rte_free(filter_ptr); + return -rte_errno; +} + +static void +ice_hash_uninit(struct ice_adapter *ad) +{ + if (ad->active_pkg_type == ICE_PKG_TYPE_OS_DEFAULT) + ice_unregister_parser(&ice_hash_parser_os, ad); + else if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) + ice_unregister_parser(&ice_hash_parser_comms, ad); +} + +static void +ice_hash_free(struct rte_flow *flow) +{ + rte_free(flow->rule); +} diff --git a/drivers/net/ice/meson.build b/drivers/net/ice/meson.build index 36b4b3c..5469e15 100644 --- a/drivers/net/ice/meson.build +++ b/drivers/net/ice/meson.build @@ -10,6 +10,7 @@ sources = files( 'ice_ethdev.c', 'ice_rxtx.c', 'ice_switch_filter.c', + 'ice_hash.c', 'ice_generic_flow.c' )