net/i40e: refactor RSS flow

1. Delete original code.
2. Add 2 tables(One maps flow pattern and RSS type to PCTYPE,
   another maps RSS type to input set).
3. Parse RSS pattern and RSS type to get PCTYPE.
4. Parse RSS action to get queues, RSS function and hash field.
5. Create and destroy RSS filters.
6. Create new files for hash flows.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
This commit is contained in:
Alvin Zhang 2021-01-08 13:35:40 +08:00 committed by Ferruh Yigit
parent c222d2a1d0
commit ef4c16fd91
6 changed files with 1627 additions and 1370 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,8 @@
#include "rte_pmd_i40e.h"
#include "base/i40e_register.h"
#include "base/i40e_type.h"
#include "base/virtchnl.h"
#define I40E_VLAN_TAG_SIZE 4
@ -1065,16 +1067,32 @@ struct i40e_customized_pctype {
};
struct i40e_rte_flow_rss_conf {
struct rte_flow_action_rss conf; /**< RSS parameters. */
uint16_t queue_region_conf; /**< Queue region config flag */
struct rte_flow_action_rss conf; /**< RSS parameters. */
uint8_t key[(I40E_VFQF_HKEY_MAX_INDEX > I40E_PFQF_HKEY_MAX_INDEX ?
I40E_VFQF_HKEY_MAX_INDEX : I40E_PFQF_HKEY_MAX_INDEX + 1) *
sizeof(uint32_t)]; /* Hash key. */
uint16_t queue[I40E_MAX_Q_PER_TC]; /**< Queues indices to use. */
bool valid; /* Check if it's valid */
};
sizeof(uint32_t)]; /**< Hash key. */
uint16_t queue[ETH_RSS_RETA_SIZE_512]; /**< Queues indices to use. */
TAILQ_HEAD(i40e_rss_conf_list, i40e_rss_filter);
bool symmetric_enable; /**< true, if enable symmetric */
uint64_t config_pctypes; /**< All PCTYPES with the flow */
uint64_t inset; /**< input sets */
uint8_t region_priority; /**< queue region priority */
uint8_t region_queue_num; /**< region queue number */
uint16_t region_queue_start; /**< region queue start */
uint32_t misc_reset_flags;
#define I40E_HASH_FLOW_RESET_FLAG_FUNC 0x01UL
#define I40E_HASH_FLOW_RESET_FLAG_KEY 0x02UL
#define I40E_HASH_FLOW_RESET_FLAG_QUEUE 0x04UL
#define I40E_HASH_FLOW_RESET_FLAG_REGION 0x08UL
/**< All PCTYPES that reset with the flow */
uint64_t reset_config_pctypes;
/**< Symmetric function should reset on PCTYPES */
uint64_t reset_symmetric_pctypes;
};
/* RSS filter list structure */
struct i40e_rss_filter {
@ -1082,6 +1100,8 @@ struct i40e_rss_filter {
struct i40e_rte_flow_rss_conf rss_filter_info;
};
TAILQ_HEAD(i40e_rss_conf_list, i40e_rss_filter);
struct i40e_vf_msg_cfg {
/* maximal VF message during a statistic period */
uint32_t max_msg;
@ -1136,6 +1156,8 @@ struct i40e_pf {
uint16_t fdir_qp_offset;
uint16_t hash_lut_size; /* The size of hash lookup table */
bool hash_filter_enabled;
uint64_t hash_enabled_queues;
/* input set bits for each pctype */
uint64_t hash_input_set[I40E_FILTER_PCTYPE_MAX];
/* store VXLAN UDP ports */
@ -1150,7 +1172,6 @@ struct i40e_pf {
struct i40e_fdir_info fdir; /* flow director info */
struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
struct i40e_rte_flow_rss_conf rss_info; /* RSS info */
struct i40e_rss_conf_list rss_config_list; /* RSS rule list */
struct i40e_queue_regions queue_region; /* queue region info */
struct i40e_fc_conf fc_conf; /* Flow control conf */
@ -1379,8 +1400,8 @@ int i40e_select_filter_input_set(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf,
enum rte_filter_type filter);
void i40e_fdir_filter_restore(struct i40e_pf *pf);
int i40e_hash_filter_inset_select(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf);
int i40e_set_hash_inset(struct i40e_hw *hw, uint64_t input_set,
uint32_t pctype, bool add);
int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode,
uint32_t retval, uint8_t *msg,
uint16_t msglen);
@ -1435,7 +1456,8 @@ int i40e_add_macvlan_filters(struct i40e_vsi *vsi,
bool is_device_supported(struct rte_eth_dev *dev, struct rte_pci_driver *drv);
bool is_i40e_supported(struct rte_eth_dev *dev);
bool is_i40evf_supported(struct rte_eth_dev *dev);
void i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw,
uint8_t enable);
int i40e_validate_input_set(enum i40e_filter_pctype pctype,
enum rte_filter_type filter, uint64_t inset);
int i40e_generate_inset_mask_reg(uint64_t inset, uint32_t *mask,
@ -1458,12 +1480,13 @@ int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
void i40e_flex_payload_reg_set_default(struct i40e_hw *hw);
void i40e_pf_disable_rss(struct i40e_pf *pf);
int i40e_pf_calc_configured_queues_num(struct i40e_pf *pf);
int i40e_pf_reset_rss_reta(struct i40e_pf *pf);
int i40e_pf_reset_rss_key(struct i40e_pf *pf);
int i40e_pf_config_rss(struct i40e_pf *pf);
int i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len);
int i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size);
int i40e_rss_conf_init(struct i40e_rte_flow_rss_conf *out,
const struct rte_flow_action_rss *in);
int i40e_config_rss_filter(struct i40e_pf *pf,
struct i40e_rte_flow_rss_conf *conf, bool add);
int i40e_vf_representor_init(struct rte_eth_dev *ethdev, void *init_params);
int i40e_vf_representor_uninit(struct rte_eth_dev *ethdev);

View File

@ -23,6 +23,7 @@
#include "base/i40e_type.h"
#include "base/i40e_prototype.h"
#include "i40e_ethdev.h"
#include "i40e_hash.h"
#define I40E_IPV6_TC_MASK (0xFF << I40E_FDIR_IPv6_TC_OFFSET)
#define I40E_IPV6_FRAG_HEADER 44
@ -118,7 +119,6 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
static int i40e_flow_flush_rss_filter(struct rte_eth_dev *dev);
static int
i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@ -4531,566 +4531,6 @@ i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
return ret;
}
/**
* This function is used to do configuration i40e existing RSS with rte_flow.
* It also enable queue region configuration using flow API for i40e.
* pattern can be used indicate what parameters will be include in flow,
* like user_priority or flowtype for queue region or HASH function for RSS.
* Action is used to transmit parameter like queue index and HASH
* function for RSS, or flowtype for queue region configuration.
* For example:
* pattern:
* Case 1: try to transform patterns to pctype. valid pctype will be
* used in parse action.
* Case 2: only ETH, indicate flowtype for queue region will be parsed.
* Case 3: only VLAN, indicate user_priority for queue region will be parsed.
* So, pattern choice is depened on the purpose of configuration of
* that flow.
* action:
* action RSS will be used to transmit valid parameter with
* struct rte_flow_action_rss for all the 3 case.
*/
static int
i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
struct i40e_rss_pattern_info *p_info,
struct i40e_queue_regions *info)
{
const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
const struct rte_flow_item *item = pattern;
enum rte_flow_item_type item_type;
struct rte_flow_item *items;
uint32_t item_num = 0; /* non-void item number of pattern*/
uint32_t i = 0;
static const struct {
enum rte_flow_item_type *item_array;
uint64_t type;
} i40e_rss_pctype_patterns[] = {
{ pattern_fdir_ipv4,
ETH_RSS_FRAG_IPV4 | ETH_RSS_NONFRAG_IPV4_OTHER },
{ pattern_fdir_ipv4_tcp, ETH_RSS_NONFRAG_IPV4_TCP },
{ pattern_fdir_ipv4_udp, ETH_RSS_NONFRAG_IPV4_UDP },
{ pattern_fdir_ipv4_sctp, ETH_RSS_NONFRAG_IPV4_SCTP },
{ pattern_fdir_ipv4_esp, ETH_RSS_ESP },
{ pattern_fdir_ipv4_udp_esp, ETH_RSS_ESP },
{ pattern_fdir_ipv6,
ETH_RSS_FRAG_IPV6 | ETH_RSS_NONFRAG_IPV6_OTHER },
{ pattern_fdir_ipv6_tcp, ETH_RSS_NONFRAG_IPV6_TCP },
{ pattern_fdir_ipv6_udp, ETH_RSS_NONFRAG_IPV6_UDP },
{ pattern_fdir_ipv6_sctp, ETH_RSS_NONFRAG_IPV6_SCTP },
{ pattern_ethertype, ETH_RSS_L2_PAYLOAD },
{ pattern_fdir_ipv6_esp, ETH_RSS_ESP },
{ pattern_fdir_ipv6_udp_esp, ETH_RSS_ESP },
};
p_info->types = I40E_RSS_TYPE_INVALID;
if (item->type == RTE_FLOW_ITEM_TYPE_END) {
p_info->types = I40E_RSS_TYPE_NONE;
return 0;
}
/* Convert pattern to RSS offload types */
while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
item_num++;
i++;
}
item_num++;
items = rte_zmalloc("i40e_pattern",
item_num * sizeof(struct rte_flow_item), 0);
if (!items) {
rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
NULL, "No memory for PMD internal items.");
return -ENOMEM;
}
i40e_pattern_skip_void_item(items, pattern);
for (i = 0; i < RTE_DIM(i40e_rss_pctype_patterns); i++) {
if (i40e_match_pattern(i40e_rss_pctype_patterns[i].item_array,
items)) {
p_info->types = i40e_rss_pctype_patterns[i].type;
break;
}
}
rte_free(items);
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item,
"Not support range");
return -rte_errno;
}
item_type = item->type;
switch (item_type) {
case RTE_FLOW_ITEM_TYPE_ETH:
p_info->action_flag = 1;
break;
case RTE_FLOW_ITEM_TYPE_VLAN:
vlan_spec = item->spec;
vlan_mask = item->mask;
if (vlan_spec && vlan_mask) {
if (vlan_mask->tci ==
rte_cpu_to_be_16(I40E_VLAN_TCI_MASK)) {
info->region[0].user_priority[0] =
(rte_be_to_cpu_16(
vlan_spec->tci) >> 13) & 0x7;
info->region[0].user_priority_num = 1;
info->queue_region_number = 1;
p_info->action_flag = 0;
}
}
break;
default:
p_info->action_flag = 0;
memset(info, 0, sizeof(struct i40e_queue_regions));
return 0;
}
}
return 0;
}
/**
* This function is used to parse RSS queue index, total queue number and
* hash functions, If the purpose of this configuration is for queue region
* configuration, it will set queue_region_conf flag to TRUE, else to FALSE.
* In queue region configuration, it also need to parse hardware flowtype
* and user_priority from configuration, it will also cheeck the validity
* of these parameters. For example, The queue region sizes should
* be any of the following values: 1, 2, 4, 8, 16, 32, 64, the
* hw_flowtype or PCTYPE max index should be 63, the user priority
* max index should be 7, and so on. And also, queue index should be
* continuous sequence and queue region index should be part of RSS
* queue index for this port.
* For hash params, the pctype in action and pattern must be same.
* Set queue index must be with non-types.
*/
static int
i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct i40e_rss_pattern_info p_info,
struct i40e_queue_regions *conf_info,
union i40e_filter_t *filter)
{
const struct rte_flow_action *act;
const struct rte_flow_action_rss *rss;
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_queue_regions *info = &pf->queue_region;
struct i40e_rte_flow_rss_conf *rss_config =
&filter->rss_conf;
struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;
uint16_t i, j, n, m, tmp, nb_types;
uint32_t index = 0;
uint64_t hf_bit = 1;
static const struct {
uint64_t rss_type;
enum i40e_filter_pctype pctype;
} pctype_match_table[] = {
{ETH_RSS_FRAG_IPV4,
I40E_FILTER_PCTYPE_FRAG_IPV4},
{ETH_RSS_NONFRAG_IPV4_TCP,
I40E_FILTER_PCTYPE_NONF_IPV4_TCP},
{ETH_RSS_NONFRAG_IPV4_UDP,
I40E_FILTER_PCTYPE_NONF_IPV4_UDP},
{ETH_RSS_NONFRAG_IPV4_SCTP,
I40E_FILTER_PCTYPE_NONF_IPV4_SCTP},
{ETH_RSS_NONFRAG_IPV4_OTHER,
I40E_FILTER_PCTYPE_NONF_IPV4_OTHER},
{ETH_RSS_FRAG_IPV6,
I40E_FILTER_PCTYPE_FRAG_IPV6},
{ETH_RSS_NONFRAG_IPV6_TCP,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP},
{ETH_RSS_NONFRAG_IPV6_UDP,
I40E_FILTER_PCTYPE_NONF_IPV6_UDP},
{ETH_RSS_NONFRAG_IPV6_SCTP,
I40E_FILTER_PCTYPE_NONF_IPV6_SCTP},
{ETH_RSS_NONFRAG_IPV6_OTHER,
I40E_FILTER_PCTYPE_NONF_IPV6_OTHER},
{ETH_RSS_L2_PAYLOAD,
I40E_FILTER_PCTYPE_L2_PAYLOAD},
};
static const struct {
uint64_t rss_type;
enum i40e_filter_pctype pctype;
} pctype_match_table_x722[] = {
{ETH_RSS_NONFRAG_IPV4_TCP,
I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK},
{ETH_RSS_NONFRAG_IPV4_UDP,
I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP},
{ETH_RSS_NONFRAG_IPV4_UDP,
I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP},
{ETH_RSS_NONFRAG_IPV6_TCP,
I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK},
{ETH_RSS_NONFRAG_IPV6_UDP,
I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP},
{ETH_RSS_NONFRAG_IPV6_UDP,
I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP},
};
NEXT_ITEM_OF_ACTION(act, actions, index);
rss = act->conf;
/**
* RSS only supports forwarding,
* check if the first not void action is RSS.
*/
if (act->type != RTE_FLOW_ACTION_TYPE_RSS) {
memset(rss_config, 0, sizeof(struct i40e_rte_flow_rss_conf));
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act, "Not supported action.");
return -rte_errno;
}
if (p_info.action_flag && rss->queue_num) {
for (j = 0; j < RTE_DIM(pctype_match_table); j++) {
if (rss->types & pctype_match_table[j].rss_type) {
conf_info->region[0].hw_flowtype[0] =
(uint8_t)pctype_match_table[j].pctype;
conf_info->region[0].flowtype_num = 1;
conf_info->queue_region_number = 1;
break;
}
}
if (hw->mac.type == I40E_MAC_X722)
for (j = 0; j < RTE_DIM(pctype_match_table_x722); j++) {
if (rss->types &
pctype_match_table_x722[j].rss_type) {
m = conf_info->region[0].flowtype_num;
conf_info->region[0].hw_flowtype[m] =
pctype_match_table_x722[j].pctype;
conf_info->region[0].flowtype_num++;
conf_info->queue_region_number = 1;
}
}
}
/**
* Do some queue region related parameters check
* in order to keep queue index for queue region to be
* continuous sequence and also to be part of RSS
* queue index for this port.
*/
if (conf_info->queue_region_number) {
for (i = 0; i < rss->queue_num; i++) {
for (j = 0; j < rss_info->conf.queue_num; j++) {
if (rss->queue[i] == rss_info->conf.queue[j])
break;
}
if (j == rss_info->conf.queue_num) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"no valid queues");
return -rte_errno;
}
}
for (i = 0; i < rss->queue_num - 1; i++) {
if (rss->queue[i + 1] != rss->queue[i] + 1) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"no valid queues");
return -rte_errno;
}
}
}
/* Parse queue region related parameters from configuration */
for (n = 0; n < conf_info->queue_region_number; n++) {
if (conf_info->region[n].user_priority_num ||
conf_info->region[n].flowtype_num) {
if (!((rte_is_power_of_2(rss->queue_num)) &&
rss->queue_num <= 64)) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
"total number of queues do not exceed the VSI allocation");
return -rte_errno;
}
if (conf_info->region[n].user_priority[n] >=
I40E_MAX_USER_PRIORITY) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"the user priority max index is 7");
return -rte_errno;
}
if (conf_info->region[n].hw_flowtype[n] >=
I40E_FILTER_PCTYPE_MAX) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"the hw_flowtype or PCTYPE max index is 63");
return -rte_errno;
}
for (i = 0; i < info->queue_region_number; i++) {
if (info->region[i].queue_num ==
rss->queue_num &&
info->region[i].queue_start_index ==
rss->queue[0])
break;
}
if (i == info->queue_region_number) {
if (i > I40E_REGION_MAX_INDEX) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"the queue region max index is 7");
return -rte_errno;
}
info->region[i].queue_num =
rss->queue_num;
info->region[i].queue_start_index =
rss->queue[0];
info->region[i].region_id =
info->queue_region_number;
j = info->region[i].user_priority_num;
tmp = conf_info->region[n].user_priority[0];
if (conf_info->region[n].user_priority_num) {
info->region[i].user_priority[j] = tmp;
info->region[i].user_priority_num++;
}
for (m = 0; m < conf_info->region[n].flowtype_num; m++) {
j = info->region[i].flowtype_num;
tmp = conf_info->region[n].hw_flowtype[m];
info->region[i].hw_flowtype[j] = tmp;
info->region[i].flowtype_num++;
}
info->queue_region_number++;
} else {
j = info->region[i].user_priority_num;
tmp = conf_info->region[n].user_priority[0];
if (conf_info->region[n].user_priority_num) {
info->region[i].user_priority[j] = tmp;
info->region[i].user_priority_num++;
}
for (m = 0; m < conf_info->region[n].flowtype_num; m++) {
j = info->region[i].flowtype_num;
tmp = conf_info->region[n].hw_flowtype[m];
info->region[i].hw_flowtype[j] = tmp;
info->region[i].flowtype_num++;
}
}
}
rss_config->queue_region_conf = TRUE;
}
/**
* Return function if this flow is used for queue region configuration
*/
if (rss_config->queue_region_conf)
return 0;
if (!rss) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"invalid rule");
return -rte_errno;
}
for (n = 0; n < rss->queue_num; n++) {
if (rss->queue[n] >= dev->data->nb_rx_queues) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act,
"queue id > max number of queues");
return -rte_errno;
}
}
if (rss->queue_num && (p_info.types || rss->types))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"RSS types must be empty while configuring queue region");
/* validate pattern and pctype */
if (!(rss->types & p_info.types) &&
(rss->types || p_info.types) && !rss->queue_num)
return rte_flow_error_set
(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
act, "invalid pctype");
nb_types = 0;
for (n = 0; n < RTE_ETH_FLOW_MAX; n++) {
if (rss->types & (hf_bit << n))
nb_types++;
if (nb_types > 1)
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
act, "multi pctype is not supported");
}
if (rss->func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR &&
(p_info.types || rss->types || rss->queue_num))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"pattern, type and queues must be empty while"
" setting hash function as simple_xor");
if (rss->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ &&
!(p_info.types && rss->types))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"pctype and queues can not be empty while"
" setting hash function as symmetric toeplitz");
/* Parse RSS related parameters from configuration */
if (rss->func >= RTE_ETH_HASH_FUNCTION_MAX ||
rss->func == RTE_ETH_HASH_FUNCTION_TOEPLITZ)
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"RSS hash functions are not supported");
if (rss->level)
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"a nonzero RSS encapsulation level is not supported");
if (rss->key_len && rss->key_len > RTE_DIM(rss_config->key))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"RSS hash key too large");
if (rss->queue_num > RTE_DIM(rss_config->queue))
return rte_flow_error_set
(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
"too many queues for RSS context");
if (i40e_rss_conf_init(rss_config, rss))
return rte_flow_error_set
(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, act,
"RSS context initialization failure");
index++;
/* check if the next not void action is END */
NEXT_ITEM_OF_ACTION(act, actions, index);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
memset(rss_config, 0, sizeof(struct i40e_rte_flow_rss_conf));
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
act, "Not supported action.");
return -rte_errno;
}
rss_config->queue_region_conf = FALSE;
return 0;
}
static int
i40e_parse_rss_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
union i40e_filter_t *filter,
struct rte_flow_error *error)
{
struct i40e_rss_pattern_info p_info;
struct i40e_queue_regions info;
int ret;
memset(&info, 0, sizeof(struct i40e_queue_regions));
memset(&p_info, 0, sizeof(struct i40e_rss_pattern_info));
ret = i40e_flow_parse_rss_pattern(dev, pattern,
error, &p_info, &info);
if (ret)
return ret;
ret = i40e_flow_parse_rss_action(dev, actions, error,
p_info, &info, filter);
if (ret)
return ret;
ret = i40e_flow_parse_attr(attr, error);
if (ret)
return ret;
cons_filter_type = RTE_ETH_FILTER_HASH;
return 0;
}
static int
i40e_config_rss_filter_set(struct rte_eth_dev *dev,
struct i40e_rte_flow_rss_conf *conf)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_rss_filter *rss_filter;
int ret;
if (conf->queue_region_conf) {
ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
} else {
ret = i40e_config_rss_filter(pf, conf, 1);
}
if (ret)
return ret;
rss_filter = rte_zmalloc("i40e_rss_filter",
sizeof(*rss_filter), 0);
if (rss_filter == NULL) {
PMD_DRV_LOG(ERR, "Failed to alloc memory.");
return -ENOMEM;
}
rss_filter->rss_filter_info = *conf;
/* the rule new created is always valid
* the existing rule covered by new rule will be set invalid
*/
rss_filter->rss_filter_info.valid = true;
TAILQ_INSERT_TAIL(&pf->rss_config_list, rss_filter, next);
return 0;
}
static int
i40e_config_rss_filter_del(struct rte_eth_dev *dev,
struct i40e_rte_flow_rss_conf *conf)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_rss_filter *rss_filter;
void *temp;
if (conf->queue_region_conf)
i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
else
i40e_config_rss_filter(pf, conf, 0);
TAILQ_FOREACH_SAFE(rss_filter, &pf->rss_config_list, next, temp) {
if (!memcmp(&rss_filter->rss_filter_info, conf,
sizeof(struct rte_flow_action_rss))) {
TAILQ_REMOVE(&pf->rss_config_list, rss_filter, next);
rte_free(rss_filter);
}
}
return 0;
}
static int
i40e_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@ -5131,9 +4571,13 @@ i40e_flow_validate(struct rte_eth_dev *dev,
i++;
if ((actions + i)->type == RTE_FLOW_ACTION_TYPE_RSS) {
ret = i40e_parse_rss_filter(dev, attr, pattern,
actions, &cons_filter, error);
return ret;
ret = i40e_flow_parse_attr(attr, error);
if (ret)
return ret;
cons_filter_type = RTE_ETH_FILTER_HASH;
return i40e_hash_parse(dev, pattern, actions + i,
&cons_filter.rss_conf, error);
}
i = 0;
@ -5248,12 +4692,11 @@ i40e_flow_create(struct rte_eth_dev *dev,
i40e_tunnel_filter_list);
break;
case RTE_ETH_FILTER_HASH:
ret = i40e_config_rss_filter_set(dev,
&cons_filter.rss_conf);
ret = i40e_hash_filter_create(pf, &cons_filter.rss_conf);
if (ret)
goto free_flow;
flow->rule = TAILQ_LAST(&pf->rss_config_list,
i40e_rss_conf_list);
i40e_rss_conf_list);
break;
default:
goto free_flow;
@ -5306,8 +4749,7 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
}
break;
case RTE_ETH_FILTER_HASH:
ret = i40e_config_rss_filter_del(dev,
&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);
ret = i40e_hash_filter_destroy(pf, flow->rule);
break;
default:
PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
@ -5455,14 +4897,11 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
return -rte_errno;
}
ret = i40e_flow_flush_rss_filter(dev);
if (ret) {
ret = i40e_hash_filter_flush(pf);
if (ret)
rte_flow_error_set(error, -ret,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
"Failed to flush RSS flows.");
return -rte_errno;
}
return ret;
}
@ -5582,36 +5021,6 @@ i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)
return ret;
}
/* remove the RSS filter */
static int
i40e_flow_flush_rss_filter(struct rte_eth_dev *dev)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct rte_flow *flow;
void *temp;
int32_t ret = -EINVAL;
ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
/* Delete RSS flows in flow list. */
TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
if (flow->filter_type != RTE_ETH_FILTER_HASH)
continue;
if (flow->rule) {
ret = i40e_config_rss_filter_del(dev,
&((struct i40e_rss_filter *)flow->rule)->rss_filter_info);
if (ret)
return ret;
}
TAILQ_REMOVE(&pf->flow_list, flow, node);
rte_free(flow);
}
return ret;
}
static int
i40e_flow_query(struct rte_eth_dev *dev __rte_unused,
struct rte_flow *flow,

1383
drivers/net/i40e/i40e_hash.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2020 Intel Corporation
*/
#ifndef _I40E_HASH_H_
#define _I40E_HASH_H_
#include <rte_ethdev.h>
#include <rte_flow.h>
#include "i40e_ethdev.h"
#ifdef __cplusplus
extern "C" {
#endif
int i40e_hash_parse(const struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
struct i40e_rte_flow_rss_conf *rss_conf,
struct rte_flow_error *error);
int i40e_hash_filter_create(struct i40e_pf *pf,
struct i40e_rte_flow_rss_conf *rss_conf);
int i40e_hash_filter_restore(struct i40e_pf *pf);
int i40e_hash_filter_destroy(struct i40e_pf *pf,
const struct i40e_rss_filter *rss_filter);
int i40e_hash_filter_flush(struct i40e_pf *pf);
#ifdef __cplusplus
}
#endif
#endif /* I40E_HASH_H_ */

View File

@ -17,6 +17,7 @@ sources = files(
'i40e_fdir.c',
'i40e_flow.c',
'i40e_tm.c',
'i40e_hash.c',
'i40e_vf_representor.c',
'rte_pmd_i40e.c'
)