diff mbox

[dpdk-dev,v2,1/2] i40e: add RSS granularity configuration

Message ID 1442906770-18805-2-git-send-email-helin.zhang@intel.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Helin Zhang Sept. 22, 2015, 7:26 a.m. UTC
The default fields of a received packet are loaded from firmware,
which cannot be modified even users want to use different fields
for RSS or filtering. Here adds a workaround to open more
flexibilities of selecting packet fields for hash calculation or
flow director to users.

Signed-off-by: Helin Zhang <helin.zhang@intel.com>
Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c  | 591 ++++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h  |   6 +
 drivers/net/i40e/i40e_fdir.c    |  31 +++
 lib/librte_ether/rte_eth_ctrl.h | 106 ++++++-
 4 files changed, 730 insertions(+), 4 deletions(-)

v2 changes:
Solved the compilation issues.
diff mbox

Patch

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..e711992 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -113,6 +113,131 @@ 
 #define I40E_PRTTSYN_TSYNENA  0x80000000
 #define I40E_PRTTSYN_TSYNTYPE 0x0e000000
 
+#define I40E_PRTQF_FD_INSET(_i, _j)  (0x00250000 + ((_i) * 64 + (_j) * 32))
+#define I40E_GLQF_FD_MSK(_i, _j)     (0x00267200 + ((_i) * 4 + (_j) * 8))
+#define I40E_GLQF_HASH_INSET(_i, _j) (0x00267600 + ((_i) * 4 + (_j) * 8))
+#define I40E_GLQF_HASH_MSK(_i, _j)   (0x00267A00 + ((_i) * 4 + (_j) * 8))
+
+#define I40E_INSET_UNKNOWN        0x00000000000000000ULL
+
+/* FD/Hash filters input set fields */
+#define I40E_INSET_DMAC            0x0000000000000001ULL
+#define I40E_INSET_SMAC            0x0000000000000002ULL
+#define I40E_INSET_VLAN_OUTER      0x0000000000000004ULL
+#define I40E_INSET_VLAN_INNER      0x0000000000000008ULL
+#define I40E_INSET_VLAN_TUNNEL     0x0000000000000010ULL
+
+#define I40E_INSET_IPV4_SRC        0x0000000000000100ULL
+#define I40E_INSET_IPV4_DST        0x0000000000000200ULL
+#define I40E_INSET_IPV6_SRC        0x0000000000000400ULL
+#define I40E_INSET_IPV6_DST        0x0000000000000800ULL
+#define I40E_INSET_SRC_PORT        0x0000000000001000ULL
+#define I40E_INSET_DST_PORT        0x0000000000002000ULL
+#define I40E_INSET_SCTP_VT         0x0000000000004000ULL
+
+/* next 8 fields can be used with masking only; two 16-bit masks per PCTYPE */
+#define I40E_INSET_IPV4_TOS        0x0000000000010000ULL
+#define I40E_INSET_IPV4_PROTO      0x0000000000020000ULL
+#define I40E_INSET_IPV4_TTL        0x0000000000040000ULL
+#define I40E_INSET_IPV6_TC         0x0000000000080000ULL
+#define I40E_INSET_IPV6_FLOW       0x0000000000100000ULL
+#define I40E_INSET_IPV6_NEXT_HDR   0x0000000000200000ULL
+#define I40E_INSET_IPV6_HOP_LIMIT  0x0000000000400000ULL
+#define I40E_INSET_TCP_FLAGS       0x0000000000800000ULL
+
+/* tunnel outer IP, valid only if flexible payload is not defined */
+#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000001000000ULL
+#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000002000000ULL
+#define I40E_INSET_TUNNEL_DMAC     0x0000000004000000ULL
+#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000008000000ULL
+#define I40E_INSET_TUNNEL_DST_PORT 0x0000000010000000ULL
+#define I40E_INSET_TUNNEL_ID       0x0000000020000000ULL
+#define I40E_INSET_GRE_NEXT_PROTO  I40E_INSET_DST_PORT
+
+/* last Ethertype for L2 PCTYPE                       */
+#define I40E_INSET_LAST_ETHER_TYPE 0x0000000100000000ULL
+
+/* 8 words of Flex Payload                            */
+#define I40E_INSET_FLEX_PAYLOAD_W1 0x0000001000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W2 0x0000002000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W3 0x0000004000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W4 0x0000008000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W5 0x0000010000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W6 0x0000020000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W7 0x0000040000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD_W8 0x0000080000000000ULL
+#define I40E_INSET_FLEX_PAYLOAD \
+	(I40E_INSET_FLEX_PAYLOAD_W1 | I40E_INSET_FLEX_PAYLOAD_W2 | \
+	I40E_INSET_FLEX_PAYLOAD_W3 | I40E_INSET_FLEX_PAYLOAD_W3 | \
+	I40E_INSET_FLEX_PAYLOAD_W5 | I40E_INSET_FLEX_PAYLOAD_W6 | \
+	I40E_INSET_FLEX_PAYLOAD_W7 | I40E_INSET_FLEX_PAYLOAD_W8)
+
+#define I40E_INSET_ALL             0xFFFFFFFFFFFFFFFFULL
+
+/**
+ * Below are values for writing un-exposed registers suggested
+ * by silicon experts
+ */
+/* Destination MAC address */
+#define I40E_REG_INSET_L2_DMAC                   0xE000000000000000ULL
+/* Source MAC address */
+#define I40E_REG_INSET_L2_SMAC                   0x1C00000000000000ULL
+/* VLAN tag in the outer L2 header */
+#define I40E_REG_INSET_L2_OUTER_VLAN             0x0000000000800000ULL
+/* VLAN tag in the inner L2 header */
+#define I40E_REG_INSET_L2_INNER_VLAN             0x0000000001000000ULL
+/* Source IPv4 address */
+#define I40E_REG_INSET_L3_SRC_IP4                0x0001800000000000ULL
+/* Destination IPv4 address */
+#define I40E_REG_INSET_L3_DST_IP4                0x0000001800000000ULL
+/* Source IPv6 address */
+#define I40E_REG_INSET_L3_SRC_IP6                0x0007F80000000000ULL
+/* Destination IPv6 address */
+#define I40E_REG_INSET_L3_DST_IP6                0x000007F800000000ULL
+/* Source L4 port */
+#define I40E_REG_INSET_L4_SRC_PORT               0x0000000400000000ULL
+/* Destination L4 port */
+#define I40E_REG_INSET_L4_DST_PORT               0x0000000200000000ULL
+/* SCTP verification tag */
+#define I40E_REG_INSET_L4_SCTP_VERIFICATION_TAG  0x0000000180000000ULL
+/* Inner destination MAC address (MAC-in-UDP/MAC-in-GRE)*/
+#define I40E_REG_INSET_TUNNEL_L2_INNER_DST_MAC   0x0000000001C00000ULL
+/* Source port of tunneling UDP */
+#define I40E_REG_INSET_TUNNEL_L4_UDP_SRC_PORT    0x0000000000200000ULL
+/* Destination port of tunneling UDP */
+#define I40E_REG_INSET_TUNNEL_L4_UDP_DST_PORT    0x0000000000100000ULL
+/* Tunneling UDP keys */
+#define I40E_REG_INSET_TUNNEL_L4_UDP_KEY         0x00000000000F8000ULL
+/* GRE version and protocol type */
+#define I40E_REG_INSET_TUNNEL_GRE_VER_PROTO_TYPE 0x0000000000300000ULL
+/* GRE key */
+#define I40E_REG_INSET_TUNNEL_GRE_KEY            0x00000000000C0000ULL
+/* Last ether type */
+#define I40E_REG_INSET_LAST_ETHER_TYPE           0x0000000000004000ULL
+/* Tunneling outer destination IPv4 address */
+#define I40E_REG_INSET_TUNNEL_L3_DST_IP4         0x00000000000000C0ULL
+/* Tunneling outer destination IPv6 address */
+#define I40E_REG_INSET_TUNNEL_L3_DST_IP6         0x0000000000003FC0ULL
+/* 1st word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD1        0x0000000000002000ULL
+/* 2nd word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD2        0x0000000000001000ULL
+/* 3rd word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD3        0x0000000000000800ULL
+/* 4th word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD4        0x0000000000000400ULL
+/* 5th word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD5        0x0000000000000200ULL
+/* 6th word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD6        0x0000000000000100ULL
+/* 7th word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD7        0x0000000000000080ULL
+/* 8th word of flex payload */
+#define I40E_REG_INSET_FLEX_PAYLOAD_WORD8        0x0000000000000040ULL
+#define I40E_REG_INSET_ALL                       0xFFFFFFFFFFFFFFFFULL
+
+#define I40E_REG_INSET_MASK_DEFAULT              0x0000000000000000ULL
+
 static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev);
 static int eth_i40e_dev_uninit(struct rte_eth_dev *eth_dev);
 static int i40e_dev_configure(struct rte_eth_dev *dev);
@@ -5451,6 +5576,466 @@  out:
 	return 0;
 }
 
+/**
+ * Validate if the input set is allowed for a specific PCTYPE
+ */
+static int
+i40e_validate_input_set(enum i40e_filter_pctype pctype, uint64_t inset)
+{
+	static const uint64_t valid_inset_table[] = {
+		[I40E_FILTER_PCTYPE_FRAG_IPV4] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV4_SRC |
+			I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS |
+			I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL |
+			I40E_INSET_TUNNEL_DMAC | I40E_INSET_TUNNEL_ID |
+			I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV4_TOS |
+			I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL |
+			I40E_INSET_TUNNEL_DMAC | I40E_INSET_TUNNEL_ID |
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
+			I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV4_TOS |
+			I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL |
+			I40E_INSET_TUNNEL_DMAC | I40E_INSET_TUNNEL_ID |
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
+			I40E_INSET_TCP_FLAGS | I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV4_TOS |
+			I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL |
+			I40E_INSET_TUNNEL_DMAC | I40E_INSET_TUNNEL_ID |
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
+			I40E_INSET_SCTP_VT | I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV4_TOS |
+			I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL |
+			I40E_INSET_TUNNEL_DMAC | I40E_INSET_TUNNEL_ID |
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_FRAG_IPV6] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV6_TC |
+			I40E_INSET_IPV6_FLOW | I40E_INSET_IPV6_NEXT_HDR |
+			I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_TUNNEL_DMAC |
+			I40E_INSET_TUNNEL_ID | I40E_INSET_IPV6_SRC |
+			I40E_INSET_IPV6_DST | I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_UDP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV6_TC |
+			I40E_INSET_IPV6_FLOW | I40E_INSET_IPV6_NEXT_HDR |
+			I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_IPV6_SRC |
+			I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
+			I40E_INSET_DST_PORT | I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV6_TC |
+			I40E_INSET_IPV6_FLOW | I40E_INSET_IPV6_NEXT_HDR |
+			I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_IPV6_SRC |
+			I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
+			I40E_INSET_DST_PORT | I40E_INSET_TCP_FLAGS |
+			I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV6_TC |
+			I40E_INSET_IPV6_FLOW | I40E_INSET_IPV6_NEXT_HDR |
+			I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_IPV6_SRC |
+			I40E_INSET_IPV6_DST | I40E_INSET_SRC_PORT |
+			I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT |
+			I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_IPV6_TC |
+			I40E_INSET_IPV6_FLOW | I40E_INSET_IPV6_NEXT_HDR |
+			I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_IPV6_SRC |
+			I40E_INSET_IPV6_DST | I40E_INSET_FLEX_PAYLOAD,
+		[I40E_FILTER_PCTYPE_L2_PAYLOAD] =
+			I40E_INSET_DMAC | I40E_INSET_SMAC |
+			I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
+			I40E_INSET_VLAN_TUNNEL | I40E_INSET_LAST_ETHER_TYPE |
+			I40E_INSET_FLEX_PAYLOAD,
+	};
+
+	if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD)
+		return -EINVAL;
+
+	if ((inset != I40E_INSET_ALL) && (inset &
+		(~valid_inset_table[pctype])))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* default input set fields combination per pctype */
+static uint64_t
+i40e_get_default_input_set(uint16_t pctype)
+{
+	static const uint64_t default_inset_table[] = {
+		[I40E_FILTER_PCTYPE_FRAG_IPV4] =
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] =
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
+			I40E_INSET_SCTP_VT,
+		[I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
+			I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST,
+		[I40E_FILTER_PCTYPE_FRAG_IPV6] =
+			I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_UDP] =
+			I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_TCP] =
+			I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] =
+			I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
+			I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
+			I40E_INSET_SCTP_VT,
+		[I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] =
+			I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST,
+		[I40E_FILTER_PCTYPE_L2_PAYLOAD] =
+			I40E_INSET_LAST_ETHER_TYPE,
+	};
+
+	if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD)
+		return 0;
+
+	return default_inset_table[pctype];
+}
+
+/**
+ * Parse the input set from index to logical bit masks
+ */
+static uint64_t
+i40e_parse_input_set(enum i40e_filter_pctype pctype,
+		     enum rte_eth_input_set_field *field,
+		     uint16_t size)
+{
+	uint64_t inset = 0;
+	uint16_t i, j;
+
+	static const struct {
+		enum rte_eth_input_set_field field;
+		uint64_t inset;
+	} inset_convert_table[] = {
+		{RTE_ETH_INPUT_SET_L2_SRC_MAC, I40E_INSET_SMAC},
+		{RTE_ETH_INPUT_SET_L2_DST_MAC, I40E_INSET_DMAC},
+		{RTE_ETH_INPUT_SET_L2_OUTER_VLAN, I40E_INSET_VLAN_OUTER},
+		{RTE_ETH_INPUT_SET_L2_INNER_VLAN, I40E_INSET_VLAN_INNER},
+		{RTE_ETH_INPUT_SET_L2_ETHERTYPE, I40E_INSET_LAST_ETHER_TYPE},
+		{RTE_ETH_INPUT_SET_L3_SRC_IP4, I40E_INSET_IPV4_SRC},
+		{RTE_ETH_INPUT_SET_L3_DST_IP4, I40E_INSET_IPV4_DST},
+		{RTE_ETH_INPUT_SET_L3_IP4_TOS, I40E_INSET_IPV4_TOS},
+		{RTE_ETH_INPUT_SET_L3_IP4_PROTO, I40E_INSET_IPV4_PROTO},
+		{RTE_ETH_INPUT_SET_L3_SRC_IP6, I40E_INSET_IPV6_SRC},
+		{RTE_ETH_INPUT_SET_L3_DST_IP6, I40E_INSET_IPV6_DST},
+		{RTE_ETH_INPUT_SET_L3_IP6_TC, I40E_INSET_IPV6_TC},
+		{RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER,
+			I40E_INSET_IPV6_NEXT_HDR},
+		{RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT, I40E_INSET_SRC_PORT},
+		{RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT, I40E_INSET_SRC_PORT},
+		{RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT, I40E_INSET_SRC_PORT},
+		{RTE_ETH_INPUT_SET_L4_UDP_DST_PORT, I40E_INSET_DST_PORT},
+		{RTE_ETH_INPUT_SET_L4_TCP_DST_PORT, I40E_INSET_DST_PORT},
+		{RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT, I40E_INSET_DST_PORT},
+		{RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG,
+			I40E_INSET_SCTP_VT},
+		{RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_DST_MAC,
+			I40E_INSET_TUNNEL_DMAC},
+		{RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_VLAN,
+			I40E_INSET_VLAN_TUNNEL},
+		{RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY, I40E_INSET_TUNNEL_ID},
+		{RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY, I40E_INSET_TUNNEL_ID},
+		{RTE_ETH_INPUT_SET_ALL, I40E_INSET_ALL},
+	};
+
+	if (!field || size > RTE_ETH_INSET_SIZE_MAX)
+		return 0;
+
+	/* Only one item allowed for default or all */
+	if (size == 1) {
+		if (field[0] == RTE_ETH_INPUT_SET_DEFAULT)
+			return i40e_get_default_input_set(pctype);
+		else if (field[0] == RTE_ETH_INPUT_SET_ALL)
+			return I40E_INSET_ALL;
+	}
+
+	for (i = 0; i < size; i++) {
+		for (j = 0; j < RTE_DIM(inset_convert_table); j++) {
+			if (field[i] == inset_convert_table[j].field) {
+				inset |= inset_convert_table[j].inset;
+				break;
+			}
+		}
+
+		/* It contains unsupported input set, return 0 immediately */
+		if (j == RTE_DIM(inset_convert_table))
+			return 0;
+	}
+
+	return inset;
+}
+
+/**
+ * Translate the input set from bit masks to register aware bit masks
+ */
+static uint64_t
+i40e_translate_input_set_reg(uint64_t inset)
+{
+	uint64_t val = 0;
+	uint16_t i;
+
+	static const struct {
+		uint64_t inset;
+		uint64_t inset_reg;
+	} inset_map[] = {
+		{I40E_INSET_DMAC, I40E_REG_INSET_L2_DMAC},
+		{I40E_INSET_SMAC, I40E_REG_INSET_L2_SMAC},
+		{I40E_INSET_VLAN_OUTER, I40E_REG_INSET_L2_OUTER_VLAN},
+		{I40E_INSET_VLAN_INNER, I40E_REG_INSET_L2_INNER_VLAN},
+		{I40E_INSET_LAST_ETHER_TYPE, I40E_REG_INSET_LAST_ETHER_TYPE},
+		{I40E_INSET_IPV4_SRC, I40E_REG_INSET_L3_SRC_IP4},
+		{I40E_INSET_IPV4_DST, I40E_REG_INSET_L3_DST_IP4},
+		{I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6},
+		{I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6},
+		{I40E_INSET_SRC_PORT, I40E_REG_INSET_L4_SRC_PORT},
+		{I40E_INSET_DST_PORT, I40E_REG_INSET_L4_DST_PORT},
+		{I40E_INSET_SCTP_VT, I40E_REG_INSET_L4_SCTP_VERIFICATION_TAG},
+		{I40E_INSET_TUNNEL_ID, I40E_REG_INSET_TUNNEL_GRE_KEY},
+		{I40E_INSET_TUNNEL_DMAC,
+			I40E_REG_INSET_TUNNEL_L2_INNER_DST_MAC},
+		{I40E_INSET_TUNNEL_IPV4_DST, I40E_REG_INSET_TUNNEL_L3_DST_IP4},
+		{I40E_INSET_TUNNEL_IPV6_DST, I40E_REG_INSET_TUNNEL_L3_DST_IP6},
+		{I40E_INSET_TUNNEL_SRC_PORT,
+			I40E_REG_INSET_TUNNEL_L4_UDP_SRC_PORT},
+		{I40E_INSET_TUNNEL_DST_PORT,
+			I40E_REG_INSET_TUNNEL_L4_UDP_DST_PORT},
+		{I40E_INSET_FLEX_PAYLOAD_W1, I40E_REG_INSET_FLEX_PAYLOAD_WORD1},
+		{I40E_INSET_FLEX_PAYLOAD_W2, I40E_REG_INSET_FLEX_PAYLOAD_WORD2},
+		{I40E_INSET_FLEX_PAYLOAD_W3, I40E_REG_INSET_FLEX_PAYLOAD_WORD3},
+		{I40E_INSET_FLEX_PAYLOAD_W4, I40E_REG_INSET_FLEX_PAYLOAD_WORD4},
+		{I40E_INSET_FLEX_PAYLOAD_W5, I40E_REG_INSET_FLEX_PAYLOAD_WORD5},
+		{I40E_INSET_FLEX_PAYLOAD_W6, I40E_REG_INSET_FLEX_PAYLOAD_WORD6},
+		{I40E_INSET_FLEX_PAYLOAD_W7, I40E_REG_INSET_FLEX_PAYLOAD_WORD7},
+		{I40E_INSET_FLEX_PAYLOAD_W8, I40E_REG_INSET_FLEX_PAYLOAD_WORD8},
+	};
+
+	if (inset == I40E_INSET_ALL)
+		return I40E_REG_INSET_ALL;
+
+	for (i = 0; i < RTE_DIM(inset_map); i++) {
+		if (inset & inset_map[i].inset)
+			val |= inset_map[i].inset_reg;
+	}
+
+	return val;
+}
+
+static int
+i40e_generate_inset_mask_reg(uint64_t inset, uint64_t *mask)
+{
+	uint8_t idx = 0;
+
+	if (!mask)
+		return -EINVAL;
+
+	*mask = I40E_REG_INSET_MASK_DEFAULT;
+	if (inset & I40E_INSET_IPV4_TOS) {
+		*mask |= (0x0009FF00 << (idx * 32));
+		idx++;
+	}
+	if (inset & I40E_INSET_IPV4_PROTO) {
+		*mask |= (0x000DFF00 << (idx * 32));
+		idx++;
+	}
+
+	return idx;
+}
+
+static void
+i40e_check_modify_reg(struct i40e_hw *hw, uint32_t addr,
+			    uint32_t val, uint8_t enable)
+{
+	uint32_t reg, reg_o = I40E_READ_REG(hw, addr);
+
+	PMD_DRV_LOG(DEBUG, "[0x%08x] original: 0x%08x\n", addr, reg_o);
+	if (enable)
+		reg = reg_o | val;
+	else
+		reg = reg_o & ~val;
+	if (reg != reg_o)
+		I40E_WRITE_REG(hw, addr, reg);
+	PMD_DRV_LOG(DEBUG, "[0x%08x] after: 0x%08x\n", addr,
+		    (uint32_t)I40E_READ_REG(hw, addr));
+}
+
+static void
+i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val)
+{
+	uint32_t reg = I40E_READ_REG(hw, addr);
+
+	PMD_DRV_LOG(DEBUG, "[0x%08x] original: 0x%08x\n", addr, reg);
+	if (reg != val)
+		I40E_WRITE_REG(hw, addr, val);
+	PMD_DRV_LOG(DEBUG, "[0x%08x] after: 0x%08x\n", addr,
+		    (uint32_t)I40E_READ_REG(hw, addr));
+}
+
+static int
+i40e_check_write_mask_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val)
+{
+	uint32_t reg = I40E_READ_REG(hw, addr);
+
+	PMD_DRV_LOG(DEBUG, "[0x%08x] original: 0x%08x\n", addr, reg);
+	if (reg != 0)
+		return -EINVAL;
+	I40E_WRITE_REG(hw, addr, val);
+	PMD_DRV_LOG(DEBUG, "[0x%08x] after: 0x%08x\n", addr,
+		    (uint32_t)I40E_READ_REG(hw, addr));
+
+	return 0;
+}
+
+int
+i40e_filter_inset_select(struct i40e_hw *hw,
+			  struct rte_eth_input_set_conf *conf,
+			  enum rte_filter_type filter)
+{
+	enum i40e_filter_pctype pctype;
+	uint64_t inset_reg, mask_reg;
+	uint64_t input_set;
+	uint32_t reg;
+	int num, i;
+
+	if (!hw || !conf) {
+		PMD_DRV_LOG(ERR, "Invalid pointer");
+		return -EFAULT;
+	}
+	pctype = i40e_flowtype_to_pctype(conf->flow_type);
+	if (pctype == 0 ||
+		pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD || (filter !=
+		RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR)) {
+		return -EINVAL;
+	}
+
+	input_set = i40e_parse_input_set(pctype, conf->field,
+					 conf->inset_size);
+	if (!input_set)
+		return -EINVAL;
+
+	if (i40e_validate_input_set(pctype, input_set) != 0)
+		return -EINVAL;
+
+	if (input_set == I40E_INSET_ALL && conf->enable) {
+		/* Return with failure if trying to enable all */
+		return -EINVAL;
+	} else if (input_set == I40E_INSET_ALL && !conf->enable) {
+		/* Clear all registers if trying to disable all */
+		if (filter == RTE_ETH_FILTER_HASH) {
+			i40e_check_write_reg(hw,
+					     I40E_GLQF_HASH_INSET(0, pctype),
+					     0x0);
+			i40e_check_write_reg(hw,
+					     I40E_GLQF_HASH_INSET(1, pctype),
+					     0x0);
+			i40e_check_write_reg(hw,
+					     I40E_GLQF_HASH_MSK(0, pctype),
+					     0x0);
+			i40e_check_write_reg(hw,
+					     I40E_GLQF_HASH_MSK(1, pctype),
+					     0x0);
+		} else if (filter == RTE_ETH_FILTER_FDIR) {
+			i40e_check_write_reg(hw,
+					     I40E_PRTQF_FD_INSET(pctype, 0),
+					     0x0);
+			i40e_check_write_reg(hw,
+					     I40E_PRTQF_FD_INSET(pctype, 1),
+					     0x0);
+			i40e_check_write_reg(hw, I40E_PRTQF_FD_MSK(pctype, 0),
+					     0x0);
+			i40e_check_write_reg(hw, I40E_PRTQF_FD_MSK(pctype, 1),
+					     0x0);
+		}
+		I40E_WRITE_FLUSH(hw);
+
+		return 0;
+	}
+
+	inset_reg = i40e_translate_input_set_reg(input_set);
+	if (!inset_reg)
+		return -EINVAL;
+
+	num = i40e_generate_inset_mask_reg(input_set, &mask_reg);
+	if (num < 0 || num > 2)
+		return -EINVAL;
+
+	if (filter == RTE_ETH_FILTER_HASH) {
+		i40e_check_modify_reg(hw, I40E_GLQF_HASH_INSET(0, pctype),
+				      (uint32_t)(inset_reg & 0xFFFFFFFF),
+				      conf->enable);
+		i40e_check_modify_reg(hw, I40E_GLQF_HASH_INSET(1, pctype),
+				      (uint32_t)((inset_reg >> 32) &
+				      0xFFFFFFFF), conf->enable);
+
+		for (i = 0; i < num; i++) {
+			reg = (uint32_t)(mask_reg >> (i * 32));
+			if (i40e_check_write_mask_reg(hw,
+						      I40E_GLQF_HASH_MSK(0,
+						      pctype), reg) == 0)
+				continue;
+			if (i40e_check_write_mask_reg(hw,
+						      I40E_GLQF_HASH_MSK(1,
+						      pctype), reg) < 0)
+				return -EINVAL;
+		}
+	} else if (filter == RTE_ETH_FILTER_FDIR) {
+		i40e_check_modify_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
+				      (uint32_t)(inset_reg & 0xFFFFFFFF),
+				      conf->enable);
+		i40e_check_modify_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1),
+				      (uint32_t)((inset_reg >> 32) &
+				      0xFFFFFFFF), conf->enable);
+		for (i = 0; i < num; i++) {
+			reg = (uint32_t)(mask_reg >> (i * 32));
+			if (i40e_check_write_mask_reg(hw,
+				I40E_PRTQF_FD_MSK(pctype, 0), reg) == 0)
+				continue;
+			if (i40e_check_write_mask_reg(hw,
+				I40E_PRTQF_FD_MSK(pctype, 1), reg) < 0)
+				return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+	I40E_WRITE_FLUSH(hw);
+
+	return 0;
+}
+
 static int
 i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info)
 {
@@ -5498,6 +6083,12 @@  i40e_hash_filter_set(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info)
 		ret = i40e_set_hash_filter_global_config(hw,
 				&(info->info.global_conf));
 		break;
+	case RTE_ETH_HASH_FILTER_INPUT_SET_SELECT:
+		ret = i40e_filter_inset_select(hw,
+					       &(info->info.input_set_conf),
+					       RTE_ETH_FILTER_HASH);
+		break;
+
 	default:
 		PMD_DRV_LOG(ERR, "Hash filter info type (%d) not supported",
 							info->info_type);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 6185657..a997a08 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -501,6 +501,12 @@  uint16_t i40e_pctype_to_flowtype(enum i40e_filter_pctype pctype);
 int i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
 			  enum rte_filter_op filter_op,
 			  void *arg);
+int i40e_select_filter_input_set(struct i40e_hw *hw,
+				 struct rte_eth_input_set_conf *conf,
+				 enum rte_filter_type filter);
+int i40e_filter_inset_select(struct i40e_hw *hw,
+			     struct rte_eth_input_set_conf *conf,
+			     enum rte_filter_type filter);
 
 /* I40E_DEV_PRIVATE_TO */
 #define I40E_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index c9ce98f..ba18c9d 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -1342,6 +1342,33 @@  i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat)
 			    I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
 }
 
+static int
+i40e_fdir_filter_set(struct rte_eth_dev *dev,
+		     struct rte_eth_hash_filter_info *info)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	int ret = 0;
+
+	if (!info) {
+		PMD_DRV_LOG(ERR, "Invalid pointer");
+		return -EFAULT;
+	}
+
+	switch (info->info_type) {
+	case RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT:
+		ret = i40e_filter_inset_select(hw,
+			&(info->info.input_set_conf), RTE_ETH_FILTER_FDIR);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "FD filter info type (%d) not supported",
+			    info->info_type);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
 /*
  * i40e_fdir_ctrl_func - deal with all operations on flow director.
  * @pf: board private structure
@@ -1382,6 +1409,10 @@  i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
 	case RTE_ETH_FILTER_INFO:
 		i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
 		break;
+	case RTE_ETH_FILTER_SET:
+		ret = i40e_fdir_filter_set(dev,
+			(struct rte_eth_hash_filter_info *)arg);
+		break;
 	case RTE_ETH_FILTER_STATS:
 		i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg);
 		break;
diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h
index 26b7b33..2a1eb36 100644
--- a/lib/librte_ether/rte_eth_ctrl.h
+++ b/lib/librte_ether/rte_eth_ctrl.h
@@ -1,7 +1,7 @@ 
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -295,7 +295,73 @@  struct rte_eth_tunnel_filter_conf {
 	uint16_t queue_id;      /** < queue number. */
 };
 
-#define RTE_ETH_FDIR_MAX_FLEXLEN         16 /** < Max length of flexbytes. */
+#define RTE_ETH_FDIR_MAX_FLEXLEN 16 /** < Max length of flexbytes. */
+#define RTE_ETH_INSET_SIZE_MAX   128 /** < Max length of input set. */
+
+/**
+ * Input set fields for Flow Director and Hash filters
+ */
+enum rte_eth_input_set_field {
+	RTE_ETH_INPUT_SET_UNKNOWN = 0,
+
+	/* L2 */
+	RTE_ETH_INPUT_SET_L2_SRC_MAC = 1,
+	RTE_ETH_INPUT_SET_L2_DST_MAC,
+	RTE_ETH_INPUT_SET_L2_OUTER_VLAN,
+	RTE_ETH_INPUT_SET_L2_INNER_VLAN,
+	RTE_ETH_INPUT_SET_L2_ETHERTYPE,
+
+	/* L3 */
+	RTE_ETH_INPUT_SET_L3_SRC_IP4 = 129,
+	RTE_ETH_INPUT_SET_L3_DST_IP4,
+	RTE_ETH_INPUT_SET_L3_SRC_IP6,
+	RTE_ETH_INPUT_SET_L3_DST_IP6,
+	RTE_ETH_INPUT_SET_L3_IP4_TOS,
+	RTE_ETH_INPUT_SET_L3_IP4_PROTO,
+	RTE_ETH_INPUT_SET_L3_IP6_TC,
+	RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER,
+
+	/* L4 */
+	RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT = 257,
+	RTE_ETH_INPUT_SET_L4_UDP_DST_PORT,
+	RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT,
+	RTE_ETH_INPUT_SET_L4_TCP_DST_PORT,
+	RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT,
+	RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT,
+	RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG,
+
+	/* Tunnel */
+	RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_DST_MAC = 385,
+	RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_SRC_MAC,
+	RTE_ETH_INPUT_SET_TUNNEL_L2_INNER_VLAN,
+	RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY,
+	RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY,
+
+	/* Flexible Payload */
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD = 641,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD,
+	RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD,
+
+	RTE_ETH_INPUT_SET_DEFAULT = 65533,
+	RTE_ETH_INPUT_SET_ALL = 65534,
+	RTE_ETH_INPUT_SET_MAX = 65535,
+};
+
+/**
+ * A structure used to define the input set configuration for
+ * flow director and hash filters
+ */
+struct rte_eth_input_set_conf {
+	uint16_t flow_type;
+	uint16_t inset_size;
+	enum rte_eth_input_set_field field[RTE_ETH_INSET_SIZE_MAX];
+	uint8_t enable;
+};
 
 /**
  * A structure used to define the input for L2 flow
@@ -504,7 +570,7 @@  struct rte_eth_fdir_flex_mask {
 
 /**
  * A structure used to define all flexible payload related setting
- * include flexpay load and flex mask
+ * include flex payload and flex mask
  */
 struct rte_eth_fdir_flex_conf {
 	uint16_t nb_payloads;  /**< The number of following payload cfg */
@@ -582,12 +648,40 @@  struct rte_eth_fdir_stats {
 };
 
 /**
+ * Flow Director filter information types.
+ */
+enum rte_eth_fdir_filter_info_type {
+	RTE_ETH_FDIR_FILTER_INFO_TYPE_UNKNOWN = 0,
+	/** Flow Director filter input set configuration */
+	RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT,
+	RTE_ETH_FDIR_FILTER_INFO_TYPE_MAX,
+};
+
+/**
+ * A structure used to set or get hash filter information, to support filter
+ * type of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FILTER_SET operation.
+ */
+/**
+ * A structure used to support Flow Director RTE_ETH_FILTER_SET operations
+  */
+struct rte_eth_fdir_filter_info {
+	enum rte_eth_fdir_filter_info_type info_type; /**< Information type */
+	/** Details of fdir filter information */
+	union {
+		/** Flow Director input set configuration per port */
+		struct rte_eth_input_set_conf input_set_conf;
+	} info;
+};
+
+/**
  * Hash filter information types.
  * - RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT is for getting/setting the
  *   information/configuration of 'symmetric hash enable' per port.
  * - RTE_ETH_HASH_FILTER_GLOBAL_CONFIG is for getting/setting the global
  *   configurations of hash filters. Those global configurations are valid
  *   for all ports of the same NIC.
+ * - RTE_ETH_HASH_FILTER_INPUT_SET_SELECT is for setting the global
+ *   hash input set fields
  */
 enum rte_eth_hash_filter_info_type {
 	RTE_ETH_HASH_FILTER_INFO_TYPE_UNKNOWN = 0,
@@ -595,6 +689,8 @@  enum rte_eth_hash_filter_info_type {
 	RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT,
 	/** Configure globally for hash filter */
 	RTE_ETH_HASH_FILTER_GLOBAL_CONFIG,
+	/** Global Hash filter input set configuration */
+	RTE_ETH_HASH_FILTER_INPUT_SET_SELECT,
 	RTE_ETH_HASH_FILTER_INFO_TYPE_MAX,
 };
 
@@ -614,7 +710,7 @@  enum rte_eth_hash_function {
  * A structure used to set or get global hash function configurations which
  * include symmetric hash enable per flow type and hash function type.
  * Each bit in sym_hash_enable_mask[] indicates if the symmetric hash of the
- * coresponding flow type is enabled or not.
+ * corresponding flow type is enabled or not.
  * Each bit in valid_bit_mask[] indicates if the corresponding bit in
  * sym_hash_enable_mask[] is valid or not. For the configurations gotten, it
  * also means if the flow type is supported by hardware or not.
@@ -639,6 +735,8 @@  struct rte_eth_hash_filter_info {
 		uint8_t enable;
 		/** Global configurations of hash filter */
 		struct rte_eth_hash_global_conf global_conf;
+		/** Global configurations of hash filter input set */
+		struct rte_eth_input_set_conf input_set_conf;
 	} info;
 };