]> git.droids-corp.org - dpdk.git/commitdiff
net/hns3: support flow action of queue region
authorChengwen Feng <fengchengwen@huawei.com>
Tue, 22 Sep 2020 12:03:21 +0000 (20:03 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Wed, 30 Sep 2020 17:19:11 +0000 (19:19 +0200)
Kunpeng 930 hardware support spread packets to region of queues which can
be configured by FDIR rule, it means user can create one FDIR rule which
action is one region of queues, and then RSS use the region info to spread
packets.

As we know, RTE_FLOW_ACTION_TYPE_RSS is used to spread packets among
several queues, user could config such as func/level/types/key/queue
parameter to control RSS function, so we provide this feature under the
RTE_FLOW_ACTION_TYPE_RSS framework.

Consider RSS input tuple don't have eth header, we use the following
rule to distinguish them (whether it's queue region configuration or
rss general configuration):
Case 1: pattern have ETH and action's queue_num > 0, indicate it is
queue region configuration.
Case other: rss general configuration.

So if user want to configure one flow which ipv4=192.168.1.192 spread to
queue region of queue 0/1/2/3, the patter should:
  RTE_FLOW_ITEM_TYPE_ETH with spec=last=mask=NULL
  RTE_FLOW_ITEM_TYPE_IPV4 with spec=192.168.1.192 last=mask=NULL
  RTE_FLOW_ITEM_TYPE_END
the action should:
  RTE_FLOW_ACTION_TYPE_RSS with queue_num=4 queue=0/1/2/3
  RTE_FLOW_ACTION_TYPE_END
after calling rte_flow_create, one FDIR rule will be created.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
drivers/net/hns3/hns3_cmd.c
drivers/net/hns3/hns3_cmd.h
drivers/net/hns3/hns3_ethdev.h
drivers/net/hns3/hns3_fdir.c
drivers/net/hns3/hns3_fdir.h
drivers/net/hns3/hns3_flow.c

index 0299072efbdd1ecb5bee589bc2f7c4cd716adccc..f7cfa00297028212608d8d1a42b948e6fc2e28ff 100644 (file)
@@ -433,8 +433,9 @@ static void hns3_parse_capability(struct hns3_hw *hw,
 
        if (hns3_get_bit(caps, HNS3_CAPS_UDP_GSO_B))
                hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_UDP_GSO_B, 1);
-       if (hns3_get_bit(caps, HNS3_CAPS_ADQ_B))
-               hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_ADQ_B, 1);
+       if (hns3_get_bit(caps, HNS3_CAPS_FD_QUEUE_REGION_B))
+               hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_FD_QUEUE_REGION_B,
+                            1);
        if (hns3_get_bit(caps, HNS3_CAPS_PTP_B))
                hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_PTP_B, 1);
        if (hns3_get_bit(caps, HNS3_CAPS_TX_PUSH_B))
index 629b1148e29a8f9ff222a81c9e7c91914072adeb..510d68c555f01b67e11d0aa23d4d811238fdc62a 100644 (file)
@@ -278,7 +278,7 @@ struct hns3_rx_priv_buff_cmd {
 enum HNS3_CAPS_BITS {
        HNS3_CAPS_UDP_GSO_B,
        HNS3_CAPS_ATR_B,
-       HNS3_CAPS_ADQ_B,
+       HNS3_CAPS_FD_QUEUE_REGION_B,
        HNS3_CAPS_PTP_B,
        HNS3_CAPS_INT_QL_B,
        HNS3_CAPS_SIMPLE_BD_B,
index 3f3f973c72ff533cc499d5da18248e713dba39ba..e1ed4d6086c047ec715c94d8b2fa588e7040e19b 100644 (file)
@@ -719,7 +719,7 @@ struct hns3_adapter {
 #define HNS3_DEV_SUPPORT_DCB_B                 0x0
 #define HNS3_DEV_SUPPORT_COPPER_B              0x1
 #define HNS3_DEV_SUPPORT_UDP_GSO_B             0x2
-#define HNS3_DEV_SUPPORT_ADQ_B                 0x3
+#define HNS3_DEV_SUPPORT_FD_QUEUE_REGION_B     0x3
 #define HNS3_DEV_SUPPORT_PTP_B                 0x4
 #define HNS3_DEV_SUPPORT_TX_PUSH_B             0x5
 #define HNS3_DEV_SUPPORT_INDEP_TXRX_B          0x6
@@ -736,9 +736,9 @@ struct hns3_adapter {
 #define hns3_dev_udp_gso_supported(hw) \
        hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_UDP_GSO_B)
 
-/* Support Application Device Queue */
-#define hns3_dev_adq_supported(hw) \
-       hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_ADQ_B)
+/* Support the queue region action rule of flow directory */
+#define hns3_dev_fd_queue_region_supported(hw) \
+       hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_FD_QUEUE_REGION_B)
 
 /* Support PTP timestamp offload */
 #define hns3_dev_ptp_supported(hw) \
index 57299232c4532138b40ba7c39c5b53d2686a6d95..65ab19db767d559bb85f838aa824755b340793a5 100644 (file)
 
 #define HNS3_FD_AD_DATA_S              32
 #define HNS3_FD_AD_DROP_B              0
-#define HNS3_FD_AD_DIRECT_QID_B        1
+#define HNS3_FD_AD_DIRECT_QID_B                1
 #define HNS3_FD_AD_QID_S               2
-#define HNS3_FD_AD_QID_M               GENMASK(12, 2)
+#define HNS3_FD_AD_QID_M               GENMASK(11, 2)
 #define HNS3_FD_AD_USE_COUNTER_B       12
 #define HNS3_FD_AD_COUNTER_NUM_S       13
-#define HNS3_FD_AD_COUNTER_NUM_M       GENMASK(20, 13)
+#define HNS3_FD_AD_COUNTER_NUM_M       GENMASK(19, 13)
 #define HNS3_FD_AD_NXT_STEP_B          20
 #define HNS3_FD_AD_NXT_KEY_S           21
-#define HNS3_FD_AD_NXT_KEY_M           GENMASK(26, 21)
-#define HNS3_FD_AD_WR_RULE_ID_B        0
+#define HNS3_FD_AD_NXT_KEY_M           GENMASK(25, 21)
+#define HNS3_FD_AD_WR_RULE_ID_B                0
 #define HNS3_FD_AD_RULE_ID_S           1
-#define HNS3_FD_AD_RULE_ID_M           GENMASK(13, 1)
-#define HNS3_FD_AD_COUNTER_HIGH_BIT     7
-#define HNS3_FD_AD_COUNTER_HIGH_BIT_B   26
+#define HNS3_FD_AD_RULE_ID_M           GENMASK(12, 1)
+#define HNS3_FD_AD_QUEUE_REGION_EN_B   16
+#define HNS3_FD_AD_QUEUE_REGION_SIZE_S 17
+#define HNS3_FD_AD_QUEUE_REGION_SIZE_M GENMASK(20, 17)
+#define HNS3_FD_AD_COUNTER_HIGH_BIT    7
+#define HNS3_FD_AD_COUNTER_HIGH_BIT_B  26
 
 enum HNS3_PORT_TYPE {
        HOST_PORT,
@@ -426,13 +429,19 @@ static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
                     action->write_rule_id_to_bd);
        hns3_set_field(ad_data, HNS3_FD_AD_RULE_ID_M, HNS3_FD_AD_RULE_ID_S,
                       action->rule_id);
+       if (action->nb_queues > 1) {
+               hns3_set_bit(ad_data, HNS3_FD_AD_QUEUE_REGION_EN_B, 1);
+               hns3_set_field(ad_data, HNS3_FD_AD_QUEUE_REGION_SIZE_M,
+                              HNS3_FD_AD_QUEUE_REGION_SIZE_S,
+                              rte_log2_u32(action->nb_queues));
+       }
        /* set extend bit if counter_id is in [128 ~ 255] */
        if (action->counter_id & BIT(HNS3_FD_AD_COUNTER_HIGH_BIT))
                hns3_set_bit(ad_data, HNS3_FD_AD_COUNTER_HIGH_BIT_B, 1);
        ad_data <<= HNS3_FD_AD_DATA_S;
        hns3_set_bit(ad_data, HNS3_FD_AD_DROP_B, action->drop_packet);
-       hns3_set_bit(ad_data, HNS3_FD_AD_DIRECT_QID_B,
-                    action->forward_to_direct_queue);
+       if (action->nb_queues == 1)
+               hns3_set_bit(ad_data, HNS3_FD_AD_DIRECT_QID_B, 1);
        hns3_set_field(ad_data, HNS3_FD_AD_QID_M, HNS3_FD_AD_QID_S,
                       action->queue_id);
        hns3_set_bit(ad_data, HNS3_FD_AD_USE_COUNTER_B, action->use_counter);
@@ -440,7 +449,7 @@ static int hns3_fd_ad_config(struct hns3_hw *hw, int loc,
                       HNS3_FD_AD_COUNTER_NUM_S, action->counter_id);
        hns3_set_bit(ad_data, HNS3_FD_AD_NXT_STEP_B, action->use_next_stage);
        hns3_set_field(ad_data, HNS3_FD_AD_NXT_KEY_M, HNS3_FD_AD_NXT_KEY_S,
-                      action->counter_id);
+                      action->next_input_key);
 
        req->ad_data = rte_cpu_to_le_64(ad_data);
        ret = hns3_cmd_send(hw, &desc, 1);
@@ -752,12 +761,12 @@ static int hns3_config_action(struct hns3_hw *hw, struct hns3_fdir_rule *rule)
 
        if (rule->action == HNS3_FD_ACTION_DROP_PACKET) {
                ad_data.drop_packet = true;
-               ad_data.forward_to_direct_queue = false;
                ad_data.queue_id = 0;
+               ad_data.nb_queues = 0;
        } else {
                ad_data.drop_packet = false;
-               ad_data.forward_to_direct_queue = true;
                ad_data.queue_id = rule->queue_id;
+               ad_data.nb_queues = rule->nb_queues;
        }
 
        if (unlikely(rule->flags & HNS3_RULE_FLAG_COUNTER)) {
index f7b4216136f0abc2d42101cc9f48a59fc0ff3952..a5760a3ccf0004a630f58b04fbbfb171e4c6e236 100644 (file)
@@ -104,8 +104,18 @@ struct hns3_fd_rule_tuples {
 struct hns3_fd_ad_data {
        uint16_t ad_id;
        uint8_t drop_packet;
-       uint8_t forward_to_direct_queue;
+       /*
+        * equal 0 when action is drop.
+        * index of queue when action is queue.
+        * index of first queue of queue region when action is queue region.
+        */
        uint16_t queue_id;
+       /*
+        * equal 0 when action is drop.
+        * equal 1 when action is queue.
+        * numbers of queues of queue region when action is queue region.
+        */
+       uint16_t nb_queues;
        uint8_t use_counter;
        uint8_t counter_id;
        uint8_t use_next_stage;
@@ -141,7 +151,18 @@ struct hns3_fdir_rule {
        uint8_t action;
        /* VF id, avaiblable when flags with HNS3_RULE_FLAG_VF_ID. */
        uint8_t vf_id;
+       /*
+        * equal 0 when action is drop.
+        * index of queue when action is queue.
+        * index of first queue of queue region when action is queue region.
+        */
        uint16_t queue_id;
+       /*
+        * equal 0 when action is drop.
+        * equal 1 when action is queue.
+        * numbers of queues of queue region when action is queue region.
+        */
+       uint16_t nb_queues;
        uint16_t location;
        struct rte_flow_action_count act_cnt;
 };
index 7ec46aef88a513096ae915dd705ef20f59151bb7..1bc591183f6ad1dbc81bdbcc40d11fab43c89a08 100644 (file)
@@ -90,16 +90,56 @@ net_addr_to_host(uint32_t *dst, const rte_be32_t *src, size_t len)
                dst[i] = rte_be_to_cpu_32(src[i]);
 }
 
-static inline const struct rte_flow_action *
-find_rss_action(const struct rte_flow_action actions[])
+/*
+ * This function is used to find rss general action.
+ * 1. As we know RSS is used to spread packets among several queues, the flow
+ *    API provide the struct rte_flow_action_rss, user could config it's field
+ *    sush as: func/level/types/key/queue to control RSS function.
+ * 2. The flow API also support queue region configuration for hns3. It was
+ *    implemented by FDIR + RSS in hns3 hardware, user can create one FDIR rule
+ *    which action is RSS queues region.
+ * 3. When action is RSS, we use the following rule to distinguish:
+ *    Case 1: pattern have ETH and action's queue_num > 0, indicate it is queue
+ *            region configuration.
+ *    Case other: an rss general action.
+ */
+static const struct rte_flow_action *
+hns3_find_rss_general_action(const struct rte_flow_item pattern[],
+                            const struct rte_flow_action actions[])
 {
-       const struct rte_flow_action *next = &actions[0];
+       const struct rte_flow_action *act = NULL;
+       const struct hns3_rss_conf *rss;
+       bool have_eth = false;
 
-       for (; next->type != RTE_FLOW_ACTION_TYPE_END; next++) {
-               if (next->type == RTE_FLOW_ACTION_TYPE_RSS)
-                       return next;
+       for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+               if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {
+                       act = actions;
+                       break;
+               }
        }
-       return NULL;
+       if (!act)
+               return NULL;
+
+       for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
+               if (pattern->type == RTE_FLOW_ITEM_TYPE_ETH) {
+                       have_eth = true;
+                       break;
+               }
+       }
+
+       rss = act->conf;
+       if (have_eth && rss->conf.queue_num) {
+               /*
+                * Patter have ETH and action's queue_num > 0, indicate this is
+                * queue region configuration.
+                * Because queue region is implemented by FDIR + RSS in hns3
+                * hardware, it need enter FDIR process, so here return NULL to
+                * avoid enter RSS process.
+                */
+               return NULL;
+       }
+
+       return act;
 }
 
 static inline struct hns3_flow_counter *
@@ -233,11 +273,53 @@ hns3_handle_action_queue(struct rte_eth_dev *dev,
                          "available queue (%d) in driver.",
                          queue->index, hw->used_rx_queues);
                return rte_flow_error_set(error, EINVAL,
-                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
-                                         "Invalid queue ID in PF");
+                                         RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+                                         action, "Invalid queue ID in PF");
        }
 
        rule->queue_id = queue->index;
+       rule->nb_queues = 1;
+       rule->action = HNS3_FD_ACTION_ACCEPT_PACKET;
+       return 0;
+}
+
+static int
+hns3_handle_action_queue_region(struct rte_eth_dev *dev,
+                               const struct rte_flow_action *action,
+                               struct hns3_fdir_rule *rule,
+                               struct rte_flow_error *error)
+{
+       struct hns3_adapter *hns = dev->data->dev_private;
+       const struct rte_flow_action_rss *conf = action->conf;
+       struct hns3_hw *hw = &hns->hw;
+       uint16_t idx;
+
+       if (!hns3_dev_fd_queue_region_supported(hw))
+               return rte_flow_error_set(error, ENOTSUP,
+                       RTE_FLOW_ERROR_TYPE_ACTION, action,
+                       "Not support config queue region!");
+
+       if ((!rte_is_power_of_2(conf->queue_num)) ||
+               conf->queue_num > hw->rss_size_max ||
+               conf->queue[0] >= hw->used_rx_queues ||
+               conf->queue[0] + conf->queue_num > hw->used_rx_queues) {
+               return rte_flow_error_set(error, EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ACTION_CONF, action,
+                       "Invalid start queue ID and queue num! the start queue "
+                       "ID must valid, the queue num must be power of 2 and "
+                       "<= rss_size_max.");
+       }
+
+       for (idx = 1; idx < conf->queue_num; idx++) {
+               if (conf->queue[idx] != conf->queue[idx - 1] + 1)
+                       return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION_CONF, action,
+                               "Invalid queue ID sequence! the queue ID "
+                               "must be continuous increment.");
+       }
+
+       rule->queue_id = conf->queue[0];
+       rule->nb_queues = conf->queue_num;
        rule->action = HNS3_FD_ACTION_ACCEPT_PACKET;
        return 0;
 }
@@ -274,6 +356,19 @@ hns3_handle_actions(struct rte_eth_dev *dev,
                case RTE_FLOW_ACTION_TYPE_DROP:
                        rule->action = HNS3_FD_ACTION_DROP_PACKET;
                        break;
+               /*
+                * Here RSS's real action is queue region.
+                * Queue region is implemented by FDIR + RSS in hns3 hardware,
+                * the FDIR's action is one queue region (start_queue_id and
+                * queue_num), then RSS spread packets to the queue region by
+                * RSS algorigthm.
+                */
+               case RTE_FLOW_ACTION_TYPE_RSS:
+                       ret = hns3_handle_action_queue_region(dev, actions,
+                                                             rule, error);
+                       if (ret)
+                               return ret;
+                       break;
                case RTE_FLOW_ACTION_TYPE_MARK:
                        mark =
                            (const struct rte_flow_action_mark *)actions->conf;
@@ -1629,7 +1724,7 @@ hns3_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
        if (ret)
                return ret;
 
-       if (find_rss_action(actions))
+       if (hns3_find_rss_general_action(pattern, actions))
                return hns3_parse_rss_filter(dev, actions, error);
 
        memset(&fdir_rule, 0, sizeof(struct hns3_fdir_rule));
@@ -1684,7 +1779,7 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
        flow_node->flow = flow;
        TAILQ_INSERT_TAIL(&process_list->flow_list, flow_node, entries);
 
-       act = find_rss_action(actions);
+       act = hns3_find_rss_general_action(pattern, actions);
        if (act) {
                rss_conf = act->conf;