ethdev: add hash function to RSS flow API action
[dpdk.git] / drivers / net / i40e / i40e_flow.c
index a32ad9b..897989b 100644 (file)
@@ -2401,7 +2401,7 @@ i40e_flow_fdir_get_pctype_value(struct i40e_pf *pf,
                break;
        }
 
-       if (cus_pctype)
+       if (cus_pctype && cus_pctype->valid)
                return cus_pctype->pctype;
 
        return I40E_FILTER_PCTYPE_INVALID;
@@ -4171,6 +4171,19 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,
        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.
+ */
 static int
 i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                            const struct rte_flow_action *actions,
@@ -4207,7 +4220,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 
        if (action_flag) {
                for (n = 0; n < 64; n++) {
-                       if (rss->rss_conf->rss_hf & (hf_bit << 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;
@@ -4216,13 +4229,19 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                }
        }
 
+       /**
+        * 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->num; i++) {
-                       for (j = 0; j < rss_info->num; j++) {
-                               if (rss->queue[i] == rss_info->queue[j])
+               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->num) {
+                       if (j == rss_info->conf.queue_num) {
                                rte_flow_error_set(error, EINVAL,
                                        RTE_FLOW_ERROR_TYPE_ACTION,
                                        act,
@@ -4231,7 +4250,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                        }
                }
 
-               for (i = 0; i < rss->num - 1; i++) {
+               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,
@@ -4242,41 +4261,41 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                }
        }
 
+       /* 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->num)) &&
-                                       rss->num <= 64)) {
-                               PMD_DRV_LOG(ERR, "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");
+                       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) {
-                               PMD_DRV_LOG(ERR, "the user priority max index is 7");
+                               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) {
-                               PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
-                               return -rte_errno;
-                       }
-
-                       if (rss_info->num < rss->num ||
-                               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,
                                        RTE_FLOW_ERROR_TYPE_ACTION,
                                        act,
-                                       "no valid queues");
+                                       "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->num &&
+                               if (info->region[i].queue_num ==
+                                   rss->queue_num &&
                                        info->region[i].queue_start_index ==
                                                rss->queue[0])
                                        break;
@@ -4284,12 +4303,15 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 
                        if (i == info->queue_region_number) {
                                if (i > I40E_REGION_MAX_INDEX) {
-                                       PMD_DRV_LOG(ERR, "the queue region max index is 7");
+                                       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->num;
+                                       rss->queue_num;
                                info->region[i].queue_start_index =
                                        rss->queue[0];
                                info->region[i].region_id =
@@ -4329,10 +4351,13 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                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 || !rss->num) {
+       if (!rss || !rss->queue_num) {
                rte_flow_error_set(error, EINVAL,
                                RTE_FLOW_ERROR_TYPE_ACTION,
                                act,
@@ -4340,7 +4365,7 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                return -rte_errno;
        }
 
-       for (n = 0; n < rss->num; n++) {
+       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,
@@ -4349,15 +4374,25 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
                        return -rte_errno;
                }
        }
-       if (rss->rss_conf)
-               rss_config->rss_conf = *rss->rss_conf;
-       else
-               rss_config->rss_conf.rss_hf =
-                       pf->adapter->flow_types_mask;
 
-       for (n = 0; n < rss->num; ++n)
-               rss_config->queue[n] = rss->queue[n];
-       rss_config->num = rss->num;
+       /* Parse RSS related parameters from configuration */
+       if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT)
+               return rte_flow_error_set
+                       (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
+                        "non-default RSS hash functions are 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 */
@@ -4877,7 +4912,7 @@ i40e_flow_flush_rss_filter(struct rte_eth_dev *dev)
 
        ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
 
-       if (rss_info->num)
+       if (rss_info->conf.queue_num)
                ret = i40e_config_rss_filter(pf, rss_info, FALSE);
        return ret;
 }