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))
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,
#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
#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) \
#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,
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);
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);
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)) {
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;
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;
};
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 *
"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;
}
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;
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));
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;