From: Chengwen Feng Date: Tue, 22 Sep 2020 12:03:21 +0000 (+0800) Subject: net/hns3: support flow action of queue region X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f8e7fcbfd0b8d883343d11a5e621350362ad77ac;p=dpdk.git net/hns3: support flow action of queue region 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 Signed-off-by: Wei Hu (Xavier) --- diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c index 0299072efb..f7cfa00297 100644 --- a/drivers/net/hns3/hns3_cmd.c +++ b/drivers/net/hns3/hns3_cmd.c @@ -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)) diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 629b1148e2..510d68c555 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -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, diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 3f3f973c72..e1ed4d6086 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -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) \ diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c index 57299232c4..65ab19db76 100644 --- a/drivers/net/hns3/hns3_fdir.c +++ b/drivers/net/hns3/hns3_fdir.c @@ -29,20 +29,23 @@ #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)) { diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h index f7b4216136..a5760a3ccf 100644 --- a/drivers/net/hns3/hns3_fdir.h +++ b/drivers/net/hns3/hns3_fdir.h @@ -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; }; diff --git a/drivers/net/hns3/hns3_flow.c b/drivers/net/hns3/hns3_flow.c index 7ec46aef88..1bc591183f 100644 --- a/drivers/net/hns3/hns3_flow.c +++ b/drivers/net/hns3/hns3_flow.c @@ -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;