* [dpdk-dev] [PATCH 0/2] i40e: RSS granularity configuration @ 2015-09-22 6:32 Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 1/2] i40e: add " Helin Zhang ` (2 more replies) 0 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 6:32 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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. It also includes the modifications in testpmd to support the testing. Helin Zhang (2): i40e: add RSS granularity configuration app/testpmd: add test commands for RSS granularity app/test-pmd/cmdline.c | 106 +++++++ drivers/net/i40e/i40e_ethdev.c | 621 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 6 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 106 ++++++- 5 files changed, 866 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH 1/2] i40e: add RSS granularity configuration 2015-09-22 6:32 [dpdk-dev] [PATCH 0/2] i40e: RSS granularity configuration Helin Zhang @ 2015-09-22 6:32 ` Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 6:32 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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 | 621 ++++++++++++++++++++++++++++++++++++++++ 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, 760 insertions(+), 4 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 2dd9fdc..3a52664 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,496 @@ 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_set_filter_input_set(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; +} + +/* convert inset fields to registers' configuration */ +int +i40e_filter_inset_select(struct i40e_hw *hw, + struct rte_eth_input_set_conf *conf, + enum rte_filter_type filter) +{ + uint64_t input_set; + uint16_t pctype; + + if (!hw || !conf) { + PMD_DRV_LOG(ERR, "Invalid pointer"); + return -EFAULT; + } + + pctype = i40e_flowtype_to_pctype(conf->flow_type); + if (pctype == 0) + return -EINVAL; + + /* convert fields array to fields map */ + 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; + + return i40e_set_filter_input_set(hw, conf, filter); +} + static int i40e_hash_filter_get(struct i40e_hw *hw, struct rte_eth_hash_filter_info *info) { @@ -5498,6 +6113,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..d96bad1 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_set_filter_input_set(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..e7cc5ee 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_select_filter_input_set(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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH 2/2] app/testpmd: add test commands for RSS granularity 2015-09-22 6:32 [dpdk-dev] [PATCH 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 1/2] i40e: add " Helin Zhang @ 2015-09-22 6:32 ` Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 6:32 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support clearing input set, or setting with new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..80098e6 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -8851,6 +8851,111 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/**/ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t enable; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"all", RTE_ETH_INPUT_SET_ALL}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->enable, "enable")) + info.info.input_set_conf.enable = 1; + else + info.info.input_set_conf.enable = 0; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#" + "fld-5th#fld-6th#fld-7th#fld-8th#all"); +cmdline_parse_token_string_t cmd_set_hash_input_set_enable = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + enable, "enable#disable"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "ssss", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_enable, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9033,6 +9138,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration 2015-09-22 6:32 [dpdk-dev] [PATCH 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 1/2] i40e: add " Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang @ 2015-09-22 7:26 ` Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 1/2] i40e: add " Helin Zhang ` (2 more replies) 2 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 7:26 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. Helin Zhang (2): i40e: add RSS granularity configuration app/testpmd: add test commands for RSS granularity app/test-pmd/cmdline.c | 106 +++++++ 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 ++++++- 5 files changed, 836 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v2 1/2] i40e: add RSS granularity configuration 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang @ 2015-09-22 7:26 ` Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 7:26 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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 --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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v2 2/2] app/testpmd: add test commands for RSS granularity 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 1/2] i40e: add " Helin Zhang @ 2015-09-22 7:26 ` Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-22 7:26 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support clearing input set, or setting with new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..80098e6 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -8851,6 +8851,111 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/**/ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t enable; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"all", RTE_ETH_INPUT_SET_ALL}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->enable, "enable")) + info.info.input_set_conf.enable = 1; + else + info.info.input_set_conf.enable = 0; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#" + "fld-5th#fld-6th#fld-7th#fld-8th#all"); +cmdline_parse_token_string_t cmd_set_hash_input_set_enable = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + enable, "enable#disable"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "ssss", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_enable, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9033,6 +9138,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 1/2] i40e: add " Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang @ 2015-09-24 7:08 ` Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 1/2] i40e: add " Helin Zhang ` (2 more replies) 2 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-24 7:08 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. Helin Zhang (2): i40e: add RSS granularity configuration app/testpmd: add test commands for RSS granularity app/test-pmd/cmdline.c | 115 ++++++++ drivers/net/i40e/i40e_ethdev.c | 628 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 6 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 108 ++++++- 5 files changed, 884 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v3 1/2] i40e: add RSS granularity configuration 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang @ 2015-09-24 7:08 ` Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-24 7:08 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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 | 628 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 6 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 108 ++++++- 4 files changed, 769 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 2dd9fdc..77e6906 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -113,6 +113,135 @@ #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 + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_GRE_VER 0x0000002000000000ULL +#define I40E_INSET_TUNNEL_GRE_PROTO_TYPE 0x0000004000000000ULL +#define I40E_INSET_TUNNEL_GRE_KEY 0x0000008000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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 */ +#define I40E_REG_INSET_TUNNEL_GRE_VERSION 0x0000000000200000ULL +/* GRE protocol type */ +#define I40E_REG_INSET_TUNNEL_GRE_PROTO_TYPE 0x0000000000100000ULL +/* 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 +5580,499 @@ 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_GRE_VER | + I40E_INSET_TUNNEL_GRE_PROTO_TYPE | + I40E_INSET_TUNNEL_GRE_KEY | + 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_GRE_KEY | + 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_GRE_KEY | + 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_GRE_KEY | + 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_GRE_VER | + I40E_INSET_TUNNEL_GRE_PROTO_TYPE | + I40E_INSET_TUNNEL_GRE_KEY | + 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_GRE_VER | + I40E_INSET_TUNNEL_GRE_PROTO_TYPE | + I40E_INSET_TUNNEL_GRE_KEY | 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_TUNNEL_GRE_VER | + I40E_INSET_TUNNEL_GRE_PROTO_TYPE | + I40E_INSET_TUNNEL_GRE_KEY | 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_GRE_KEY}, + {RTE_ETH_INPUT_SET_TUNNEL_GRE_VERSION, + I40E_INSET_TUNNEL_GRE_VER}, + {RTE_ETH_INPUT_SET_TUNNEL_GRE_PROTOCOL_TYPE, + I40E_INSET_TUNNEL_GRE_PROTO_TYPE}, + {RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY, I40E_INSET_TUNNEL_GRE_KEY}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + {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_GRE_KEY, 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_TUNNEL_GRE_VER, I40E_REG_INSET_TUNNEL_GRE_VERSION}, + {I40E_INSET_TUNNEL_GRE_PROTO_TYPE, + I40E_REG_INSET_TUNNEL_GRE_PROTO_TYPE}, + {I40E_INSET_TUNNEL_GRE_KEY, I40E_REG_INSET_TUNNEL_GRE_KEY}, + {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_GLQF_FD_MSK(0, pctype), + 0x0); + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(1, pctype), + 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_GLQF_FD_MSK(0, pctype), reg) == 0) + continue; + if (i40e_check_write_mask_reg(hw, + I40E_GLQF_FD_MSK(1, pctype), 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 +6120,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..a7f2ee7 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,75 @@ 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_VERSION, + RTE_ETH_INPUT_SET_TUNNEL_GRE_PROTOCOL_TYPE, + 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 +572,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 +650,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 +691,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 +712,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 +737,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v3 2/2] app/testpmd: add test commands for RSS granularity 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 1/2] i40e: add " Helin Zhang @ 2015-09-24 7:08 ` Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-09-24 7:08 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support clearing input set, or setting with new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) v3 changes: Support selecting more input set fields. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..06bc26e 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -8851,6 +8851,120 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t enable; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"gre-ver", RTE_ETH_INPUT_SET_TUNNEL_GRE_VERSION}, + {"gre-proto-type", RTE_ETH_INPUT_SET_TUNNEL_GRE_PROTOCOL_TYPE}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"all", RTE_ETH_INPUT_SET_ALL}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->enable, "enable")) + info.info.input_set_conf.enable = 1; + else + info.info.input_set_conf.enable = 0; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#gre-ver#gre-proto-type#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#fld-8th#all"); +cmdline_parse_token_string_t cmd_set_hash_input_set_enable = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + enable, "enable#disable"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload src-ipv4|dst-ipv4|" + "src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|gre-ver|" + "gre-proto-type|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|all enable|disable", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_enable, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9033,6 +9147,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 1/2] i40e: add " Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang @ 2015-10-20 3:42 ` Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 1/2] " Helin Zhang ` (2 more replies) 2 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-20 3:42 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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 flow director. Here adds more flexibilities of selecting or adding packet fields for hash calculation or flow director to users. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. Helin Zhang (2): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity app/test-pmd/cmdline.c | 196 +++++++++++ drivers/net/i40e/i40e_ethdev.c | 752 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 117 ++++++- 5 files changed, 1099 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v4 1/2] i40e: RSS/FD granularity configuration 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang @ 2015-10-20 3:42 ` Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-20 3:42 UTC (permalink / raw) To: dev; +Cc: yulong.pei 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 flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for 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 | 752 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 117 ++++++- 4 files changed, 903 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 2dd9fdc..9bf7898 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -113,6 +113,140 @@ #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_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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 +5585,618 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input, uint8_t input_type) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + if (input_type == I40E_TRANSLATE_INSET) { + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + } else { /* Translate register aware inset to input set */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if ((input & inset_map[i].inset_reg) == + inset_map[i].inset_reg) + val |= inset_map[i].inset; + } + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + uint64_t reg = i40e_get_reg_inset(hw, filter, pctype); + + input_set |= i40e_translate_input_set_reg(reg, + I40E_TRANSLATE_REG); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg = i40e_translate_input_set_reg(input_set, + I40E_TRANSLATE_INSET); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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 +6244,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..32e968c 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -102,6 +102,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -501,6 +502,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..4ba86ee 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,84 @@ 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -504,7 +581,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 +659,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 +700,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 +721,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 +746,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v4 2/2] app/testpmd: add test commands for RSS/FD granularity 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 1/2] " Helin Zhang @ 2015-10-20 3:42 ` Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-20 3:42 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..a71b200 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -8851,6 +8851,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9033,6 +9227,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 1/2] " Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-10-29 4:09 ` Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 1/2] " Helin Zhang ` (2 more replies) 2 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 4:09 UTC (permalink / raw) To: dev; +Cc: yulong.pei The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting or adding packet fields for hash calculation or flow director to users. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. Helin Zhang (2): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity app/test-pmd/cmdline.c | 196 +++++++++++ drivers/net/i40e/i40e_ethdev.c | 742 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 5 files changed, 1086 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v5 1/2] i40e: RSS/FD granularity configuration 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang @ 2015-10-29 4:09 ` Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 4:09 UTC (permalink / raw) To: dev; +Cc: yulong.pei The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for 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 | 742 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 4 files changed, 890 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 478e94d..fb262a5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -113,6 +113,142 @@ #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_FD_MSK_FIELD 0x0000FFFF +#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_GLQF_HASH_MSK_FIELD 0x0000FFFF + +#define I40E_INSET_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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); @@ -5455,6 +5591,606 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg & I40E_GLQF_HASH_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg & I40E_GLQF_FD_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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 = 0, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + inset_reg |= i40e_get_reg_inset(hw, filter, pctype); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg |= i40e_translate_input_set_reg(input_set); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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) { @@ -5502,6 +6238,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..32e968c 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -102,6 +102,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -501,6 +502,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 770c76c..11829f1 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,84 @@ 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -535,7 +612,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 */ @@ -615,12 +692,37 @@ 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 FDIR filter information, to support filter type + * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation. + */ +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, @@ -628,6 +730,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, }; @@ -647,7 +751,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. @@ -672,6 +776,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v5 2/2] app/testpmd: add test commands for RSS/FD granularity 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 1/2] " Helin Zhang @ 2015-10-29 4:09 ` Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 4:09 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b3c36f3..7b7143b 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -9111,6 +9111,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9297,6 +9491,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 1/2] " Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-10-29 6:02 ` Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 1/3] " Helin Zhang ` (3 more replies) 2 siblings, 4 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 6:02 UTC (permalink / raw) To: dev; +Cc: yulong.pei The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting or adding packet fields for hash calculation or flow director to users. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v6 changes: Updated documentation. Helin Zhang (3): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity doc: update release notes and testpmd guide app/test-pmd/cmdline.c | 218 ++++++++ doc/guides/rel_notes/release_2_2.rst | 2 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 ++ drivers/net/i40e/i40e_ethdev.c | 742 ++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 ++++- 7 files changed, 1143 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v6 1/3] i40e: RSS/FD granularity configuration 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang @ 2015-10-29 6:02 ` Helin Zhang 2015-10-29 9:38 ` Bruce Richardson 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 2/3] app/testpmd: add test commands for RSS/FD granularity Helin Zhang ` (2 subsequent siblings) 3 siblings, 1 reply; 37+ messages in thread From: Helin Zhang @ 2015-10-29 6:02 UTC (permalink / raw) To: dev; +Cc: yulong.pei The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for 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 | 742 ++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 4 files changed, 890 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 478e94d..fb262a5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -113,6 +113,142 @@ #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_FD_MSK_FIELD 0x0000FFFF +#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_GLQF_HASH_MSK_FIELD 0x0000FFFF + +#define I40E_INSET_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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); @@ -5455,6 +5591,606 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg & I40E_GLQF_HASH_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg & I40E_GLQF_FD_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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 = 0, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + inset_reg |= i40e_get_reg_inset(hw, filter, pctype); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg |= i40e_translate_input_set_reg(input_set); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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) { @@ -5502,6 +6238,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..32e968c 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -102,6 +102,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -501,6 +502,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 770c76c..11829f1 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,84 @@ 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -535,7 +612,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 */ @@ -615,12 +692,37 @@ 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 FDIR filter information, to support filter type + * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation. + */ +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, @@ -628,6 +730,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, }; @@ -647,7 +751,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. @@ -672,6 +776,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/3] i40e: RSS/FD granularity configuration 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 1/3] " Helin Zhang @ 2015-10-29 9:38 ` Bruce Richardson 2015-10-30 1:58 ` Zhang, Helin 0 siblings, 1 reply; 37+ messages in thread From: Bruce Richardson @ 2015-10-29 9:38 UTC (permalink / raw) To: Helin Zhang; +Cc: dev On Thu, Oct 29, 2015 at 02:02:50PM +0800, Helin Zhang wrote: > The default input set of fields of a received packet are loaded from > firmware, which cannot be modified even users want to use different > fields for RSS or flow director. Here adds more flexibilities of > selecting packet fields for hash calculation or flow director for > 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 | 742 ++++++++++++++++++++++++++++++++++++++++ > drivers/net/i40e/i40e_ethdev.h | 7 + > drivers/net/i40e/i40e_fdir.c | 31 ++ > lib/librte_ether/rte_eth_ctrl.h | 114 +++++- > 4 files changed, 890 insertions(+), 4 deletions(-) > <snip> > @@ -672,6 +776,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; > }; > Hi Helin, Just to check: Does this change affect the size of the structure and cause ABI issues? /Bruce ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/3] i40e: RSS/FD granularity configuration 2015-10-29 9:38 ` Bruce Richardson @ 2015-10-30 1:58 ` Zhang, Helin 0 siblings, 0 replies; 37+ messages in thread From: Zhang, Helin @ 2015-10-30 1:58 UTC (permalink / raw) To: Richardson, Bruce; +Cc: dev > -----Original Message----- > From: Richardson, Bruce > Sent: Thursday, October 29, 2015 5:39 PM > To: Zhang, Helin > Cc: dev@dpdk.org; Pei, Yulong > Subject: Re: [dpdk-dev] [PATCH v6 1/3] i40e: RSS/FD granularity configuration > > On Thu, Oct 29, 2015 at 02:02:50PM +0800, Helin Zhang wrote: > > The default input set of fields of a received packet are loaded from > > firmware, which cannot be modified even users want to use different > > fields for RSS or flow director. Here adds more flexibilities of > > selecting packet fields for hash calculation or flow director for > > 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 | 742 > ++++++++++++++++++++++++++++++++++++++++ > > drivers/net/i40e/i40e_ethdev.h | 7 + > > drivers/net/i40e/i40e_fdir.c | 31 ++ > > lib/librte_ether/rte_eth_ctrl.h | 114 +++++- > > 4 files changed, 890 insertions(+), 4 deletions(-) > > > <snip> > > @@ -672,6 +776,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; > > }; > > > Hi Helin, > > Just to check: Does this change affect the size of the structure and cause ABI > issues? Bruce, you are right, there should be ABI issue with the structure size. Thank you very much! I will change the size of ' struct rte_eth_input_set_conf ' to smaller one, and then no ABI issue this time. But I will announce ABI change to support configuring more than one input sets, and then make the change next time. /Helin > > /Bruce ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v6 2/3] app/testpmd: add test commands for RSS/FD granularity 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 1/3] " Helin Zhang @ 2015-10-29 6:02 ` Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 3/3] doc: update release notes and testpmd guide Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang 3 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 6:02 UTC (permalink / raw) To: dev; +Cc: yulong.pei Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b3c36f3..1a2cb7d 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -690,6 +690,28 @@ static void cmd_help_long_parsed(void *parsed_result, "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)" " (enable|disable)\n" " Set the global configurations of hash filters.\n\n" + + "set_hash_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|" + "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|" + "ipv6-next-header|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|" + "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for hash.\n\n" + + "set_fdir_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|" + "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|" + "sctp-src-port|sctp-dst-port|sctp-veri-tag|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for FDir.\n\n" ); } } @@ -9111,6 +9133,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9297,6 +9513,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v6 3/3] doc: update release notes and testpmd guide 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 1/3] " Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 2/3] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-10-29 6:02 ` Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang 3 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-29 6:02 UTC (permalink / raw) To: dev; +Cc: yulong.pei Update release notes with the newly added feature of RSS/FD input set granularity, and testpmd guide with newly added commands for RSS/FD input set granularity testing. Signed-off-by: Helin Zhang <helin.zhang@intel.com> --- doc/guides/rel_notes/release_2_2.rst | 2 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index be6f827..8fc8917 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -23,6 +23,8 @@ New Features * **Added vhost-user multiple queue support.** +* **Added RSS/FD input set granularity on Intel X710/XL710.** + Resolved Issues --------------- diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 71d831b..f5951c0 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -1777,3 +1777,36 @@ Set the global configurations of hash filters:: For example, to enable simple_xor for flow type of ipv6 on port 2:: testpmd> set_hash_global_config 2 simple_xor ipv6 enable + +set_hash_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for hash:: + + set_hash_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other| \ + l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos| \ + ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + udp-key|gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th| \ + fld-8th|none) (select|add) + +For example, to add source IP to hash input set for flow type of ipv4 on port 0:: + + testpmd> set_hash_input_set 0 ipv4 src-ipv4 add + +set_fdir_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for Fdir:: + + set_fdir_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload) + (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|fld-8th|none) \ + (select|add) + +For example to add source IP to FD input set for flow type of ipv4 on port 0:: + + testpmd> set_fdir_input_set 0 ipv4 src-ipv4 add -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang ` (2 preceding siblings ...) 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 3/3] doc: update release notes and testpmd guide Helin Zhang @ 2015-10-30 3:11 ` Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 1/2] " Helin Zhang ` (3 more replies) 3 siblings, 4 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-30 3:11 UTC (permalink / raw) To: dev v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v6 changes: Updated documentation. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Split documentation into pieces and put them directly into the patch of code changes directly. Helin Zhang (2): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity app/test-pmd/cmdline.c | 218 ++++++++ doc/guides/rel_notes/deprecation.rst | 5 + doc/guides/rel_notes/release_2_2.rst | 3 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 ++ drivers/net/i40e/i40e_ethdev.c | 742 ++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 ++++- 8 files changed, 1149 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang @ 2015-10-30 3:11 ` Helin Zhang 2015-10-30 13:46 ` Thomas Monjalon 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang ` (2 subsequent siblings) 3 siblings, 1 reply; 37+ messages in thread From: Helin Zhang @ 2015-10-30 3:11 UTC (permalink / raw) To: dev The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for users. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- doc/guides/rel_notes/deprecation.rst | 5 + doc/guides/rel_notes/release_2_2.rst | 3 + drivers/net/i40e/i40e_ethdev.c | 742 +++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 6 files changed, 898 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Moved documentation as part of this patch. diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index a391ff0..856cb0f 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -52,3 +52,8 @@ Deprecation Notices and table action handlers will be updated: the pipeline parameter will be added, the packets mask parameter will be either removed (for input port action handler) or made input-only. + +* ABI changes are planned in release 2.3 for macro of RTE_ETH_INSET_SIZE_MAX, + struct rte_eth_input_set_conf, to support selecting more than one input set + items, and which will affect struct rte_eth_fdir_filter_info and + struct rte_eth_hash_filter_info. diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index 89e4d58..2a54ce6 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -31,6 +31,9 @@ New Features * **Added vhost-user multiple queue support.** +* **Added RSS/FD input set granularity on Intel X710/XL710.** + + Resolved Issues --------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 478e94d..fb262a5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -113,6 +113,142 @@ #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_FD_MSK_FIELD 0x0000FFFF +#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_GLQF_HASH_MSK_FIELD 0x0000FFFF + +#define I40E_INSET_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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); @@ -5455,6 +5591,606 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg & I40E_GLQF_HASH_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg & I40E_GLQF_FD_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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 = 0, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + inset_reg |= i40e_get_reg_inset(hw, filter, pctype); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg |= i40e_translate_input_set_reg(input_set); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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) { @@ -5502,6 +6238,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..32e968c 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -102,6 +102,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -501,6 +502,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 770c76c..3dc10db 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,84 @@ 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 1 /** < 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -535,7 +612,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 */ @@ -615,12 +692,37 @@ 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 FDIR filter information, to support filter type + * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation. + */ +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, @@ -628,6 +730,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, }; @@ -647,7 +751,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. @@ -672,6 +776,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 1/2] " Helin Zhang @ 2015-10-30 13:46 ` Thomas Monjalon 2015-11-02 2:11 ` Zhang, Helin 0 siblings, 1 reply; 37+ messages in thread From: Thomas Monjalon @ 2015-10-30 13:46 UTC (permalink / raw) To: Helin Zhang; +Cc: dev 2015-10-30 11:11, Helin Zhang: > v7 changes: > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Why it would avoid ABI changes? Have you passed the ABI checker? ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-10-30 13:46 ` Thomas Monjalon @ 2015-11-02 2:11 ` Zhang, Helin 2015-11-02 7:27 ` Thomas Monjalon 0 siblings, 1 reply; 37+ messages in thread From: Zhang, Helin @ 2015-11-02 2:11 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev > -----Original Message----- > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > Sent: Friday, October 30, 2015 9:47 PM > To: Zhang, Helin > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration > > 2015-10-30 11:11, Helin Zhang: > > v7 changes: > > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. > > Why it would avoid ABI changes? > Have you passed the ABI checker? Hi Thomas The only structure modified is ' struct rte_eth_hash_filter_info ', where a new element (struct rte_eth_input_set_conf input_set_conf) was added. But I kept its structure the same size as another one (struct rte_eth_hash_global_conf global_conf) already in that union, they are both in 12 bytes. That means nothing changed for ' struct rte_eth_hash_filter_info'. In addition, macro of ' RTE_ETH_INSET_SIZE_MAX ' was added by me in this patch set, and I modified its default value from 128 to 1 in the latest version, which does not affect ABI, as it is a totally new macro. A new element was added at the last of ' enum rte_eth_hash_filter_info_type ', I don't think it will affect ABI as well. struct rte_eth_hash_filter_info { enum rte_eth_hash_filter_info_type info_type; /**< Information type */ /** Details of hash filter information */ union { /** For RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT */ 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; }; I did ABI check, but it seems that something wrong in running that check on all PMDs, like below. While all other checks are quite well. I am not sure if anybody else can run it successfully. preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... ERROR: the input dump d1 is invalid preparation, please wait ... Regards, Helin ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-11-02 2:11 ` Zhang, Helin @ 2015-11-02 7:27 ` Thomas Monjalon 2015-11-02 7:59 ` Zhang, Helin 0 siblings, 1 reply; 37+ messages in thread From: Thomas Monjalon @ 2015-11-02 7:27 UTC (permalink / raw) To: Zhang, Helin; +Cc: dev 2015-11-02 02:11, Zhang, Helin: > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > > 2015-10-30 11:11, Helin Zhang: > > > v7 changes: > > > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. > > > > Why it would avoid ABI changes? > > Have you passed the ABI checker? > > Hi Thomas > > The only structure modified is ' struct rte_eth_hash_filter_info ', where a new > element (struct rte_eth_input_set_conf input_set_conf) was added. But I kept its > structure the same size as another one (struct rte_eth_hash_global_conf global_conf) > already in that union, they are both in 12 bytes. That means nothing changed for > ' struct rte_eth_hash_filter_info'. First, it should be justified in the commit message. Second, I think it's wrong: The union has struct rte_eth_hash_global_conf = enum + uint32_t + uint32_t You are adding struct rte_eth_input_set_conf = uint16_t + uint16_t + enum + enum I'm not sure we can assume the sizes are the same. The ethdev ABI is already broken in this release. So maybe we can agree that it's not a big deal but it should be notified in the release notes and, in this case, you could keep your original patch with 128 enums. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-11-02 7:27 ` Thomas Monjalon @ 2015-11-02 7:59 ` Zhang, Helin 2015-11-02 8:23 ` Thomas Monjalon 0 siblings, 1 reply; 37+ messages in thread From: Zhang, Helin @ 2015-11-02 7:59 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev > -----Original Message----- > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > Sent: Monday, November 2, 2015 3:28 PM > To: Zhang, Helin > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration > > 2015-11-02 02:11, Zhang, Helin: > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > > > 2015-10-30 11:11, Helin Zhang: > > > > v7 changes: > > > > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. > > > > > > Why it would avoid ABI changes? > > > Have you passed the ABI checker? > > > > Hi Thomas > > > > The only structure modified is ' struct rte_eth_hash_filter_info ', > > where a new element (struct rte_eth_input_set_conf input_set_conf) was > > added. But I kept its structure the same size as another one (struct > > rte_eth_hash_global_conf global_conf) already in that union, they are > > both in 12 bytes. That means nothing changed for ' struct > rte_eth_hash_filter_info'. > > First, it should be justified in the commit message. > Second, I think it's wrong: > The union has struct rte_eth_hash_global_conf = enum + uint32_t + uint32_t You > are adding struct rte_eth_input_set_conf = uint16_t + uint16_t + enum + enum > I'm not sure we can assume the sizes are the same. Oh, yes, the size might not be the same on all platforms. > > The ethdev ABI is already broken in this release. So maybe we can agree that it's > not a big deal but it should be notified in the release notes and, in this case, you > could keep your original patch with 128 enums. That's bad, but good for me. Can I just enable v6 as 'new', and disable 'v7'? Or I need a new version? Thank you very much! Helin ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/2] i40e: RSS/FD granularity configuration 2015-11-02 7:59 ` Zhang, Helin @ 2015-11-02 8:23 ` Thomas Monjalon 0 siblings, 0 replies; 37+ messages in thread From: Thomas Monjalon @ 2015-11-02 8:23 UTC (permalink / raw) To: Zhang, Helin; +Cc: dev 2015-11-02 07:59, Zhang, Helin: > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > > 2015-11-02 02:11, Zhang, Helin: > > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > > > > 2015-10-30 11:11, Helin Zhang: > > > > > v7 changes: > > > > > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. > > > > > > > > Why it would avoid ABI changes? > > > > Have you passed the ABI checker? > > > > > > Hi Thomas > > > > > > The only structure modified is ' struct rte_eth_hash_filter_info ', > > > where a new element (struct rte_eth_input_set_conf input_set_conf) was > > > added. But I kept its structure the same size as another one (struct > > > rte_eth_hash_global_conf global_conf) already in that union, they are > > > both in 12 bytes. That means nothing changed for ' struct > > rte_eth_hash_filter_info'. > > > > First, it should be justified in the commit message. > > Second, I think it's wrong: > > The union has struct rte_eth_hash_global_conf = enum + uint32_t + uint32_t You > > are adding struct rte_eth_input_set_conf = uint16_t + uint16_t + enum + enum > > I'm not sure we can assume the sizes are the same. > Oh, yes, the size might not be the same on all platforms. > > > > > The ethdev ABI is already broken in this release. So maybe we can agree that it's > > not a big deal but it should be notified in the release notes and, in this case, you > > could keep your original patch with 128 enums. > That's bad, but good for me. Can I just enable v6 as 'new', and disable 'v7'? > Or I need a new version? I think you need a new version to notify ABI change in the release notes. ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v7 2/2] app/testpmd: add test commands for RSS/FD granularity 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 1/2] " Helin Zhang @ 2015-10-30 3:11 ` Helin Zhang 2015-10-30 7:59 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Wu, Jingjing 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang 3 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-10-30 3:11 UTC (permalink / raw) To: dev Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 218 ++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 +++++ 2 files changed, 251 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. v7 changes: Moved the documentation as part of this patch. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b3c36f3..1a2cb7d 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -690,6 +690,28 @@ static void cmd_help_long_parsed(void *parsed_result, "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)" " (enable|disable)\n" " Set the global configurations of hash filters.\n\n" + + "set_hash_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|" + "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|" + "ipv6-next-header|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|" + "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for hash.\n\n" + + "set_fdir_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|" + "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|" + "sctp-src-port|sctp-dst-port|sctp-veri-tag|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for FDir.\n\n" ); } } @@ -9111,6 +9133,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9297,6 +9513,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 71d831b..f5951c0 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -1777,3 +1777,36 @@ Set the global configurations of hash filters:: For example, to enable simple_xor for flow type of ipv6 on port 2:: testpmd> set_hash_global_config 2 simple_xor ipv6 enable + +set_hash_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for hash:: + + set_hash_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other| \ + l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos| \ + ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + udp-key|gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th| \ + fld-8th|none) (select|add) + +For example, to add source IP to hash input set for flow type of ipv4 on port 0:: + + testpmd> set_hash_input_set 0 ipv4 src-ipv4 add + +set_fdir_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for Fdir:: + + set_fdir_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload) + (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|fld-8th|none) \ + (select|add) + +For example to add source IP to FD input set for flow type of ipv4 on port 0:: + + testpmd> set_fdir_input_set 0 ipv4 src-ipv4 add -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 1/2] " Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-10-30 7:59 ` Wu, Jingjing 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang 3 siblings, 0 replies; 37+ messages in thread From: Wu, Jingjing @ 2015-10-30 7:59 UTC (permalink / raw) To: Zhang, Helin, dev > -----Original Message----- > From: Zhang, Helin > Sent: Friday, October 30, 2015 11:11 AM > To: dev@dpdk.org > Cc: Pei, Yulong; Liu, Yong; Wu, Jingjing; Zhang, Helin > Subject: [PATCH v7 0/2] i40e: RSS/FD granularity configuration > > v2 changes: > Solved the compilation issues. > > v3 changes: > Support selecting more input set fields. > > v4 changes: > Removed operation of 'delete', as it is not necessary. > Added FD granularity in both pmd and testpmd, as it is similar to RSS > granularity. > > v5 changes: > Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6- > tcp pc types. > Added clear masking operations during checking if MASK registers are > opcupied or not. > Reworked several annotations. > > v6 changes: > Updated documentation. > > v7 changes: > Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. > Split documentation into pieces and put them directly into the patch of code > changes directly. > > Helin Zhang (2): > i40e: RSS/FD granularity configuration > app/testpmd: add test commands for RSS/FD granularity > > app/test-pmd/cmdline.c | 218 ++++++++ > doc/guides/rel_notes/deprecation.rst | 5 + > doc/guides/rel_notes/release_2_2.rst | 3 + > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 ++ > drivers/net/i40e/i40e_ethdev.c | 742 > ++++++++++++++++++++++++++++ > drivers/net/i40e/i40e_ethdev.h | 7 + > drivers/net/i40e/i40e_fdir.c | 31 ++ > lib/librte_ether/rte_eth_ctrl.h | 114 ++++- > 8 files changed, 1149 insertions(+), 4 deletions(-) > > -- > 1.9.3 Acked-by: Jingjing Wu <jingjing.wu@intel.com> ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v8 0/2] i40e: RSS/FD granularity configuration 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang ` (2 preceding siblings ...) 2015-10-30 7:59 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Wu, Jingjing @ 2015-11-02 14:32 ` Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 1/2] " Helin Zhang ` (2 more replies) 3 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-02 14:32 UTC (permalink / raw) To: dev The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting or adding packet fields for hash calculation or flow director to users. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v6 changes: Updated documentation. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Split documentation into pieces and put them directly into the patch of code changes directly. v8 changes: Modified RTE_ETH_INSET_SIZE_MAX from 1 to 128, as ABI changes is allowed in ethdev. Updated release notes. Helin Zhang (2): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity app/test-pmd/cmdline.c | 218 ++++++++ doc/guides/rel_notes/deprecation.rst | 5 + doc/guides/rel_notes/release_2_2.rst | 2 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 ++ drivers/net/i40e/i40e_ethdev.c | 742 ++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 ++++- 8 files changed, 1148 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v8 1/2] i40e: RSS/FD granularity configuration 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang @ 2015-11-02 14:32 ` Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-02 14:32 UTC (permalink / raw) To: dev The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for users. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- doc/guides/rel_notes/deprecation.rst | 5 + doc/guides/rel_notes/release_2_2.rst | 2 + drivers/net/i40e/i40e_ethdev.c | 742 +++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 6 files changed, 897 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Moved documentation as part of this patch. v8 changes: Modified RTE_ETH_INSET_SIZE_MAX from 1 to 128, as ABI changes is allowed in ethdev. Updated release notes. diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index a391ff0..a4c5b51 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -52,3 +52,8 @@ Deprecation Notices and table action handlers will be updated: the pipeline parameter will be added, the packets mask parameter will be either removed (for input port action handler) or made input-only. + +* ABI changes are planned in release 2.2 for macro of RTE_ETH_INSET_SIZE_MAX, + struct rte_eth_input_set_conf, to support selecting more input set items at + a time, and which will affect struct rte_eth_fdir_filter_info and + struct rte_eth_hash_filter_info. diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index 8a20044..f42f0d4 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -59,6 +59,8 @@ New Features * **Added port hotplug support to xenvirt.** +* **Added RSS/FD input set granularity on Intel X710/XL710.** + Resolved Issues --------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 8381c8e..75c368f 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -139,6 +139,142 @@ #define I40E_DEFAULT_DCB_APP_NUM 1 #define I40E_DEFAULT_DCB_APP_PRIO 3 +#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_FD_MSK_FIELD 0x0000FFFF +#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_GLQF_HASH_MSK_FIELD 0x0000FFFF + +#define I40E_INSET_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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); @@ -5708,6 +5844,606 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 immediately */ + if (j == RTE_DIM(inset_convert_table)) + return ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg & I40E_GLQF_HASH_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg & I40E_GLQF_FD_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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 = 0, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + inset_reg |= i40e_get_reg_inset(hw, filter, pctype); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg |= i40e_translate_input_set_reg(input_set); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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) { @@ -5755,6 +6491,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 062878b..fe79030 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -107,6 +107,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -538,6 +539,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); void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, struct rte_eth_rxq_info *qinfo); 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 770c76c..ae73c36 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,84 @@ 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -535,7 +612,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 */ @@ -615,12 +692,37 @@ 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 FDIR filter information, to support filter type + * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation. + */ +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, @@ -628,6 +730,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, }; @@ -647,7 +751,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. @@ -672,6 +776,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v8 2/2] app/testpmd: add test commands for RSS/FD granularity 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 1/2] " Helin Zhang @ 2015-11-02 14:32 ` Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-02 14:32 UTC (permalink / raw) To: dev Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 218 ++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 +++++ 2 files changed, 251 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. v7 changes: Moved the documentation as part of this patch. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0afdc96..6a384a2 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -692,6 +692,28 @@ static void cmd_help_long_parsed(void *parsed_result, "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)" " (enable|disable)\n" " Set the global configurations of hash filters.\n\n" + + "set_hash_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|" + "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|" + "ipv6-next-header|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|" + "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for hash.\n\n" + + "set_fdir_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|" + "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|" + "sctp-src-port|sctp-dst-port|sctp-veri-tag|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for FDir.\n\n" ); } } @@ -9205,6 +9227,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9392,6 +9608,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 2d0599d..75b0a57 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -1779,3 +1779,36 @@ Set the global configurations of hash filters:: For example, to enable simple_xor for flow type of ipv6 on port 2:: testpmd> set_hash_global_config 2 simple_xor ipv6 enable + +set_hash_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for hash:: + + set_hash_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other| \ + l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos| \ + ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + udp-key|gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th| \ + fld-8th|none) (select|add) + +For example, to add source IP to hash input set for flow type of ipv4 on port 0:: + + testpmd> set_hash_input_set 0 ipv4 src-ipv4 add + +set_fdir_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for Fdir:: + + set_fdir_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload) + (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|fld-8th|none) \ + (select|add) + +For example to add source IP to FD input set for flow type of ipv4 on port 0:: + + testpmd> set_fdir_input_set 0 ipv4 src-ipv4 add -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 1/2] " Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-11-03 16:07 ` Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 1/2] " Helin Zhang ` (2 more replies) 2 siblings, 3 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-03 16:07 UTC (permalink / raw) To: dev The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting or adding packet fields for hash calculation or flow director to users. It also includes the modifications in testpmd to support the testing. v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity in both pmd and testpmd, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v6 changes: Updated documentation. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Split documentation into pieces and put them directly into the patch of code changes directly. v8 changes: Modified RTE_ETH_INSET_SIZE_MAX from 1 to 128, as ABI changes is allowed in ethdev. Updated release notes. v9 changes: Updated release notes. Helin Zhang (2): i40e: RSS/FD granularity configuration app/testpmd: add test commands for RSS/FD granularity app/test-pmd/cmdline.c | 218 ++++++++ doc/guides/rel_notes/release_2_2.rst | 6 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 ++ drivers/net/i40e/i40e_ethdev.c | 742 ++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 ++++- 7 files changed, 1147 insertions(+), 4 deletions(-) -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v9 1/2] i40e: RSS/FD granularity configuration 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang @ 2015-11-03 16:07 ` Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-11-03 23:25 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Thomas Monjalon 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-03 16:07 UTC (permalink / raw) To: dev The default input set of fields of a received packet are loaded from firmware, which cannot be modified even users want to use different fields for RSS or flow director. Here adds more flexibilities of selecting packet fields for hash calculation or flow director for users. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- doc/guides/rel_notes/release_2_2.rst | 6 + drivers/net/i40e/i40e_ethdev.c | 742 +++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_ethdev.h | 7 + drivers/net/i40e/i40e_fdir.c | 31 ++ lib/librte_ether/rte_eth_ctrl.h | 114 +++++- 5 files changed, 896 insertions(+), 4 deletions(-) v2 changes: Solved the compilation issues. v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete', as it is not necessary. Added FD granularity, as it is similar to RSS granularity. v5 changes: Fixed issue of generating wrong input set for registers on ipv6-udp and ipv6-tcp pc types. Added clear masking operations during checking if MASK registers are opcupied or not. Reworked several annotations. v7 changes: Modified RTE_ETH_INSET_SIZE_MAX from 128 to 1, to avoid ABI changes. Moved documentation as part of this patch. v8 changes: Modified RTE_ETH_INSET_SIZE_MAX from 1 to 128, as ABI changes is allowed in ethdev. Updated release notes. v9 changes: Updated release notes. diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index 16fcc89..bbca629 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -79,6 +79,8 @@ New Features * **Added port hotplug support to xenvirt.** +* **Added RSS/FD input set granularity on Intel X710/XL710.** + Resolved Issues --------------- @@ -205,6 +207,10 @@ ABI Changes * librte_cfgfile: Allow longer names and values by increasing the constants CFG_NAME_LEN and CFG_VALUE_LEN to 64 and 256 respectively. +* librte_ether: New union element of struct rte_eth_input_set_conf + input_set_conf will be added into struct rte_eth_hash_filter_info from 2.2, + which result in changing the size of struct rte_eth_hash_filter_info. + Shared Library Versions ----------------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index d852bf1..e8fd7f1 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -139,6 +139,142 @@ #define I40E_DEFAULT_DCB_APP_NUM 1 #define I40E_DEFAULT_DCB_APP_PRIO 3 +#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_FD_MSK_FIELD 0x0000FFFF +#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_GLQF_HASH_MSK_FIELD 0x0000FFFF + +#define I40E_INSET_NONE 0x00000000000000000ULL + +/* bit0 ~ bit 7 */ +#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 + +/* bit 8 ~ bit 15 */ +#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 + +/* bit 16 ~ bit 31 */ +#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 + +/* bit 32 ~ bit 47, tunnel fields */ +#define I40E_INSET_TUNNEL_IPV4_DST 0x0000000100000000ULL +#define I40E_INSET_TUNNEL_IPV6_DST 0x0000000200000000ULL +#define I40E_INSET_TUNNEL_DMAC 0x0000000400000000ULL +#define I40E_INSET_TUNNEL_SRC_PORT 0x0000000800000000ULL +#define I40E_INSET_TUNNEL_DST_PORT 0x0000001000000000ULL +#define I40E_INSET_TUNNEL_ID 0x0000002000000000ULL + +/* bit 48 ~ bit 55 */ +#define I40E_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL + +/* bit 56 ~ bit 63, Flex Payload */ +#define I40E_INSET_FLEX_PAYLOAD_W1 0x0100000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W2 0x0200000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W3 0x0400000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W4 0x0800000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W5 0x1000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W6 0x2000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W7 0x4000000000000000ULL +#define I40E_INSET_FLEX_PAYLOAD_W8 0x8000000000000000ULL +#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) + +/** + * 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 +/* IPv4 Type of Service (TOS) */ +#define I40E_REG_INSET_L3_IP4_TOS 0x0040000000000000ULL +/* IPv4 Protocol */ +#define I40E_REG_INSET_L3_IP4_PROTO 0x0004000000000000ULL +/* Source IPv6 address */ +#define I40E_REG_INSET_L3_SRC_IP6 0x0007F80000000000ULL +/* Destination IPv6 address */ +#define I40E_REG_INSET_L3_DST_IP6 0x000007F800000000ULL +/* IPv6 Traffic Class (TC) */ +#define I40E_REG_INSET_L3_IP6_TC 0x0040000000000000ULL +/* IPv6 Next Header */ +#define I40E_REG_INSET_L3_IP6_NEXT_HDR 0x0008000000000000ULL +/* 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 +/* UDP Tunneling ID, NVGRE/GRE key */ +#define I40E_REG_INSET_TUNNEL_ID 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_MASK_DEFAULT 0x0000000000000000ULL + +#define I40E_TRANSLATE_INSET 0 +#define I40E_TRANSLATE_REG 1 + +#define I40E_INSET_IPV4_TOS_MASK 0x0009FF00UL +#define I40E_INSET_IPV4_PROTO_MASK 0x000DFF00UL +#define I40E_INSET_IPV6_TC_MASK 0x0009F00FUL +#define I40E_INSET_IPV6_NEXT_HDR_MASK 0x000C00FFUL + 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); @@ -6022,6 +6158,606 @@ out: return 0; } +/** + * Valid input sets for hash and flow director filters per PCTYPE + */ +static uint64_t +i40e_get_valid_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter) +{ + uint64_t valid; + + static const uint64_t valid_hash_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_TUNNEL_ID | + 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, + }; + + /** + * Flow director supports only fields defined in + * union rte_eth_fdir_flow. + */ + static const uint64_t valid_fdir_inset_table[] = { + [I40E_FILTER_PCTYPE_FRAG_IPV4] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + 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_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_FRAG_IPV6] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = + 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_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | + I40E_INSET_FLEX_PAYLOAD, + [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_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = + I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | + I40E_INSET_FLEX_PAYLOAD, + [I40E_FILTER_PCTYPE_L2_PAYLOAD] = + I40E_INSET_LAST_ETHER_TYPE | I40E_INSET_FLEX_PAYLOAD, + }; + + if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) + return 0; + if (filter == RTE_ETH_FILTER_HASH) + valid = valid_hash_inset_table[pctype]; + else + valid = valid_fdir_inset_table[pctype]; + + return valid; +} + +/** + * Validate if the input set is allowed for a specific PCTYPE + */ +static int +i40e_validate_input_set(enum i40e_filter_pctype pctype, + enum rte_filter_type filter, uint64_t inset) +{ + uint64_t valid; + + valid = i40e_get_valid_input_set(pctype, filter); + if (inset & (~valid)) + 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 int +i40e_parse_input_set(uint64_t *inset, + enum i40e_filter_pctype pctype, + enum rte_eth_input_set_field *field, + uint16_t size) +{ + uint16_t i, j; + int ret = -EINVAL; + + static const struct { + enum rte_eth_input_set_field field; + uint64_t inset; + } inset_convert_table[] = { + {RTE_ETH_INPUT_SET_NONE, I40E_INSET_NONE}, + {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_FLEX_PAYLOAD_1ST_WORD, + I40E_INSET_FLEX_PAYLOAD_W1}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD, + I40E_INSET_FLEX_PAYLOAD_W2}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD, + I40E_INSET_FLEX_PAYLOAD_W3}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W4}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W5}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W6}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W7}, + {RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD, + I40E_INSET_FLEX_PAYLOAD_W8}, + }; + + if (!inset || !field || size > RTE_ETH_INSET_SIZE_MAX) + return ret; + + /* Only one item allowed for default or all */ + if (size == 1) { + if (field[0] == RTE_ETH_INPUT_SET_DEFAULT) { + *inset = i40e_get_default_input_set(pctype); + return 0; + } else if (field[0] == RTE_ETH_INPUT_SET_NONE) { + *inset = I40E_INSET_NONE; + return 0; + } + } + + for (i = 0, *inset = 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 immediately */ + if (j == RTE_DIM(inset_convert_table)) + return ret; + } + + return 0; +} + +/** + * Translate the input set from bit masks to register aware bit masks + * and vice versa + */ +static uint64_t +i40e_translate_input_set_reg(uint64_t input) +{ + 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_IPV4_TOS, I40E_REG_INSET_L3_IP4_TOS}, + {I40E_INSET_IPV4_PROTO, I40E_REG_INSET_L3_IP4_PROTO}, + {I40E_INSET_IPV6_SRC, I40E_REG_INSET_L3_SRC_IP6}, + {I40E_INSET_IPV6_DST, I40E_REG_INSET_L3_DST_IP6}, + {I40E_INSET_IPV6_TC, I40E_REG_INSET_L3_IP6_TC}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_REG_INSET_L3_IP6_NEXT_HDR}, + {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_ID}, + {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_TUNNEL_ID, I40E_REG_INSET_TUNNEL_ID}, + {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 (input == 0) + return val; + + /* Translate input set to register aware inset */ + for (i = 0; i < RTE_DIM(inset_map); i++) { + if (input & inset_map[i].inset) + val |= inset_map[i].inset_reg; + } + + return val; +} + +static uint8_t +i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask, uint8_t nb_elem) +{ + uint8_t i, idx = 0; + + static const struct { + uint64_t inset; + uint32_t mask; + } inset_mask_map[] = { + {I40E_INSET_IPV4_TOS, I40E_INSET_IPV4_TOS_MASK}, + {I40E_INSET_IPV4_PROTO, I40E_INSET_IPV4_PROTO_MASK}, + {I40E_INSET_IPV6_TC, I40E_INSET_IPV6_TC_MASK}, + {I40E_INSET_IPV6_NEXT_HDR, I40E_INSET_IPV6_NEXT_HDR_MASK}, + }; + + if (!inset || !mask || !nb_elem) + return 0; + + if (!inset && nb_elem >= I40E_INSET_MASK_NUM_REG) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) + mask[i] = 0; + return I40E_INSET_MASK_NUM_REG; + } + + for (i = 0, idx = 0; i < RTE_DIM(inset_mask_map); i++) { + if (idx >= nb_elem) + break; + if (inset & inset_mask_map[i].inset) { + mask[idx] = inset_mask_map[i].mask; + idx++; + } + } + + return idx; +} + +static uint64_t +i40e_get_reg_inset(struct i40e_hw *hw, enum rte_filter_type filter, + enum i40e_filter_pctype pctype) +{ + uint64_t reg = 0; + + if (filter == RTE_ETH_FILTER_HASH) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(1, pctype)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_GLQF_HASH_INSET(0, pctype)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + reg = I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 1)); + reg <<= I40E_32_BIT_WIDTH; + reg |= I40E_READ_REG(hw, I40E_PRTQF_FD_INSET(pctype, 0)); + } + + return reg; +} + +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_set_hash_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_HASH_MSK(i, pctype)); + if (reg & I40E_GLQF_HASH_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_HASH_MSK(i, pctype), + mask_reg[j]); + } + + return 0; +} + +static int +i40e_set_fd_inset_mask(struct i40e_hw *hw, + enum i40e_filter_pctype pctype, + enum rte_filter_input_set_op op, + uint32_t *mask_reg, + uint8_t num) +{ + uint32_t reg; + uint8_t i; + + if (!mask_reg || num > RTE_ETH_INPUT_SET_SELECT) + return -EINVAL; + + if (op == RTE_ETH_INPUT_SET_SELECT) { + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + 0); + if (i >= num) + continue; + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[i]); + } + } else if (op == RTE_ETH_INPUT_SET_ADD) { + uint8_t j, count = 0; + + for (i = 0; i < I40E_INSET_MASK_NUM_REG; i++) { + reg = I40E_READ_REG(hw, I40E_GLQF_FD_MSK(i, pctype)); + if (reg & I40E_GLQF_FD_MSK_FIELD) + count++; + } + if (count + num > I40E_INSET_MASK_NUM_REG) + return -EINVAL; + + for (i = count, j = 0; i < I40E_INSET_MASK_NUM_REG; i++, j++) + i40e_check_write_reg(hw, I40E_GLQF_FD_MSK(i, pctype), + mask_reg[j]); + } + + 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 = 0, input_set; + uint32_t mask_reg[I40E_INSET_MASK_NUM_REG]; + uint8_t num; + int ret; + + 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) { + PMD_DRV_LOG(ERR, "Not supported flow type (%u)", + conf->flow_type); + return -EINVAL; + } + if (filter != RTE_ETH_FILTER_HASH && filter != RTE_ETH_FILTER_FDIR) { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + return -EINVAL; + } + + ret = i40e_parse_input_set(&input_set, pctype, conf->field, + conf->inset_size); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to parse input set"); + return -EINVAL; + } + if (i40e_validate_input_set(pctype, filter, input_set) != 0) { + PMD_DRV_LOG(ERR, "Invalid input set"); + return -EINVAL; + } + + if (conf->op == RTE_ETH_INPUT_SET_ADD) { + inset_reg |= i40e_get_reg_inset(hw, filter, pctype); + } else if (conf->op != RTE_ETH_INPUT_SET_SELECT) { + PMD_DRV_LOG(ERR, "Unsupported input set operation"); + return -EINVAL; + } + num = i40e_generate_inset_mask_reg(input_set, mask_reg, + I40E_INSET_MASK_NUM_REG); + inset_reg |= i40e_translate_input_set_reg(input_set); + + if (filter == RTE_ETH_FILTER_HASH) { + ret = i40e_set_hash_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(0, pctype), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_GLQF_HASH_INSET(1, pctype), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else if (filter == RTE_ETH_FILTER_FDIR) { + ret = i40e_set_fd_inset_mask(hw, pctype, conf->op, mask_reg, + num); + if (ret) + return -EINVAL; + + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0), + (uint32_t)(inset_reg & UINT32_MAX)); + i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1), + (uint32_t)((inset_reg >> + I40E_32_BIT_WIDTH) & UINT32_MAX)); + } else { + PMD_DRV_LOG(ERR, "Not supported filter type (%u)", filter); + 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) { @@ -6069,6 +6805,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 de3b9d9..d480c26 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -107,6 +107,7 @@ enum i40e_flxpld_layer_idx { #define I40E_FDIR_BITMASK_NUM_WORD 2 /* max number of bitmask words */ #define I40E_FDIR_MAX_FLEXWORD_NUM 8 /* max number of flexpayload words */ #define I40E_FDIR_MAX_FLEX_LEN 16 /* len in bytes of flex payload */ +#define I40E_INSET_MASK_NUM_REG 2 /* number of input set mask registers */ /* i40e flags */ #define I40E_FLAG_RSS (1ULL << 0) @@ -541,6 +542,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); void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, struct rte_eth_rxq_info *qinfo); 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 770c76c..ae73c36 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,84 @@ 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_NONE = 65534, + RTE_ETH_INPUT_SET_MAX = 65535, +}; + +/** + * Filters input set operations + */ +enum rte_filter_input_set_op { + RTE_ETH_INPUT_SET_OP_UNKNOWN, + RTE_ETH_INPUT_SET_SELECT, /**< select input set */ + RTE_ETH_INPUT_SET_ADD, /**< add input set entry */ + RTE_ETH_INPUT_SET_OP_MAX +}; + + +/** + * 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]; + enum rte_filter_input_set_op op; +}; /** * A structure used to define the input for L2 flow @@ -535,7 +612,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 */ @@ -615,12 +692,37 @@ 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 FDIR filter information, to support filter type + * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation. + */ +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, @@ -628,6 +730,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, }; @@ -647,7 +751,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. @@ -672,6 +776,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; }; -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* [dpdk-dev] [PATCH v9 2/2] app/testpmd: add test commands for RSS/FD granularity 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 1/2] " Helin Zhang @ 2015-11-03 16:07 ` Helin Zhang 2015-11-03 23:25 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Thomas Monjalon 2 siblings, 0 replies; 37+ messages in thread From: Helin Zhang @ 2015-11-03 16:07 UTC (permalink / raw) To: dev Test commands are added to support selecting input set, or adding new input set per different pctype. Signed-off-by: Helin Zhang <helin.zhang@intel.com> Signed-off-by: Andrey Chilikin <andrey.chilikin@intel.com> --- app/test-pmd/cmdline.c | 218 ++++++++++++++++++++++++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 33 +++++ 2 files changed, 251 insertions(+) v3 changes: Support selecting more input set fields. v4 changes: Removed operation of 'delete'. Added test commands for FD granularity. v7 changes: Moved the documentation as part of this patch. diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0afdc96..6a384a2 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -692,6 +692,28 @@ static void cmd_help_long_parsed(void *parsed_result, "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)" " (enable|disable)\n" " Set the global configurations of hash filters.\n\n" + + "set_hash_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|" + "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|" + "ipv6-next-header|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|" + "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for hash.\n\n" + + "set_fdir_input_set (port_id) (ipv4|ipv4-frag|" + "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|" + "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|" + "l2_payload) (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|" + "udp-src-port|udp-dst-port|tcp-src-port|tcp-dst-port|" + "sctp-src-port|sctp-dst-port|sctp-veri-tag|fld-1st|" + "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|" + "fld-8th|none) (select|add)\n" + " Set the input set for FDir.\n\n" ); } } @@ -9205,6 +9227,200 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* Set hash input set */ +struct cmd_set_hash_input_set_result { + cmdline_fixed_string_t set_hash_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static enum rte_eth_input_set_field +str2inset(char *string) +{ + uint16_t i; + + static const struct { + char str[32]; + enum rte_eth_input_set_field inset; + } inset_table[] = { + {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN}, + {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN}, + {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4}, + {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4}, + {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS}, + {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO}, + {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6}, + {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6}, + {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC}, + {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER}, + {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT}, + {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT}, + {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT}, + {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT}, + {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT}, + {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT}, + {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG}, + {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY}, + {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY}, + {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD}, + {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD}, + {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD}, + {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD}, + {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD}, + {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD}, + {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD}, + {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD}, + {"none", RTE_ETH_INPUT_SET_NONE}, + }; + + for (i = 0; i < RTE_DIM(inset_table); i++) { + if (!strcmp(string, inset_table[i].str)) + return inset_table[i].inset; + } + + return RTE_ETH_INPUT_SET_UNKNOWN; +} + +static void +cmd_set_hash_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_hash_input_set_result *res = parsed_result; + struct rte_eth_hash_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_hash_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + set_hash_input_set, "set_hash_input_set"); +cmdline_parse_token_num_t cmd_set_hash_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_hash_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + inset_field, + "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#" + "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#" + "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#" + "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#" + "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#" + "fld-8th#none"); +cmdline_parse_token_string_t cmd_set_hash_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_hash_input_set = { + .f = cmd_set_hash_input_set_parsed, + .data = NULL, + .help_str = "set_hash_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|" + "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|" + "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|" + "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_hash_input_set_cmd, + (void *)&cmd_set_hash_input_set_port_id, + (void *)&cmd_set_hash_input_set_flow_type, + (void *)&cmd_set_hash_input_set_field, + (void *)&cmd_set_hash_input_set_select, + NULL, + }, +}; + +/* Set flow director input set */ +struct cmd_set_fdir_input_set_result { + cmdline_fixed_string_t set_fdir_input_set; + uint8_t port_id; + cmdline_fixed_string_t flow_type; + cmdline_fixed_string_t inset_field; + cmdline_fixed_string_t select; +}; + +static void +cmd_set_fdir_input_set_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_fdir_input_set_result *res = parsed_result; + struct rte_eth_fdir_filter_info info; + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(res->flow_type); + info.info.input_set_conf.field[0] = str2inset(res->inset_field); + info.info.input_set_conf.inset_size = 1; + if (!strcmp(res->select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(res->select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR, + RTE_ETH_FILTER_SET, &info); +} + +cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + set_fdir_input_set, "set_fdir_input_set"); +cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result, + port_id, UINT8); +cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + flow_type, + "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#" + "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_field = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + inset_field, + "src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#udp-src-port#udp-dst-port#" + "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#" + "sctp-veri-tag#fld-1st#fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#" + "fld-7th#fld-8th#none"); +cmdline_parse_token_string_t cmd_set_fdir_input_set_select = + TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result, + select, "select#add"); + +cmdline_parse_inst_t cmd_set_fdir_input_set = { + .f = cmd_set_fdir_input_set_parsed, + .data = NULL, + .help_str = "set_fdir_input_set <port_id> " + "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|ipv6-frag|" + "ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload " + "src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port|" + "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|" + "fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|" + "fld-7th|fld-8th|none select|add", + .tokens = { + (void *)&cmd_set_fdir_input_set_cmd, + (void *)&cmd_set_fdir_input_set_port_id, + (void *)&cmd_set_fdir_input_set_flow_type, + (void *)&cmd_set_fdir_input_set_field, + (void *)&cmd_set_fdir_input_set_select, + NULL, + }, +}; + /* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ struct cmd_mcast_addr_result { cmdline_fixed_string_t mcast_addr_cmd; @@ -9392,6 +9608,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_set_hash_input_set, + (cmdline_parse_inst_t *)&cmd_set_fdir_input_set, (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 2d0599d..75b0a57 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -1779,3 +1779,36 @@ Set the global configurations of hash filters:: For example, to enable simple_xor for flow type of ipv6 on port 2:: testpmd> set_hash_global_config 2 simple_xor ipv6 enable + +set_hash_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for hash:: + + set_hash_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other| \ + l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos| \ + ipv4-proto|ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + udp-key|gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th| \ + fld-8th|none) (select|add) + +For example, to add source IP to hash input set for flow type of ipv4 on port 0:: + + testpmd> set_hash_input_set 0 ipv4 src-ipv4 add + +set_fdir_input_set +~~~~~~~~~~~~~~~~~~ + +Set the input set for Fdir:: + + set_fdir_input_set (port_id) (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \ + ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload) + (src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|udp-src-port|udp-dst-port| \ + tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag| \ + fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|fld-8th|none) \ + (select|add) + +For example to add source IP to FD input set for flow type of ipv4 on port 0:: + + testpmd> set_fdir_input_set 0 ipv4 src-ipv4 add -- 1.9.3 ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 1/2] " Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang @ 2015-11-03 23:25 ` Thomas Monjalon 2 siblings, 0 replies; 37+ messages in thread From: Thomas Monjalon @ 2015-11-03 23:25 UTC (permalink / raw) To: Helin Zhang; +Cc: dev 2015-11-04 00:07, Helin Zhang: > The default input set of fields of a received packet are loaded from firmware, > which cannot be modified even users want to use different fields for RSS or > flow director. Here adds more flexibilities of selecting or adding packet > fields for hash calculation or flow director to users. It also includes the > modifications in testpmd to support the testing. Applied, thanks ^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2015-11-03 23:27 UTC | newest] Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-09-22 6:32 [dpdk-dev] [PATCH 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 1/2] i40e: add " Helin Zhang 2015-09-22 6:32 ` [dpdk-dev] [PATCH 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 1/2] i40e: add " Helin Zhang 2015-09-22 7:26 ` [dpdk-dev] [PATCH v2 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 0/2] i40e: RSS granularity configuration Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 1/2] i40e: add " Helin Zhang 2015-09-24 7:08 ` [dpdk-dev] [PATCH v3 2/2] app/testpmd: add test commands for RSS granularity Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 1/2] " Helin Zhang 2015-10-20 3:42 ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 1/2] " Helin Zhang 2015-10-29 4:09 ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 0/3] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 1/3] " Helin Zhang 2015-10-29 9:38 ` Bruce Richardson 2015-10-30 1:58 ` Zhang, Helin 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 2/3] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-29 6:02 ` [dpdk-dev] [PATCH v6 3/3] doc: update release notes and testpmd guide Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 1/2] " Helin Zhang 2015-10-30 13:46 ` Thomas Monjalon 2015-11-02 2:11 ` Zhang, Helin 2015-11-02 7:27 ` Thomas Monjalon 2015-11-02 7:59 ` Zhang, Helin 2015-11-02 8:23 ` Thomas Monjalon 2015-10-30 3:11 ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-10-30 7:59 ` [dpdk-dev] [PATCH v7 0/2] i40e: RSS/FD granularity configuration Wu, Jingjing 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 " Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 1/2] " Helin Zhang 2015-11-02 14:32 ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 1/2] " Helin Zhang 2015-11-03 16:07 ` [dpdk-dev] [PATCH v9 2/2] app/testpmd: add test commands for RSS/FD granularity Helin Zhang 2015-11-03 23:25 ` [dpdk-dev] [PATCH v9 0/2] i40e: RSS/FD granularity configuration Thomas Monjalon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).