From: Xueming Li Date: Mon, 23 Apr 2018 12:33:00 +0000 (+0800) Subject: net/mlx5: support 16 hardware priorities X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=b43802b4bdfe5aeafe562d4093fd908f63acce48;p=dpdk.git net/mlx5: support 16 hardware priorities This patch supports new 16 Verbs flow priorities by trying to create a simple flow of priority 15. If 16 priorities not available, fallback to traditional 8 priorities. Verb priority mapping: 8 priorities >=16 priorities Control flow: 4-7 8-15 User normal flow: 1-3 4-7 User tunnel flow: 0-2 0-3 Signed-off-by: Xueming Li Acked-by: Nelio Laranjeiro --- diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 5f7ec12b86..24edcdab49 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -197,6 +197,7 @@ mlx5_dev_close(struct rte_eth_dev *dev) priv->txqs_n = 0; priv->txqs = NULL; } + mlx5_flow_delete_drop_queue(dev); if (priv->pd != NULL) { assert(priv->ctx != NULL); claim_zero(mlx5_glue->dealloc_pd(priv->pd)); @@ -622,6 +623,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, unsigned int cqe_comp; unsigned int tunnel_en = 0; unsigned int swp = 0; + unsigned int verb_priorities = 0; int idx; int i; struct mlx5dv_context attrs_out = {0}; @@ -1018,6 +1020,22 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, mlx5_link_update(eth_dev, 0); /* Store device configuration on private structure. */ priv->config = config; + /* Create drop queue. */ + err = mlx5_flow_create_drop_queue(eth_dev); + if (err) { + DRV_LOG(ERR, "port %u drop queue allocation failed: %s", + eth_dev->data->port_id, strerror(rte_errno)); + goto port_error; + } + /* Supported Verbs flow priority number detection. */ + if (verb_priorities == 0) + verb_priorities = mlx5_get_max_verbs_prio(eth_dev); + if (verb_priorities < MLX5_VERBS_FLOW_PRIO_8) { + DRV_LOG(ERR, "port %u wrong Verbs flow priorities: %u", + eth_dev->data->port_id, verb_priorities); + goto port_error; + } + priv->config.max_verbs_prio = verb_priorities; continue; port_error: if (priv) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 236e832064..a0c393ef9c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -90,6 +90,7 @@ struct mlx5_dev_config { unsigned int mpw_hdr_dseg:1; /* Enable DSEGs in the title WQEBB. */ unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */ unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */ + unsigned int max_verbs_prio; /* Number of Verb flow priorities. */ unsigned int tso_max_payload_sz; /* Maximum TCP payload for TSO. */ unsigned int ind_table_max_size; /* Maximum indirection table size. */ int txq_inline; /* Maximum packet size for inlining. */ @@ -106,6 +107,9 @@ enum mlx5_verbs_alloc_type { MLX5_VERBS_ALLOC_TYPE_RX_QUEUE, }; +/* 8 Verbs priorities. */ +#define MLX5_VERBS_FLOW_PRIO_8 8 + /** * Verbs allocator needs a context to know in the callback which kind of * resources it is allocating. @@ -256,6 +260,7 @@ int mlx5_traffic_restart(struct rte_eth_dev *dev); /* mlx5_flow.c */ +unsigned int mlx5_get_max_verbs_prio(struct rte_eth_dev *dev); int mlx5_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, const struct rte_flow_item items[], diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 41a7c64776..477705300a 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -31,8 +31,8 @@ #include "mlx5_prm.h" #include "mlx5_glue.h" -/* Define minimal priority for control plane flows. */ -#define MLX5_CTRL_FLOW_PRIORITY 4 +/* Flow priority for control plane flows. */ +#define MLX5_CTRL_FLOW_PRIORITY 1 /* Internet Protocol versions. */ #define MLX5_IPV4 4 @@ -128,7 +128,7 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_SRC_PORT_TCP | IBV_RX_HASH_DST_PORT_TCP), .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_TCP, - .flow_priority = 1, + .flow_priority = 0, .ip_version = MLX5_IPV4, }, [HASH_RXQ_UDPV4] = { @@ -137,7 +137,7 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_SRC_PORT_UDP | IBV_RX_HASH_DST_PORT_UDP), .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV4_UDP, - .flow_priority = 1, + .flow_priority = 0, .ip_version = MLX5_IPV4, }, [HASH_RXQ_IPV4] = { @@ -145,7 +145,7 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_DST_IPV4), .dpdk_rss_hf = (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4), - .flow_priority = 2, + .flow_priority = 1, .ip_version = MLX5_IPV4, }, [HASH_RXQ_TCPV6] = { @@ -154,7 +154,7 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_SRC_PORT_TCP | IBV_RX_HASH_DST_PORT_TCP), .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_TCP, - .flow_priority = 1, + .flow_priority = 0, .ip_version = MLX5_IPV6, }, [HASH_RXQ_UDPV6] = { @@ -163,7 +163,7 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_SRC_PORT_UDP | IBV_RX_HASH_DST_PORT_UDP), .dpdk_rss_hf = ETH_RSS_NONFRAG_IPV6_UDP, - .flow_priority = 1, + .flow_priority = 0, .ip_version = MLX5_IPV6, }, [HASH_RXQ_IPV6] = { @@ -171,13 +171,13 @@ const struct hash_rxq_init hash_rxq_init[] = { IBV_RX_HASH_DST_IPV6), .dpdk_rss_hf = (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6), - .flow_priority = 2, + .flow_priority = 1, .ip_version = MLX5_IPV6, }, [HASH_RXQ_ETH] = { .hash_fields = 0, .dpdk_rss_hf = 0, - .flow_priority = 3, + .flow_priority = 2, }, }; @@ -909,30 +909,50 @@ mlx5_flow_convert_allocate(unsigned int size, struct rte_flow_error *error) * Make inner packet matching with an higher priority from the non Inner * matching. * + * @param dev + * Pointer to Ethernet device. * @param[in, out] parser * Internal parser structure. * @param attr * User flow attribute. */ static void -mlx5_flow_update_priority(struct mlx5_flow_parse *parser, +mlx5_flow_update_priority(struct rte_eth_dev *dev, + struct mlx5_flow_parse *parser, const struct rte_flow_attr *attr) { + struct priv *priv = dev->data->dev_private; unsigned int i; + uint16_t priority; + /* 8 priorities >= 16 priorities + * Control flow: 4-7 8-15 + * User normal flow: 1-3 4-7 + * User tunnel flow: 0-2 0-3 + */ + priority = attr->priority * MLX5_VERBS_FLOW_PRIO_8; + if (priv->config.max_verbs_prio == MLX5_VERBS_FLOW_PRIO_8) + priority /= 2; + /* + * Lower non-tunnel flow Verbs priority 1 if only support 8 Verbs + * priorities, lower 4 otherwise. + */ + if (!parser->inner) { + if (priv->config.max_verbs_prio == MLX5_VERBS_FLOW_PRIO_8) + priority += 1; + else + priority += MLX5_VERBS_FLOW_PRIO_8 / 2; + } if (parser->drop) { - parser->queue[HASH_RXQ_ETH].ibv_attr->priority = - attr->priority + - hash_rxq_init[HASH_RXQ_ETH].flow_priority; + parser->queue[HASH_RXQ_ETH].ibv_attr->priority = priority + + hash_rxq_init[HASH_RXQ_ETH].flow_priority; return; } for (i = 0; i != hash_rxq_init_n; ++i) { - if (parser->queue[i].ibv_attr) { - parser->queue[i].ibv_attr->priority = - attr->priority + - hash_rxq_init[i].flow_priority - - (parser->inner ? 1 : 0); - } + if (!parser->queue[i].ibv_attr) + continue; + parser->queue[i].ibv_attr->priority = priority + + hash_rxq_init[i].flow_priority; } } @@ -1167,7 +1187,7 @@ mlx5_flow_convert(struct rte_eth_dev *dev, */ if (!parser->drop) mlx5_flow_convert_finalise(parser); - mlx5_flow_update_priority(parser, attr); + mlx5_flow_update_priority(dev, parser, attr); exit_free: /* Only verification is expected, all resources should be released. */ if (!parser->create) { @@ -3162,3 +3182,56 @@ mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, } return 0; } + +/** + * Detect number of Verbs flow priorities supported. + * + * @param dev + * Pointer to Ethernet device. + * + * @return + * number of supported Verbs flow priority. + */ +unsigned int +mlx5_get_max_verbs_prio(struct rte_eth_dev *dev) +{ + struct priv *priv = dev->data->dev_private; + unsigned int verb_priorities = MLX5_VERBS_FLOW_PRIO_8; + struct { + struct ibv_flow_attr attr; + struct ibv_flow_spec_eth eth; + struct ibv_flow_spec_action_drop drop; + } flow_attr = { + .attr = { + .num_of_specs = 2, + }, + .eth = { + .type = IBV_FLOW_SPEC_ETH, + .size = sizeof(struct ibv_flow_spec_eth), + }, + .drop = { + .size = sizeof(struct ibv_flow_spec_action_drop), + .type = IBV_FLOW_SPEC_ACTION_DROP, + }, + }; + struct ibv_flow *flow; + + do { + flow_attr.attr.priority = verb_priorities - 1; + flow = mlx5_glue->create_flow(priv->flow_drop_queue->qp, + &flow_attr.attr); + if (flow) { + claim_zero(mlx5_glue->destroy_flow(flow)); + /* Try more priorities. */ + verb_priorities *= 2; + } else { + /* Failed, restore last right number. */ + verb_priorities /= 2; + break; + } + } while (1); + DRV_LOG(DEBUG, "port %u Verbs flow priorities: %d," + " user flow priorities: %d", + dev->data->port_id, verb_priorities, MLX5_CTRL_FLOW_PRIORITY); + return verb_priorities; +} diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index ee08c56770..fc56d1ee81 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -148,12 +148,6 @@ mlx5_dev_start(struct rte_eth_dev *dev) int ret; dev->data->dev_started = 1; - ret = mlx5_flow_create_drop_queue(dev); - if (ret) { - DRV_LOG(ERR, "port %u drop queue allocation failed: %s", - dev->data->port_id, strerror(rte_errno)); - goto error; - } DRV_LOG(DEBUG, "port %u allocating and configuring hash Rx queues", dev->data->port_id); rte_mempool_walk(mlx5_mp2mr_iter, priv); @@ -202,7 +196,6 @@ error: mlx5_traffic_disable(dev); mlx5_txq_stop(dev); mlx5_rxq_stop(dev); - mlx5_flow_delete_drop_queue(dev); rte_errno = ret; /* Restore rte_errno. */ return -rte_errno; } @@ -237,7 +230,6 @@ mlx5_dev_stop(struct rte_eth_dev *dev) mlx5_rxq_stop(dev); for (mr = LIST_FIRST(&priv->mr); mr; mr = LIST_FIRST(&priv->mr)) mlx5_mr_release(mr); - mlx5_flow_delete_drop_queue(dev); } /**