X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_verbs.c;h=b93fd4d2c96296225e0ab76887c98d3e333d0b07;hb=6428e0327cf864f681a5890e18eed622bf607f9f;hp=0ec9acd7a2a48aebbafbd36b34afd41191605d3f;hpb=8bb81f2649b1a17978357822c7f49b75c40109ac;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c index 0ec9acd7a2..b93fd4d2c9 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; } @@ -349,7 +357,7 @@ flow_verbs_counter_release(struct rte_eth_dev *dev, uint32_t counter) struct mlx5_flow_counter *cnt; cnt = flow_verbs_counter_get_by_idx(dev, counter, &pool); - if (IS_SHARED_CNT(counter) && + if (IS_LEGACY_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) @@ -1248,7 +1256,8 @@ flow_verbs_validate(struct rte_eth_dev *dev, uint64_t last_item = 0; uint8_t next_protocol = 0xff; uint16_t ether_type = 0; - char errstr[32]; + bool is_empty_vlan = false; + uint16_t udp_dport = 0; if (items == NULL) return -1; @@ -1276,6 +1285,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; @@ -1301,6 +1312,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 @@ -1353,6 +1365,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 : @@ -1370,8 +1391,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; @@ -1399,15 +1421,23 @@ 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: - snprintf(errstr, sizeof(errstr), "item type %d not supported", - items->type); return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, - NULL, errstr); + NULL, "item not supported"); } 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: @@ -1699,11 +1729,10 @@ flow_verbs_translate(struct rte_eth_dev *dev, struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); struct mlx5_flow_rss_desc *rss_desc; - char errstr[32]; MLX5_ASSERT(wks); - rss_desc = &wks->rss_desc[!!wks->flow_nested_idx]; - if (priority == MLX5_FLOW_PRIO_RSVD) + 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; @@ -1802,8 +1831,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)); @@ -1814,8 +1844,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)); @@ -1847,11 +1878,9 @@ flow_verbs_translate(struct rte_eth_dev *dev, item_flags |= MLX5_FLOW_LAYER_MPLS; break; default: - snprintf(errstr, sizeof(errstr), "item type %d not supported", - items->type); return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, - NULL, errstr); + NULL, "item not supported"); } } dev_flow->handle->layers = item_flags; @@ -1886,15 +1915,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); @@ -1962,39 +1986,23 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow, struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); MLX5_ASSERT(wks); - for (idx = wks->flow_idx - 1; idx >= wks->flow_nested_idx; idx--) { + 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 = - &wks->rss_desc[!!wks->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), - false); + 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) { @@ -2033,15 +2041,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);