From patchwork Mon Oct 13 10:23:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chilikin, Andrey" X-Patchwork-Id: 806 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 478D17E88; Mon, 13 Oct 2014 12:17:05 +0200 (CEST) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id C43E87E69 for ; Mon, 13 Oct 2014 12:17:02 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 13 Oct 2014 03:24:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,709,1406617200"; d="scan'208";a="587930230" Received: from irsmsx102.ger.corp.intel.com ([163.33.3.155]) by orsmga001.jf.intel.com with ESMTP; 13 Oct 2014 03:24:40 -0700 Received: from irsmsx109.ger.corp.intel.com (163.33.3.23) by IRSMSX102.ger.corp.intel.com (163.33.3.155) with Microsoft SMTP Server (TLS) id 14.3.195.1; Mon, 13 Oct 2014 11:23:25 +0100 Received: from irsmsx106.ger.corp.intel.com ([169.254.8.193]) by IRSMSX109.ger.corp.intel.com ([169.254.13.253]) with mapi id 14.03.0195.001; Mon, 13 Oct 2014 11:23:24 +0100 From: "Chilikin, Andrey" To: "Zhang, Helin" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH v4 4/7] i40e: add hash filter control implementation Thread-Index: AQHP5qzu1udpDUr+skq3cycj50ibe5wtzlyg Date: Mon, 13 Oct 2014 10:23:24 +0000 Message-ID: References: <1412058028-10971-2-git-send-email-helin.zhang@intel.com> <1413180766-12211-1-git-send-email-helin.zhang@intel.com> <1413180766-12211-5-git-send-email-helin.zhang@intel.com> In-Reply-To: <1413180766-12211-5-git-send-email-helin.zhang@intel.com> Accept-Language: en-GB, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [163.33.239.181] MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v4 4/7] i40e: add hash filter control implementation X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Hi Helin, Should we define packet classification types separately and do not reuse bit shifts for RSS register as pctypes? Packet classification is a global index table which used by RSS Hash Enable registers, not vice versa. For example, there is no Packet classification named "ETH_RSS_NONF_IPV4_UDP_SHIFT" in Table 7-15 of XL710 Datasheet, it is "PCTYPE_NONF_IPV4_UDP", so switch (info->pctype) { case PCTYPE_NONF_IPV4_UDP: case PCTYPE_NONF_IPV4_TCP: ... Is more clean and readable for me than switch (info->pctype) { case ETH_RSS_NONF_IPV4_UDP_SHIFT: case ETH_RSS_NONF_IPV4_TCP_SHIFT: We can rerefine ETH_RSS_* using PCTYPE_* though: #define ETH_RSS_NONF_IPV4_UDP_SHIFT PCTYPE_NONF_IPV4_UDP and so one Regards, Andrey -----Original Message----- From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Helin Zhang Sent: Monday, October 13, 2014 7:13 AM To: dev@dpdk.org Subject: [dpdk-dev] [PATCH v4 4/7] i40e: add hash filter control implementation Hash filter control has been implemented for i40e. It includes getting/setting - hash function type - symmetric hash enable per pctype (packet classification type) - symmetric hash enable per port - filter swap configuration Signed-off-by: Helin Zhang --- lib/librte_pmd_i40e/i40e_ethdev.c | 402 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) .rss_hash_update = i40e_dev_rss_hash_update, .rss_hash_conf_get = i40e_dev_rss_hash_conf_get, + .filter_ctrl = i40e_dev_filter_ctrl, }; static struct eth_driver rte_i40e_pmd = { @@ -4162,3 +4167,400 @@ i40e_pf_config_mq_rx(struct i40e_pf *pf) return 0; } + +/* Get the symmetric hash enable configurations per PCTYPE */ static +int i40e_get_symmetric_hash_enable_per_pctype(struct i40e_hw *hw, + struct rte_eth_sym_hash_ena_info *info) { + uint32_t reg; + + switch (info->pctype) { + case ETH_RSS_NONF_IPV4_UDP_SHIFT: + case ETH_RSS_NONF_IPV4_TCP_SHIFT: + case ETH_RSS_NONF_IPV4_SCTP_SHIFT: + case ETH_RSS_NONF_IPV4_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV4_SHIFT: + case ETH_RSS_NONF_IPV6_UDP_SHIFT: + case ETH_RSS_NONF_IPV6_TCP_SHIFT: + case ETH_RSS_NONF_IPV6_SCTP_SHIFT: + case ETH_RSS_NONF_IPV6_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV6_SHIFT: + case ETH_RSS_L2_PAYLOAD_SHIFT: + reg = I40E_READ_REG(hw, I40E_GLQF_HSYM(info->pctype)); + info->enable = reg & I40E_GLQF_HSYM_SYMH_ENA_MASK ? 1 : 0; + break; + default: + PMD_DRV_LOG(ERR, "PCTYPE[%u] not supported", info->pctype); + return -EINVAL; + } + + return 0; +} + +/* Set the symmetric hash enable configurations per PCTYPE */ static +int i40e_set_symmetric_hash_enable_per_pctype(struct i40e_hw *hw, + const struct rte_eth_sym_hash_ena_info *info) { + uint32_t reg; + + switch (info->pctype) { + case ETH_RSS_NONF_IPV4_UDP_SHIFT: + case ETH_RSS_NONF_IPV4_TCP_SHIFT: + case ETH_RSS_NONF_IPV4_SCTP_SHIFT: + case ETH_RSS_NONF_IPV4_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV4_SHIFT: + case ETH_RSS_NONF_IPV6_UDP_SHIFT: + case ETH_RSS_NONF_IPV6_TCP_SHIFT: + case ETH_RSS_NONF_IPV6_SCTP_SHIFT: + case ETH_RSS_NONF_IPV6_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV6_SHIFT: + case ETH_RSS_L2_PAYLOAD_SHIFT: + reg = info->enable ? I40E_GLQF_HSYM_SYMH_ENA_MASK : 0; + I40E_WRITE_REG(hw, I40E_GLQF_HSYM(info->pctype), reg); + I40E_WRITE_FLUSH(hw); + break; + default: + PMD_DRV_LOG(ERR, "PCTYPE[%u] not supported", info->pctype); + return -EINVAL; + } + + return 0; +} + +/* Get the symmetric hash enable configurations per port */ static void +i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t +*enable) { + uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); + + *enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0; } + +/* Set the symmetric hash enable configurations per port */ static void +i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t +enable) { + uint32_t reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0); + + if (enable > 0) { + if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) { + PMD_DRV_LOG(INFO, "Symmetric hash has already " + "been enabled"); + return; + } + reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK; + } else { + if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) { + PMD_DRV_LOG(INFO, "Symmetric hash has already " + "been disabled"); + return; + } + reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK; + } + I40E_WRITE_REG(hw, I40E_PRTQF_CTL_0, reg); + I40E_WRITE_FLUSH(hw); +} + +/* Get filter swap configurations */ +static int +i40e_get_filter_swap(struct i40e_hw *hw, struct +rte_eth_filter_swap_info *info) { + uint32_t reg; + + switch (info->pctype) { + case ETH_RSS_NONF_IPV4_UDP_SHIFT: + case ETH_RSS_NONF_IPV4_TCP_SHIFT: + case ETH_RSS_NONF_IPV4_SCTP_SHIFT: + case ETH_RSS_NONF_IPV4_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV4_SHIFT: + case ETH_RSS_NONF_IPV6_UDP_SHIFT: + case ETH_RSS_NONF_IPV6_TCP_SHIFT: + case ETH_RSS_NONF_IPV6_SCTP_SHIFT: + case ETH_RSS_NONF_IPV6_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV6_SHIFT: + case ETH_RSS_L2_PAYLOAD_SHIFT: + reg = I40E_READ_REG(hw, I40E_GLQF_SWAP(0, info->pctype)); + PMD_DRV_LOG(DEBUG, "Value read from I40E_GLQF_SWAP[0,%d]: " + "0x%x", info->pctype, reg); + + /** + * The offset and length read from register in word unit, + * which need to be converted in byte unit before being saved. + */ + info->off0_src0 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC0_MASK) >> + I40E_GLQF_SWAP_OFF0_SRC0_SHIFT) << 1; + info->off0_src1 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF0_SRC1_MASK) >> + I40E_GLQF_SWAP_OFF0_SRC1_SHIFT) << 1; + info->len0 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN0_MASK) >> + I40E_GLQF_SWAP_FLEN0_SHIFT) << 1; + info->off1_src0 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC0_MASK) >> + I40E_GLQF_SWAP_OFF1_SRC0_SHIFT) << 1; + info->off1_src1 = + (uint8_t)((reg & I40E_GLQF_SWAP_OFF1_SRC1_MASK) >> + I40E_GLQF_SWAP_OFF1_SRC1_SHIFT) << 1; + info->len1 = (uint8_t)((reg & I40E_GLQF_SWAP_FLEN1_MASK) >> + I40E_GLQF_SWAP_FLEN1_SHIFT) << 1; + break; + default: + PMD_DRV_LOG(ERR, "PCTYPE[%u] not supported", info->pctype); + return -EINVAL; + } + + return 0; +} + +/* Set filter swap configurations */ +static int +i40e_set_filter_swap(struct i40e_hw *hw, + const struct rte_eth_filter_swap_info *info) { #define +I40E_FIELD_LEN_MAX 0x1f #define I40E_FIELD_OFFSET_MAX 0x7f + uint32_t reg; + + switch (info->pctype) { + case ETH_RSS_NONF_IPV4_UDP_SHIFT: + case ETH_RSS_NONF_IPV4_TCP_SHIFT: + case ETH_RSS_NONF_IPV4_SCTP_SHIFT: + case ETH_RSS_NONF_IPV4_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV4_SHIFT: + case ETH_RSS_NONF_IPV6_UDP_SHIFT: + case ETH_RSS_NONF_IPV6_TCP_SHIFT: + case ETH_RSS_NONF_IPV6_SCTP_SHIFT: + case ETH_RSS_NONF_IPV6_OTHER_SHIFT: + case ETH_RSS_FRAG_IPV6_SHIFT: + case ETH_RSS_L2_PAYLOAD_SHIFT: + if (info->off0_src0 > I40E_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off0_src0 (0x%x) exceeds the " + "maximum of 0x%x", info->off0_src0, + I40E_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->off0_src1 > I40E_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off0_src1 (0x%x) exceeds the " + "maximum of 0x%x", info->off0_src1, + I40E_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->len0 > I40E_FIELD_LEN_MAX) { + PMD_DRV_LOG(ERR, "len0 (0x%x) exceeds the maximum " + "of 0x%x", info->len0, I40E_FIELD_LEN_MAX); + return I40E_ERR_PARAM; + } else if (info->off1_src0 > I40E_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off1_src0 (0x%x) exceeds the " + "maximum of 0x%x", info->off1_src0, + I40E_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->off1_src1 > I40E_FIELD_OFFSET_MAX) { + PMD_DRV_LOG(ERR, "off1_src1 (0x%x) exceeds the " + "maximum of 0x%x", info->off1_src1, + I40E_FIELD_OFFSET_MAX); + return I40E_ERR_PARAM; + } else if (info->len1 > I40E_FIELD_LEN_MAX) { + PMD_DRV_LOG(ERR, "len1 (0x%x) exceeds the maximum " + "of 0x%x", info->len1, I40E_FIELD_LEN_MAX); + return I40E_ERR_PARAM; + } + + /** + * The offset and length given in byte unit, which need to be + * converted in word unit before being written to the register, + * as hardware requires it in word unit. + */ + reg = (info->off0_src0 >> 1) << I40E_GLQF_SWAP_OFF0_SRC0_SHIFT; + reg |= (info->off0_src1 >> 1) << + I40E_GLQF_SWAP_OFF0_SRC1_SHIFT; + reg |= (info->len0 >> 1) << I40E_GLQF_SWAP_FLEN0_SHIFT; + reg |= (info->off1_src0 >> 1) << + I40E_GLQF_SWAP_OFF1_SRC0_SHIFT; + reg |= (info->off1_src1 >> 1) << + I40E_GLQF_SWAP_OFF1_SRC1_SHIFT; + reg |= (info->len1 >> 1) << I40E_GLQF_SWAP_FLEN1_SHIFT; + + PMD_DRV_LOG(DEBUG, "Value to be written to " + "I40E_GLQF_SWAP[0,%d]: 0x%x", info->pctype, reg); + I40E_WRITE_REG(hw, I40E_GLQF_SWAP(0, info->pctype), reg); + I40E_WRITE_FLUSH(hw); + break; + default: + PMD_DRV_LOG(ERR, "PCTYPE[%u] not supported", info->pctype); + return -EINVAL; + } + + return 0; +} + +/* Get hash function type */ +static void +i40e_get_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function +*hf) { + uint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL); + + if (reg & I40E_GLQF_CTL_HTOEP_MASK) + *hf = RTE_ETH_HASH_FUNCTION_TOEPLITZ; + else + *hf = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; + + PMD_DRV_LOG(INFO, "Hash function is %s", + (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); } + +/* Set hash function type */ +static int +i40e_set_hash_function(struct i40e_hw *hw, enum rte_eth_hash_function +hf) { + uint32_t reg = I40E_READ_REG(hw, I40E_GLQF_CTL); + + if (hf == RTE_ETH_HASH_FUNCTION_TOEPLITZ) { + if (reg & I40E_GLQF_CTL_HTOEP_MASK) { + PMD_DRV_LOG(DEBUG, "Hash function already set to " + "Toeplitz"); + return 0; + } + reg |= I40E_GLQF_CTL_HTOEP_MASK; + } else if (hf == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { + if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) { + PMD_DRV_LOG(DEBUG, "Hash function already set to " + "Simple XOR"); + return 0; + } + reg &= ~I40E_GLQF_CTL_HTOEP_MASK; + } else { + PMD_DRV_LOG(ERR, "Unknown hash function type"); + return -EINVAL; + } + + PMD_DRV_LOG(INFO, "Hash function set to %s", + (reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR"); + I40E_WRITE_REG(hw, I40E_GLQF_CTL, reg); + I40E_WRITE_FLUSH(hw); + + return 0; +} + +static int +i40e_hash_filter_get(struct i40e_hw *hw, struct +rte_eth_hash_filter_info *info) { + int ret = 0; + + if (!hw || !info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_INFO_TYPE_SYM_HASH_ENA_PER_PCTYPE: + ret = i40e_get_symmetric_hash_enable_per_pctype(hw, + &(info->info.sym_hash_ena)); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_SYM_HASH_ENA_PER_PORT: + i40e_get_symmetric_hash_enable_per_port(hw, + &(info->info.enable)); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_FILTER_SWAP: + ret = i40e_get_filter_swap(hw, &(info->info.filter_swap)); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_HASH_FUNCTION: + i40e_get_hash_function(hw, &(info->info.hash_function)); + break; + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + break; + } + + return ret; +} + +static int +i40e_hash_filter_set(struct i40e_hw *hw, struct +rte_eth_hash_filter_info *info) { + int ret = 0; + + if (!hw || !info) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + switch (info->info_type) { + case RTE_ETH_HASH_FILTER_INFO_TYPE_SYM_HASH_ENA_PER_PCTYPE: + ret = i40e_set_symmetric_hash_enable_per_pctype(hw, + &(info->info.sym_hash_ena)); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_SYM_HASH_ENA_PER_PORT: + i40e_set_symmetric_hash_enable_per_port(hw, info->info.enable); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_FILTER_SWAP: + ret = i40e_set_filter_swap(hw, &(info->info.filter_swap)); + break; + case RTE_ETH_HASH_FILTER_INFO_TYPE_HASH_FUNCTION: + ret = i40e_set_hash_function(hw, info->info.hash_function); + break; + default: + PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported", + info->info_type); + ret = -EINVAL; + break; + } + + return ret; +} + +/* Operations for hash function */ +static int +i40e_hash_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_op filter_op, + void *arg) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret = 0; + + switch (filter_op) { + case RTE_ETH_FILTER_OP_NONE: + break; + case RTE_ETH_FILTER_OP_GET: + ret = i40e_hash_filter_get(hw, + (struct rte_eth_hash_filter_info *)arg); + break; + case RTE_ETH_FILTER_OP_SET: + ret = i40e_hash_filter_set(hw, + (struct rte_eth_hash_filter_info *)arg); + break; + default: + PMD_DRV_LOG(WARNING, "Filter operation (%d) not supported", + filter_op); + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int +i40e_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg) +{ + int ret = -ENOTSUP; + + switch (filter_type) { + case RTE_ETH_FILTER_HASH: + ret = i40e_hash_filter_ctrl(dev, filter_op, arg); + break; + case RTE_ETH_FILTER_FDIR: + break; + case RTE_ETH_FILTER_TUNNEL: + break; + default: + PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", + filter_type); + break; + } + + return ret; +} -- 1.8.1.4 diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c index 46c43a7..60b619b 100644 --- a/lib/librte_pmd_i40e/i40e_ethdev.c +++ b/lib/librte_pmd_i40e/i40e_ethdev.c @@ -216,6 +216,10 @@ static int i40e_dev_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); static int i40e_dev_rss_hash_conf_get(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf); +static int i40e_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg); /* Default hash key buffer for RSS */ static uint32_t rss_key_default[I40E_PFQF_HKEY_MAX_INDEX + 1]; @@ -267,6 +271,7 @@ static struct eth_dev_ops i40e_eth_dev_ops = { .reta_query = i40e_dev_rss_reta_query,