X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_verbs.c;h=1627c3905fa4e3b8205dc5993186643aee4556ed;hb=250e2ed8d85d038ce864052ebd6f9af51db40df2;hp=710622ce92e6d57671f317d8870accdcda43b7ab;hpb=2b5b1aeb39d0b7be0c14a637186a28c12c01c630;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c index 710622ce92..1627c3905f 100644 --- a/drivers/net/mlx5/mlx5_flow_verbs.c +++ b/drivers/net/mlx5/mlx5_flow_verbs.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -23,7 +23,7 @@ #include "mlx5_defs.h" #include "mlx5.h" #include "mlx5_flow.h" -#include "mlx5_rxtx.h" +#include "mlx5_rx.h" #define VERBS_SPEC_INNER(item_flags) \ (!!((item_flags) & MLX5_FLOW_LAYER_TUNNEL) ? IBV_FLOW_SPEC_INNER : 0) @@ -39,6 +39,12 @@ static const uint32_t priority_map_5[][MLX5_PRIORITY_MAP_MAX] = { { 9, 10, 11 }, { 12, 13, 14 }, }; +/* Verbs specification header. */ +struct ibv_spec_header { + enum ibv_flow_spec_type type; + uint16_t size; +}; + /** * Discover the maximum number of priority available. * @@ -72,12 +78,12 @@ mlx5_flow_discover_priorities(struct rte_eth_dev *dev) }, }; struct ibv_flow *flow; - struct mlx5_hrxq *drop = mlx5_drop_action_create(dev); + struct mlx5_hrxq *drop = priv->drop_queue.hrxq; uint16_t vprio[] = { 8, 16 }; int i; int priority = 0; - if (!drop) { + if (!drop->qp) { rte_errno = ENOTSUP; return -rte_errno; } @@ -89,7 +95,6 @@ mlx5_flow_discover_priorities(struct rte_eth_dev *dev) claim_zero(mlx5_glue->destroy_flow(flow)); priority = vprio[i]; } - mlx5_drop_action_destroy(dev); switch (priority) { case 8: priority = RTE_DIM(priority_map_3); @@ -104,8 +109,11 @@ mlx5_flow_discover_priorities(struct rte_eth_dev *dev) dev->data->port_id, priority); return -rte_errno; } - DRV_LOG(INFO, "port %u flow maximum priority: %d", - dev->data->port_id, priority); + DRV_LOG(INFO, "port %u supported flow priorities:" + " 0-%d for ingress or egress root table," + " 0-%d for non-root table or transfer root table.", + dev->data->port_id, priority - 2, + MLX5_NON_ROOT_FLOW_MAX_PRIO - 1); return priority; } @@ -242,8 +250,6 @@ flow_verbs_counter_create(struct rte_eth_dev *dev, * * @param[in] dev * Pointer to the Ethernet device structure. - * @param[in] shared - * Indicate if this counter is shared with other flows. * @param[in] id * Counter identifier. * @@ -251,21 +257,17 @@ flow_verbs_counter_create(struct rte_eth_dev *dev, * Index to the counter, 0 otherwise and rte_errno is set. */ static uint32_t -flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id) +flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t id __rte_unused) { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; struct mlx5_flow_counter_pool *pool = NULL; struct mlx5_flow_counter *cnt = NULL; - union mlx5_l3t_data data; uint32_t n_valid = cmng->n_valid; uint32_t pool_idx, cnt_idx; uint32_t i; int ret; - if (shared && !mlx5_l3t_get_entry(priv->sh->cnt_id_tbl, id, &data) && - data.dword) - return data.dword; for (pool_idx = 0; pool_idx < n_valid; ++pool_idx) { pool = cmng->pools[pool_idx]; if (!pool) @@ -312,13 +314,6 @@ flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id) TAILQ_REMOVE(&pool->counters[0], cnt, next); i = MLX5_CNT_ARRAY_IDX(pool, cnt); cnt_idx = MLX5_MAKE_CNT_IDX(pool_idx, i); - if (shared) { - data.dword = cnt_idx; - if (mlx5_l3t_set_entry(priv->sh->cnt_id_tbl, id, &data)) - return 0; - cnt->shared_info.id = id; - cnt_idx |= MLX5_CNT_SHARED_OFFSET; - } /* Create counter with Verbs. */ ret = flow_verbs_counter_create(dev, cnt); if (!ret) { @@ -344,14 +339,10 @@ flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id) static void flow_verbs_counter_release(struct rte_eth_dev *dev, uint32_t counter) { - struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_counter_pool *pool; struct mlx5_flow_counter *cnt; cnt = flow_verbs_counter_get_by_idx(dev, counter, &pool); - if (IS_SHARED_CNT(counter) && - mlx5_l3t_clear_entry(priv->sh->cnt_id_tbl, cnt->shared_info.id)) - return; #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) claim_zero(mlx5_glue->destroy_counter_set ((struct ibv_counter_set *)cnt->dcs_when_active)); @@ -1190,8 +1181,7 @@ flow_verbs_translate_action_count(struct mlx5_flow *dev_flow, #endif if (!flow->counter) { - flow->counter = flow_verbs_counter_new(dev, count->shared, - count->id); + flow->counter = flow_verbs_counter_new(dev, count->id); if (!flow->counter) return rte_flow_error_set(error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION, @@ -1248,6 +1238,8 @@ flow_verbs_validate(struct rte_eth_dev *dev, uint64_t last_item = 0; uint8_t next_protocol = 0xff; uint16_t ether_type = 0; + bool is_empty_vlan = false; + uint16_t udp_dport = 0; if (items == NULL) return -1; @@ -1263,7 +1255,7 @@ flow_verbs_validate(struct rte_eth_dev *dev, break; case RTE_FLOW_ITEM_TYPE_ETH: ret = mlx5_flow_validate_item_eth(items, item_flags, - error); + false, error); if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : @@ -1275,6 +1267,8 @@ flow_verbs_validate(struct rte_eth_dev *dev, ether_type &= ((const struct rte_flow_item_eth *) items->mask)->type; + if (ether_type == RTE_BE16(RTE_ETHER_TYPE_VLAN)) + is_empty_vlan = true; ether_type = rte_be_to_cpu_16(ether_type); } else { ether_type = 0; @@ -1300,6 +1294,7 @@ flow_verbs_validate(struct rte_eth_dev *dev, } else { ether_type = 0; } + is_empty_vlan = false; break; case RTE_FLOW_ITEM_TYPE_IPV4: ret = mlx5_flow_validate_item_ipv4 @@ -1352,6 +1347,15 @@ flow_verbs_validate(struct rte_eth_dev *dev, ret = mlx5_flow_validate_item_udp(items, item_flags, next_protocol, error); + const struct rte_flow_item_udp *spec = items->spec; + const struct rte_flow_item_udp *mask = items->mask; + if (!mask) + mask = &rte_flow_item_udp_mask; + if (spec != NULL) + udp_dport = rte_be_to_cpu_16 + (spec->hdr.dst_port & + mask->hdr.dst_port); + if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : @@ -1369,8 +1373,9 @@ flow_verbs_validate(struct rte_eth_dev *dev, MLX5_FLOW_LAYER_OUTER_L4_TCP; break; case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = mlx5_flow_validate_item_vxlan(items, item_flags, - error); + ret = mlx5_flow_validate_item_vxlan(dev, udp_dport, + items, item_flags, + attr, error); if (ret < 0) return ret; last_item = MLX5_FLOW_LAYER_VXLAN; @@ -1398,6 +1403,12 @@ flow_verbs_validate(struct rte_eth_dev *dev, return ret; last_item = MLX5_FLOW_LAYER_MPLS; break; + case RTE_FLOW_ITEM_TYPE_ICMP: + case RTE_FLOW_ITEM_TYPE_ICMP6: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, + NULL, "ICMP/ICMP6 " + "item not supported"); default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, @@ -1405,6 +1416,10 @@ flow_verbs_validate(struct rte_eth_dev *dev, } item_flags |= last_item; } + if (is_empty_vlan) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ITEM, NULL, + "VLAN matching without vid specification is not supported"); for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { switch (actions->type) { case RTE_FLOW_ACTION_TYPE_VOID: @@ -1623,7 +1638,9 @@ flow_verbs_prepare(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow; struct mlx5_flow_handle *dev_handle; struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); + MLX5_ASSERT(wks); size += flow_verbs_get_actions_size(actions); size += flow_verbs_get_items_size(items); if (size > MLX5_VERBS_MAX_SPEC_ACT_SIZE) { @@ -1633,7 +1650,7 @@ flow_verbs_prepare(struct rte_eth_dev *dev, return NULL; } /* In case of corrupting the memory. */ - if (priv->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) { + if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) { rte_flow_error_set(error, ENOSPC, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "not free temporary device flow"); @@ -1647,8 +1664,8 @@ flow_verbs_prepare(struct rte_eth_dev *dev, "not enough memory to create flow handle"); return NULL; } - /* No multi-thread supporting. */ - dev_flow = &((struct mlx5_flow *)priv->inter_flows)[priv->flow_idx++]; + MLX5_ASSERT(wks->flow_idx + 1 < RTE_DIM(wks->flows)); + dev_flow = &wks->flows[wks->flow_idx++]; dev_flow->handle = dev_handle; dev_flow->handle_idx = handle_idx; /* Memcpy is used, only size needs to be cleared to 0. */ @@ -1692,11 +1709,12 @@ flow_verbs_translate(struct rte_eth_dev *dev, uint64_t priority = attr->priority; uint32_t subpriority = 0; struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_rss_desc *rss_desc = &((struct mlx5_flow_rss_desc *) - priv->rss_desc) - [!!priv->flow_nested_idx]; + struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); + struct mlx5_flow_rss_desc *rss_desc; - if (priority == MLX5_FLOW_PRIO_RSVD) + MLX5_ASSERT(wks); + rss_desc = &wks->rss_desc; + if (priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) priority = priv->config.flow_prio - 1; for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { int ret; @@ -1795,8 +1813,9 @@ flow_verbs_translate(struct rte_eth_dev *dev, flow_verbs_translate_item_tcp(dev_flow, items, item_flags); subpriority = MLX5_PRIORITY_MAP_L4; - dev_flow->hash_fields |= - mlx5_flow_hashfields_adjust + if (dev_flow->hash_fields != 0) + dev_flow->hash_fields |= + mlx5_flow_hashfields_adjust (rss_desc, tunnel, ETH_RSS_TCP, (IBV_RX_HASH_SRC_PORT_TCP | IBV_RX_HASH_DST_PORT_TCP)); @@ -1807,8 +1826,9 @@ flow_verbs_translate(struct rte_eth_dev *dev, flow_verbs_translate_item_udp(dev_flow, items, item_flags); subpriority = MLX5_PRIORITY_MAP_L4; - dev_flow->hash_fields |= - mlx5_flow_hashfields_adjust + if (dev_flow->hash_fields != 0) + dev_flow->hash_fields |= + mlx5_flow_hashfields_adjust (rss_desc, tunnel, ETH_RSS_UDP, (IBV_RX_HASH_SRC_PORT_UDP | IBV_RX_HASH_DST_PORT_UDP)); @@ -1842,8 +1862,7 @@ flow_verbs_translate(struct rte_eth_dev *dev, default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, - NULL, - "item not supported"); + NULL, "item not supported"); } } dev_flow->handle->layers = item_flags; @@ -1878,15 +1897,10 @@ flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow) handle->drv_flow = NULL; } /* hrxq is union, don't touch it only the flag is set. */ - if (handle->rix_hrxq) { - if (handle->fate_action == MLX5_FLOW_FATE_DROP) { - mlx5_drop_action_destroy(dev); - handle->rix_hrxq = 0; - } else if (handle->fate_action == - MLX5_FLOW_FATE_QUEUE) { - mlx5_hrxq_release(dev, handle->rix_hrxq); - handle->rix_hrxq = 0; - } + if (handle->rix_hrxq && + handle->fate_action == MLX5_FLOW_FATE_QUEUE) { + mlx5_hrxq_release(dev, handle->rix_hrxq); + handle->rix_hrxq = 0; } if (handle->vf_vlan.tag && handle->vf_vlan.created) mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); @@ -1951,40 +1965,26 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow, uint32_t dev_handles; int err; int idx; + struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); - for (idx = priv->flow_idx - 1; idx >= priv->flow_nested_idx; idx--) { - dev_flow = &((struct mlx5_flow *)priv->inter_flows)[idx]; + MLX5_ASSERT(wks); + for (idx = wks->flow_idx - 1; idx >= 0; idx--) { + dev_flow = &wks->flows[idx]; handle = dev_flow->handle; if (handle->fate_action == MLX5_FLOW_FATE_DROP) { - hrxq = mlx5_drop_action_create(dev); - if (!hrxq) { - rte_flow_error_set - (error, errno, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "cannot get drop hash queue"); - goto error; - } + MLX5_ASSERT(priv->drop_queue.hrxq); + hrxq = priv->drop_queue.hrxq; } else { uint32_t hrxq_idx; - struct mlx5_flow_rss_desc *rss_desc = - &((struct mlx5_flow_rss_desc *)priv->rss_desc) - [!!priv->flow_nested_idx]; + struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc; MLX5_ASSERT(rss_desc->queue_num); - hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key, - MLX5_RSS_HASH_KEY_LEN, - dev_flow->hash_fields, - rss_desc->queue, - rss_desc->queue_num); - if (!hrxq_idx) - hrxq_idx = mlx5_hrxq_new - (dev, rss_desc->key, - MLX5_RSS_HASH_KEY_LEN, - dev_flow->hash_fields, - rss_desc->queue, - rss_desc->queue_num, - !!(handle->layers & - MLX5_FLOW_LAYER_TUNNEL)); + rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN; + rss_desc->hash_fields = dev_flow->hash_fields; + rss_desc->tunnel = !!(handle->layers & + MLX5_FLOW_LAYER_TUNNEL); + rss_desc->shared_rss = 0; + hrxq_idx = mlx5_hrxq_get(dev, rss_desc); hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); if (!hrxq) { @@ -2023,15 +2023,10 @@ error: SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, dev_handles, handle, next) { /* hrxq is union, don't touch it only the flag is set. */ - if (handle->rix_hrxq) { - if (handle->fate_action == MLX5_FLOW_FATE_DROP) { - mlx5_drop_action_destroy(dev); - handle->rix_hrxq = 0; - } else if (handle->fate_action == - MLX5_FLOW_FATE_QUEUE) { - mlx5_hrxq_release(dev, handle->rix_hrxq); - handle->rix_hrxq = 0; - } + if (handle->rix_hrxq && + handle->fate_action == MLX5_FLOW_FATE_QUEUE) { + mlx5_hrxq_release(dev, handle->rix_hrxq); + handle->rix_hrxq = 0; } if (handle->vf_vlan.tag && handle->vf_vlan.created) mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); @@ -2072,6 +2067,17 @@ flow_verbs_query(struct rte_eth_dev *dev, return ret; } +static int +flow_verbs_sync_domain(struct rte_eth_dev *dev, uint32_t domains, + uint32_t flags) +{ + RTE_SET_USED(dev); + RTE_SET_USED(domains); + RTE_SET_USED(flags); + + return 0; +} + const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = { .validate = flow_verbs_validate, .prepare = flow_verbs_prepare, @@ -2080,4 +2086,5 @@ const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = { .remove = flow_verbs_remove, .destroy = flow_verbs_destroy, .query = flow_verbs_query, + .sync_domain = flow_verbs_sync_domain, };