184c406e7SOri Kam /* SPDX-License-Identifier: BSD-3-Clause 284c406e7SOri Kam * Copyright 2018 Mellanox Technologies, Ltd 384c406e7SOri Kam */ 484c406e7SOri Kam 584c406e7SOri Kam #include <netinet/in.h> 684c406e7SOri Kam #include <sys/queue.h> 784c406e7SOri Kam #include <stdalign.h> 884c406e7SOri Kam #include <stdint.h> 984c406e7SOri Kam #include <string.h> 1084c406e7SOri Kam 1184c406e7SOri Kam #include <rte_common.h> 1284c406e7SOri Kam #include <rte_ether.h> 13df96fd0dSBruce Richardson #include <ethdev_driver.h> 1484c406e7SOri Kam #include <rte_flow.h> 1584c406e7SOri Kam #include <rte_flow_driver.h> 1684c406e7SOri Kam #include <rte_malloc.h> 1784c406e7SOri Kam #include <rte_ip.h> 1884c406e7SOri Kam 197b4f1e6bSMatan Azrad #include <mlx5_glue.h> 207b4f1e6bSMatan Azrad #include <mlx5_prm.h> 2183c2047cSSuanming Mou #include <mlx5_malloc.h> 227b4f1e6bSMatan Azrad 2384c406e7SOri Kam #include "mlx5_defs.h" 247b4f1e6bSMatan Azrad #include "mlx5.h" 2584c406e7SOri Kam #include "mlx5_flow.h" 26151cbe3aSMichael Baum #include "mlx5_rx.h" 2772185352SMaayan Kashani #include "mlx5_flow_os.h" 2884c406e7SOri Kam 294a78c88eSYongseok Koh #define VERBS_SPEC_INNER(item_flags) \ 304a78c88eSYongseok Koh (!!((item_flags) & MLX5_FLOW_LAYER_TUNNEL) ? IBV_FLOW_SPEC_INNER : 0) 314a78c88eSYongseok Koh 32f1ae0b35SOphir Munk /* Verbs specification header. */ 33f1ae0b35SOphir Munk struct ibv_spec_header { 34f1ae0b35SOphir Munk enum ibv_flow_spec_type type; 35f1ae0b35SOphir Munk uint16_t size; 36f1ae0b35SOphir Munk }; 37f1ae0b35SOphir Munk 383eca5f8aSOphir Munk /** 393eca5f8aSOphir Munk * Discover the maximum number of priority available. 403eca5f8aSOphir Munk * 413eca5f8aSOphir Munk * @param[in] dev 423eca5f8aSOphir Munk * Pointer to the Ethernet device structure. 43c5042f93SDmitry Kozlyuk * @param[in] vprio 44c5042f93SDmitry Kozlyuk * Expected result variants. 45c5042f93SDmitry Kozlyuk * @param[in] vprio_n 46c5042f93SDmitry Kozlyuk * Number of entries in @p vprio array. 473eca5f8aSOphir Munk * @return 48c5042f93SDmitry Kozlyuk * Number of supported flow priority on success, a negative errno 493eca5f8aSOphir Munk * value otherwise and rte_errno is set. 503eca5f8aSOphir Munk */ 51c5042f93SDmitry Kozlyuk static int 52c5042f93SDmitry Kozlyuk flow_verbs_discover_priorities(struct rte_eth_dev *dev, 53c5042f93SDmitry Kozlyuk const uint16_t *vprio, int vprio_n) 543eca5f8aSOphir Munk { 553eca5f8aSOphir Munk struct mlx5_priv *priv = dev->data->dev_private; 563eca5f8aSOphir Munk struct { 573eca5f8aSOphir Munk struct ibv_flow_attr attr; 583eca5f8aSOphir Munk struct ibv_flow_spec_eth eth; 593eca5f8aSOphir Munk struct ibv_flow_spec_action_drop drop; 603eca5f8aSOphir Munk } flow_attr = { 613eca5f8aSOphir Munk .attr = { 623eca5f8aSOphir Munk .num_of_specs = 2, 633eca5f8aSOphir Munk .port = (uint8_t)priv->dev_port, 643eca5f8aSOphir Munk }, 653eca5f8aSOphir Munk .eth = { 663eca5f8aSOphir Munk .type = IBV_FLOW_SPEC_ETH, 673eca5f8aSOphir Munk .size = sizeof(struct ibv_flow_spec_eth), 683eca5f8aSOphir Munk }, 693eca5f8aSOphir Munk .drop = { 703eca5f8aSOphir Munk .size = sizeof(struct ibv_flow_spec_action_drop), 713eca5f8aSOphir Munk .type = IBV_FLOW_SPEC_ACTION_DROP, 723eca5f8aSOphir Munk }, 733eca5f8aSOphir Munk }; 743eca5f8aSOphir Munk struct ibv_flow *flow; 7565b3cd0dSSuanming Mou struct mlx5_hrxq *drop = priv->drop_queue.hrxq; 763eca5f8aSOphir Munk int i; 773eca5f8aSOphir Munk int priority = 0; 783eca5f8aSOphir Munk 791d47e933SXueming Li #if defined(HAVE_MLX5DV_DR_DEVX_PORT) || defined(HAVE_MLX5DV_DR_DEVX_PORT_V35) 801d47e933SXueming Li /* If DevX supported, driver must support 16 verbs flow priorities. */ 81c5042f93SDmitry Kozlyuk priority = 16; 821d47e933SXueming Li goto out; 831d47e933SXueming Li #endif 8465b3cd0dSSuanming Mou if (!drop->qp) { 853eca5f8aSOphir Munk rte_errno = ENOTSUP; 863eca5f8aSOphir Munk return -rte_errno; 873eca5f8aSOphir Munk } 88c5042f93SDmitry Kozlyuk for (i = 0; i != vprio_n; i++) { 893eca5f8aSOphir Munk flow_attr.attr.priority = vprio[i] - 1; 903eca5f8aSOphir Munk flow = mlx5_glue->create_flow(drop->qp, &flow_attr.attr); 913eca5f8aSOphir Munk if (!flow) 923eca5f8aSOphir Munk break; 933eca5f8aSOphir Munk claim_zero(mlx5_glue->destroy_flow(flow)); 943eca5f8aSOphir Munk priority = vprio[i]; 953eca5f8aSOphir Munk } 961d47e933SXueming Li #if defined(HAVE_MLX5DV_DR_DEVX_PORT) || defined(HAVE_MLX5DV_DR_DEVX_PORT_V35) 971d47e933SXueming Li out: 981d47e933SXueming Li #endif 995f8ae44dSDong Zhou DRV_LOG(INFO, "port %u supported flow priorities:" 1005f8ae44dSDong Zhou " 0-%d for ingress or egress root table," 1015f8ae44dSDong Zhou " 0-%d for non-root table or transfer root table.", 1025f8ae44dSDong Zhou dev->data->port_id, priority - 2, 1035f8ae44dSDong Zhou MLX5_NON_ROOT_FLOW_MAX_PRIO - 1); 1043eca5f8aSOphir Munk return priority; 1053eca5f8aSOphir Munk } 1063eca5f8aSOphir Munk 1073eca5f8aSOphir Munk /** 108c3d3b140SSuanming Mou * Get Verbs flow counter by index. 109c3d3b140SSuanming Mou * 110c3d3b140SSuanming Mou * @param[in] dev 111c3d3b140SSuanming Mou * Pointer to the Ethernet device structure. 112c3d3b140SSuanming Mou * @param[in] idx 113c3d3b140SSuanming Mou * mlx5 flow counter index in the container. 114c3d3b140SSuanming Mou * @param[out] ppool 115c3d3b140SSuanming Mou * mlx5 flow counter pool in the container, 116c3d3b140SSuanming Mou * 117c3d3b140SSuanming Mou * @return 118c3d3b140SSuanming Mou * A pointer to the counter, NULL otherwise. 119c3d3b140SSuanming Mou */ 120c3d3b140SSuanming Mou static struct mlx5_flow_counter * 121c3d3b140SSuanming Mou flow_verbs_counter_get_by_idx(struct rte_eth_dev *dev, 122c3d3b140SSuanming Mou uint32_t idx, 123c3d3b140SSuanming Mou struct mlx5_flow_counter_pool **ppool) 124c3d3b140SSuanming Mou { 125c3d3b140SSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 12604a4de75SMichael Baum struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng; 127c3d3b140SSuanming Mou struct mlx5_flow_counter_pool *pool; 128c3d3b140SSuanming Mou 129df051a3eSSuanming Mou idx = (idx - 1) & (MLX5_CNT_SHARED_OFFSET - 1); 130994829e6SSuanming Mou pool = cmng->pools[idx / MLX5_COUNTERS_PER_POOL]; 131c3d3b140SSuanming Mou MLX5_ASSERT(pool); 132c3d3b140SSuanming Mou if (ppool) 133c3d3b140SSuanming Mou *ppool = pool; 1348d93c830SDong Zhou return MLX5_POOL_GET_CNT(pool, idx % MLX5_COUNTERS_PER_POOL); 135c3d3b140SSuanming Mou } 136c3d3b140SSuanming Mou 137c3d3b140SSuanming Mou /** 138db48f9dbSViacheslav Ovsiienko * Create Verbs flow counter with Verbs library. 139db48f9dbSViacheslav Ovsiienko * 140db48f9dbSViacheslav Ovsiienko * @param[in] dev 141db48f9dbSViacheslav Ovsiienko * Pointer to the Ethernet device structure. 142db48f9dbSViacheslav Ovsiienko * @param[in, out] counter 143db48f9dbSViacheslav Ovsiienko * mlx5 flow counter object, contains the counter id, 144db48f9dbSViacheslav Ovsiienko * handle of created Verbs flow counter is returned 145db48f9dbSViacheslav Ovsiienko * in cs field (if counters are supported). 146db48f9dbSViacheslav Ovsiienko * 147db48f9dbSViacheslav Ovsiienko * @return 148db48f9dbSViacheslav Ovsiienko * 0 On success else a negative errno value is returned 149db48f9dbSViacheslav Ovsiienko * and rte_errno is set. 150db48f9dbSViacheslav Ovsiienko */ 151db48f9dbSViacheslav Ovsiienko static int 152db48f9dbSViacheslav Ovsiienko flow_verbs_counter_create(struct rte_eth_dev *dev, 1532b5b1aebSSuanming Mou struct mlx5_flow_counter *counter) 154db48f9dbSViacheslav Ovsiienko { 155db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) 156dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 157ca1418ceSMichael Baum struct ibv_context *ctx = priv->sh->cdev->ctx; 158db48f9dbSViacheslav Ovsiienko struct ibv_counter_set_init_attr init = { 1592b5b1aebSSuanming Mou .counter_set_id = counter->shared_info.id}; 160db48f9dbSViacheslav Ovsiienko 1612b5b1aebSSuanming Mou counter->dcs_when_free = mlx5_glue->create_counter_set(ctx, &init); 1622b5b1aebSSuanming Mou if (!counter->dcs_when_free) { 163db48f9dbSViacheslav Ovsiienko rte_errno = ENOTSUP; 164db48f9dbSViacheslav Ovsiienko return -ENOTSUP; 165db48f9dbSViacheslav Ovsiienko } 166db48f9dbSViacheslav Ovsiienko return 0; 167db48f9dbSViacheslav Ovsiienko #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 168dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 169ca1418ceSMichael Baum struct ibv_context *ctx = priv->sh->cdev->ctx; 170db48f9dbSViacheslav Ovsiienko struct ibv_counters_init_attr init = {0}; 1710c15f3c0SAli Alnubani struct ibv_counter_attach_attr attach; 172db48f9dbSViacheslav Ovsiienko int ret; 173db48f9dbSViacheslav Ovsiienko 1740c15f3c0SAli Alnubani memset(&attach, 0, sizeof(attach)); 1752b5b1aebSSuanming Mou counter->dcs_when_free = mlx5_glue->create_counters(ctx, &init); 1762b5b1aebSSuanming Mou if (!counter->dcs_when_free) { 177db48f9dbSViacheslav Ovsiienko rte_errno = ENOTSUP; 178db48f9dbSViacheslav Ovsiienko return -ENOTSUP; 179db48f9dbSViacheslav Ovsiienko } 180db48f9dbSViacheslav Ovsiienko attach.counter_desc = IBV_COUNTER_PACKETS; 181db48f9dbSViacheslav Ovsiienko attach.index = 0; 1822b5b1aebSSuanming Mou ret = mlx5_glue->attach_counters(counter->dcs_when_free, &attach, NULL); 183db48f9dbSViacheslav Ovsiienko if (!ret) { 184db48f9dbSViacheslav Ovsiienko attach.counter_desc = IBV_COUNTER_BYTES; 185db48f9dbSViacheslav Ovsiienko attach.index = 1; 186db48f9dbSViacheslav Ovsiienko ret = mlx5_glue->attach_counters 1872b5b1aebSSuanming Mou (counter->dcs_when_free, &attach, NULL); 188db48f9dbSViacheslav Ovsiienko } 189db48f9dbSViacheslav Ovsiienko if (ret) { 1902b5b1aebSSuanming Mou claim_zero(mlx5_glue->destroy_counters(counter->dcs_when_free)); 1912b5b1aebSSuanming Mou counter->dcs_when_free = NULL; 192db48f9dbSViacheslav Ovsiienko rte_errno = ret; 193db48f9dbSViacheslav Ovsiienko return -ret; 194db48f9dbSViacheslav Ovsiienko } 195db48f9dbSViacheslav Ovsiienko return 0; 196db48f9dbSViacheslav Ovsiienko #else 197db48f9dbSViacheslav Ovsiienko (void)dev; 198db48f9dbSViacheslav Ovsiienko (void)counter; 199db48f9dbSViacheslav Ovsiienko rte_errno = ENOTSUP; 200db48f9dbSViacheslav Ovsiienko return -ENOTSUP; 201db48f9dbSViacheslav Ovsiienko #endif 202db48f9dbSViacheslav Ovsiienko } 203db48f9dbSViacheslav Ovsiienko 204db48f9dbSViacheslav Ovsiienko /** 20584c406e7SOri Kam * Get a flow counter. 20684c406e7SOri Kam * 20784c406e7SOri Kam * @param[in] dev 20884c406e7SOri Kam * Pointer to the Ethernet device structure. 20984c406e7SOri Kam * @param[in] id 21084c406e7SOri Kam * Counter identifier. 21184c406e7SOri Kam * 21284c406e7SOri Kam * @return 213956d5c74SSuanming Mou * Index to the counter, 0 otherwise and rte_errno is set. 21484c406e7SOri Kam */ 215956d5c74SSuanming Mou static uint32_t 21692ef4b8fSAndrew Rybchenko flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t id __rte_unused) 21784c406e7SOri Kam { 218dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 21904a4de75SMichael Baum struct mlx5_flow_counter_mng *cmng = &priv->sh->sws_cmng; 220c3d3b140SSuanming Mou struct mlx5_flow_counter_pool *pool = NULL; 221c3d3b140SSuanming Mou struct mlx5_flow_counter *cnt = NULL; 2223aa27915SSuanming Mou uint32_t n_valid = cmng->n_valid; 223df051a3eSSuanming Mou uint32_t pool_idx, cnt_idx; 224c3d3b140SSuanming Mou uint32_t i; 225db48f9dbSViacheslav Ovsiienko int ret; 22684c406e7SOri Kam 227c3d3b140SSuanming Mou for (pool_idx = 0; pool_idx < n_valid; ++pool_idx) { 228994829e6SSuanming Mou pool = cmng->pools[pool_idx]; 229c3d3b140SSuanming Mou if (!pool) 230c3d3b140SSuanming Mou continue; 231ac79183dSSuanming Mou cnt = TAILQ_FIRST(&pool->counters[0]); 232c3d3b140SSuanming Mou if (cnt) 233c3d3b140SSuanming Mou break; 234c3d3b140SSuanming Mou } 23584c406e7SOri Kam if (!cnt) { 236c3d3b140SSuanming Mou uint32_t size; 237c3d3b140SSuanming Mou 238a94e89e4SMichael Baum if (n_valid == MLX5_COUNTER_POOLS_MAX_NUM) { 239a94e89e4SMichael Baum DRV_LOG(ERR, "All counter is in used, try again later."); 240a94e89e4SMichael Baum rte_errno = EAGAIN; 241956d5c74SSuanming Mou return 0; 242c3d3b140SSuanming Mou } 243c3d3b140SSuanming Mou /* Allocate memory for new pool */ 2442b5b1aebSSuanming Mou size = sizeof(*pool) + sizeof(*cnt) * MLX5_COUNTERS_PER_POOL; 24583c2047cSSuanming Mou pool = mlx5_malloc(MLX5_MEM_ZERO, size, 0, SOCKET_ID_ANY); 246c3d3b140SSuanming Mou if (!pool) 247956d5c74SSuanming Mou return 0; 248c3d3b140SSuanming Mou for (i = 0; i < MLX5_COUNTERS_PER_POOL; ++i) { 2498d93c830SDong Zhou cnt = MLX5_POOL_GET_CNT(pool, i); 250ac79183dSSuanming Mou TAILQ_INSERT_HEAD(&pool->counters[0], cnt, next); 251c3d3b140SSuanming Mou } 2528d93c830SDong Zhou cnt = MLX5_POOL_GET_CNT(pool, 0); 253994829e6SSuanming Mou cmng->pools[n_valid] = pool; 254c3d3b140SSuanming Mou pool_idx = n_valid; 2553aa27915SSuanming Mou cmng->n_valid++; 25684c406e7SOri Kam } 2572b5b1aebSSuanming Mou TAILQ_REMOVE(&pool->counters[0], cnt, next); 2588d93c830SDong Zhou i = MLX5_CNT_ARRAY_IDX(pool, cnt); 259df051a3eSSuanming Mou cnt_idx = MLX5_MAKE_CNT_IDX(pool_idx, i); 2602b5b1aebSSuanming Mou /* Create counter with Verbs. */ 2612b5b1aebSSuanming Mou ret = flow_verbs_counter_create(dev, cnt); 2622b5b1aebSSuanming Mou if (!ret) { 2632b5b1aebSSuanming Mou cnt->dcs_when_active = cnt->dcs_when_free; 264db48f9dbSViacheslav Ovsiienko cnt->hits = 0; 265db48f9dbSViacheslav Ovsiienko cnt->bytes = 0; 266df051a3eSSuanming Mou return cnt_idx; 267db48f9dbSViacheslav Ovsiienko } 2682b5b1aebSSuanming Mou TAILQ_INSERT_HEAD(&pool->counters[0], cnt, next); 269db48f9dbSViacheslav Ovsiienko /* Some error occurred in Verbs library. */ 270db48f9dbSViacheslav Ovsiienko rte_errno = -ret; 271956d5c74SSuanming Mou return 0; 27284c406e7SOri Kam } 27384c406e7SOri Kam 27484c406e7SOri Kam /** 27584c406e7SOri Kam * Release a flow counter. 27684c406e7SOri Kam * 2775382d28cSMatan Azrad * @param[in] dev 2785382d28cSMatan Azrad * Pointer to the Ethernet device structure. 27984c406e7SOri Kam * @param[in] counter 280956d5c74SSuanming Mou * Index to the counter handler. 28184c406e7SOri Kam */ 28284c406e7SOri Kam static void 283956d5c74SSuanming Mou flow_verbs_counter_release(struct rte_eth_dev *dev, uint32_t counter) 28484c406e7SOri Kam { 285c3d3b140SSuanming Mou struct mlx5_flow_counter_pool *pool; 286c3d3b140SSuanming Mou struct mlx5_flow_counter *cnt; 2875382d28cSMatan Azrad 288df051a3eSSuanming Mou cnt = flow_verbs_counter_get_by_idx(dev, counter, &pool); 289db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) 2902b5b1aebSSuanming Mou claim_zero(mlx5_glue->destroy_counter_set 2912b5b1aebSSuanming Mou ((struct ibv_counter_set *)cnt->dcs_when_active)); 292db48f9dbSViacheslav Ovsiienko #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 2932b5b1aebSSuanming Mou claim_zero(mlx5_glue->destroy_counters 2942b5b1aebSSuanming Mou ((struct ibv_counters *)cnt->dcs_when_active)); 295db48f9dbSViacheslav Ovsiienko #endif 296ac79183dSSuanming Mou TAILQ_INSERT_HEAD(&pool->counters[0], cnt, next); 29784c406e7SOri Kam } 29884c406e7SOri Kam 29984c406e7SOri Kam /** 30006629d86SViacheslav Ovsiienko * Query a flow counter via Verbs library call. 30106629d86SViacheslav Ovsiienko * 30206629d86SViacheslav Ovsiienko * @see rte_flow_query() 30306629d86SViacheslav Ovsiienko * @see rte_flow_ops 30406629d86SViacheslav Ovsiienko */ 30506629d86SViacheslav Ovsiienko static int 30606629d86SViacheslav Ovsiienko flow_verbs_counter_query(struct rte_eth_dev *dev __rte_unused, 307db48f9dbSViacheslav Ovsiienko struct rte_flow *flow, void *data, 30806629d86SViacheslav Ovsiienko struct rte_flow_error *error) 30906629d86SViacheslav Ovsiienko { 310db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \ 311db48f9dbSViacheslav Ovsiienko defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 312956d5c74SSuanming Mou if (flow->counter) { 313826b8a87SSuanming Mou struct mlx5_flow_counter_pool *pool; 314c3d3b140SSuanming Mou struct mlx5_flow_counter *cnt = flow_verbs_counter_get_by_idx 315826b8a87SSuanming Mou (dev, flow->counter, &pool); 31606629d86SViacheslav Ovsiienko struct rte_flow_query_count *qc = data; 31706629d86SViacheslav Ovsiienko uint64_t counters[2] = {0, 0}; 318db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) 31906629d86SViacheslav Ovsiienko struct ibv_query_counter_set_attr query_cs_attr = { 3202b5b1aebSSuanming Mou .dcs_when_free = (struct ibv_counter_set *) 3212b5b1aebSSuanming Mou cnt->dcs_when_active, 32206629d86SViacheslav Ovsiienko .query_flags = IBV_COUNTER_SET_FORCE_UPDATE, 32306629d86SViacheslav Ovsiienko }; 32406629d86SViacheslav Ovsiienko struct ibv_counter_set_data query_out = { 32506629d86SViacheslav Ovsiienko .out = counters, 32606629d86SViacheslav Ovsiienko .outlen = 2 * sizeof(uint64_t), 32706629d86SViacheslav Ovsiienko }; 32806629d86SViacheslav Ovsiienko int err = mlx5_glue->query_counter_set(&query_cs_attr, 32906629d86SViacheslav Ovsiienko &query_out); 330db48f9dbSViacheslav Ovsiienko #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 331db48f9dbSViacheslav Ovsiienko int err = mlx5_glue->query_counters 3322b5b1aebSSuanming Mou ((struct ibv_counters *)cnt->dcs_when_active, counters, 333db48f9dbSViacheslav Ovsiienko RTE_DIM(counters), 334db48f9dbSViacheslav Ovsiienko IBV_READ_COUNTERS_ATTR_PREFER_CACHED); 335db48f9dbSViacheslav Ovsiienko #endif 33606629d86SViacheslav Ovsiienko if (err) 33706629d86SViacheslav Ovsiienko return rte_flow_error_set 33806629d86SViacheslav Ovsiienko (error, err, 33906629d86SViacheslav Ovsiienko RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 34006629d86SViacheslav Ovsiienko NULL, 34106629d86SViacheslav Ovsiienko "cannot read counter"); 34206629d86SViacheslav Ovsiienko qc->hits_set = 1; 34306629d86SViacheslav Ovsiienko qc->bytes_set = 1; 344c3d3b140SSuanming Mou qc->hits = counters[0] - cnt->hits; 345c3d3b140SSuanming Mou qc->bytes = counters[1] - cnt->bytes; 34606629d86SViacheslav Ovsiienko if (qc->reset) { 347c3d3b140SSuanming Mou cnt->hits = counters[0]; 348c3d3b140SSuanming Mou cnt->bytes = counters[1]; 34906629d86SViacheslav Ovsiienko } 35006629d86SViacheslav Ovsiienko return 0; 35106629d86SViacheslav Ovsiienko } 35206629d86SViacheslav Ovsiienko return rte_flow_error_set(error, EINVAL, 35306629d86SViacheslav Ovsiienko RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 35406629d86SViacheslav Ovsiienko NULL, 35506629d86SViacheslav Ovsiienko "flow does not have counter"); 35606629d86SViacheslav Ovsiienko #else 357db48f9dbSViacheslav Ovsiienko (void)flow; 358db48f9dbSViacheslav Ovsiienko (void)data; 35906629d86SViacheslav Ovsiienko return rte_flow_error_set(error, ENOTSUP, 36006629d86SViacheslav Ovsiienko RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 36106629d86SViacheslav Ovsiienko NULL, 36206629d86SViacheslav Ovsiienko "counters are not available"); 36306629d86SViacheslav Ovsiienko #endif 36406629d86SViacheslav Ovsiienko } 36506629d86SViacheslav Ovsiienko 36606629d86SViacheslav Ovsiienko /** 3674a78c88eSYongseok Koh * Add a verbs item specification into @p verbs. 36884c406e7SOri Kam * 3694a78c88eSYongseok Koh * @param[out] verbs 3704a78c88eSYongseok Koh * Pointer to verbs structure. 37184c406e7SOri Kam * @param[in] src 37284c406e7SOri Kam * Create specification. 37384c406e7SOri Kam * @param[in] size 37484c406e7SOri Kam * Size in bytes of the specification to copy. 37584c406e7SOri Kam */ 37684c406e7SOri Kam static void 377e7bfa359SBing Zhao flow_verbs_spec_add(struct mlx5_flow_verbs_workspace *verbs, 378c42f44bdSBing Zhao void *src, unsigned int size) 37984c406e7SOri Kam { 38084c406e7SOri Kam void *dst; 38184c406e7SOri Kam 3824a78c88eSYongseok Koh if (!verbs) 3834a78c88eSYongseok Koh return; 3848e46d4e1SAlexander Kozyrev MLX5_ASSERT(verbs->specs); 38584c406e7SOri Kam dst = (void *)(verbs->specs + verbs->size); 38684c406e7SOri Kam memcpy(dst, src, size); 387e7bfa359SBing Zhao ++verbs->attr.num_of_specs; 38884c406e7SOri Kam verbs->size += size; 38984c406e7SOri Kam } 39084c406e7SOri Kam 39184c406e7SOri Kam /** 39284c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 39384c406e7SOri Kam * the input is valid and that there is space to insert the requested item 39484c406e7SOri Kam * into the flow. 39584c406e7SOri Kam * 3964a78c88eSYongseok Koh * @param[in, out] dev_flow 3974a78c88eSYongseok Koh * Pointer to dev_flow structure. 39884c406e7SOri Kam * @param[in] item 39984c406e7SOri Kam * Item specification. 40084c406e7SOri Kam * @param[in] item_flags 4014a78c88eSYongseok Koh * Parsed item flags. 40284c406e7SOri Kam */ 40384c406e7SOri Kam static void 4044a78c88eSYongseok Koh flow_verbs_translate_item_eth(struct mlx5_flow *dev_flow, 4054a78c88eSYongseok Koh const struct rte_flow_item *item, 4064a78c88eSYongseok Koh uint64_t item_flags) 40784c406e7SOri Kam { 40884c406e7SOri Kam const struct rte_flow_item_eth *spec = item->spec; 40984c406e7SOri Kam const struct rte_flow_item_eth *mask = item->mask; 41084c406e7SOri Kam const unsigned int size = sizeof(struct ibv_flow_spec_eth); 41184c406e7SOri Kam struct ibv_flow_spec_eth eth = { 4124a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_ETH | VERBS_SPEC_INNER(item_flags), 41384c406e7SOri Kam .size = size, 41484c406e7SOri Kam }; 41584c406e7SOri Kam 41684c406e7SOri Kam if (!mask) 41784c406e7SOri Kam mask = &rte_flow_item_eth_mask; 41884c406e7SOri Kam if (spec) { 41984c406e7SOri Kam unsigned int i; 42084c406e7SOri Kam 4218275d5fcSThomas Monjalon memcpy(ð.val.dst_mac, spec->hdr.dst_addr.addr_bytes, 42235b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 4238275d5fcSThomas Monjalon memcpy(ð.val.src_mac, spec->hdr.src_addr.addr_bytes, 42435b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 4258275d5fcSThomas Monjalon eth.val.ether_type = spec->hdr.ether_type; 4268275d5fcSThomas Monjalon memcpy(ð.mask.dst_mac, mask->hdr.dst_addr.addr_bytes, 42735b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 4288275d5fcSThomas Monjalon memcpy(ð.mask.src_mac, mask->hdr.src_addr.addr_bytes, 42935b2d13fSOlivier Matz RTE_ETHER_ADDR_LEN); 4308275d5fcSThomas Monjalon eth.mask.ether_type = mask->hdr.ether_type; 43184c406e7SOri Kam /* Remove unwanted bits from values. */ 43235b2d13fSOlivier Matz for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i) { 43384c406e7SOri Kam eth.val.dst_mac[i] &= eth.mask.dst_mac[i]; 43484c406e7SOri Kam eth.val.src_mac[i] &= eth.mask.src_mac[i]; 43584c406e7SOri Kam } 43684c406e7SOri Kam eth.val.ether_type &= eth.mask.ether_type; 43784c406e7SOri Kam } 4384a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, ð, size); 43984c406e7SOri Kam } 44084c406e7SOri Kam 44184c406e7SOri Kam /** 44284c406e7SOri Kam * Update the VLAN tag in the Verbs Ethernet specification. 44384c406e7SOri Kam * This function assumes that the input is valid and there is space to add 44484c406e7SOri Kam * the requested item. 44584c406e7SOri Kam * 44684c406e7SOri Kam * @param[in, out] attr 44784c406e7SOri Kam * Pointer to Verbs attributes structure. 44884c406e7SOri Kam * @param[in] eth 44984c406e7SOri Kam * Verbs structure containing the VLAN information to copy. 45084c406e7SOri Kam */ 45184c406e7SOri Kam static void 45284c406e7SOri Kam flow_verbs_item_vlan_update(struct ibv_flow_attr *attr, 45384c406e7SOri Kam struct ibv_flow_spec_eth *eth) 45484c406e7SOri Kam { 45584c406e7SOri Kam unsigned int i; 45684c406e7SOri Kam const enum ibv_flow_spec_type search = eth->type; 45784c406e7SOri Kam struct ibv_spec_header *hdr = (struct ibv_spec_header *) 45884c406e7SOri Kam ((uint8_t *)attr + sizeof(struct ibv_flow_attr)); 45984c406e7SOri Kam 46084c406e7SOri Kam for (i = 0; i != attr->num_of_specs; ++i) { 46184c406e7SOri Kam if (hdr->type == search) { 46284c406e7SOri Kam struct ibv_flow_spec_eth *e = 46384c406e7SOri Kam (struct ibv_flow_spec_eth *)hdr; 46484c406e7SOri Kam 46584c406e7SOri Kam e->val.vlan_tag = eth->val.vlan_tag; 46684c406e7SOri Kam e->mask.vlan_tag = eth->mask.vlan_tag; 46784c406e7SOri Kam e->val.ether_type = eth->val.ether_type; 46884c406e7SOri Kam e->mask.ether_type = eth->mask.ether_type; 46984c406e7SOri Kam break; 47084c406e7SOri Kam } 47184c406e7SOri Kam hdr = (struct ibv_spec_header *)((uint8_t *)hdr + hdr->size); 47284c406e7SOri Kam } 47384c406e7SOri Kam } 47484c406e7SOri Kam 47584c406e7SOri Kam /** 47684c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 47784c406e7SOri Kam * the input is valid and that there is space to insert the requested item 47884c406e7SOri Kam * into the flow. 47984c406e7SOri Kam * 48084c406e7SOri Kam * @param[in, out] dev_flow 48184c406e7SOri Kam * Pointer to dev_flow structure. 4824a78c88eSYongseok Koh * @param[in] item 4834a78c88eSYongseok Koh * Item specification. 4844a78c88eSYongseok Koh * @param[in] item_flags 4854a78c88eSYongseok Koh * Parsed item flags. 48684c406e7SOri Kam */ 48784c406e7SOri Kam static void 4884a78c88eSYongseok Koh flow_verbs_translate_item_vlan(struct mlx5_flow *dev_flow, 4894a78c88eSYongseok Koh const struct rte_flow_item *item, 4904a78c88eSYongseok Koh uint64_t item_flags) 49184c406e7SOri Kam { 49284c406e7SOri Kam const struct rte_flow_item_vlan *spec = item->spec; 49384c406e7SOri Kam const struct rte_flow_item_vlan *mask = item->mask; 49484c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_eth); 4954a78c88eSYongseok Koh const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 49684c406e7SOri Kam struct ibv_flow_spec_eth eth = { 4974a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_ETH | VERBS_SPEC_INNER(item_flags), 49884c406e7SOri Kam .size = size, 49984c406e7SOri Kam }; 50084c406e7SOri Kam const uint32_t l2m = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 50184c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L2; 50284c406e7SOri Kam 50384c406e7SOri Kam if (!mask) 50484c406e7SOri Kam mask = &rte_flow_item_vlan_mask; 50584c406e7SOri Kam if (spec) { 5068275d5fcSThomas Monjalon eth.val.vlan_tag = spec->hdr.vlan_tci; 5078275d5fcSThomas Monjalon eth.mask.vlan_tag = mask->hdr.vlan_tci; 50884c406e7SOri Kam eth.val.vlan_tag &= eth.mask.vlan_tag; 5098275d5fcSThomas Monjalon eth.val.ether_type = spec->hdr.eth_proto; 5108275d5fcSThomas Monjalon eth.mask.ether_type = mask->hdr.eth_proto; 51184c406e7SOri Kam eth.val.ether_type &= eth.mask.ether_type; 51284c406e7SOri Kam } 5134a78c88eSYongseok Koh if (!(item_flags & l2m)) 5144a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, ð, size); 5154a78c88eSYongseok Koh else 516e7bfa359SBing Zhao flow_verbs_item_vlan_update(&dev_flow->verbs.attr, ð); 517dfedf3e3SViacheslav Ovsiienko if (!tunnel) 518e7bfa359SBing Zhao dev_flow->handle->vf_vlan.tag = 5198275d5fcSThomas Monjalon rte_be_to_cpu_16(spec->hdr.vlan_tci) & 0x0fff; 52084c406e7SOri Kam } 52184c406e7SOri Kam 52284c406e7SOri Kam /** 52384c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 52484c406e7SOri Kam * the input is valid and that there is space to insert the requested item 52584c406e7SOri Kam * into the flow. 52684c406e7SOri Kam * 5274a78c88eSYongseok Koh * @param[in, out] dev_flow 5284a78c88eSYongseok Koh * Pointer to dev_flow structure. 52984c406e7SOri Kam * @param[in] item 53084c406e7SOri Kam * Item specification. 5314a78c88eSYongseok Koh * @param[in] item_flags 5324a78c88eSYongseok Koh * Parsed item flags. 53384c406e7SOri Kam */ 53484c406e7SOri Kam static void 5354a78c88eSYongseok Koh flow_verbs_translate_item_ipv4(struct mlx5_flow *dev_flow, 5364a78c88eSYongseok Koh const struct rte_flow_item *item, 5374a78c88eSYongseok Koh uint64_t item_flags) 53884c406e7SOri Kam { 53984c406e7SOri Kam const struct rte_flow_item_ipv4 *spec = item->spec; 54084c406e7SOri Kam const struct rte_flow_item_ipv4 *mask = item->mask; 54184c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_ipv4_ext); 54284c406e7SOri Kam struct ibv_flow_spec_ipv4_ext ipv4 = { 5434a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_IPV4_EXT | VERBS_SPEC_INNER(item_flags), 54484c406e7SOri Kam .size = size, 54584c406e7SOri Kam }; 54684c406e7SOri Kam 54784c406e7SOri Kam if (!mask) 54884c406e7SOri Kam mask = &rte_flow_item_ipv4_mask; 54984c406e7SOri Kam if (spec) { 55084c406e7SOri Kam ipv4.val = (struct ibv_flow_ipv4_ext_filter){ 55184c406e7SOri Kam .src_ip = spec->hdr.src_addr, 55284c406e7SOri Kam .dst_ip = spec->hdr.dst_addr, 55384c406e7SOri Kam .proto = spec->hdr.next_proto_id, 55484c406e7SOri Kam .tos = spec->hdr.type_of_service, 55584c406e7SOri Kam }; 55684c406e7SOri Kam ipv4.mask = (struct ibv_flow_ipv4_ext_filter){ 55784c406e7SOri Kam .src_ip = mask->hdr.src_addr, 55884c406e7SOri Kam .dst_ip = mask->hdr.dst_addr, 55984c406e7SOri Kam .proto = mask->hdr.next_proto_id, 56084c406e7SOri Kam .tos = mask->hdr.type_of_service, 56184c406e7SOri Kam }; 56284c406e7SOri Kam /* Remove unwanted bits from values. */ 56384c406e7SOri Kam ipv4.val.src_ip &= ipv4.mask.src_ip; 56484c406e7SOri Kam ipv4.val.dst_ip &= ipv4.mask.dst_ip; 56584c406e7SOri Kam ipv4.val.proto &= ipv4.mask.proto; 56684c406e7SOri Kam ipv4.val.tos &= ipv4.mask.tos; 56784c406e7SOri Kam } 5684a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &ipv4, size); 56984c406e7SOri Kam } 57084c406e7SOri Kam 57184c406e7SOri Kam /** 57284c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 57384c406e7SOri Kam * the input is valid and that there is space to insert the requested item 57484c406e7SOri Kam * into the flow. 57584c406e7SOri Kam * 5764a78c88eSYongseok Koh * @param[in, out] dev_flow 5774a78c88eSYongseok Koh * Pointer to dev_flow structure. 57884c406e7SOri Kam * @param[in] item 57984c406e7SOri Kam * Item specification. 5804a78c88eSYongseok Koh * @param[in] item_flags 5814a78c88eSYongseok Koh * Parsed item flags. 58284c406e7SOri Kam */ 58384c406e7SOri Kam static void 5844a78c88eSYongseok Koh flow_verbs_translate_item_ipv6(struct mlx5_flow *dev_flow, 5854a78c88eSYongseok Koh const struct rte_flow_item *item, 5864a78c88eSYongseok Koh uint64_t item_flags) 58784c406e7SOri Kam { 58884c406e7SOri Kam const struct rte_flow_item_ipv6 *spec = item->spec; 58984c406e7SOri Kam const struct rte_flow_item_ipv6 *mask = item->mask; 59084c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_ipv6); 59184c406e7SOri Kam struct ibv_flow_spec_ipv6 ipv6 = { 5924a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_IPV6 | VERBS_SPEC_INNER(item_flags), 59384c406e7SOri Kam .size = size, 59484c406e7SOri Kam }; 59584c406e7SOri Kam 59684c406e7SOri Kam if (!mask) 59784c406e7SOri Kam mask = &rte_flow_item_ipv6_mask; 59884c406e7SOri Kam if (spec) { 59984c406e7SOri Kam unsigned int i; 60084c406e7SOri Kam uint32_t vtc_flow_val; 60184c406e7SOri Kam uint32_t vtc_flow_mask; 60284c406e7SOri Kam 603*89b5642dSRobin Jarry memcpy(&ipv6.val.src_ip, &spec->hdr.src_addr, 60484c406e7SOri Kam RTE_DIM(ipv6.val.src_ip)); 605*89b5642dSRobin Jarry memcpy(&ipv6.val.dst_ip, &spec->hdr.dst_addr, 60684c406e7SOri Kam RTE_DIM(ipv6.val.dst_ip)); 607*89b5642dSRobin Jarry memcpy(&ipv6.mask.src_ip, &mask->hdr.src_addr, 60884c406e7SOri Kam RTE_DIM(ipv6.mask.src_ip)); 609*89b5642dSRobin Jarry memcpy(&ipv6.mask.dst_ip, &mask->hdr.dst_addr, 61084c406e7SOri Kam RTE_DIM(ipv6.mask.dst_ip)); 61184c406e7SOri Kam vtc_flow_val = rte_be_to_cpu_32(spec->hdr.vtc_flow); 61284c406e7SOri Kam vtc_flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow); 61384c406e7SOri Kam ipv6.val.flow_label = 61424ac604eSOlivier Matz rte_cpu_to_be_32((vtc_flow_val & RTE_IPV6_HDR_FL_MASK) >> 61524ac604eSOlivier Matz RTE_IPV6_HDR_FL_SHIFT); 61624ac604eSOlivier Matz ipv6.val.traffic_class = (vtc_flow_val & RTE_IPV6_HDR_TC_MASK) >> 61724ac604eSOlivier Matz RTE_IPV6_HDR_TC_SHIFT; 61884c406e7SOri Kam ipv6.val.next_hdr = spec->hdr.proto; 61984c406e7SOri Kam ipv6.mask.flow_label = 62024ac604eSOlivier Matz rte_cpu_to_be_32((vtc_flow_mask & RTE_IPV6_HDR_FL_MASK) >> 62124ac604eSOlivier Matz RTE_IPV6_HDR_FL_SHIFT); 62224ac604eSOlivier Matz ipv6.mask.traffic_class = (vtc_flow_mask & RTE_IPV6_HDR_TC_MASK) >> 62324ac604eSOlivier Matz RTE_IPV6_HDR_TC_SHIFT; 62484c406e7SOri Kam ipv6.mask.next_hdr = mask->hdr.proto; 62584c406e7SOri Kam /* Remove unwanted bits from values. */ 62684c406e7SOri Kam for (i = 0; i < RTE_DIM(ipv6.val.src_ip); ++i) { 62784c406e7SOri Kam ipv6.val.src_ip[i] &= ipv6.mask.src_ip[i]; 62884c406e7SOri Kam ipv6.val.dst_ip[i] &= ipv6.mask.dst_ip[i]; 62984c406e7SOri Kam } 63084c406e7SOri Kam ipv6.val.flow_label &= ipv6.mask.flow_label; 63184c406e7SOri Kam ipv6.val.traffic_class &= ipv6.mask.traffic_class; 63284c406e7SOri Kam ipv6.val.next_hdr &= ipv6.mask.next_hdr; 63384c406e7SOri Kam } 6344a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &ipv6, size); 63584c406e7SOri Kam } 63684c406e7SOri Kam 63784c406e7SOri Kam /** 63884c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 63984c406e7SOri Kam * the input is valid and that there is space to insert the requested item 64084c406e7SOri Kam * into the flow. 64184c406e7SOri Kam * 6424a78c88eSYongseok Koh * @param[in, out] dev_flow 6434a78c88eSYongseok Koh * Pointer to dev_flow structure. 64484c406e7SOri Kam * @param[in] item 64584c406e7SOri Kam * Item specification. 6464a78c88eSYongseok Koh * @param[in] item_flags 6474a78c88eSYongseok Koh * Parsed item flags. 64884c406e7SOri Kam */ 64984c406e7SOri Kam static void 6504a78c88eSYongseok Koh flow_verbs_translate_item_tcp(struct mlx5_flow *dev_flow, 6514a78c88eSYongseok Koh const struct rte_flow_item *item, 6524a78c88eSYongseok Koh uint64_t item_flags __rte_unused) 65384c406e7SOri Kam { 65484c406e7SOri Kam const struct rte_flow_item_tcp *spec = item->spec; 65584c406e7SOri Kam const struct rte_flow_item_tcp *mask = item->mask; 65684c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_tcp_udp); 65784c406e7SOri Kam struct ibv_flow_spec_tcp_udp tcp = { 6584a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_TCP | VERBS_SPEC_INNER(item_flags), 65984c406e7SOri Kam .size = size, 66084c406e7SOri Kam }; 66184c406e7SOri Kam 66284c406e7SOri Kam if (!mask) 66384c406e7SOri Kam mask = &rte_flow_item_tcp_mask; 66484c406e7SOri Kam if (spec) { 66584c406e7SOri Kam tcp.val.dst_port = spec->hdr.dst_port; 66684c406e7SOri Kam tcp.val.src_port = spec->hdr.src_port; 66784c406e7SOri Kam tcp.mask.dst_port = mask->hdr.dst_port; 66884c406e7SOri Kam tcp.mask.src_port = mask->hdr.src_port; 66984c406e7SOri Kam /* Remove unwanted bits from values. */ 67084c406e7SOri Kam tcp.val.src_port &= tcp.mask.src_port; 67184c406e7SOri Kam tcp.val.dst_port &= tcp.mask.dst_port; 67284c406e7SOri Kam } 6734a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &tcp, size); 67484c406e7SOri Kam } 67584c406e7SOri Kam 67684c406e7SOri Kam /** 67784c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 67884c406e7SOri Kam * the input is valid and that there is space to insert the requested item 67984c406e7SOri Kam * into the flow. 68084c406e7SOri Kam * 6814a78c88eSYongseok Koh * @param[in, out] dev_flow 6824a78c88eSYongseok Koh * Pointer to dev_flow structure. 68384c406e7SOri Kam * @param[in] item 68484c406e7SOri Kam * Item specification. 6854a78c88eSYongseok Koh * @param[in] item_flags 6864a78c88eSYongseok Koh * Parsed item flags. 68784c406e7SOri Kam */ 68872185352SMaayan Kashani #ifdef HAVE_IBV_FLOW_SPEC_ESP 68972185352SMaayan Kashani static void 69072185352SMaayan Kashani flow_verbs_translate_item_esp(struct mlx5_flow *dev_flow, 69172185352SMaayan Kashani const struct rte_flow_item *item, 69272185352SMaayan Kashani uint64_t item_flags __rte_unused) 69372185352SMaayan Kashani { 69472185352SMaayan Kashani const struct rte_flow_item_esp *spec = item->spec; 69572185352SMaayan Kashani const struct rte_flow_item_esp *mask = item->mask; 69672185352SMaayan Kashani unsigned int size = sizeof(struct ibv_flow_spec_esp); 69772185352SMaayan Kashani struct ibv_flow_spec_esp esp = { 69872185352SMaayan Kashani .type = IBV_FLOW_SPEC_ESP | VERBS_SPEC_INNER(item_flags), 69972185352SMaayan Kashani .size = size, 70072185352SMaayan Kashani }; 70172185352SMaayan Kashani 70272185352SMaayan Kashani if (!mask) 70372185352SMaayan Kashani mask = &rte_flow_item_esp_mask; 70472185352SMaayan Kashani if (spec) { 70572185352SMaayan Kashani esp.val.spi = spec->hdr.spi & mask->hdr.spi; 70672185352SMaayan Kashani esp.mask.spi = mask->hdr.spi; 70772185352SMaayan Kashani } 70872185352SMaayan Kashani flow_verbs_spec_add(&dev_flow->verbs, &esp, size); 70972185352SMaayan Kashani } 71072185352SMaayan Kashani #endif 71172185352SMaayan Kashani 71272185352SMaayan Kashani /** 71372185352SMaayan Kashani * Convert the @p item into a Verbs specification. This function assumes that 71472185352SMaayan Kashani * the input is valid and that there is space to insert the requested item 71572185352SMaayan Kashani * into the flow. 71672185352SMaayan Kashani * 71772185352SMaayan Kashani * @param[in, out] dev_flow 71872185352SMaayan Kashani * Pointer to dev_flow structure. 71972185352SMaayan Kashani * @param[in] item 72072185352SMaayan Kashani * Item specification. 72172185352SMaayan Kashani * @param[in] item_flags 72272185352SMaayan Kashani * Parsed item flags. 72372185352SMaayan Kashani */ 72484c406e7SOri Kam static void 7254a78c88eSYongseok Koh flow_verbs_translate_item_udp(struct mlx5_flow *dev_flow, 7264a78c88eSYongseok Koh const struct rte_flow_item *item, 7274a78c88eSYongseok Koh uint64_t item_flags __rte_unused) 7284a78c88eSYongseok Koh { 7294a78c88eSYongseok Koh const struct rte_flow_item_udp *spec = item->spec; 7304a78c88eSYongseok Koh const struct rte_flow_item_udp *mask = item->mask; 7314a78c88eSYongseok Koh unsigned int size = sizeof(struct ibv_flow_spec_tcp_udp); 7324a78c88eSYongseok Koh struct ibv_flow_spec_tcp_udp udp = { 7334a78c88eSYongseok Koh .type = IBV_FLOW_SPEC_UDP | VERBS_SPEC_INNER(item_flags), 7344a78c88eSYongseok Koh .size = size, 7354a78c88eSYongseok Koh }; 7364a78c88eSYongseok Koh 7374a78c88eSYongseok Koh if (!mask) 7384a78c88eSYongseok Koh mask = &rte_flow_item_udp_mask; 7394a78c88eSYongseok Koh if (spec) { 7404a78c88eSYongseok Koh udp.val.dst_port = spec->hdr.dst_port; 7414a78c88eSYongseok Koh udp.val.src_port = spec->hdr.src_port; 7424a78c88eSYongseok Koh udp.mask.dst_port = mask->hdr.dst_port; 7434a78c88eSYongseok Koh udp.mask.src_port = mask->hdr.src_port; 7444a78c88eSYongseok Koh /* Remove unwanted bits from values. */ 7454a78c88eSYongseok Koh udp.val.src_port &= udp.mask.src_port; 7464a78c88eSYongseok Koh udp.val.dst_port &= udp.mask.dst_port; 7474a78c88eSYongseok Koh } 7488a2e026aSRaslan Darawsheh item++; 7498a2e026aSRaslan Darawsheh while (item->type == RTE_FLOW_ITEM_TYPE_VOID) 7508a2e026aSRaslan Darawsheh item++; 7518a2e026aSRaslan Darawsheh if (!(udp.val.dst_port & udp.mask.dst_port)) { 7528a2e026aSRaslan Darawsheh switch ((item)->type) { 7538a2e026aSRaslan Darawsheh case RTE_FLOW_ITEM_TYPE_VXLAN: 7548a2e026aSRaslan Darawsheh udp.val.dst_port = htons(MLX5_UDP_PORT_VXLAN); 7558a2e026aSRaslan Darawsheh udp.mask.dst_port = 0xffff; 7568a2e026aSRaslan Darawsheh break; 7578a2e026aSRaslan Darawsheh case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 7588a2e026aSRaslan Darawsheh udp.val.dst_port = htons(MLX5_UDP_PORT_VXLAN_GPE); 7598a2e026aSRaslan Darawsheh udp.mask.dst_port = 0xffff; 7608a2e026aSRaslan Darawsheh break; 7618a2e026aSRaslan Darawsheh case RTE_FLOW_ITEM_TYPE_MPLS: 7628a2e026aSRaslan Darawsheh udp.val.dst_port = htons(MLX5_UDP_PORT_MPLS); 7638a2e026aSRaslan Darawsheh udp.mask.dst_port = 0xffff; 7648a2e026aSRaslan Darawsheh break; 7658a2e026aSRaslan Darawsheh default: 7668a2e026aSRaslan Darawsheh break; 7678a2e026aSRaslan Darawsheh } 7688a2e026aSRaslan Darawsheh } 7698a2e026aSRaslan Darawsheh 7704a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &udp, size); 7714a78c88eSYongseok Koh } 7724a78c88eSYongseok Koh 7734a78c88eSYongseok Koh /** 7744a78c88eSYongseok Koh * Convert the @p item into a Verbs specification. This function assumes that 7754a78c88eSYongseok Koh * the input is valid and that there is space to insert the requested item 7764a78c88eSYongseok Koh * into the flow. 7774a78c88eSYongseok Koh * 7784a78c88eSYongseok Koh * @param[in, out] dev_flow 7794a78c88eSYongseok Koh * Pointer to dev_flow structure. 7804a78c88eSYongseok Koh * @param[in] item 7814a78c88eSYongseok Koh * Item specification. 7824a78c88eSYongseok Koh * @param[in] item_flags 7834a78c88eSYongseok Koh * Parsed item flags. 7844a78c88eSYongseok Koh */ 7854a78c88eSYongseok Koh static void 7864a78c88eSYongseok Koh flow_verbs_translate_item_vxlan(struct mlx5_flow *dev_flow, 7874a78c88eSYongseok Koh const struct rte_flow_item *item, 7884a78c88eSYongseok Koh uint64_t item_flags __rte_unused) 78984c406e7SOri Kam { 79084c406e7SOri Kam const struct rte_flow_item_vxlan *spec = item->spec; 79184c406e7SOri Kam const struct rte_flow_item_vxlan *mask = item->mask; 79284c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_tunnel); 79384c406e7SOri Kam struct ibv_flow_spec_tunnel vxlan = { 79484c406e7SOri Kam .type = IBV_FLOW_SPEC_VXLAN_TUNNEL, 79584c406e7SOri Kam .size = size, 79684c406e7SOri Kam }; 79784c406e7SOri Kam union vni { 79884c406e7SOri Kam uint32_t vlan_id; 79984c406e7SOri Kam uint8_t vni[4]; 80084c406e7SOri Kam } id = { .vlan_id = 0, }; 80184c406e7SOri Kam 80284c406e7SOri Kam if (!mask) 80384c406e7SOri Kam mask = &rte_flow_item_vxlan_mask; 80484c406e7SOri Kam if (spec) { 8055ec2a97eSThomas Monjalon memcpy(&id.vni[1], spec->hdr.vni, 3); 80684c406e7SOri Kam vxlan.val.tunnel_id = id.vlan_id; 8075ec2a97eSThomas Monjalon memcpy(&id.vni[1], mask->hdr.vni, 3); 80884c406e7SOri Kam vxlan.mask.tunnel_id = id.vlan_id; 80984c406e7SOri Kam /* Remove unwanted bits from values. */ 81084c406e7SOri Kam vxlan.val.tunnel_id &= vxlan.mask.tunnel_id; 81184c406e7SOri Kam } 8124a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &vxlan, size); 81384c406e7SOri Kam } 81484c406e7SOri Kam 81584c406e7SOri Kam /** 81684c406e7SOri Kam * Convert the @p item into a Verbs specification. This function assumes that 81784c406e7SOri Kam * the input is valid and that there is space to insert the requested item 81884c406e7SOri Kam * into the flow. 81984c406e7SOri Kam * 8204a78c88eSYongseok Koh * @param[in, out] dev_flow 8214a78c88eSYongseok Koh * Pointer to dev_flow structure. 82284c406e7SOri Kam * @param[in] item 82384c406e7SOri Kam * Item specification. 8244a78c88eSYongseok Koh * @param[in] item_flags 8254a78c88eSYongseok Koh * Parsed item flags. 82684c406e7SOri Kam */ 82784c406e7SOri Kam static void 8284a78c88eSYongseok Koh flow_verbs_translate_item_vxlan_gpe(struct mlx5_flow *dev_flow, 8294a78c88eSYongseok Koh const struct rte_flow_item *item, 8304a78c88eSYongseok Koh uint64_t item_flags __rte_unused) 83184c406e7SOri Kam { 83284c406e7SOri Kam const struct rte_flow_item_vxlan_gpe *spec = item->spec; 83384c406e7SOri Kam const struct rte_flow_item_vxlan_gpe *mask = item->mask; 83484c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_tunnel); 83584c406e7SOri Kam struct ibv_flow_spec_tunnel vxlan_gpe = { 83684c406e7SOri Kam .type = IBV_FLOW_SPEC_VXLAN_TUNNEL, 83784c406e7SOri Kam .size = size, 83884c406e7SOri Kam }; 83984c406e7SOri Kam union vni { 84084c406e7SOri Kam uint32_t vlan_id; 84184c406e7SOri Kam uint8_t vni[4]; 84284c406e7SOri Kam } id = { .vlan_id = 0, }; 84384c406e7SOri Kam 84484c406e7SOri Kam if (!mask) 84584c406e7SOri Kam mask = &rte_flow_item_vxlan_gpe_mask; 84684c406e7SOri Kam if (spec) { 8475ec2a97eSThomas Monjalon memcpy(&id.vni[1], spec->hdr.vni, 3); 84884c406e7SOri Kam vxlan_gpe.val.tunnel_id = id.vlan_id; 8495ec2a97eSThomas Monjalon memcpy(&id.vni[1], mask->hdr.vni, 3); 85084c406e7SOri Kam vxlan_gpe.mask.tunnel_id = id.vlan_id; 85184c406e7SOri Kam /* Remove unwanted bits from values. */ 85284c406e7SOri Kam vxlan_gpe.val.tunnel_id &= vxlan_gpe.mask.tunnel_id; 85384c406e7SOri Kam } 8544a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &vxlan_gpe, size); 85584c406e7SOri Kam } 85684c406e7SOri Kam 85784c406e7SOri Kam /** 85884c406e7SOri Kam * Update the protocol in Verbs IPv4/IPv6 spec. 85984c406e7SOri Kam * 86084c406e7SOri Kam * @param[in, out] attr 86184c406e7SOri Kam * Pointer to Verbs attributes structure. 86284c406e7SOri Kam * @param[in] search 86384c406e7SOri Kam * Specification type to search in order to update the IP protocol. 86484c406e7SOri Kam * @param[in] protocol 86584c406e7SOri Kam * Protocol value to set if none is present in the specification. 86684c406e7SOri Kam */ 86784c406e7SOri Kam static void 86884c406e7SOri Kam flow_verbs_item_gre_ip_protocol_update(struct ibv_flow_attr *attr, 86984c406e7SOri Kam enum ibv_flow_spec_type search, 87084c406e7SOri Kam uint8_t protocol) 87184c406e7SOri Kam { 87284c406e7SOri Kam unsigned int i; 87384c406e7SOri Kam struct ibv_spec_header *hdr = (struct ibv_spec_header *) 87484c406e7SOri Kam ((uint8_t *)attr + sizeof(struct ibv_flow_attr)); 87584c406e7SOri Kam 87684c406e7SOri Kam if (!attr) 87784c406e7SOri Kam return; 87884c406e7SOri Kam for (i = 0; i != attr->num_of_specs; ++i) { 87984c406e7SOri Kam if (hdr->type == search) { 88084c406e7SOri Kam union { 88184c406e7SOri Kam struct ibv_flow_spec_ipv4_ext *ipv4; 88284c406e7SOri Kam struct ibv_flow_spec_ipv6 *ipv6; 88384c406e7SOri Kam } ip; 88484c406e7SOri Kam 88584c406e7SOri Kam switch (search) { 88684c406e7SOri Kam case IBV_FLOW_SPEC_IPV4_EXT: 88784c406e7SOri Kam ip.ipv4 = (struct ibv_flow_spec_ipv4_ext *)hdr; 88884c406e7SOri Kam if (!ip.ipv4->val.proto) { 88984c406e7SOri Kam ip.ipv4->val.proto = protocol; 89084c406e7SOri Kam ip.ipv4->mask.proto = 0xff; 89184c406e7SOri Kam } 89284c406e7SOri Kam break; 89384c406e7SOri Kam case IBV_FLOW_SPEC_IPV6: 89484c406e7SOri Kam ip.ipv6 = (struct ibv_flow_spec_ipv6 *)hdr; 89584c406e7SOri Kam if (!ip.ipv6->val.next_hdr) { 89684c406e7SOri Kam ip.ipv6->val.next_hdr = protocol; 89784c406e7SOri Kam ip.ipv6->mask.next_hdr = 0xff; 89884c406e7SOri Kam } 89984c406e7SOri Kam break; 90084c406e7SOri Kam default: 90184c406e7SOri Kam break; 90284c406e7SOri Kam } 90384c406e7SOri Kam break; 90484c406e7SOri Kam } 90584c406e7SOri Kam hdr = (struct ibv_spec_header *)((uint8_t *)hdr + hdr->size); 90684c406e7SOri Kam } 90784c406e7SOri Kam } 90884c406e7SOri Kam 90984c406e7SOri Kam /** 91098008ce6SDariusz Sosnowski * Reserve space for GRE spec in spec buffer. 91184c406e7SOri Kam * 9124a78c88eSYongseok Koh * @param[in,out] dev_flow 9134a78c88eSYongseok Koh * Pointer to dev_flow structure. 91498008ce6SDariusz Sosnowski * 91598008ce6SDariusz Sosnowski * @return 91698008ce6SDariusz Sosnowski * Pointer to reserved space in spec buffer. 91798008ce6SDariusz Sosnowski */ 91898008ce6SDariusz Sosnowski static uint8_t * 91998008ce6SDariusz Sosnowski flow_verbs_reserve_gre(struct mlx5_flow *dev_flow) 92098008ce6SDariusz Sosnowski { 92198008ce6SDariusz Sosnowski uint8_t *buffer; 92298008ce6SDariusz Sosnowski struct mlx5_flow_verbs_workspace *verbs = &dev_flow->verbs; 92398008ce6SDariusz Sosnowski #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT 92498008ce6SDariusz Sosnowski unsigned int size = sizeof(struct ibv_flow_spec_tunnel); 92598008ce6SDariusz Sosnowski struct ibv_flow_spec_tunnel tunnel = { 92698008ce6SDariusz Sosnowski .type = IBV_FLOW_SPEC_VXLAN_TUNNEL, 92798008ce6SDariusz Sosnowski .size = size, 92898008ce6SDariusz Sosnowski }; 92998008ce6SDariusz Sosnowski #else 93098008ce6SDariusz Sosnowski unsigned int size = sizeof(struct ibv_flow_spec_gre); 93198008ce6SDariusz Sosnowski struct ibv_flow_spec_gre tunnel = { 93298008ce6SDariusz Sosnowski .type = IBV_FLOW_SPEC_GRE, 93398008ce6SDariusz Sosnowski .size = size, 93498008ce6SDariusz Sosnowski }; 93598008ce6SDariusz Sosnowski #endif 93698008ce6SDariusz Sosnowski 93798008ce6SDariusz Sosnowski buffer = verbs->specs + verbs->size; 93898008ce6SDariusz Sosnowski flow_verbs_spec_add(verbs, &tunnel, size); 93998008ce6SDariusz Sosnowski return buffer; 94098008ce6SDariusz Sosnowski } 94198008ce6SDariusz Sosnowski 94298008ce6SDariusz Sosnowski /** 94398008ce6SDariusz Sosnowski * Convert the @p item into a Verbs specification. This function assumes that 94498008ce6SDariusz Sosnowski * the input is valid and that Verbs specification will be placed in 94598008ce6SDariusz Sosnowski * the pre-reserved space. 94698008ce6SDariusz Sosnowski * 94798008ce6SDariusz Sosnowski * @param[in, out] dev_flow 94898008ce6SDariusz Sosnowski * Pointer to dev_flow structure. 94998008ce6SDariusz Sosnowski * @param[in, out] gre_spec 95098008ce6SDariusz Sosnowski * Pointer to space reserved for GRE spec. 95184c406e7SOri Kam * @param[in] item 95284c406e7SOri Kam * Item specification. 9534a78c88eSYongseok Koh * @param[in] item_flags 9544a78c88eSYongseok Koh * Parsed item flags. 95584c406e7SOri Kam */ 95684c406e7SOri Kam static void 9574a78c88eSYongseok Koh flow_verbs_translate_item_gre(struct mlx5_flow *dev_flow, 95898008ce6SDariusz Sosnowski uint8_t *gre_spec, 9594a78c88eSYongseok Koh const struct rte_flow_item *item __rte_unused, 9604a78c88eSYongseok Koh uint64_t item_flags) 96184c406e7SOri Kam { 962e7bfa359SBing Zhao struct mlx5_flow_verbs_workspace *verbs = &dev_flow->verbs; 96384c406e7SOri Kam #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT 96484c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_tunnel); 96584c406e7SOri Kam struct ibv_flow_spec_tunnel tunnel = { 96684c406e7SOri Kam .type = IBV_FLOW_SPEC_VXLAN_TUNNEL, 96784c406e7SOri Kam .size = size, 96884c406e7SOri Kam }; 96984c406e7SOri Kam #else 970985b4792SGregory Etelson static const struct rte_flow_item_gre empty_gre = {0,}; 97184c406e7SOri Kam const struct rte_flow_item_gre *spec = item->spec; 97284c406e7SOri Kam const struct rte_flow_item_gre *mask = item->mask; 97384c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_gre); 97484c406e7SOri Kam struct ibv_flow_spec_gre tunnel = { 97584c406e7SOri Kam .type = IBV_FLOW_SPEC_GRE, 97684c406e7SOri Kam .size = size, 97784c406e7SOri Kam }; 97884c406e7SOri Kam 979985b4792SGregory Etelson if (!spec) { 980985b4792SGregory Etelson spec = &empty_gre; 981985b4792SGregory Etelson mask = &empty_gre; 982985b4792SGregory Etelson } else { 98384c406e7SOri Kam if (!mask) 98484c406e7SOri Kam mask = &rte_flow_item_gre_mask; 985985b4792SGregory Etelson } 98684c406e7SOri Kam tunnel.val.c_ks_res0_ver = spec->c_rsvd0_ver; 98784c406e7SOri Kam tunnel.val.protocol = spec->protocol; 98884c406e7SOri Kam tunnel.mask.c_ks_res0_ver = mask->c_rsvd0_ver; 98984c406e7SOri Kam tunnel.mask.protocol = mask->protocol; 99084c406e7SOri Kam /* Remove unwanted bits from values. */ 99184c406e7SOri Kam tunnel.val.c_ks_res0_ver &= tunnel.mask.c_ks_res0_ver; 99284c406e7SOri Kam tunnel.val.key &= tunnel.mask.key; 993985b4792SGregory Etelson if (tunnel.mask.protocol) { 994985b4792SGregory Etelson tunnel.val.protocol &= tunnel.mask.protocol; 995985b4792SGregory Etelson } else { 996985b4792SGregory Etelson tunnel.val.protocol = mlx5_translate_tunnel_etypes(item_flags); 997985b4792SGregory Etelson if (tunnel.val.protocol) { 998985b4792SGregory Etelson tunnel.mask.protocol = 0xFFFF; 999985b4792SGregory Etelson tunnel.val.protocol = 1000985b4792SGregory Etelson rte_cpu_to_be_16(tunnel.val.protocol); 1001985b4792SGregory Etelson } 100284c406e7SOri Kam } 100384c406e7SOri Kam #endif 10044a78c88eSYongseok Koh if (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) 1005e7bfa359SBing Zhao flow_verbs_item_gre_ip_protocol_update(&verbs->attr, 100684c406e7SOri Kam IBV_FLOW_SPEC_IPV4_EXT, 100784c406e7SOri Kam IPPROTO_GRE); 100884c406e7SOri Kam else 1009e7bfa359SBing Zhao flow_verbs_item_gre_ip_protocol_update(&verbs->attr, 101084c406e7SOri Kam IBV_FLOW_SPEC_IPV6, 101184c406e7SOri Kam IPPROTO_GRE); 101298008ce6SDariusz Sosnowski MLX5_ASSERT(gre_spec); 101398008ce6SDariusz Sosnowski memcpy(gre_spec, &tunnel, size); 101484c406e7SOri Kam } 101584c406e7SOri Kam 101684c406e7SOri Kam /** 101784c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 101884c406e7SOri Kam * the input is valid and that there is space to insert the requested action 101984c406e7SOri Kam * into the flow. This function also return the action that was added. 102084c406e7SOri Kam * 10214a78c88eSYongseok Koh * @param[in, out] dev_flow 10224a78c88eSYongseok Koh * Pointer to dev_flow structure. 102384c406e7SOri Kam * @param[in] item 102484c406e7SOri Kam * Item specification. 10254a78c88eSYongseok Koh * @param[in] item_flags 10264a78c88eSYongseok Koh * Parsed item flags. 102784c406e7SOri Kam */ 102884c406e7SOri Kam static void 10294a78c88eSYongseok Koh flow_verbs_translate_item_mpls(struct mlx5_flow *dev_flow __rte_unused, 10304a78c88eSYongseok Koh const struct rte_flow_item *item __rte_unused, 10314a78c88eSYongseok Koh uint64_t item_flags __rte_unused) 103284c406e7SOri Kam { 103384c406e7SOri Kam #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 103484c406e7SOri Kam const struct rte_flow_item_mpls *spec = item->spec; 103584c406e7SOri Kam const struct rte_flow_item_mpls *mask = item->mask; 103684c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_mpls); 103784c406e7SOri Kam struct ibv_flow_spec_mpls mpls = { 103884c406e7SOri Kam .type = IBV_FLOW_SPEC_MPLS, 103984c406e7SOri Kam .size = size, 104084c406e7SOri Kam }; 104184c406e7SOri Kam 104284c406e7SOri Kam if (!mask) 104384c406e7SOri Kam mask = &rte_flow_item_mpls_mask; 104484c406e7SOri Kam if (spec) { 104584c406e7SOri Kam memcpy(&mpls.val.label, spec, sizeof(mpls.val.label)); 104684c406e7SOri Kam memcpy(&mpls.mask.label, mask, sizeof(mpls.mask.label)); 104784c406e7SOri Kam /* Remove unwanted bits from values. */ 104884c406e7SOri Kam mpls.val.label &= mpls.mask.label; 104984c406e7SOri Kam } 10504a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &mpls, size); 105184c406e7SOri Kam #endif 105284c406e7SOri Kam } 105384c406e7SOri Kam 105484c406e7SOri Kam /** 105584c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 105684c406e7SOri Kam * the input is valid and that there is space to insert the requested action 10574a78c88eSYongseok Koh * into the flow. 105884c406e7SOri Kam * 105984c406e7SOri Kam * @param[in] dev_flow 106084c406e7SOri Kam * Pointer to mlx5_flow. 10614a78c88eSYongseok Koh * @param[in] action 10624a78c88eSYongseok Koh * Action configuration. 106384c406e7SOri Kam */ 106484c406e7SOri Kam static void 10654a78c88eSYongseok Koh flow_verbs_translate_action_drop 10664a78c88eSYongseok Koh (struct mlx5_flow *dev_flow, 10674a78c88eSYongseok Koh const struct rte_flow_action *action __rte_unused) 106884c406e7SOri Kam { 106984c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_action_drop); 107084c406e7SOri Kam struct ibv_flow_spec_action_drop drop = { 107184c406e7SOri Kam .type = IBV_FLOW_SPEC_ACTION_DROP, 107284c406e7SOri Kam .size = size, 107384c406e7SOri Kam }; 107484c406e7SOri Kam 10754a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &drop, size); 107684c406e7SOri Kam } 107784c406e7SOri Kam 107884c406e7SOri Kam /** 107984c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 108084c406e7SOri Kam * the input is valid and that there is space to insert the requested action 10814a78c88eSYongseok Koh * into the flow. 108284c406e7SOri Kam * 1083e745f900SSuanming Mou * @param[in] rss_desc 1084e745f900SSuanming Mou * Pointer to mlx5_flow_rss_desc. 10854a78c88eSYongseok Koh * @param[in] action 10864a78c88eSYongseok Koh * Action configuration. 108784c406e7SOri Kam */ 108884c406e7SOri Kam static void 1089e745f900SSuanming Mou flow_verbs_translate_action_queue(struct mlx5_flow_rss_desc *rss_desc, 10904a78c88eSYongseok Koh const struct rte_flow_action *action) 109184c406e7SOri Kam { 109284c406e7SOri Kam const struct rte_flow_action_queue *queue = action->conf; 109384c406e7SOri Kam 1094e745f900SSuanming Mou rss_desc->queue[0] = queue->index; 1095e745f900SSuanming Mou rss_desc->queue_num = 1; 109684c406e7SOri Kam } 109784c406e7SOri Kam 109884c406e7SOri Kam /** 109984c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 110084c406e7SOri Kam * the input is valid and that there is space to insert the requested action 11014a78c88eSYongseok Koh * into the flow. 110284c406e7SOri Kam * 1103e745f900SSuanming Mou * @param[in] rss_desc 1104e745f900SSuanming Mou * Pointer to mlx5_flow_rss_desc. 110584c406e7SOri Kam * @param[in] action 110684c406e7SOri Kam * Action configuration. 110784c406e7SOri Kam */ 110884c406e7SOri Kam static void 1109e745f900SSuanming Mou flow_verbs_translate_action_rss(struct mlx5_flow_rss_desc *rss_desc, 11104a78c88eSYongseok Koh const struct rte_flow_action *action) 111184c406e7SOri Kam { 111284c406e7SOri Kam const struct rte_flow_action_rss *rss = action->conf; 1113f1b85a27SOphir Munk const uint8_t *rss_key; 111484c406e7SOri Kam 1115e745f900SSuanming Mou memcpy(rss_desc->queue, rss->queue, rss->queue_num * sizeof(uint16_t)); 1116e745f900SSuanming Mou rss_desc->queue_num = rss->queue_num; 1117f1b85a27SOphir Munk /* NULL RSS key indicates default RSS key. */ 1118f1b85a27SOphir Munk rss_key = !rss->key ? rss_hash_default_key : rss->key; 1119e745f900SSuanming Mou memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN); 1120e205c95fSViacheslav Ovsiienko /* 1121e205c95fSViacheslav Ovsiienko * rss->level and rss.types should be set in advance when expanding 1122e205c95fSViacheslav Ovsiienko * items for RSS. 1123e205c95fSViacheslav Ovsiienko */ 112484c406e7SOri Kam } 112584c406e7SOri Kam 112684c406e7SOri Kam /** 112784c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 112884c406e7SOri Kam * the input is valid and that there is space to insert the requested action 11294a78c88eSYongseok Koh * into the flow. 113084c406e7SOri Kam * 113184c406e7SOri Kam * @param[in] dev_flow 113284c406e7SOri Kam * Pointer to mlx5_flow. 11334a78c88eSYongseok Koh * @param[in] action 11344a78c88eSYongseok Koh * Action configuration. 113584c406e7SOri Kam */ 113684c406e7SOri Kam static void 113784c406e7SOri Kam flow_verbs_translate_action_flag 11384a78c88eSYongseok Koh (struct mlx5_flow *dev_flow, 11394a78c88eSYongseok Koh const struct rte_flow_action *action __rte_unused) 114084c406e7SOri Kam { 114184c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_action_tag); 114284c406e7SOri Kam struct ibv_flow_spec_action_tag tag = { 114384c406e7SOri Kam .type = IBV_FLOW_SPEC_ACTION_TAG, 114484c406e7SOri Kam .size = size, 114584c406e7SOri Kam .tag_id = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT), 114684c406e7SOri Kam }; 114784c406e7SOri Kam 11484a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &tag, size); 114984c406e7SOri Kam } 115084c406e7SOri Kam 115184c406e7SOri Kam /** 115284c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 115384c406e7SOri Kam * the input is valid and that there is space to insert the requested action 11544a78c88eSYongseok Koh * into the flow. 115584c406e7SOri Kam * 115684c406e7SOri Kam * @param[in] dev_flow 115784c406e7SOri Kam * Pointer to mlx5_flow. 11584a78c88eSYongseok Koh * @param[in] action 11594a78c88eSYongseok Koh * Action configuration. 116084c406e7SOri Kam */ 116184c406e7SOri Kam static void 11624a78c88eSYongseok Koh flow_verbs_translate_action_mark(struct mlx5_flow *dev_flow, 11634a78c88eSYongseok Koh const struct rte_flow_action *action) 116484c406e7SOri Kam { 116584c406e7SOri Kam const struct rte_flow_action_mark *mark = action->conf; 116684c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_action_tag); 116784c406e7SOri Kam struct ibv_flow_spec_action_tag tag = { 116884c406e7SOri Kam .type = IBV_FLOW_SPEC_ACTION_TAG, 116984c406e7SOri Kam .size = size, 11704a78c88eSYongseok Koh .tag_id = mlx5_flow_mark_set(mark->id), 117184c406e7SOri Kam }; 117284c406e7SOri Kam 11734a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &tag, size); 117484c406e7SOri Kam } 117584c406e7SOri Kam 117684c406e7SOri Kam /** 117784c406e7SOri Kam * Convert the @p action into a Verbs specification. This function assumes that 117884c406e7SOri Kam * the input is valid and that there is space to insert the requested action 11794a78c88eSYongseok Koh * into the flow. 118084c406e7SOri Kam * 118184c406e7SOri Kam * @param[in] dev 118284c406e7SOri Kam * Pointer to the Ethernet device structure. 118384c406e7SOri Kam * @param[in] action 118484c406e7SOri Kam * Action configuration. 118584c406e7SOri Kam * @param[in] dev_flow 118684c406e7SOri Kam * Pointer to mlx5_flow. 118784c406e7SOri Kam * @param[out] error 118884c406e7SOri Kam * Pointer to error structure. 118984c406e7SOri Kam * 119084c406e7SOri Kam * @return 119184c406e7SOri Kam * 0 On success else a negative errno value is returned and rte_errno is set. 119284c406e7SOri Kam */ 119384c406e7SOri Kam static int 11944a78c88eSYongseok Koh flow_verbs_translate_action_count(struct mlx5_flow *dev_flow, 119584c406e7SOri Kam const struct rte_flow_action *action, 11964a78c88eSYongseok Koh struct rte_eth_dev *dev, 119784c406e7SOri Kam struct rte_flow_error *error) 119884c406e7SOri Kam { 119984c406e7SOri Kam const struct rte_flow_action_count *count = action->conf; 120084c406e7SOri Kam struct rte_flow *flow = dev_flow->flow; 1201db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \ 1202db48f9dbSViacheslav Ovsiienko defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 1203826b8a87SSuanming Mou struct mlx5_flow_counter_pool *pool; 1204826b8a87SSuanming Mou struct mlx5_flow_counter *cnt = NULL; 120584c406e7SOri Kam unsigned int size = sizeof(struct ibv_flow_spec_counter_action); 120684c406e7SOri Kam struct ibv_flow_spec_counter_action counter = { 120784c406e7SOri Kam .type = IBV_FLOW_SPEC_ACTION_COUNT, 120884c406e7SOri Kam .size = size, 120984c406e7SOri Kam }; 121084c406e7SOri Kam #endif 121184c406e7SOri Kam 121284c406e7SOri Kam if (!flow->counter) { 121392ef4b8fSAndrew Rybchenko flow->counter = flow_verbs_counter_new(dev, count->id); 121484c406e7SOri Kam if (!flow->counter) 121584c406e7SOri Kam return rte_flow_error_set(error, rte_errno, 121684c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, 121784c406e7SOri Kam action, 121884c406e7SOri Kam "cannot get counter" 121984c406e7SOri Kam " context."); 122084c406e7SOri Kam } 1221db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) 1222826b8a87SSuanming Mou cnt = flow_verbs_counter_get_by_idx(dev, flow->counter, &pool); 12232b5b1aebSSuanming Mou counter.counter_set_handle = 12242b5b1aebSSuanming Mou ((struct ibv_counter_set *)cnt->dcs_when_active)->handle; 12254a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &counter, size); 1226db48f9dbSViacheslav Ovsiienko #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 1227826b8a87SSuanming Mou cnt = flow_verbs_counter_get_by_idx(dev, flow->counter, &pool); 12282b5b1aebSSuanming Mou counter.counters = (struct ibv_counters *)cnt->dcs_when_active; 12294a78c88eSYongseok Koh flow_verbs_spec_add(&dev_flow->verbs, &counter, size); 123084c406e7SOri Kam #endif 123184c406e7SOri Kam return 0; 123284c406e7SOri Kam } 123384c406e7SOri Kam 123484c406e7SOri Kam /** 1235c16e10f1SDariusz Sosnowski * Validates @p attributes of the flow rule. 1236c16e10f1SDariusz Sosnowski * 1237c16e10f1SDariusz Sosnowski * This function is used if and only if legacy Verbs flow engine is used. 1238c16e10f1SDariusz Sosnowski * 1239c16e10f1SDariusz Sosnowski * @param[in] dev 1240c16e10f1SDariusz Sosnowski * Pointer to the Ethernet device structure. 1241c16e10f1SDariusz Sosnowski * @param[in] attributes 1242c16e10f1SDariusz Sosnowski * Pointer to flow attributes 1243c16e10f1SDariusz Sosnowski * @param[out] error 1244c16e10f1SDariusz Sosnowski * Pointer to error structure. 1245c16e10f1SDariusz Sosnowski * 1246c16e10f1SDariusz Sosnowski * @return 1247c16e10f1SDariusz Sosnowski * 0 on success, a negative errno value otherwise and rte_errno is set. 1248c16e10f1SDariusz Sosnowski */ 1249c16e10f1SDariusz Sosnowski static int 1250c16e10f1SDariusz Sosnowski flow_verbs_validate_attributes(struct rte_eth_dev *dev, 1251c16e10f1SDariusz Sosnowski const struct rte_flow_attr *attributes, 1252c16e10f1SDariusz Sosnowski struct rte_flow_error *error) 1253c16e10f1SDariusz Sosnowski { 1254c16e10f1SDariusz Sosnowski struct mlx5_priv *priv = dev->data->dev_private; 1255c16e10f1SDariusz Sosnowski uint32_t priority_max = priv->sh->flow_max_priority - 1; 1256c16e10f1SDariusz Sosnowski 1257c16e10f1SDariusz Sosnowski if (attributes->group) 1258c16e10f1SDariusz Sosnowski return rte_flow_error_set(error, ENOTSUP, 1259c16e10f1SDariusz Sosnowski RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 1260c16e10f1SDariusz Sosnowski NULL, "groups is not supported"); 1261c16e10f1SDariusz Sosnowski if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR && 1262c16e10f1SDariusz Sosnowski attributes->priority >= priority_max) 1263c16e10f1SDariusz Sosnowski return rte_flow_error_set(error, ENOTSUP, 1264c16e10f1SDariusz Sosnowski RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1265c16e10f1SDariusz Sosnowski NULL, "priority out of range"); 1266c16e10f1SDariusz Sosnowski if (attributes->egress) 1267c16e10f1SDariusz Sosnowski return rte_flow_error_set(error, ENOTSUP, 1268c16e10f1SDariusz Sosnowski RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1269c16e10f1SDariusz Sosnowski "egress is not supported"); 1270c16e10f1SDariusz Sosnowski if (attributes->transfer) 1271c16e10f1SDariusz Sosnowski return rte_flow_error_set(error, ENOTSUP, 1272c16e10f1SDariusz Sosnowski RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 1273c16e10f1SDariusz Sosnowski NULL, "transfer is not supported"); 1274c16e10f1SDariusz Sosnowski if (!attributes->ingress) 1275c16e10f1SDariusz Sosnowski return rte_flow_error_set(error, EINVAL, 1276c16e10f1SDariusz Sosnowski RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1277c16e10f1SDariusz Sosnowski NULL, 1278c16e10f1SDariusz Sosnowski "ingress attribute is mandatory"); 1279c16e10f1SDariusz Sosnowski return 0; 1280c16e10f1SDariusz Sosnowski } 1281c16e10f1SDariusz Sosnowski 1282c16e10f1SDariusz Sosnowski /** 128384c406e7SOri Kam * Internal validation function. For validating both actions and items. 128484c406e7SOri Kam * 128584c406e7SOri Kam * @param[in] dev 128684c406e7SOri Kam * Pointer to the Ethernet device structure. 128784c406e7SOri Kam * @param[in] attr 128884c406e7SOri Kam * Pointer to the flow attributes. 128984c406e7SOri Kam * @param[in] items 129084c406e7SOri Kam * Pointer to the list of items. 129184c406e7SOri Kam * @param[in] actions 129284c406e7SOri Kam * Pointer to the list of actions. 1293b67b4ecbSDekel Peled * @param[in] external 1294b67b4ecbSDekel Peled * This flow rule is created by request external to PMD. 129572a944dbSBing Zhao * @param[in] hairpin 129672a944dbSBing Zhao * Number of hairpin TX actions, 0 means classic flow. 129784c406e7SOri Kam * @param[out] error 129884c406e7SOri Kam * Pointer to the error structure. 129984c406e7SOri Kam * 130084c406e7SOri Kam * @return 130184c406e7SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 130284c406e7SOri Kam */ 130384c406e7SOri Kam static int 130484c406e7SOri Kam flow_verbs_validate(struct rte_eth_dev *dev, 130584c406e7SOri Kam const struct rte_flow_attr *attr, 130684c406e7SOri Kam const struct rte_flow_item items[], 130784c406e7SOri Kam const struct rte_flow_action actions[], 1308b67b4ecbSDekel Peled bool external __rte_unused, 130972a944dbSBing Zhao int hairpin __rte_unused, 131084c406e7SOri Kam struct rte_flow_error *error) 131184c406e7SOri Kam { 131284c406e7SOri Kam int ret; 13130ddd1143SYongseok Koh uint64_t action_flags = 0; 13140ddd1143SYongseok Koh uint64_t item_flags = 0; 131538f7efaaSDekel Peled uint64_t last_item = 0; 131684c406e7SOri Kam uint8_t next_protocol = 0xff; 1317fba32130SXiaoyu Min uint16_t ether_type = 0; 1318b6aaaa22SShiri Kuzin bool is_empty_vlan = false; 1319a1fd0c82SRongwei Liu uint16_t udp_dport = 0; 1320c1f0cdaeSDariusz Sosnowski /* Verbs interface does not support groups higher than 0. */ 1321c1f0cdaeSDariusz Sosnowski bool is_root = true; 132284c406e7SOri Kam 132384c406e7SOri Kam if (items == NULL) 132484c406e7SOri Kam return -1; 1325c16e10f1SDariusz Sosnowski ret = flow_verbs_validate_attributes(dev, attr, error); 132684c406e7SOri Kam if (ret < 0) 132784c406e7SOri Kam return ret; 132884c406e7SOri Kam for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 13294a78c88eSYongseok Koh int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 133084c406e7SOri Kam int ret = 0; 133124663641SYongseok Koh 133284c406e7SOri Kam switch (items->type) { 133390385c46SMaayan Kashani #ifdef HAVE_IBV_FLOW_SPEC_ESP 133472185352SMaayan Kashani case RTE_FLOW_ITEM_TYPE_ESP: 133580c67625SGregory Etelson ret = mlx5_flow_os_validate_item_esp(dev, items, 133680c67625SGregory Etelson item_flags, 133772185352SMaayan Kashani next_protocol, 133872185352SMaayan Kashani error); 133972185352SMaayan Kashani if (ret < 0) 134072185352SMaayan Kashani return ret; 134172185352SMaayan Kashani last_item = MLX5_FLOW_ITEM_ESP; 134272185352SMaayan Kashani break; 134390385c46SMaayan Kashani #endif 134484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 134584c406e7SOri Kam break; 134684c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 134780c67625SGregory Etelson ret = mlx5_flow_validate_item_eth(dev, items, item_flags, 134886b59a1aSMatan Azrad false, error); 134984c406e7SOri Kam if (ret < 0) 135084c406e7SOri Kam return ret; 135138f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 135284c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L2; 1353fba32130SXiaoyu Min if (items->mask != NULL && items->spec != NULL) { 1354fba32130SXiaoyu Min ether_type = 1355fba32130SXiaoyu Min ((const struct rte_flow_item_eth *) 13568275d5fcSThomas Monjalon items->spec)->hdr.ether_type; 1357fba32130SXiaoyu Min ether_type &= 1358fba32130SXiaoyu Min ((const struct rte_flow_item_eth *) 13598275d5fcSThomas Monjalon items->mask)->hdr.ether_type; 1360b6aaaa22SShiri Kuzin if (ether_type == RTE_BE16(RTE_ETHER_TYPE_VLAN)) 1361b6aaaa22SShiri Kuzin is_empty_vlan = true; 1362fba32130SXiaoyu Min ether_type = rte_be_to_cpu_16(ether_type); 1363fba32130SXiaoyu Min } else { 1364fba32130SXiaoyu Min ether_type = 0; 1365fba32130SXiaoyu Min } 136684c406e7SOri Kam break; 136784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 136884c406e7SOri Kam ret = mlx5_flow_validate_item_vlan(items, item_flags, 1369dfedf3e3SViacheslav Ovsiienko dev, error); 137084c406e7SOri Kam if (ret < 0) 137184c406e7SOri Kam return ret; 137238f7efaaSDekel Peled last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 | 13734a78c88eSYongseok Koh MLX5_FLOW_LAYER_INNER_VLAN) : 13744a78c88eSYongseok Koh (MLX5_FLOW_LAYER_OUTER_L2 | 13754a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_VLAN); 1376fba32130SXiaoyu Min if (items->mask != NULL && items->spec != NULL) { 1377fba32130SXiaoyu Min ether_type = 1378fba32130SXiaoyu Min ((const struct rte_flow_item_vlan *) 13798275d5fcSThomas Monjalon items->spec)->hdr.eth_proto; 1380fba32130SXiaoyu Min ether_type &= 1381fba32130SXiaoyu Min ((const struct rte_flow_item_vlan *) 13828275d5fcSThomas Monjalon items->mask)->hdr.eth_proto; 1383fba32130SXiaoyu Min ether_type = rte_be_to_cpu_16(ether_type); 1384fba32130SXiaoyu Min } else { 1385fba32130SXiaoyu Min ether_type = 0; 1386fba32130SXiaoyu Min } 1387b6aaaa22SShiri Kuzin is_empty_vlan = false; 138884c406e7SOri Kam break; 138984c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 13906859e67eSDekel Peled ret = mlx5_flow_validate_item_ipv4 139180c67625SGregory Etelson (dev, items, item_flags, 13926859e67eSDekel Peled last_item, ether_type, NULL, 13936859e67eSDekel Peled MLX5_ITEM_RANGE_NOT_ACCEPTED, 1394fba32130SXiaoyu Min error); 139584c406e7SOri Kam if (ret < 0) 139684c406e7SOri Kam return ret; 139738f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 139884c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L3_IPV4; 139984c406e7SOri Kam if (items->mask != NULL && 140084c406e7SOri Kam ((const struct rte_flow_item_ipv4 *) 14013193c249SYongseok Koh items->mask)->hdr.next_proto_id) { 140284c406e7SOri Kam next_protocol = 140384c406e7SOri Kam ((const struct rte_flow_item_ipv4 *) 140484c406e7SOri Kam (items->spec))->hdr.next_proto_id; 14053193c249SYongseok Koh next_protocol &= 14063193c249SYongseok Koh ((const struct rte_flow_item_ipv4 *) 14073193c249SYongseok Koh (items->mask))->hdr.next_proto_id; 14083193c249SYongseok Koh } else { 14093193c249SYongseok Koh /* Reset for inner layer. */ 14103193c249SYongseok Koh next_protocol = 0xff; 14113193c249SYongseok Koh } 141284c406e7SOri Kam break; 141384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 141480c67625SGregory Etelson ret = mlx5_flow_validate_item_ipv6(dev, items, 141580c67625SGregory Etelson item_flags, 1416fba32130SXiaoyu Min last_item, 1417fba32130SXiaoyu Min ether_type, NULL, 1418fba32130SXiaoyu Min error); 141984c406e7SOri Kam if (ret < 0) 142084c406e7SOri Kam return ret; 142138f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 142284c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L3_IPV6; 142384c406e7SOri Kam if (items->mask != NULL && 142484c406e7SOri Kam ((const struct rte_flow_item_ipv6 *) 14253193c249SYongseok Koh items->mask)->hdr.proto) { 142684c406e7SOri Kam next_protocol = 142784c406e7SOri Kam ((const struct rte_flow_item_ipv6 *) 142884c406e7SOri Kam items->spec)->hdr.proto; 14293193c249SYongseok Koh next_protocol &= 14303193c249SYongseok Koh ((const struct rte_flow_item_ipv6 *) 14313193c249SYongseok Koh items->mask)->hdr.proto; 14323193c249SYongseok Koh } else { 14333193c249SYongseok Koh /* Reset for inner layer. */ 14343193c249SYongseok Koh next_protocol = 0xff; 14353193c249SYongseok Koh } 143684c406e7SOri Kam break; 143784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_UDP: 143880c67625SGregory Etelson ret = mlx5_flow_validate_item_udp(dev, items, 143980c67625SGregory Etelson item_flags, 144084c406e7SOri Kam next_protocol, 144184c406e7SOri Kam error); 1442a1fd0c82SRongwei Liu const struct rte_flow_item_udp *spec = items->spec; 1443a1fd0c82SRongwei Liu const struct rte_flow_item_udp *mask = items->mask; 1444a1fd0c82SRongwei Liu if (!mask) 1445a1fd0c82SRongwei Liu mask = &rte_flow_item_udp_mask; 1446a1fd0c82SRongwei Liu if (spec != NULL) 1447a1fd0c82SRongwei Liu udp_dport = rte_be_to_cpu_16 1448a1fd0c82SRongwei Liu (spec->hdr.dst_port & 1449a1fd0c82SRongwei Liu mask->hdr.dst_port); 1450a1fd0c82SRongwei Liu 145184c406e7SOri Kam if (ret < 0) 145284c406e7SOri Kam return ret; 145338f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 145484c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L4_UDP; 145584c406e7SOri Kam break; 145684c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 145792378c2bSMoti Haimovsky ret = mlx5_flow_validate_item_tcp 145880c67625SGregory Etelson (dev, items, item_flags, 145992378c2bSMoti Haimovsky next_protocol, 146092378c2bSMoti Haimovsky &rte_flow_item_tcp_mask, 146192378c2bSMoti Haimovsky error); 146284c406e7SOri Kam if (ret < 0) 146384c406e7SOri Kam return ret; 146438f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 146584c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L4_TCP; 146684c406e7SOri Kam break; 146784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 1468a1fd0c82SRongwei Liu ret = mlx5_flow_validate_item_vxlan(dev, udp_dport, 1469a1fd0c82SRongwei Liu items, item_flags, 14701939eb6fSDariusz Sosnowski is_root, error); 147184c406e7SOri Kam if (ret < 0) 147284c406e7SOri Kam return ret; 147338f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_VXLAN; 147484c406e7SOri Kam break; 147584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 147684c406e7SOri Kam ret = mlx5_flow_validate_item_vxlan_gpe(items, 147784c406e7SOri Kam item_flags, 147884c406e7SOri Kam dev, error); 147984c406e7SOri Kam if (ret < 0) 148084c406e7SOri Kam return ret; 148138f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_VXLAN_GPE; 148284c406e7SOri Kam break; 148384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 148480c67625SGregory Etelson ret = mlx5_flow_validate_item_gre(dev, items, item_flags, 148584c406e7SOri Kam next_protocol, error); 148684c406e7SOri Kam if (ret < 0) 148784c406e7SOri Kam return ret; 148838f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_GRE; 148984c406e7SOri Kam break; 149084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 149138f7efaaSDekel Peled ret = mlx5_flow_validate_item_mpls(dev, items, 149238f7efaaSDekel Peled item_flags, 149338f7efaaSDekel Peled last_item, error); 149484c406e7SOri Kam if (ret < 0) 149584c406e7SOri Kam return ret; 149638f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_MPLS; 149784c406e7SOri Kam break; 149858df16e0SDekel Peled case RTE_FLOW_ITEM_TYPE_ICMP: 149958df16e0SDekel Peled case RTE_FLOW_ITEM_TYPE_ICMP6: 150084c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 150184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ITEM, 150258df16e0SDekel Peled NULL, "ICMP/ICMP6 " 150358df16e0SDekel Peled "item not supported"); 150458df16e0SDekel Peled default: 150558df16e0SDekel Peled return rte_flow_error_set(error, ENOTSUP, 150658df16e0SDekel Peled RTE_FLOW_ERROR_TYPE_ITEM, 150758df16e0SDekel Peled NULL, "item not supported"); 150884c406e7SOri Kam } 150938f7efaaSDekel Peled item_flags |= last_item; 151084c406e7SOri Kam } 1511b6aaaa22SShiri Kuzin if (is_empty_vlan) 1512b6aaaa22SShiri Kuzin return rte_flow_error_set(error, ENOTSUP, 1513b6aaaa22SShiri Kuzin RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1514b6aaaa22SShiri Kuzin "VLAN matching without vid specification is not supported"); 151584c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 151684c406e7SOri Kam switch (actions->type) { 151784c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 151884c406e7SOri Kam break; 151984c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 152084c406e7SOri Kam ret = mlx5_flow_validate_action_flag(action_flags, 15213e9fa079SDekel Peled attr, 152284c406e7SOri Kam error); 152384c406e7SOri Kam if (ret < 0) 152484c406e7SOri Kam return ret; 152584c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_FLAG; 152684c406e7SOri Kam break; 152784c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 1528d6dc072aSGregory Etelson ret = mlx5_flow_validate_action_mark(dev, actions, 152984c406e7SOri Kam action_flags, 15303e9fa079SDekel Peled attr, 153184c406e7SOri Kam error); 153284c406e7SOri Kam if (ret < 0) 153384c406e7SOri Kam return ret; 153484c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_MARK; 153584c406e7SOri Kam break; 153684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 1537c1f0cdaeSDariusz Sosnowski ret = mlx5_flow_validate_action_drop(dev, 1538c1f0cdaeSDariusz Sosnowski is_root, 15393e9fa079SDekel Peled attr, 154084c406e7SOri Kam error); 154184c406e7SOri Kam if (ret < 0) 154284c406e7SOri Kam return ret; 154384c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_DROP; 154484c406e7SOri Kam break; 154584c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 154684c406e7SOri Kam ret = mlx5_flow_validate_action_queue(actions, 154784c406e7SOri Kam action_flags, dev, 15483e9fa079SDekel Peled attr, 154984c406e7SOri Kam error); 155084c406e7SOri Kam if (ret < 0) 155184c406e7SOri Kam return ret; 155284c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_QUEUE; 155384c406e7SOri Kam break; 155484c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 155584c406e7SOri Kam ret = mlx5_flow_validate_action_rss(actions, 155684c406e7SOri Kam action_flags, dev, 15571183f12fSOri Kam attr, item_flags, 155884c406e7SOri Kam error); 155984c406e7SOri Kam if (ret < 0) 156084c406e7SOri Kam return ret; 156184c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_RSS; 156284c406e7SOri Kam break; 156384c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 15643e9fa079SDekel Peled ret = mlx5_flow_validate_action_count(dev, attr, error); 156584c406e7SOri Kam if (ret < 0) 156684c406e7SOri Kam return ret; 156784c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_COUNT; 156884c406e7SOri Kam break; 156984c406e7SOri Kam default: 157084c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 157184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, 157284c406e7SOri Kam actions, 157384c406e7SOri Kam "action not supported"); 157484c406e7SOri Kam } 157584c406e7SOri Kam } 157670faf9aeSDekel Peled /* 157770faf9aeSDekel Peled * Validate the drop action mutual exclusion with other actions. 157870faf9aeSDekel Peled * Drop action is mutually-exclusive with any other action, except for 157970faf9aeSDekel Peled * Count action. 158070faf9aeSDekel Peled */ 158170faf9aeSDekel Peled if ((action_flags & MLX5_FLOW_ACTION_DROP) && 158270faf9aeSDekel Peled (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT))) 158370faf9aeSDekel Peled return rte_flow_error_set(error, EINVAL, 158470faf9aeSDekel Peled RTE_FLOW_ERROR_TYPE_ACTION, NULL, 158570faf9aeSDekel Peled "Drop action is mutually-exclusive " 158670faf9aeSDekel Peled "with any other action, except for " 158770faf9aeSDekel Peled "Count action"); 158884c406e7SOri Kam if (!(action_flags & MLX5_FLOW_FATE_ACTIONS)) 158984c406e7SOri Kam return rte_flow_error_set(error, EINVAL, 159084c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, actions, 159184c406e7SOri Kam "no fate action is found"); 159284c406e7SOri Kam return 0; 159384c406e7SOri Kam } 159484c406e7SOri Kam 159584c406e7SOri Kam /** 159684c406e7SOri Kam * Calculate the required bytes that are needed for the action part of the verbs 1597c1cfb132SYongseok Koh * flow. 159884c406e7SOri Kam * 159984c406e7SOri Kam * @param[in] actions 160084c406e7SOri Kam * Pointer to the list of actions. 160184c406e7SOri Kam * 160284c406e7SOri Kam * @return 160384c406e7SOri Kam * The size of the memory needed for all actions. 160484c406e7SOri Kam */ 160584c406e7SOri Kam static int 1606c1cfb132SYongseok Koh flow_verbs_get_actions_size(const struct rte_flow_action actions[]) 160784c406e7SOri Kam { 160884c406e7SOri Kam int size = 0; 160984c406e7SOri Kam 161084c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 161184c406e7SOri Kam switch (actions->type) { 161284c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 161384c406e7SOri Kam break; 161484c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 161584c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_tag); 161684c406e7SOri Kam break; 161784c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 161884c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_tag); 161984c406e7SOri Kam break; 162084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 162184c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_drop); 162284c406e7SOri Kam break; 162384c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 162484c406e7SOri Kam break; 162584c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 162684c406e7SOri Kam break; 162784c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 1628db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \ 1629db48f9dbSViacheslav Ovsiienko defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 163084c406e7SOri Kam size += sizeof(struct ibv_flow_spec_counter_action); 163184c406e7SOri Kam #endif 163284c406e7SOri Kam break; 163384c406e7SOri Kam default: 163484c406e7SOri Kam break; 163584c406e7SOri Kam } 163684c406e7SOri Kam } 163784c406e7SOri Kam return size; 163884c406e7SOri Kam } 163984c406e7SOri Kam 164084c406e7SOri Kam /** 164184c406e7SOri Kam * Calculate the required bytes that are needed for the item part of the verbs 1642c1cfb132SYongseok Koh * flow. 164384c406e7SOri Kam * 1644c1cfb132SYongseok Koh * @param[in] items 164584c406e7SOri Kam * Pointer to the list of items. 164684c406e7SOri Kam * 164784c406e7SOri Kam * @return 164884c406e7SOri Kam * The size of the memory needed for all items. 164984c406e7SOri Kam */ 165084c406e7SOri Kam static int 1651c1cfb132SYongseok Koh flow_verbs_get_items_size(const struct rte_flow_item items[]) 165284c406e7SOri Kam { 165384c406e7SOri Kam int size = 0; 165484c406e7SOri Kam 165584c406e7SOri Kam for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 165684c406e7SOri Kam switch (items->type) { 165784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 165884c406e7SOri Kam break; 165984c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 166084c406e7SOri Kam size += sizeof(struct ibv_flow_spec_eth); 166184c406e7SOri Kam break; 166284c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 166384c406e7SOri Kam size += sizeof(struct ibv_flow_spec_eth); 166484c406e7SOri Kam break; 166584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 166684c406e7SOri Kam size += sizeof(struct ibv_flow_spec_ipv4_ext); 166784c406e7SOri Kam break; 166884c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 166984c406e7SOri Kam size += sizeof(struct ibv_flow_spec_ipv6); 167084c406e7SOri Kam break; 167184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_UDP: 167284c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tcp_udp); 167384c406e7SOri Kam break; 167484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 167584c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tcp_udp); 167684c406e7SOri Kam break; 167784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 167884c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 167984c406e7SOri Kam break; 168084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 168184c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 168284c406e7SOri Kam break; 168384c406e7SOri Kam #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 168484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 168584c406e7SOri Kam size += sizeof(struct ibv_flow_spec_gre); 168684c406e7SOri Kam break; 168784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 168884c406e7SOri Kam size += sizeof(struct ibv_flow_spec_mpls); 168984c406e7SOri Kam break; 169084c406e7SOri Kam #else 169184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 169284c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 169384c406e7SOri Kam break; 169484c406e7SOri Kam #endif 169584c406e7SOri Kam default: 169684c406e7SOri Kam break; 169784c406e7SOri Kam } 169884c406e7SOri Kam } 169984c406e7SOri Kam return size; 170084c406e7SOri Kam } 170184c406e7SOri Kam 170284c406e7SOri Kam /** 170384c406e7SOri Kam * Internal preparation function. Allocate mlx5_flow with the required size. 170484c406e7SOri Kam * The required size is calculate based on the actions and items. This function 170584c406e7SOri Kam * also returns the detected actions and items for later use. 170684c406e7SOri Kam * 1707e7bfa359SBing Zhao * @param[in] dev 1708e7bfa359SBing Zhao * Pointer to Ethernet device. 170984c406e7SOri Kam * @param[in] attr 171084c406e7SOri Kam * Pointer to the flow attributes. 171184c406e7SOri Kam * @param[in] items 171284c406e7SOri Kam * Pointer to the list of items. 171384c406e7SOri Kam * @param[in] actions 171484c406e7SOri Kam * Pointer to the list of actions. 171584c406e7SOri Kam * @param[out] error 171684c406e7SOri Kam * Pointer to the error structure. 171784c406e7SOri Kam * 171884c406e7SOri Kam * @return 171984c406e7SOri Kam * Pointer to mlx5_flow object on success, otherwise NULL and rte_errno 172084c406e7SOri Kam * is set. 172184c406e7SOri Kam */ 172284c406e7SOri Kam static struct mlx5_flow * 1723e7bfa359SBing Zhao flow_verbs_prepare(struct rte_eth_dev *dev, 1724e7bfa359SBing Zhao const struct rte_flow_attr *attr __rte_unused, 172584c406e7SOri Kam const struct rte_flow_item items[], 172684c406e7SOri Kam const struct rte_flow_action actions[], 172784c406e7SOri Kam struct rte_flow_error *error) 172884c406e7SOri Kam { 1729e7bfa359SBing Zhao size_t size = 0; 1730b88341caSSuanming Mou uint32_t handle_idx = 0; 1731e205c95fSViacheslav Ovsiienko struct mlx5_flow *dev_flow; 1732e7bfa359SBing Zhao struct mlx5_flow_handle *dev_handle; 1733e7bfa359SBing Zhao struct mlx5_priv *priv = dev->data->dev_private; 17348bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 173584c406e7SOri Kam 17368bb81f26SXueming Li MLX5_ASSERT(wks); 1737c1cfb132SYongseok Koh size += flow_verbs_get_actions_size(actions); 1738c1cfb132SYongseok Koh size += flow_verbs_get_items_size(items); 1739e7bfa359SBing Zhao if (size > MLX5_VERBS_MAX_SPEC_ACT_SIZE) { 1740e7bfa359SBing Zhao rte_flow_error_set(error, E2BIG, 174184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1742e7bfa359SBing Zhao "Verbs spec/action size too large"); 174384c406e7SOri Kam return NULL; 174484c406e7SOri Kam } 1745e7bfa359SBing Zhao /* In case of corrupting the memory. */ 17468bb81f26SXueming Li if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) { 1747e7bfa359SBing Zhao rte_flow_error_set(error, ENOSPC, 1748e7bfa359SBing Zhao RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1749e7bfa359SBing Zhao "not free temporary device flow"); 1750e7bfa359SBing Zhao return NULL; 1751e7bfa359SBing Zhao } 1752b88341caSSuanming Mou dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 1753b88341caSSuanming Mou &handle_idx); 1754e7bfa359SBing Zhao if (!dev_handle) { 1755e7bfa359SBing Zhao rte_flow_error_set(error, ENOMEM, 1756e7bfa359SBing Zhao RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1757e7bfa359SBing Zhao "not enough memory to create flow handle"); 1758e7bfa359SBing Zhao return NULL; 1759e7bfa359SBing Zhao } 17608bb81f26SXueming Li MLX5_ASSERT(wks->flow_idx + 1 < RTE_DIM(wks->flows)); 17618bb81f26SXueming Li dev_flow = &wks->flows[wks->flow_idx++]; 1762e7bfa359SBing Zhao dev_flow->handle = dev_handle; 1763b88341caSSuanming Mou dev_flow->handle_idx = handle_idx; 1764e7bfa359SBing Zhao /* Memcpy is used, only size needs to be cleared to 0. */ 1765e7bfa359SBing Zhao dev_flow->verbs.size = 0; 1766e7bfa359SBing Zhao dev_flow->verbs.attr.num_of_specs = 0; 1767e205c95fSViacheslav Ovsiienko dev_flow->ingress = attr->ingress; 17680efc99beSOphir Munk dev_flow->hash_fields = 0; 1769c42f44bdSBing Zhao /* Need to set transfer attribute: not supported in Verbs mode. */ 1770e205c95fSViacheslav Ovsiienko return dev_flow; 177184c406e7SOri Kam } 177284c406e7SOri Kam 177384c406e7SOri Kam /** 177484c406e7SOri Kam * Fill the flow with verb spec. 177584c406e7SOri Kam * 177684c406e7SOri Kam * @param[in] dev 177784c406e7SOri Kam * Pointer to Ethernet device. 177884c406e7SOri Kam * @param[in, out] dev_flow 177984c406e7SOri Kam * Pointer to the mlx5 flow. 178084c406e7SOri Kam * @param[in] attr 178184c406e7SOri Kam * Pointer to the flow attributes. 178284c406e7SOri Kam * @param[in] items 178384c406e7SOri Kam * Pointer to the list of items. 178484c406e7SOri Kam * @param[in] actions 178584c406e7SOri Kam * Pointer to the list of actions. 178684c406e7SOri Kam * @param[out] error 178784c406e7SOri Kam * Pointer to the error structure. 178884c406e7SOri Kam * 178984c406e7SOri Kam * @return 1790de90612fSDekel Peled * 0 on success, else a negative errno value otherwise and rte_errno is set. 179184c406e7SOri Kam */ 179284c406e7SOri Kam static int 179384c406e7SOri Kam flow_verbs_translate(struct rte_eth_dev *dev, 179484c406e7SOri Kam struct mlx5_flow *dev_flow, 179584c406e7SOri Kam const struct rte_flow_attr *attr, 179684c406e7SOri Kam const struct rte_flow_item items[], 179784c406e7SOri Kam const struct rte_flow_action actions[], 179884c406e7SOri Kam struct rte_flow_error *error) 179984c406e7SOri Kam { 180084c406e7SOri Kam uint64_t item_flags = 0; 18014a78c88eSYongseok Koh uint64_t action_flags = 0; 180284c406e7SOri Kam uint64_t priority = attr->priority; 18034a78c88eSYongseok Koh uint32_t subpriority = 0; 1804dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 18058bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 18068bb81f26SXueming Li struct mlx5_flow_rss_desc *rss_desc; 1807df498655SGregory Etelson const struct rte_flow_item *tunnel_item = NULL; 180898008ce6SDariusz Sosnowski uint8_t *gre_spec = NULL; 180984c406e7SOri Kam 18108bb81f26SXueming Li MLX5_ASSERT(wks); 18110064bf43SXueming Li rss_desc = &wks->rss_desc; 18125f8ae44dSDong Zhou if (priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) 18133c4338a4SJiawei Wang priority = priv->sh->flow_max_priority - 1; 181484c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 181584c406e7SOri Kam int ret; 18164a78c88eSYongseok Koh 181784c406e7SOri Kam switch (actions->type) { 181884c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 181984c406e7SOri Kam break; 182084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 18214a78c88eSYongseok Koh flow_verbs_translate_action_flag(dev_flow, actions); 18224a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_FLAG; 1823082becbfSRaja Zidane wks->mark = 1; 182484c406e7SOri Kam break; 182584c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 18264a78c88eSYongseok Koh flow_verbs_translate_action_mark(dev_flow, actions); 18274a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_MARK; 1828082becbfSRaja Zidane wks->mark = 1; 182984c406e7SOri Kam break; 183084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 18314a78c88eSYongseok Koh flow_verbs_translate_action_drop(dev_flow, actions); 18324a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_DROP; 1833488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP; 183484c406e7SOri Kam break; 183584c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 1836e745f900SSuanming Mou flow_verbs_translate_action_queue(rss_desc, actions); 18374a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_QUEUE; 1838488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 183984c406e7SOri Kam break; 184084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 1841e745f900SSuanming Mou flow_verbs_translate_action_rss(rss_desc, actions); 18424a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_RSS; 1843488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 184484c406e7SOri Kam break; 184584c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 18464a78c88eSYongseok Koh ret = flow_verbs_translate_action_count(dev_flow, 184784c406e7SOri Kam actions, 18484a78c88eSYongseok Koh dev, error); 184984c406e7SOri Kam if (ret < 0) 185084c406e7SOri Kam return ret; 18514a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_COUNT; 185284c406e7SOri Kam break; 185384c406e7SOri Kam default: 185484c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 185584c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, 185684c406e7SOri Kam actions, 185784c406e7SOri Kam "action not supported"); 185884c406e7SOri Kam } 185984c406e7SOri Kam } 1860488d13abSSuanming Mou dev_flow->act_flags = action_flags; 186184c406e7SOri Kam for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 18624a78c88eSYongseok Koh int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 18634a78c88eSYongseok Koh 186484c406e7SOri Kam switch (items->type) { 186584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 186684c406e7SOri Kam break; 186784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 18684a78c88eSYongseok Koh flow_verbs_translate_item_eth(dev_flow, items, 18694a78c88eSYongseok Koh item_flags); 18704a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L2; 18714a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 18724a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L2; 187384c406e7SOri Kam break; 187484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 18754a78c88eSYongseok Koh flow_verbs_translate_item_vlan(dev_flow, items, 18764a78c88eSYongseok Koh item_flags); 18774a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L2; 18784a78c88eSYongseok Koh item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 | 18794a78c88eSYongseok Koh MLX5_FLOW_LAYER_INNER_VLAN) : 18804a78c88eSYongseok Koh (MLX5_FLOW_LAYER_OUTER_L2 | 18814a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_VLAN); 188284c406e7SOri Kam break; 188384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 18844a78c88eSYongseok Koh flow_verbs_translate_item_ipv4(dev_flow, items, 18854a78c88eSYongseok Koh item_flags); 18864a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L3; 1887e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 18884a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1889e745f900SSuanming Mou (rss_desc, tunnel, 18904a78c88eSYongseok Koh MLX5_IPV4_LAYER_TYPES, 18914a78c88eSYongseok Koh MLX5_IPV4_IBV_RX_HASH); 18924a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 18934a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L3_IPV4; 189484c406e7SOri Kam break; 189584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 18964a78c88eSYongseok Koh flow_verbs_translate_item_ipv6(dev_flow, items, 18974a78c88eSYongseok Koh item_flags); 18984a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L3; 1899e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 19004a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1901e745f900SSuanming Mou (rss_desc, tunnel, 19024a78c88eSYongseok Koh MLX5_IPV6_LAYER_TYPES, 19034a78c88eSYongseok Koh MLX5_IPV6_IBV_RX_HASH); 19044a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 19054a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L3_IPV6; 190684c406e7SOri Kam break; 190784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 19084a78c88eSYongseok Koh flow_verbs_translate_item_tcp(dev_flow, items, 19094a78c88eSYongseok Koh item_flags); 19104a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L4; 19115e1db76dSLior Margalit if (dev_flow->hash_fields != 0) 1912e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 19134a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1914295968d1SFerruh Yigit (rss_desc, tunnel, RTE_ETH_RSS_TCP, 19154a78c88eSYongseok Koh (IBV_RX_HASH_SRC_PORT_TCP | 19164a78c88eSYongseok Koh IBV_RX_HASH_DST_PORT_TCP)); 19174a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 19184a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L4_TCP; 19194a78c88eSYongseok Koh break; 19204a78c88eSYongseok Koh case RTE_FLOW_ITEM_TYPE_UDP: 19214a78c88eSYongseok Koh flow_verbs_translate_item_udp(dev_flow, items, 19224a78c88eSYongseok Koh item_flags); 19234a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L4; 19245e1db76dSLior Margalit if (dev_flow->hash_fields != 0) 1925e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 19264a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1927295968d1SFerruh Yigit (rss_desc, tunnel, RTE_ETH_RSS_UDP, 19284a78c88eSYongseok Koh (IBV_RX_HASH_SRC_PORT_UDP | 19294a78c88eSYongseok Koh IBV_RX_HASH_DST_PORT_UDP)); 19304a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 19314a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L4_UDP; 193284c406e7SOri Kam break; 193372185352SMaayan Kashani #ifdef HAVE_IBV_FLOW_SPEC_ESP 193472185352SMaayan Kashani case RTE_FLOW_ITEM_TYPE_ESP: 193572185352SMaayan Kashani flow_verbs_translate_item_esp(dev_flow, items, 193672185352SMaayan Kashani item_flags); 193772185352SMaayan Kashani dev_flow->hash_fields |= 193872185352SMaayan Kashani mlx5_flow_hashfields_adjust 193972185352SMaayan Kashani (rss_desc, tunnel, 194072185352SMaayan Kashani RTE_ETH_RSS_ESP, 194172185352SMaayan Kashani IBV_RX_HASH_IPSEC_SPI); 194272185352SMaayan Kashani item_flags |= MLX5_FLOW_ITEM_ESP; 194372185352SMaayan Kashani break; 194472185352SMaayan Kashani #endif 194584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 19464a78c88eSYongseok Koh flow_verbs_translate_item_vxlan(dev_flow, items, 19474a78c88eSYongseok Koh item_flags); 1948750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19494a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_VXLAN; 195084c406e7SOri Kam break; 195184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 19524a78c88eSYongseok Koh flow_verbs_translate_item_vxlan_gpe(dev_flow, items, 19534a78c88eSYongseok Koh item_flags); 1954750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19554a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE; 195684c406e7SOri Kam break; 195784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 195898008ce6SDariusz Sosnowski gre_spec = flow_verbs_reserve_gre(dev_flow); 1959750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19604a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_GRE; 1961df498655SGregory Etelson tunnel_item = items; 196284c406e7SOri Kam break; 196384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 19644a78c88eSYongseok Koh flow_verbs_translate_item_mpls(dev_flow, items, 19654a78c88eSYongseok Koh item_flags); 1966750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19674a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_MPLS; 196884c406e7SOri Kam break; 196984c406e7SOri Kam default: 197084c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 197184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ITEM, 197258df16e0SDekel Peled NULL, "item not supported"); 197384c406e7SOri Kam } 197484c406e7SOri Kam } 1975985b4792SGregory Etelson if (item_flags & MLX5_FLOW_LAYER_GRE) 197698008ce6SDariusz Sosnowski flow_verbs_translate_item_gre(dev_flow, gre_spec, 197798008ce6SDariusz Sosnowski tunnel_item, item_flags); 1978e7bfa359SBing Zhao dev_flow->handle->layers = item_flags; 1979e7bfa359SBing Zhao /* Other members of attr will be ignored. */ 1980e7bfa359SBing Zhao dev_flow->verbs.attr.priority = 19814a78c88eSYongseok Koh mlx5_flow_adjust_priority(dev, priority, subpriority); 198291389890SOphir Munk dev_flow->verbs.attr.port = (uint8_t)priv->dev_port; 198384c406e7SOri Kam return 0; 198484c406e7SOri Kam } 198584c406e7SOri Kam 198684c406e7SOri Kam /** 198784c406e7SOri Kam * Remove the flow from the NIC but keeps it in memory. 198884c406e7SOri Kam * 198984c406e7SOri Kam * @param[in] dev 199084c406e7SOri Kam * Pointer to the Ethernet device structure. 199184c406e7SOri Kam * @param[in, out] flow 199284c406e7SOri Kam * Pointer to flow structure. 199384c406e7SOri Kam */ 199484c406e7SOri Kam static void 199584c406e7SOri Kam flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow) 199684c406e7SOri Kam { 1997b88341caSSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 1998e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 1999b88341caSSuanming Mou uint32_t handle_idx; 200084c406e7SOri Kam 200184c406e7SOri Kam if (!flow) 200284c406e7SOri Kam return; 2003b88341caSSuanming Mou SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 2004b88341caSSuanming Mou handle_idx, handle, next) { 2005341c8941SDekel Peled if (handle->drv_flow) { 2006341c8941SDekel Peled claim_zero(mlx5_glue->destroy_flow(handle->drv_flow)); 2007341c8941SDekel Peled handle->drv_flow = NULL; 200884c406e7SOri Kam } 20096fc18392SSuanming Mou /* hrxq is union, don't touch it only the flag is set. */ 201065b3cd0dSSuanming Mou if (handle->rix_hrxq && 201165b3cd0dSSuanming Mou handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 201277749adaSSuanming Mou mlx5_hrxq_release(dev, handle->rix_hrxq); 201377749adaSSuanming Mou handle->rix_hrxq = 0; 201484c406e7SOri Kam } 2015e7bfa359SBing Zhao if (handle->vf_vlan.tag && handle->vf_vlan.created) 2016e7bfa359SBing Zhao mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); 201784c406e7SOri Kam } 201884c406e7SOri Kam } 201984c406e7SOri Kam 202084c406e7SOri Kam /** 202184c406e7SOri Kam * Remove the flow from the NIC and the memory. 202284c406e7SOri Kam * 202384c406e7SOri Kam * @param[in] dev 202484c406e7SOri Kam * Pointer to the Ethernet device structure. 202584c406e7SOri Kam * @param[in, out] flow 202684c406e7SOri Kam * Pointer to flow structure. 202784c406e7SOri Kam */ 202884c406e7SOri Kam static void 202984c406e7SOri Kam flow_verbs_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 203084c406e7SOri Kam { 2031b88341caSSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2032e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 203384c406e7SOri Kam 203484c406e7SOri Kam if (!flow) 203584c406e7SOri Kam return; 203684c406e7SOri Kam flow_verbs_remove(dev, flow); 2037b88341caSSuanming Mou while (flow->dev_handles) { 2038b88341caSSuanming Mou uint32_t tmp_idx = flow->dev_handles; 2039b88341caSSuanming Mou 2040b88341caSSuanming Mou handle = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 2041b88341caSSuanming Mou tmp_idx); 2042b88341caSSuanming Mou if (!handle) 2043b88341caSSuanming Mou return; 2044b88341caSSuanming Mou flow->dev_handles = handle->next.next; 2045b88341caSSuanming Mou mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 2046b88341caSSuanming Mou tmp_idx); 204784c406e7SOri Kam } 204884be903cSViacheslav Ovsiienko if (flow->counter) { 20495382d28cSMatan Azrad flow_verbs_counter_release(dev, flow->counter); 2050956d5c74SSuanming Mou flow->counter = 0; 205184be903cSViacheslav Ovsiienko } 205284c406e7SOri Kam } 205384c406e7SOri Kam 205484c406e7SOri Kam /** 205584c406e7SOri Kam * Apply the flow to the NIC. 205684c406e7SOri Kam * 205784c406e7SOri Kam * @param[in] dev 205884c406e7SOri Kam * Pointer to the Ethernet device structure. 205984c406e7SOri Kam * @param[in, out] flow 206084c406e7SOri Kam * Pointer to flow structure. 206184c406e7SOri Kam * @param[out] error 206284c406e7SOri Kam * Pointer to error structure. 206384c406e7SOri Kam * 206484c406e7SOri Kam * @return 206584c406e7SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 206684c406e7SOri Kam */ 206784c406e7SOri Kam static int 206884c406e7SOri Kam flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow, 206984c406e7SOri Kam struct rte_flow_error *error) 207084c406e7SOri Kam { 2071dfedf3e3SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 2072e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 207384c406e7SOri Kam struct mlx5_flow *dev_flow; 2074772dc0ebSSuanming Mou struct mlx5_hrxq *hrxq; 2075b88341caSSuanming Mou uint32_t dev_handles; 207684c406e7SOri Kam int err; 2077e7bfa359SBing Zhao int idx; 20788bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 207984c406e7SOri Kam 20808bb81f26SXueming Li MLX5_ASSERT(wks); 20810064bf43SXueming Li for (idx = wks->flow_idx - 1; idx >= 0; idx--) { 20828bb81f26SXueming Li dev_flow = &wks->flows[idx]; 2083e7bfa359SBing Zhao handle = dev_flow->handle; 2084488d13abSSuanming Mou if (handle->fate_action == MLX5_FLOW_FATE_DROP) { 208565b3cd0dSSuanming Mou MLX5_ASSERT(priv->drop_queue.hrxq); 208665b3cd0dSSuanming Mou hrxq = priv->drop_queue.hrxq; 208784c406e7SOri Kam } else { 20880064bf43SXueming Li struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc; 208984c406e7SOri Kam 2090e745f900SSuanming Mou MLX5_ASSERT(rss_desc->queue_num); 2091e1592b6cSSuanming Mou rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN; 2092e1592b6cSSuanming Mou rss_desc->hash_fields = dev_flow->hash_fields; 2093e1592b6cSSuanming Mou rss_desc->tunnel = !!(handle->layers & 2094e1592b6cSSuanming Mou MLX5_FLOW_LAYER_TUNNEL); 2095fabf8a37SSuanming Mou rss_desc->shared_rss = 0; 20963a2f674bSSuanming Mou hrxq = mlx5_hrxq_get(dev, rss_desc); 209784c406e7SOri Kam if (!hrxq) { 209884c406e7SOri Kam rte_flow_error_set 209984c406e7SOri Kam (error, rte_errno, 210084c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 210184c406e7SOri Kam "cannot get hash queue"); 210284c406e7SOri Kam goto error; 210384c406e7SOri Kam } 21043a2f674bSSuanming Mou handle->rix_hrxq = hrxq->idx; 210584c406e7SOri Kam } 2106772dc0ebSSuanming Mou MLX5_ASSERT(hrxq); 2107341c8941SDekel Peled handle->drv_flow = mlx5_glue->create_flow 2108341c8941SDekel Peled (hrxq->qp, &dev_flow->verbs.attr); 2109341c8941SDekel Peled if (!handle->drv_flow) { 211084c406e7SOri Kam rte_flow_error_set(error, errno, 211184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 211284c406e7SOri Kam NULL, 211384c406e7SOri Kam "hardware refuses to create flow"); 211484c406e7SOri Kam goto error; 211584c406e7SOri Kam } 2116dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context && 2117e7bfa359SBing Zhao handle->vf_vlan.tag && !handle->vf_vlan.created) { 2118dfedf3e3SViacheslav Ovsiienko /* 2119dfedf3e3SViacheslav Ovsiienko * The rule contains the VLAN pattern. 2120dfedf3e3SViacheslav Ovsiienko * For VF we are going to create VLAN 2121dfedf3e3SViacheslav Ovsiienko * interface to make hypervisor set correct 2122dfedf3e3SViacheslav Ovsiienko * e-Switch vport context. 2123dfedf3e3SViacheslav Ovsiienko */ 2124e7bfa359SBing Zhao mlx5_vlan_vmwa_acquire(dev, &handle->vf_vlan); 2125dfedf3e3SViacheslav Ovsiienko } 212684c406e7SOri Kam } 212784c406e7SOri Kam return 0; 212884c406e7SOri Kam error: 212984c406e7SOri Kam err = rte_errno; /* Save rte_errno before cleanup. */ 2130b88341caSSuanming Mou SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 2131b88341caSSuanming Mou dev_handles, handle, next) { 21326fc18392SSuanming Mou /* hrxq is union, don't touch it only the flag is set. */ 213365b3cd0dSSuanming Mou if (handle->rix_hrxq && 213465b3cd0dSSuanming Mou handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 213577749adaSSuanming Mou mlx5_hrxq_release(dev, handle->rix_hrxq); 213677749adaSSuanming Mou handle->rix_hrxq = 0; 213784c406e7SOri Kam } 2138e7bfa359SBing Zhao if (handle->vf_vlan.tag && handle->vf_vlan.created) 2139e7bfa359SBing Zhao mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); 214084c406e7SOri Kam } 214184c406e7SOri Kam rte_errno = err; /* Restore rte_errno. */ 214284c406e7SOri Kam return -rte_errno; 214384c406e7SOri Kam } 214484c406e7SOri Kam 2145684dafe7SMoti Haimovsky /** 2146684dafe7SMoti Haimovsky * Query a flow. 2147684dafe7SMoti Haimovsky * 2148684dafe7SMoti Haimovsky * @see rte_flow_query() 2149684dafe7SMoti Haimovsky * @see rte_flow_ops 2150684dafe7SMoti Haimovsky */ 2151684dafe7SMoti Haimovsky static int 2152684dafe7SMoti Haimovsky flow_verbs_query(struct rte_eth_dev *dev, 2153684dafe7SMoti Haimovsky struct rte_flow *flow, 2154684dafe7SMoti Haimovsky const struct rte_flow_action *actions, 2155684dafe7SMoti Haimovsky void *data, 2156684dafe7SMoti Haimovsky struct rte_flow_error *error) 2157684dafe7SMoti Haimovsky { 2158684dafe7SMoti Haimovsky int ret = -EINVAL; 2159684dafe7SMoti Haimovsky 2160684dafe7SMoti Haimovsky for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2161684dafe7SMoti Haimovsky switch (actions->type) { 2162684dafe7SMoti Haimovsky case RTE_FLOW_ACTION_TYPE_VOID: 2163684dafe7SMoti Haimovsky break; 2164684dafe7SMoti Haimovsky case RTE_FLOW_ACTION_TYPE_COUNT: 216506629d86SViacheslav Ovsiienko ret = flow_verbs_counter_query(dev, flow, data, error); 2166684dafe7SMoti Haimovsky break; 2167684dafe7SMoti Haimovsky default: 2168684dafe7SMoti Haimovsky return rte_flow_error_set(error, ENOTSUP, 2169684dafe7SMoti Haimovsky RTE_FLOW_ERROR_TYPE_ACTION, 2170684dafe7SMoti Haimovsky actions, 2171684dafe7SMoti Haimovsky "action not supported"); 2172684dafe7SMoti Haimovsky } 2173684dafe7SMoti Haimovsky } 2174684dafe7SMoti Haimovsky return ret; 2175684dafe7SMoti Haimovsky } 2176684dafe7SMoti Haimovsky 217723f627e0SBing Zhao static int 217823f627e0SBing Zhao flow_verbs_sync_domain(struct rte_eth_dev *dev, uint32_t domains, 217923f627e0SBing Zhao uint32_t flags) 218023f627e0SBing Zhao { 218123f627e0SBing Zhao RTE_SET_USED(dev); 218223f627e0SBing Zhao RTE_SET_USED(domains); 218323f627e0SBing Zhao RTE_SET_USED(flags); 218423f627e0SBing Zhao 218523f627e0SBing Zhao return 0; 218623f627e0SBing Zhao } 218723f627e0SBing Zhao 21880c76d1c9SYongseok Koh const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = { 2189e38776c3SMaayan Kashani .list_create = flow_legacy_list_create, 2190e38776c3SMaayan Kashani .list_destroy = flow_legacy_list_destroy, 219184c406e7SOri Kam .validate = flow_verbs_validate, 219284c406e7SOri Kam .prepare = flow_verbs_prepare, 219384c406e7SOri Kam .translate = flow_verbs_translate, 219484c406e7SOri Kam .apply = flow_verbs_apply, 219584c406e7SOri Kam .remove = flow_verbs_remove, 219684c406e7SOri Kam .destroy = flow_verbs_destroy, 2197684dafe7SMoti Haimovsky .query = flow_verbs_query, 219823f627e0SBing Zhao .sync_domain = flow_verbs_sync_domain, 2199c5042f93SDmitry Kozlyuk .discover_priorities = flow_verbs_discover_priorities, 2200c68bb7a6SAsaf Penso .get_aged_flows = flow_null_get_aged_flows, 2201c68bb7a6SAsaf Penso .counter_alloc = flow_null_counter_allocate, 2202c68bb7a6SAsaf Penso .counter_free = flow_null_counter_free, 2203c68bb7a6SAsaf Penso .counter_query = flow_null_counter_query, 220484c406e7SOri Kam }; 2205