-
- default:
- break;
- }
- }
-
- /* Get filter specification */
- if ((o_vlan_mask != NULL) && (o_vlan_mask->tci ==
- rte_cpu_to_be_16(I40E_TCI_MASK)) &&
- (i_vlan_mask != NULL) &&
- (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
- filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
- & I40E_TCI_MASK;
- filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
- & I40E_TCI_MASK;
- } else {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- NULL,
- "Invalid filter type");
- return -rte_errno;
- }
-
- filter->tunnel_type = I40E_TUNNEL_TYPE_QINQ;
- return 0;
-}
-
-static int
-i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
- const struct rte_flow_attr *attr,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error,
- union i40e_filter_t *filter)
-{
- struct i40e_tunnel_filter_conf *tunnel_filter =
- &filter->consistent_tunnel_filter;
- int ret;
-
- ret = i40e_flow_parse_qinq_pattern(dev, pattern,
- error, tunnel_filter);
- if (ret)
- return ret;
-
- ret = i40e_flow_parse_tunnel_action(dev, actions, error, tunnel_filter);
- if (ret)
- return ret;
-
- ret = i40e_flow_parse_attr(attr, error);
- if (ret)
- return ret;
-
- cons_filter_type = RTE_ETH_FILTER_TUNNEL;
-
- 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_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;
- rte_free(items);
- return 0;
- }
- }
-
- 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_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:
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Not support range");
- return -rte_errno;
- }
- }
-
- 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_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, tmp, nb_types;
- uint32_t index = 0;
- uint64_t hf_bit = 1;
-
- 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) {
- for (n = 0; n < 64; n++) {
- if (rss->types & (hf_bit << n)) {
- conf_info->region[0].hw_flowtype[0] = n;
- conf_info->region[0].flowtype_num = 1;
- conf_info->queue_region_number = 1;
- break;
- }
- }
- }
-
- /**
- * 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)) {