[dpdk-dev,v2,3/6] i40e: support of 'rx_classification_filter_ctl'
diff mbox

Message ID 1406535955-31070-4-git-send-email-helin.zhang@intel.com
State Superseded, archived
Headers show

Commit Message

Helin Zhang July 28, 2014, 8:25 a.m. UTC
'rx_classification_filter_ctl' was defined as a common API
for receive classification filter features. Eight commands
has been implemented for selecting hash functions of
'Toeplitz' and 'Simple XOR', and configuring symmetric hash
functions. In detail,
RTE_CMD_GET_SYM_HASH_ENABLE_PER_PCTYPE:
 - Get symmetric hash enable configuration per 'PCTYPE'.
RTE_CMD_SET_SYM_HASH_ENABLE_PER_PCTYPE:
 - Set symmetric hash enable configuration per 'PCTYPE'.
RTE_CMD_GET_SYM_HASH_ENABLE_PER_PORT:
 - Get symmetric hash enable configuration per port.
RTE_CMD_SET_SYM_HASH_ENABLE_PER_PORT:
 - Set symmetric hash enable configuration per port.
RTE_CMD_GET_FILTER_SWAP:
 - Get filter swap configurations.
RTE_CMD_SET_FILTER_SWAP:
 - Set filter swap configurations.
RTE_CMD_GET_HASH_FUNCTION:
 - Get current hash function.
RTE_CMD_SET_HASH_FUNCTION:
 - Set hash function of 'Toeplitz' or 'Simple XOR'.
Note that 'PCTYPE' means 'Packet Classification Type'.

Signed-off-by: Helin Zhang <helin.zhang@intel.com>
---
 lib/librte_pmd_i40e/Makefile      |   6 +
 lib/librte_pmd_i40e/i40e_ethdev.c | 385 ++++++++++++++++++++++++++++++++++++++
 lib/librte_pmd_i40e/i40e_ethdev.h |   2 +
 lib/librte_pmd_i40e/rte_i40e.h    | 108 +++++++++++
 4 files changed, 501 insertions(+)
 create mode 100644 lib/librte_pmd_i40e/rte_i40e.h

Patch
diff mbox

diff --git a/lib/librte_pmd_i40e/Makefile b/lib/librte_pmd_i40e/Makefile
index 4b31675..a777a76 100644
--- a/lib/librte_pmd_i40e/Makefile
+++ b/lib/librte_pmd_i40e/Makefile
@@ -87,6 +87,12 @@  SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_rxtx.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev_vf.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_pf.c
+
+#
+# Export include file
+#
+SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include += rte_i40e.h
+
 # this lib depends upon:
 DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_eal lib/librte_ether
 DEPDIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += lib/librte_mempool lib/librte_mbuf
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index 9ed31b5..4403af4 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -48,6 +48,7 @@ 
 #include <rte_malloc.h>
 #include <rte_memcpy.h>
 #include <rte_dev.h>
+#include <rte_eth_features.h>
 
 #include "i40e_logs.h"
 #include "i40e/i40e_register_x710_int.h"
@@ -203,6 +204,9 @@  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_rx_classification_filter_ctl(struct rte_eth_dev *dev,
+					     enum rte_eth_command cmd,
+					     void *args);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_PFQF_HKEY_MAX_INDEX + 1];
@@ -248,6 +252,7 @@  static struct eth_dev_ops i40e_eth_dev_ops = {
 	.reta_query                   = i40e_dev_rss_reta_query,
 	.rss_hash_update              = i40e_dev_rss_hash_update,
 	.rss_hash_conf_get            = i40e_dev_rss_hash_conf_get,
+	.rx_classification_filter_ctl = i40e_rx_classification_filter_ctl,
 };
 
 static struct eth_driver rte_i40e_pmd = {
@@ -3956,3 +3961,383 @@  i40e_pf_config_mq_rx(struct i40e_pf *pf)
 
 	return 0;
 }
+
+static int
+i40e_get_filter_swap(struct i40e_hw *hw, struct rte_i40e_filter_swap_info *info)
+{
+	uint32_t reg;
+
+	if (!hw || !info) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	switch (info->pctype) {
+	case ETH_PCTYPE_NONF_IPV4_UDP:
+	case ETH_PCTYPE_NONF_IPV4_TCP:
+	case ETH_PCTYPE_NONF_IPV4_SCTP:
+	case ETH_PCTYPE_NONF_IPV4_OTHER:
+	case ETH_PCTYPE_FRAG_IPV4:
+	case ETH_PCTYPE_NONF_IPV6_UDP:
+	case ETH_PCTYPE_NONF_IPV6_TCP:
+	case ETH_PCTYPE_NONF_IPV6_SCTP:
+	case ETH_PCTYPE_NONF_IPV6_OTHER:
+	case ETH_PCTYPE_FRAG_IPV6:
+	case ETH_PCTYPE_L2_PAYLOAD:
+		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\n", 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;
+	case ETH_PCTYPE_FCOE_OX:
+	case ETH_PCTYPE_FCOE_RX:
+	case ETH_PCTYPE_FCOE_OTHER:
+	default:
+		PMD_DRV_LOG(ERR, "PCTYPE[%u] is out of supported range\n",
+							info->pctype);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+i40e_set_filter_swap(struct i40e_hw *hw, struct rte_i40e_filter_swap_info *info)
+{
+#define I40E_FIELD_LEN_MAX 0x1f
+#define I40E_FIELD_OFFSET_MAX 0x7f
+	uint32_t reg;
+
+	if (!hw || !info) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	switch (info->pctype) {
+	case ETH_PCTYPE_NONF_IPV4_UDP:
+	case ETH_PCTYPE_NONF_IPV4_TCP:
+	case ETH_PCTYPE_NONF_IPV4_SCTP:
+	case ETH_PCTYPE_NONF_IPV4_OTHER:
+	case ETH_PCTYPE_FRAG_IPV4:
+	case ETH_PCTYPE_NONF_IPV6_UDP:
+	case ETH_PCTYPE_NONF_IPV6_TCP:
+	case ETH_PCTYPE_NONF_IPV6_SCTP:
+	case ETH_PCTYPE_NONF_IPV6_OTHER:
+	case ETH_PCTYPE_FRAG_IPV6:
+	case ETH_PCTYPE_L2_PAYLOAD:
+		if (info->off0_src0 > I40E_FIELD_OFFSET_MAX) {
+			PMD_DRV_LOG(ERR, "off0_src0 (0x%x) exceeds the "
+				"maximum of 0x%x\n", info->off0_src0,
+						I40E_FIELD_OFFSET_MAX);
+			return -1;
+		} else if (info->off0_src1 > I40E_FIELD_OFFSET_MAX) {
+			PMD_DRV_LOG(ERR, "off0_src1 (0x%x) exceeds the "
+				"maximum of 0x%x\n", info->off0_src1,
+						I40E_FIELD_OFFSET_MAX);
+			return -1;
+		} else if (info->len0 > I40E_FIELD_LEN_MAX) {
+			PMD_DRV_LOG(ERR, "len0 (0x%x) exceeds the maximum "
+				"of 0x%x\n", info->len0, I40E_FIELD_LEN_MAX);
+			return -1;
+		} else if (info->off1_src0 > I40E_FIELD_OFFSET_MAX) {
+			PMD_DRV_LOG(ERR, "off1_src0 (0x%x) exceeds the "
+				"maximum of 0x%x\n", info->off1_src0,
+						I40E_FIELD_OFFSET_MAX);
+			return -1;
+		} else if (info->off1_src1 > I40E_FIELD_OFFSET_MAX) {
+			PMD_DRV_LOG(ERR, "off1_src1 (0x%x) exceeds the "
+				"maximum of 0x%x\n", info->off1_src1,
+						I40E_FIELD_OFFSET_MAX);
+			return -1;
+		} else if (info->len1 > I40E_FIELD_LEN_MAX) {
+			PMD_DRV_LOG(ERR, "len1 (0x%x) exceeds the maximum "
+				"of 0x%x\n", info->len1, I40E_FIELD_LEN_MAX);
+			return -1;
+		}
+
+		/**
+		 * 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\n", info->pctype, reg);
+		I40E_WRITE_REG(hw, I40E_GLQF_SWAP(0, info->pctype), reg);
+		I40E_WRITE_FLUSH(hw);
+		break;
+	case ETH_PCTYPE_FCOE_OX:
+	case ETH_PCTYPE_FCOE_RX:
+	case ETH_PCTYPE_FCOE_OTHER:
+	default:
+		PMD_DRV_LOG(ERR, "PCTYPE[%u] is out of supported range\n",
+							info->pctype);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+i40e_get_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable)
+{
+	uint32_t reg;
+
+	if (!hw || !enable) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	reg = I40E_READ_REG(hw, I40E_PRTQF_CTL_0);
+	*enable = reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK ? 1 : 0;
+
+	return 0;
+}
+
+static int
+i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t *enable)
+{
+	uint32_t reg;
+
+	if (!hw || !enable) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	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\n");
+			return 0;
+		}
+		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\n");
+			return 0;
+		}
+		reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK;
+	}
+	I40E_WRITE_REG(hw, I40E_PRTQF_CTL_0, reg);
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
+static int
+i40e_get_symmetric_hash_enable_per_pctype(struct i40e_hw *hw,
+			struct rte_i40e_sym_hash_enable_info *info)
+{
+	uint32_t reg;
+
+	if (!hw || !info) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	switch (info->pctype) {
+	case ETH_PCTYPE_NONF_IPV4_UDP:
+	case ETH_PCTYPE_NONF_IPV4_TCP:
+	case ETH_PCTYPE_NONF_IPV4_SCTP:
+	case ETH_PCTYPE_NONF_IPV4_OTHER:
+	case ETH_PCTYPE_FRAG_IPV4:
+	case ETH_PCTYPE_NONF_IPV6_UDP:
+	case ETH_PCTYPE_NONF_IPV6_TCP:
+	case ETH_PCTYPE_NONF_IPV6_SCTP:
+	case ETH_PCTYPE_NONF_IPV6_OTHER:
+	case ETH_PCTYPE_FRAG_IPV6:
+	case ETH_PCTYPE_L2_PAYLOAD:
+		reg = I40E_READ_REG(hw, I40E_GLQF_HSYM(info->pctype));
+		break;
+	case ETH_PCTYPE_FCOE_OX:
+	case ETH_PCTYPE_FCOE_RX:
+	case ETH_PCTYPE_FCOE_OTHER:
+	default:
+		PMD_DRV_LOG(ERR, "PCTYPE[%u] is out of supported range\n",
+							info->pctype);
+		return -1;
+	}
+
+	info->enable = reg & I40E_GLQF_HSYM_SYMH_ENA_MASK ? 1 : 0;
+
+	return 0;
+}
+
+static int
+i40e_set_symmetric_hash_enable_per_pctype(struct i40e_hw *hw,
+			struct rte_i40e_sym_hash_enable_info *info)
+{
+	uint32_t reg;
+
+	if (!hw || !info) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	switch (info->pctype) {
+	case ETH_PCTYPE_NONF_IPV4_UDP:
+	case ETH_PCTYPE_NONF_IPV4_TCP:
+	case ETH_PCTYPE_NONF_IPV4_SCTP:
+	case ETH_PCTYPE_NONF_IPV4_OTHER:
+	case ETH_PCTYPE_FRAG_IPV4:
+	case ETH_PCTYPE_NONF_IPV6_UDP:
+	case ETH_PCTYPE_NONF_IPV6_TCP:
+	case ETH_PCTYPE_NONF_IPV6_SCTP:
+	case ETH_PCTYPE_NONF_IPV6_OTHER:
+	case ETH_PCTYPE_FRAG_IPV6:
+	case ETH_PCTYPE_L2_PAYLOAD:
+		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;
+	case ETH_PCTYPE_FCOE_OX:
+	case ETH_PCTYPE_FCOE_RX:
+	case ETH_PCTYPE_FCOE_OTHER:
+	default:
+		PMD_DRV_LOG(ERR, "PCTYPE[%u] is out of supported range\n",
+							info->pctype);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+i40e_set_hash_function(struct i40e_hw *hw, enum rte_i40e_hash_function *hf)
+{
+	uint32_t reg;
+
+	if (!hw || !hf) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	reg = I40E_READ_REG(hw, I40E_GLQF_CTL);
+	if (*hf == rte_i40e_hash_function_toeplitz) {
+		if (reg & I40E_GLQF_CTL_HTOEP_MASK) {
+			PMD_DRV_LOG(DEBUG, "Hash function already set to "
+							"Toeplitz\n");
+			return 0;
+		}
+		reg |= I40E_GLQF_CTL_HTOEP_MASK;
+	} else if (*hf == rte_i40e_hash_function_simple_xor) {
+		if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) {
+			PMD_DRV_LOG(DEBUG, "Hash function already set to "
+							"Simple XOR\n");
+			return 0;
+		}
+		reg &= ~I40E_GLQF_CTL_HTOEP_MASK;
+	} else {
+		PMD_DRV_LOG(ERR, "Unknown hash function type\n");
+		return -1;
+	}
+	PMD_DRV_LOG(INFO, "Hash function set to %s\n",
+		(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_get_hash_function(struct i40e_hw *hw, enum rte_i40e_hash_function *hf)
+{
+	uint32_t reg;
+
+	if (!hw || !hf) {
+		PMD_DRV_LOG(ERR, "Invalid pointer\n");
+		return -1;
+	}
+
+	reg = I40E_READ_REG(hw, I40E_GLQF_CTL);
+	if (reg & I40E_GLQF_CTL_HTOEP_MASK)
+		*hf = rte_i40e_hash_function_toeplitz;
+	else
+		*hf = rte_i40e_hash_function_simple_xor;
+
+	PMD_DRV_LOG(INFO, "Hash function is %s\n",
+		(reg & I40E_GLQF_CTL_HTOEP_MASK) ? "Toeplitz" : "Simple XOR");
+
+	return 0;
+}
+
+static int
+i40e_rx_classification_filter_ctl(struct rte_eth_dev *dev,
+				  enum rte_eth_command cmd,
+				  void *args)
+{
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	int ret = 0;
+
+	switch (cmd) {
+	case RTE_CMD_GET_SYM_HASH_ENABLE_PER_PCTYPE:
+		ret = i40e_get_symmetric_hash_enable_per_pctype(hw,
+			(struct rte_i40e_sym_hash_enable_info *)args);
+		break;
+	case RTE_CMD_SET_SYM_HASH_ENABLE_PER_PCTYPE:
+		ret = i40e_set_symmetric_hash_enable_per_pctype(hw,
+			(struct rte_i40e_sym_hash_enable_info *)args);
+		break;
+	case RTE_CMD_GET_SYM_HASH_ENABLE_PER_PORT:
+		ret = i40e_get_symmetric_hash_enable_per_port(hw,
+						(uint8_t *)args);
+		break;
+	case RTE_CMD_SET_SYM_HASH_ENABLE_PER_PORT:
+		ret = i40e_set_symmetric_hash_enable_per_port(hw,
+						(uint8_t *)args);
+		break;
+	case RTE_CMD_GET_FILTER_SWAP:
+		ret = i40e_get_filter_swap(hw,
+			(struct rte_i40e_filter_swap_info *)args);
+		break;
+	case RTE_CMD_SET_FILTER_SWAP:
+		ret = i40e_set_filter_swap(hw,
+			(struct rte_i40e_filter_swap_info *)args);
+		break;
+	case RTE_CMD_GET_HASH_FUNCTION:
+		ret = i40e_get_hash_function(hw,
+			(enum rte_i40e_hash_function *)args);
+		break;
+	case RTE_CMD_SET_HASH_FUNCTION:
+		ret = i40e_set_hash_function(hw,
+			(enum rte_i40e_hash_function *)args);
+		break;
+	default:
+		ret = -1;
+		PMD_DRV_LOG(ERR, "Unknown command which is not "
+					"supported by i40e\n");
+		break;
+	}
+
+	return ret;
+}
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h
index 64deef2..001201b 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.h
+++ b/lib/librte_pmd_i40e/i40e_ethdev.h
@@ -34,6 +34,8 @@ 
 #ifndef _I40E_ETHDEV_H_
 #define _I40E_ETHDEV_H_
 
+#include "rte_i40e.h"
+
 #define I40E_AQ_LEN               32
 #define I40E_AQ_BUF_SZ            4096
 /* Number of queues per TC should be one of 1, 2, 4, 8, 16, 32, 64 */
diff --git a/lib/librte_pmd_i40e/rte_i40e.h b/lib/librte_pmd_i40e/rte_i40e.h
new file mode 100644
index 0000000..041cbab
--- /dev/null
+++ b/lib/librte_pmd_i40e/rte_i40e.h
@@ -0,0 +1,108 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_I40E_H_
+#define _RTE_I40E_H_
+
+/**
+ * @file
+ *
+ * RTE I40E
+ *
+ * The I40E defines the commands and structures specifically for i40e hardware
+ * features. As different types of NIC hardware may have different features,
+ * they might not be common for all types of NIC hardwares. The commands and
+ * structures can be used in applications directly together with generalized
+ * APIs declared in rte_ethdev.h. The commands couldn't be supported by
+ * non-i40e PMD.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * For commands:
+ * 'RTE_CMD_GET_HASH_FUNCTION'
+ * 'RTE_CMD_SET_HASH_FUNCTION'
+ *
+ * This enum indicates the possible hash functions of i40e.
+ */
+enum rte_i40e_hash_function {
+	rte_i40e_hash_function_unknown = 0,
+	rte_i40e_hash_function_toeplitz,
+	rte_i40e_hash_function_simple_xor,
+};
+
+/**
+ * For commands:
+ * 'RTE_CMD_GET_FILTER_SWAP'
+ * 'RTE_CMD_SET_FILTER_SWAP'
+ *
+ * A structure used to get/set filter swap. All of the offsets and
+ * length are defined in bytes.
+ */
+struct rte_i40e_filter_swap_info {
+	/**< Packet classification type, defined in rte_ethdev.h */
+	uint8_t pctype;
+	/**< Offset of the 1st field of the 1st couple to be swapped. */
+	uint8_t off0_src0;
+	/**< Offset of the 2nd field of the 1st couple to be swapped. */
+	uint8_t off0_src1;
+	/**< Field length of the first couple. */
+	uint8_t len0;
+	/**< Offset of the 1st field of the 2nd couple to be swapped. */
+	uint8_t off1_src0;
+	/**< Offset of the 2nd field of the 2nd couple to be swapped. */
+	uint8_t off1_src1;
+	/**< Field length of the second couple. */
+	uint8_t len1;
+};
+
+/**
+ * For commands:
+ * 'RTE_CMD_GET_SYM_HASH_ENABLE_PER_PCTYPE'
+ * 'RTE_CMD_SET_SYM_HASH_ENABLE_PER_PCTYPE'
+ *
+ * A structure used to set/get symmetric hash enable per pctype.
+ */
+struct rte_i40e_sym_hash_enable_info {
+	uint8_t pctype; /**< packet classification type */
+	uint8_t enable; /**< enable or disable flag */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif /* _RTE_I40E_H_ */