net/i40e: fix flow RSS queue index check
[dpdk.git] / drivers / net / i40e / i40e_flow.c
index 8bf1304..a32ad9b 100644 (file)
@@ -1939,7 +1939,8 @@ static uint16_t
 i40e_get_outer_vlan(struct rte_eth_dev *dev)
 {
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-       int qinq = dev->data->dev_conf.rxmode.hw_vlan_extend;
+       int qinq = dev->data->dev_conf.rxmode.offloads &
+               DEV_RX_OFFLOAD_VLAN_EXTEND;
        uint64_t reg_r = 0;
        uint16_t reg_id;
        uint16_t tpid;
@@ -2260,6 +2261,7 @@ i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
                          (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
                          (layer_idx * I40E_MAX_FLXPLD_FIED);
                I40E_WRITE_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
+               i40e_global_cfg_warning(I40E_WARNING_ENA_FLX_PLD);
        }
 
        /* Set flex pit */
@@ -2850,6 +2852,14 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                return -rte_errno;
                        }
 
+                       if (pf->support_multi_driver) {
+                               rte_flow_error_set(error, ENOTSUP,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "Unsupported flexible payload.");
+                               return -rte_errno;
+                       }
+
                        ret = i40e_flow_check_raw_item(item, raw_spec, error);
                        if (ret < 0)
                                return ret;
@@ -4141,7 +4151,8 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,
                                if (vlan_mask->tci ==
                                        rte_cpu_to_be_16(I40E_TCI_MASK)) {
                                        info->region[0].user_priority[0] =
-                                               (vlan_spec->tci >> 13) & 0x7;
+                                               (rte_be_to_cpu_16(
+                                               vlan_spec->tci) >> 13) & 0x7;
                                        info->region[0].user_priority_num = 1;
                                        info->queue_region_number = 1;
                                        *action_flag = 0;
@@ -4205,6 +4216,32 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                }
        }
 
+       if (conf_info->queue_region_number) {
+               for (i = 0; i < rss->num; i++) {
+                       for (j = 0; j < rss_info->num; j++) {
+                               if (rss->queue[i] == rss_info->queue[j])
+                                       break;
+                       }
+                       if (j == rss_info->num) {
+                               rte_flow_error_set(error, EINVAL,
+                                       RTE_FLOW_ERROR_TYPE_ACTION,
+                                       act,
+                                       "no valid queues");
+                               return -rte_errno;
+                       }
+               }
+
+               for (i = 0; i < rss->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;
+                       }
+               }
+       }
+
        for (n = 0; n < conf_info->queue_region_number; n++) {
                if (conf_info->region[n].user_priority_num ||
                                conf_info->region[n].flowtype_num) {
@@ -4228,7 +4265,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                        }
 
                        if (rss_info->num < rss->num ||
-                               rss_info->queue[0] < rss->queue[0] ||
+                               rss->queue[0] < rss_info->queue[0] ||
                                (rss->queue[0] + rss->num >
                                        rss_info->num + rss_info->queue[0])) {
                                rte_flow_error_set(error, EINVAL,
@@ -4376,14 +4413,15 @@ i40e_config_rss_filter_set(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);
+       int ret;
 
        if (conf->queue_region_conf) {
-               i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+               ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
                conf->queue_region_conf = 0;
        } else {
-               i40e_config_rss_filter(pf, conf, 1);
+               ret = i40e_config_rss_filter(pf, conf, 1);
        }
-       return 0;
+       return ret;
 }
 
 static int
@@ -4536,6 +4574,8 @@ i40e_flow_create(struct rte_eth_dev *dev,
        case RTE_ETH_FILTER_HASH:
                ret = i40e_config_rss_filter_set(dev,
                            &cons_filter.rss_conf);
+               if (ret)
+                       goto free_flow;
                flow->rule = &pf->rss_info;
                break;
        default: