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 60384c406e7SOri Kam memcpy(&ipv6.val.src_ip, spec->hdr.src_addr, 60484c406e7SOri Kam RTE_DIM(ipv6.val.src_ip)); 60584c406e7SOri Kam memcpy(&ipv6.val.dst_ip, spec->hdr.dst_addr, 60684c406e7SOri Kam RTE_DIM(ipv6.val.dst_ip)); 60784c406e7SOri Kam memcpy(&ipv6.mask.src_ip, mask->hdr.src_addr, 60884c406e7SOri Kam RTE_DIM(ipv6.mask.src_ip)); 60984c406e7SOri Kam 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; 13201939eb6fSDariusz Sosnowski bool is_root; 132184c406e7SOri Kam 132284c406e7SOri Kam if (items == NULL) 132384c406e7SOri Kam return -1; 1324c16e10f1SDariusz Sosnowski ret = flow_verbs_validate_attributes(dev, attr, error); 132584c406e7SOri Kam if (ret < 0) 132684c406e7SOri Kam return ret; 13271939eb6fSDariusz Sosnowski is_root = 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) { 1333*90385c46SMaayan Kashani #ifdef HAVE_IBV_FLOW_SPEC_ESP 133472185352SMaayan Kashani case RTE_FLOW_ITEM_TYPE_ESP: 133572185352SMaayan Kashani ret = mlx5_flow_os_validate_item_esp(items, item_flags, 133672185352SMaayan Kashani next_protocol, 133772185352SMaayan Kashani error); 133872185352SMaayan Kashani if (ret < 0) 133972185352SMaayan Kashani return ret; 134072185352SMaayan Kashani last_item = MLX5_FLOW_ITEM_ESP; 134172185352SMaayan Kashani break; 1342*90385c46SMaayan Kashani #endif 134384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 134484c406e7SOri Kam break; 134584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 134684c406e7SOri Kam ret = mlx5_flow_validate_item_eth(items, item_flags, 134786b59a1aSMatan Azrad false, error); 134884c406e7SOri Kam if (ret < 0) 134984c406e7SOri Kam return ret; 135038f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 135184c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L2; 1352fba32130SXiaoyu Min if (items->mask != NULL && items->spec != NULL) { 1353fba32130SXiaoyu Min ether_type = 1354fba32130SXiaoyu Min ((const struct rte_flow_item_eth *) 13558275d5fcSThomas Monjalon items->spec)->hdr.ether_type; 1356fba32130SXiaoyu Min ether_type &= 1357fba32130SXiaoyu Min ((const struct rte_flow_item_eth *) 13588275d5fcSThomas Monjalon items->mask)->hdr.ether_type; 1359b6aaaa22SShiri Kuzin if (ether_type == RTE_BE16(RTE_ETHER_TYPE_VLAN)) 1360b6aaaa22SShiri Kuzin is_empty_vlan = true; 1361fba32130SXiaoyu Min ether_type = rte_be_to_cpu_16(ether_type); 1362fba32130SXiaoyu Min } else { 1363fba32130SXiaoyu Min ether_type = 0; 1364fba32130SXiaoyu Min } 136584c406e7SOri Kam break; 136684c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 136784c406e7SOri Kam ret = mlx5_flow_validate_item_vlan(items, item_flags, 1368dfedf3e3SViacheslav Ovsiienko dev, error); 136984c406e7SOri Kam if (ret < 0) 137084c406e7SOri Kam return ret; 137138f7efaaSDekel Peled last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 | 13724a78c88eSYongseok Koh MLX5_FLOW_LAYER_INNER_VLAN) : 13734a78c88eSYongseok Koh (MLX5_FLOW_LAYER_OUTER_L2 | 13744a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_VLAN); 1375fba32130SXiaoyu Min if (items->mask != NULL && items->spec != NULL) { 1376fba32130SXiaoyu Min ether_type = 1377fba32130SXiaoyu Min ((const struct rte_flow_item_vlan *) 13788275d5fcSThomas Monjalon items->spec)->hdr.eth_proto; 1379fba32130SXiaoyu Min ether_type &= 1380fba32130SXiaoyu Min ((const struct rte_flow_item_vlan *) 13818275d5fcSThomas Monjalon items->mask)->hdr.eth_proto; 1382fba32130SXiaoyu Min ether_type = rte_be_to_cpu_16(ether_type); 1383fba32130SXiaoyu Min } else { 1384fba32130SXiaoyu Min ether_type = 0; 1385fba32130SXiaoyu Min } 1386b6aaaa22SShiri Kuzin is_empty_vlan = false; 138784c406e7SOri Kam break; 138884c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 13896859e67eSDekel Peled ret = mlx5_flow_validate_item_ipv4 13906859e67eSDekel Peled (items, item_flags, 13916859e67eSDekel Peled last_item, ether_type, NULL, 13926859e67eSDekel Peled MLX5_ITEM_RANGE_NOT_ACCEPTED, 1393fba32130SXiaoyu Min error); 139484c406e7SOri Kam if (ret < 0) 139584c406e7SOri Kam return ret; 139638f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 139784c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L3_IPV4; 139884c406e7SOri Kam if (items->mask != NULL && 139984c406e7SOri Kam ((const struct rte_flow_item_ipv4 *) 14003193c249SYongseok Koh items->mask)->hdr.next_proto_id) { 140184c406e7SOri Kam next_protocol = 140284c406e7SOri Kam ((const struct rte_flow_item_ipv4 *) 140384c406e7SOri Kam (items->spec))->hdr.next_proto_id; 14043193c249SYongseok Koh next_protocol &= 14053193c249SYongseok Koh ((const struct rte_flow_item_ipv4 *) 14063193c249SYongseok Koh (items->mask))->hdr.next_proto_id; 14073193c249SYongseok Koh } else { 14083193c249SYongseok Koh /* Reset for inner layer. */ 14093193c249SYongseok Koh next_protocol = 0xff; 14103193c249SYongseok Koh } 141184c406e7SOri Kam break; 141284c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 141384c406e7SOri Kam ret = mlx5_flow_validate_item_ipv6(items, item_flags, 1414fba32130SXiaoyu Min last_item, 1415fba32130SXiaoyu Min ether_type, NULL, 1416fba32130SXiaoyu Min error); 141784c406e7SOri Kam if (ret < 0) 141884c406e7SOri Kam return ret; 141938f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 142084c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L3_IPV6; 142184c406e7SOri Kam if (items->mask != NULL && 142284c406e7SOri Kam ((const struct rte_flow_item_ipv6 *) 14233193c249SYongseok Koh items->mask)->hdr.proto) { 142484c406e7SOri Kam next_protocol = 142584c406e7SOri Kam ((const struct rte_flow_item_ipv6 *) 142684c406e7SOri Kam items->spec)->hdr.proto; 14273193c249SYongseok Koh next_protocol &= 14283193c249SYongseok Koh ((const struct rte_flow_item_ipv6 *) 14293193c249SYongseok Koh items->mask)->hdr.proto; 14303193c249SYongseok Koh } else { 14313193c249SYongseok Koh /* Reset for inner layer. */ 14323193c249SYongseok Koh next_protocol = 0xff; 14333193c249SYongseok Koh } 143484c406e7SOri Kam break; 143584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_UDP: 143684c406e7SOri Kam ret = mlx5_flow_validate_item_udp(items, item_flags, 143784c406e7SOri Kam next_protocol, 143884c406e7SOri Kam error); 1439a1fd0c82SRongwei Liu const struct rte_flow_item_udp *spec = items->spec; 1440a1fd0c82SRongwei Liu const struct rte_flow_item_udp *mask = items->mask; 1441a1fd0c82SRongwei Liu if (!mask) 1442a1fd0c82SRongwei Liu mask = &rte_flow_item_udp_mask; 1443a1fd0c82SRongwei Liu if (spec != NULL) 1444a1fd0c82SRongwei Liu udp_dport = rte_be_to_cpu_16 1445a1fd0c82SRongwei Liu (spec->hdr.dst_port & 1446a1fd0c82SRongwei Liu mask->hdr.dst_port); 1447a1fd0c82SRongwei Liu 144884c406e7SOri Kam if (ret < 0) 144984c406e7SOri Kam return ret; 145038f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 145184c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L4_UDP; 145284c406e7SOri Kam break; 145384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 145492378c2bSMoti Haimovsky ret = mlx5_flow_validate_item_tcp 145592378c2bSMoti Haimovsky (items, item_flags, 145692378c2bSMoti Haimovsky next_protocol, 145792378c2bSMoti Haimovsky &rte_flow_item_tcp_mask, 145892378c2bSMoti Haimovsky error); 145984c406e7SOri Kam if (ret < 0) 146084c406e7SOri Kam return ret; 146138f7efaaSDekel Peled last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 146284c406e7SOri Kam MLX5_FLOW_LAYER_OUTER_L4_TCP; 146384c406e7SOri Kam break; 146484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 1465a1fd0c82SRongwei Liu ret = mlx5_flow_validate_item_vxlan(dev, udp_dport, 1466a1fd0c82SRongwei Liu items, item_flags, 14671939eb6fSDariusz Sosnowski is_root, error); 146884c406e7SOri Kam if (ret < 0) 146984c406e7SOri Kam return ret; 147038f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_VXLAN; 147184c406e7SOri Kam break; 147284c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 147384c406e7SOri Kam ret = mlx5_flow_validate_item_vxlan_gpe(items, 147484c406e7SOri Kam item_flags, 147584c406e7SOri Kam dev, error); 147684c406e7SOri Kam if (ret < 0) 147784c406e7SOri Kam return ret; 147838f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_VXLAN_GPE; 147984c406e7SOri Kam break; 148084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 148184c406e7SOri Kam ret = mlx5_flow_validate_item_gre(items, item_flags, 148284c406e7SOri Kam next_protocol, error); 148384c406e7SOri Kam if (ret < 0) 148484c406e7SOri Kam return ret; 148538f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_GRE; 148684c406e7SOri Kam break; 148784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 148838f7efaaSDekel Peled ret = mlx5_flow_validate_item_mpls(dev, items, 148938f7efaaSDekel Peled item_flags, 149038f7efaaSDekel Peled last_item, error); 149184c406e7SOri Kam if (ret < 0) 149284c406e7SOri Kam return ret; 149338f7efaaSDekel Peled last_item = MLX5_FLOW_LAYER_MPLS; 149484c406e7SOri Kam break; 149558df16e0SDekel Peled case RTE_FLOW_ITEM_TYPE_ICMP: 149658df16e0SDekel Peled case RTE_FLOW_ITEM_TYPE_ICMP6: 149784c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 149884c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ITEM, 149958df16e0SDekel Peled NULL, "ICMP/ICMP6 " 150058df16e0SDekel Peled "item not supported"); 150158df16e0SDekel Peled default: 150258df16e0SDekel Peled return rte_flow_error_set(error, ENOTSUP, 150358df16e0SDekel Peled RTE_FLOW_ERROR_TYPE_ITEM, 150458df16e0SDekel Peled NULL, "item not supported"); 150584c406e7SOri Kam } 150638f7efaaSDekel Peled item_flags |= last_item; 150784c406e7SOri Kam } 1508b6aaaa22SShiri Kuzin if (is_empty_vlan) 1509b6aaaa22SShiri Kuzin return rte_flow_error_set(error, ENOTSUP, 1510b6aaaa22SShiri Kuzin RTE_FLOW_ERROR_TYPE_ITEM, NULL, 1511b6aaaa22SShiri Kuzin "VLAN matching without vid specification is not supported"); 151284c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 151384c406e7SOri Kam switch (actions->type) { 151484c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 151584c406e7SOri Kam break; 151684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 151784c406e7SOri Kam ret = mlx5_flow_validate_action_flag(action_flags, 15183e9fa079SDekel Peled attr, 151984c406e7SOri Kam error); 152084c406e7SOri Kam if (ret < 0) 152184c406e7SOri Kam return ret; 152284c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_FLAG; 152384c406e7SOri Kam break; 152484c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 152584c406e7SOri Kam ret = mlx5_flow_validate_action_mark(actions, 152684c406e7SOri Kam action_flags, 15273e9fa079SDekel Peled attr, 152884c406e7SOri Kam error); 152984c406e7SOri Kam if (ret < 0) 153084c406e7SOri Kam return ret; 153184c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_MARK; 153284c406e7SOri Kam break; 153384c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 153484c406e7SOri Kam ret = mlx5_flow_validate_action_drop(action_flags, 15353e9fa079SDekel Peled attr, 153684c406e7SOri Kam error); 153784c406e7SOri Kam if (ret < 0) 153884c406e7SOri Kam return ret; 153984c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_DROP; 154084c406e7SOri Kam break; 154184c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 154284c406e7SOri Kam ret = mlx5_flow_validate_action_queue(actions, 154384c406e7SOri Kam action_flags, dev, 15443e9fa079SDekel Peled attr, 154584c406e7SOri Kam error); 154684c406e7SOri Kam if (ret < 0) 154784c406e7SOri Kam return ret; 154884c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_QUEUE; 154984c406e7SOri Kam break; 155084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 155184c406e7SOri Kam ret = mlx5_flow_validate_action_rss(actions, 155284c406e7SOri Kam action_flags, dev, 15531183f12fSOri Kam attr, item_flags, 155484c406e7SOri Kam error); 155584c406e7SOri Kam if (ret < 0) 155684c406e7SOri Kam return ret; 155784c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_RSS; 155884c406e7SOri Kam break; 155984c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 15603e9fa079SDekel Peled ret = mlx5_flow_validate_action_count(dev, attr, error); 156184c406e7SOri Kam if (ret < 0) 156284c406e7SOri Kam return ret; 156384c406e7SOri Kam action_flags |= MLX5_FLOW_ACTION_COUNT; 156484c406e7SOri Kam break; 156584c406e7SOri Kam default: 156684c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 156784c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, 156884c406e7SOri Kam actions, 156984c406e7SOri Kam "action not supported"); 157084c406e7SOri Kam } 157184c406e7SOri Kam } 157270faf9aeSDekel Peled /* 157370faf9aeSDekel Peled * Validate the drop action mutual exclusion with other actions. 157470faf9aeSDekel Peled * Drop action is mutually-exclusive with any other action, except for 157570faf9aeSDekel Peled * Count action. 157670faf9aeSDekel Peled */ 157770faf9aeSDekel Peled if ((action_flags & MLX5_FLOW_ACTION_DROP) && 157870faf9aeSDekel Peled (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT))) 157970faf9aeSDekel Peled return rte_flow_error_set(error, EINVAL, 158070faf9aeSDekel Peled RTE_FLOW_ERROR_TYPE_ACTION, NULL, 158170faf9aeSDekel Peled "Drop action is mutually-exclusive " 158270faf9aeSDekel Peled "with any other action, except for " 158370faf9aeSDekel Peled "Count action"); 158484c406e7SOri Kam if (!(action_flags & MLX5_FLOW_FATE_ACTIONS)) 158584c406e7SOri Kam return rte_flow_error_set(error, EINVAL, 158684c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, actions, 158784c406e7SOri Kam "no fate action is found"); 158884c406e7SOri Kam return 0; 158984c406e7SOri Kam } 159084c406e7SOri Kam 159184c406e7SOri Kam /** 159284c406e7SOri Kam * Calculate the required bytes that are needed for the action part of the verbs 1593c1cfb132SYongseok Koh * flow. 159484c406e7SOri Kam * 159584c406e7SOri Kam * @param[in] actions 159684c406e7SOri Kam * Pointer to the list of actions. 159784c406e7SOri Kam * 159884c406e7SOri Kam * @return 159984c406e7SOri Kam * The size of the memory needed for all actions. 160084c406e7SOri Kam */ 160184c406e7SOri Kam static int 1602c1cfb132SYongseok Koh flow_verbs_get_actions_size(const struct rte_flow_action actions[]) 160384c406e7SOri Kam { 160484c406e7SOri Kam int size = 0; 160584c406e7SOri Kam 160684c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 160784c406e7SOri Kam switch (actions->type) { 160884c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 160984c406e7SOri Kam break; 161084c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 161184c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_tag); 161284c406e7SOri Kam break; 161384c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 161484c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_tag); 161584c406e7SOri Kam break; 161684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 161784c406e7SOri Kam size += sizeof(struct ibv_flow_spec_action_drop); 161884c406e7SOri Kam break; 161984c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 162084c406e7SOri Kam break; 162184c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 162284c406e7SOri Kam break; 162384c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 1624db48f9dbSViacheslav Ovsiienko #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \ 1625db48f9dbSViacheslav Ovsiienko defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45) 162684c406e7SOri Kam size += sizeof(struct ibv_flow_spec_counter_action); 162784c406e7SOri Kam #endif 162884c406e7SOri Kam break; 162984c406e7SOri Kam default: 163084c406e7SOri Kam break; 163184c406e7SOri Kam } 163284c406e7SOri Kam } 163384c406e7SOri Kam return size; 163484c406e7SOri Kam } 163584c406e7SOri Kam 163684c406e7SOri Kam /** 163784c406e7SOri Kam * Calculate the required bytes that are needed for the item part of the verbs 1638c1cfb132SYongseok Koh * flow. 163984c406e7SOri Kam * 1640c1cfb132SYongseok Koh * @param[in] items 164184c406e7SOri Kam * Pointer to the list of items. 164284c406e7SOri Kam * 164384c406e7SOri Kam * @return 164484c406e7SOri Kam * The size of the memory needed for all items. 164584c406e7SOri Kam */ 164684c406e7SOri Kam static int 1647c1cfb132SYongseok Koh flow_verbs_get_items_size(const struct rte_flow_item items[]) 164884c406e7SOri Kam { 164984c406e7SOri Kam int size = 0; 165084c406e7SOri Kam 165184c406e7SOri Kam for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 165284c406e7SOri Kam switch (items->type) { 165384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 165484c406e7SOri Kam break; 165584c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 165684c406e7SOri Kam size += sizeof(struct ibv_flow_spec_eth); 165784c406e7SOri Kam break; 165884c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 165984c406e7SOri Kam size += sizeof(struct ibv_flow_spec_eth); 166084c406e7SOri Kam break; 166184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 166284c406e7SOri Kam size += sizeof(struct ibv_flow_spec_ipv4_ext); 166384c406e7SOri Kam break; 166484c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 166584c406e7SOri Kam size += sizeof(struct ibv_flow_spec_ipv6); 166684c406e7SOri Kam break; 166784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_UDP: 166884c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tcp_udp); 166984c406e7SOri Kam break; 167084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 167184c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tcp_udp); 167284c406e7SOri Kam break; 167384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 167484c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 167584c406e7SOri Kam break; 167684c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 167784c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 167884c406e7SOri Kam break; 167984c406e7SOri Kam #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 168084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 168184c406e7SOri Kam size += sizeof(struct ibv_flow_spec_gre); 168284c406e7SOri Kam break; 168384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 168484c406e7SOri Kam size += sizeof(struct ibv_flow_spec_mpls); 168584c406e7SOri Kam break; 168684c406e7SOri Kam #else 168784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 168884c406e7SOri Kam size += sizeof(struct ibv_flow_spec_tunnel); 168984c406e7SOri Kam break; 169084c406e7SOri Kam #endif 169184c406e7SOri Kam default: 169284c406e7SOri Kam break; 169384c406e7SOri Kam } 169484c406e7SOri Kam } 169584c406e7SOri Kam return size; 169684c406e7SOri Kam } 169784c406e7SOri Kam 169884c406e7SOri Kam /** 169984c406e7SOri Kam * Internal preparation function. Allocate mlx5_flow with the required size. 170084c406e7SOri Kam * The required size is calculate based on the actions and items. This function 170184c406e7SOri Kam * also returns the detected actions and items for later use. 170284c406e7SOri Kam * 1703e7bfa359SBing Zhao * @param[in] dev 1704e7bfa359SBing Zhao * Pointer to Ethernet device. 170584c406e7SOri Kam * @param[in] attr 170684c406e7SOri Kam * Pointer to the flow attributes. 170784c406e7SOri Kam * @param[in] items 170884c406e7SOri Kam * Pointer to the list of items. 170984c406e7SOri Kam * @param[in] actions 171084c406e7SOri Kam * Pointer to the list of actions. 171184c406e7SOri Kam * @param[out] error 171284c406e7SOri Kam * Pointer to the error structure. 171384c406e7SOri Kam * 171484c406e7SOri Kam * @return 171584c406e7SOri Kam * Pointer to mlx5_flow object on success, otherwise NULL and rte_errno 171684c406e7SOri Kam * is set. 171784c406e7SOri Kam */ 171884c406e7SOri Kam static struct mlx5_flow * 1719e7bfa359SBing Zhao flow_verbs_prepare(struct rte_eth_dev *dev, 1720e7bfa359SBing Zhao const struct rte_flow_attr *attr __rte_unused, 172184c406e7SOri Kam const struct rte_flow_item items[], 172284c406e7SOri Kam const struct rte_flow_action actions[], 172384c406e7SOri Kam struct rte_flow_error *error) 172484c406e7SOri Kam { 1725e7bfa359SBing Zhao size_t size = 0; 1726b88341caSSuanming Mou uint32_t handle_idx = 0; 1727e205c95fSViacheslav Ovsiienko struct mlx5_flow *dev_flow; 1728e7bfa359SBing Zhao struct mlx5_flow_handle *dev_handle; 1729e7bfa359SBing Zhao struct mlx5_priv *priv = dev->data->dev_private; 17308bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 173184c406e7SOri Kam 17328bb81f26SXueming Li MLX5_ASSERT(wks); 1733c1cfb132SYongseok Koh size += flow_verbs_get_actions_size(actions); 1734c1cfb132SYongseok Koh size += flow_verbs_get_items_size(items); 1735e7bfa359SBing Zhao if (size > MLX5_VERBS_MAX_SPEC_ACT_SIZE) { 1736e7bfa359SBing Zhao rte_flow_error_set(error, E2BIG, 173784c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1738e7bfa359SBing Zhao "Verbs spec/action size too large"); 173984c406e7SOri Kam return NULL; 174084c406e7SOri Kam } 1741e7bfa359SBing Zhao /* In case of corrupting the memory. */ 17428bb81f26SXueming Li if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) { 1743e7bfa359SBing Zhao rte_flow_error_set(error, ENOSPC, 1744e7bfa359SBing Zhao RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1745e7bfa359SBing Zhao "not free temporary device flow"); 1746e7bfa359SBing Zhao return NULL; 1747e7bfa359SBing Zhao } 1748b88341caSSuanming Mou dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 1749b88341caSSuanming Mou &handle_idx); 1750e7bfa359SBing Zhao if (!dev_handle) { 1751e7bfa359SBing Zhao rte_flow_error_set(error, ENOMEM, 1752e7bfa359SBing Zhao RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 1753e7bfa359SBing Zhao "not enough memory to create flow handle"); 1754e7bfa359SBing Zhao return NULL; 1755e7bfa359SBing Zhao } 17568bb81f26SXueming Li MLX5_ASSERT(wks->flow_idx + 1 < RTE_DIM(wks->flows)); 17578bb81f26SXueming Li dev_flow = &wks->flows[wks->flow_idx++]; 1758e7bfa359SBing Zhao dev_flow->handle = dev_handle; 1759b88341caSSuanming Mou dev_flow->handle_idx = handle_idx; 1760e7bfa359SBing Zhao /* Memcpy is used, only size needs to be cleared to 0. */ 1761e7bfa359SBing Zhao dev_flow->verbs.size = 0; 1762e7bfa359SBing Zhao dev_flow->verbs.attr.num_of_specs = 0; 1763e205c95fSViacheslav Ovsiienko dev_flow->ingress = attr->ingress; 17640efc99beSOphir Munk dev_flow->hash_fields = 0; 1765c42f44bdSBing Zhao /* Need to set transfer attribute: not supported in Verbs mode. */ 1766e205c95fSViacheslav Ovsiienko return dev_flow; 176784c406e7SOri Kam } 176884c406e7SOri Kam 176984c406e7SOri Kam /** 177084c406e7SOri Kam * Fill the flow with verb spec. 177184c406e7SOri Kam * 177284c406e7SOri Kam * @param[in] dev 177384c406e7SOri Kam * Pointer to Ethernet device. 177484c406e7SOri Kam * @param[in, out] dev_flow 177584c406e7SOri Kam * Pointer to the mlx5 flow. 177684c406e7SOri Kam * @param[in] attr 177784c406e7SOri Kam * Pointer to the flow attributes. 177884c406e7SOri Kam * @param[in] items 177984c406e7SOri Kam * Pointer to the list of items. 178084c406e7SOri Kam * @param[in] actions 178184c406e7SOri Kam * Pointer to the list of actions. 178284c406e7SOri Kam * @param[out] error 178384c406e7SOri Kam * Pointer to the error structure. 178484c406e7SOri Kam * 178584c406e7SOri Kam * @return 1786de90612fSDekel Peled * 0 on success, else a negative errno value otherwise and rte_errno is set. 178784c406e7SOri Kam */ 178884c406e7SOri Kam static int 178984c406e7SOri Kam flow_verbs_translate(struct rte_eth_dev *dev, 179084c406e7SOri Kam struct mlx5_flow *dev_flow, 179184c406e7SOri Kam const struct rte_flow_attr *attr, 179284c406e7SOri Kam const struct rte_flow_item items[], 179384c406e7SOri Kam const struct rte_flow_action actions[], 179484c406e7SOri Kam struct rte_flow_error *error) 179584c406e7SOri Kam { 179684c406e7SOri Kam uint64_t item_flags = 0; 17974a78c88eSYongseok Koh uint64_t action_flags = 0; 179884c406e7SOri Kam uint64_t priority = attr->priority; 17994a78c88eSYongseok Koh uint32_t subpriority = 0; 1800dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private; 18018bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 18028bb81f26SXueming Li struct mlx5_flow_rss_desc *rss_desc; 1803df498655SGregory Etelson const struct rte_flow_item *tunnel_item = NULL; 180498008ce6SDariusz Sosnowski uint8_t *gre_spec = NULL; 180584c406e7SOri Kam 18068bb81f26SXueming Li MLX5_ASSERT(wks); 18070064bf43SXueming Li rss_desc = &wks->rss_desc; 18085f8ae44dSDong Zhou if (priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) 18093c4338a4SJiawei Wang priority = priv->sh->flow_max_priority - 1; 181084c406e7SOri Kam for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 181184c406e7SOri Kam int ret; 18124a78c88eSYongseok Koh 181384c406e7SOri Kam switch (actions->type) { 181484c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_VOID: 181584c406e7SOri Kam break; 181684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_FLAG: 18174a78c88eSYongseok Koh flow_verbs_translate_action_flag(dev_flow, actions); 18184a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_FLAG; 1819082becbfSRaja Zidane wks->mark = 1; 182084c406e7SOri Kam break; 182184c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_MARK: 18224a78c88eSYongseok Koh flow_verbs_translate_action_mark(dev_flow, actions); 18234a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_MARK; 1824082becbfSRaja Zidane wks->mark = 1; 182584c406e7SOri Kam break; 182684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_DROP: 18274a78c88eSYongseok Koh flow_verbs_translate_action_drop(dev_flow, actions); 18284a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_DROP; 1829488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP; 183084c406e7SOri Kam break; 183184c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_QUEUE: 1832e745f900SSuanming Mou flow_verbs_translate_action_queue(rss_desc, actions); 18334a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_QUEUE; 1834488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 183584c406e7SOri Kam break; 183684c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_RSS: 1837e745f900SSuanming Mou flow_verbs_translate_action_rss(rss_desc, actions); 18384a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_RSS; 1839488d13abSSuanming Mou dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; 184084c406e7SOri Kam break; 184184c406e7SOri Kam case RTE_FLOW_ACTION_TYPE_COUNT: 18424a78c88eSYongseok Koh ret = flow_verbs_translate_action_count(dev_flow, 184384c406e7SOri Kam actions, 18444a78c88eSYongseok Koh dev, error); 184584c406e7SOri Kam if (ret < 0) 184684c406e7SOri Kam return ret; 18474a78c88eSYongseok Koh action_flags |= MLX5_FLOW_ACTION_COUNT; 184884c406e7SOri Kam break; 184984c406e7SOri Kam default: 185084c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 185184c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ACTION, 185284c406e7SOri Kam actions, 185384c406e7SOri Kam "action not supported"); 185484c406e7SOri Kam } 185584c406e7SOri Kam } 1856488d13abSSuanming Mou dev_flow->act_flags = action_flags; 185784c406e7SOri Kam for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 18584a78c88eSYongseok Koh int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 18594a78c88eSYongseok Koh 186084c406e7SOri Kam switch (items->type) { 186184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VOID: 186284c406e7SOri Kam break; 186384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_ETH: 18644a78c88eSYongseok Koh flow_verbs_translate_item_eth(dev_flow, items, 18654a78c88eSYongseok Koh item_flags); 18664a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L2; 18674a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 18684a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L2; 186984c406e7SOri Kam break; 187084c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VLAN: 18714a78c88eSYongseok Koh flow_verbs_translate_item_vlan(dev_flow, items, 18724a78c88eSYongseok Koh item_flags); 18734a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L2; 18744a78c88eSYongseok Koh item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 | 18754a78c88eSYongseok Koh MLX5_FLOW_LAYER_INNER_VLAN) : 18764a78c88eSYongseok Koh (MLX5_FLOW_LAYER_OUTER_L2 | 18774a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_VLAN); 187884c406e7SOri Kam break; 187984c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV4: 18804a78c88eSYongseok Koh flow_verbs_translate_item_ipv4(dev_flow, items, 18814a78c88eSYongseok Koh item_flags); 18824a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L3; 1883e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 18844a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1885e745f900SSuanming Mou (rss_desc, tunnel, 18864a78c88eSYongseok Koh MLX5_IPV4_LAYER_TYPES, 18874a78c88eSYongseok Koh MLX5_IPV4_IBV_RX_HASH); 18884a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 18894a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L3_IPV4; 189084c406e7SOri Kam break; 189184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_IPV6: 18924a78c88eSYongseok Koh flow_verbs_translate_item_ipv6(dev_flow, items, 18934a78c88eSYongseok Koh item_flags); 18944a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L3; 1895e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 18964a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1897e745f900SSuanming Mou (rss_desc, tunnel, 18984a78c88eSYongseok Koh MLX5_IPV6_LAYER_TYPES, 18994a78c88eSYongseok Koh MLX5_IPV6_IBV_RX_HASH); 19004a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 19014a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L3_IPV6; 190284c406e7SOri Kam break; 190384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_TCP: 19044a78c88eSYongseok Koh flow_verbs_translate_item_tcp(dev_flow, items, 19054a78c88eSYongseok Koh item_flags); 19064a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L4; 19075e1db76dSLior Margalit if (dev_flow->hash_fields != 0) 1908e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 19094a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1910295968d1SFerruh Yigit (rss_desc, tunnel, RTE_ETH_RSS_TCP, 19114a78c88eSYongseok Koh (IBV_RX_HASH_SRC_PORT_TCP | 19124a78c88eSYongseok Koh IBV_RX_HASH_DST_PORT_TCP)); 19134a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP : 19144a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L4_TCP; 19154a78c88eSYongseok Koh break; 19164a78c88eSYongseok Koh case RTE_FLOW_ITEM_TYPE_UDP: 19174a78c88eSYongseok Koh flow_verbs_translate_item_udp(dev_flow, items, 19184a78c88eSYongseok Koh item_flags); 19194a78c88eSYongseok Koh subpriority = MLX5_PRIORITY_MAP_L4; 19205e1db76dSLior Margalit if (dev_flow->hash_fields != 0) 1921e205c95fSViacheslav Ovsiienko dev_flow->hash_fields |= 19224a78c88eSYongseok Koh mlx5_flow_hashfields_adjust 1923295968d1SFerruh Yigit (rss_desc, tunnel, RTE_ETH_RSS_UDP, 19244a78c88eSYongseok Koh (IBV_RX_HASH_SRC_PORT_UDP | 19254a78c88eSYongseok Koh IBV_RX_HASH_DST_PORT_UDP)); 19264a78c88eSYongseok Koh item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP : 19274a78c88eSYongseok Koh MLX5_FLOW_LAYER_OUTER_L4_UDP; 192884c406e7SOri Kam break; 192972185352SMaayan Kashani #ifdef HAVE_IBV_FLOW_SPEC_ESP 193072185352SMaayan Kashani case RTE_FLOW_ITEM_TYPE_ESP: 193172185352SMaayan Kashani flow_verbs_translate_item_esp(dev_flow, items, 193272185352SMaayan Kashani item_flags); 193372185352SMaayan Kashani dev_flow->hash_fields |= 193472185352SMaayan Kashani mlx5_flow_hashfields_adjust 193572185352SMaayan Kashani (rss_desc, tunnel, 193672185352SMaayan Kashani RTE_ETH_RSS_ESP, 193772185352SMaayan Kashani IBV_RX_HASH_IPSEC_SPI); 193872185352SMaayan Kashani item_flags |= MLX5_FLOW_ITEM_ESP; 193972185352SMaayan Kashani break; 194072185352SMaayan Kashani #endif 194184c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN: 19424a78c88eSYongseok Koh flow_verbs_translate_item_vxlan(dev_flow, items, 19434a78c88eSYongseok Koh item_flags); 1944750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19454a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_VXLAN; 194684c406e7SOri Kam break; 194784c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 19484a78c88eSYongseok Koh flow_verbs_translate_item_vxlan_gpe(dev_flow, items, 19494a78c88eSYongseok Koh item_flags); 1950750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19514a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE; 195284c406e7SOri Kam break; 195384c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_GRE: 195498008ce6SDariusz Sosnowski gre_spec = flow_verbs_reserve_gre(dev_flow); 1955750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19564a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_GRE; 1957df498655SGregory Etelson tunnel_item = items; 195884c406e7SOri Kam break; 195984c406e7SOri Kam case RTE_FLOW_ITEM_TYPE_MPLS: 19604a78c88eSYongseok Koh flow_verbs_translate_item_mpls(dev_flow, items, 19614a78c88eSYongseok Koh item_flags); 1962750ff30aSGregory Etelson subpriority = MLX5_TUNNEL_PRIO_GET(rss_desc); 19634a78c88eSYongseok Koh item_flags |= MLX5_FLOW_LAYER_MPLS; 196484c406e7SOri Kam break; 196584c406e7SOri Kam default: 196684c406e7SOri Kam return rte_flow_error_set(error, ENOTSUP, 196784c406e7SOri Kam RTE_FLOW_ERROR_TYPE_ITEM, 196858df16e0SDekel Peled NULL, "item not supported"); 196984c406e7SOri Kam } 197084c406e7SOri Kam } 1971985b4792SGregory Etelson if (item_flags & MLX5_FLOW_LAYER_GRE) 197298008ce6SDariusz Sosnowski flow_verbs_translate_item_gre(dev_flow, gre_spec, 197398008ce6SDariusz Sosnowski tunnel_item, item_flags); 1974e7bfa359SBing Zhao dev_flow->handle->layers = item_flags; 1975e7bfa359SBing Zhao /* Other members of attr will be ignored. */ 1976e7bfa359SBing Zhao dev_flow->verbs.attr.priority = 19774a78c88eSYongseok Koh mlx5_flow_adjust_priority(dev, priority, subpriority); 197891389890SOphir Munk dev_flow->verbs.attr.port = (uint8_t)priv->dev_port; 197984c406e7SOri Kam return 0; 198084c406e7SOri Kam } 198184c406e7SOri Kam 198284c406e7SOri Kam /** 198384c406e7SOri Kam * Remove the flow from the NIC but keeps it in memory. 198484c406e7SOri Kam * 198584c406e7SOri Kam * @param[in] dev 198684c406e7SOri Kam * Pointer to the Ethernet device structure. 198784c406e7SOri Kam * @param[in, out] flow 198884c406e7SOri Kam * Pointer to flow structure. 198984c406e7SOri Kam */ 199084c406e7SOri Kam static void 199184c406e7SOri Kam flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow) 199284c406e7SOri Kam { 1993b88341caSSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 1994e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 1995b88341caSSuanming Mou uint32_t handle_idx; 199684c406e7SOri Kam 199784c406e7SOri Kam if (!flow) 199884c406e7SOri Kam return; 1999b88341caSSuanming Mou SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 2000b88341caSSuanming Mou handle_idx, handle, next) { 2001341c8941SDekel Peled if (handle->drv_flow) { 2002341c8941SDekel Peled claim_zero(mlx5_glue->destroy_flow(handle->drv_flow)); 2003341c8941SDekel Peled handle->drv_flow = NULL; 200484c406e7SOri Kam } 20056fc18392SSuanming Mou /* hrxq is union, don't touch it only the flag is set. */ 200665b3cd0dSSuanming Mou if (handle->rix_hrxq && 200765b3cd0dSSuanming Mou handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 200877749adaSSuanming Mou mlx5_hrxq_release(dev, handle->rix_hrxq); 200977749adaSSuanming Mou handle->rix_hrxq = 0; 201084c406e7SOri Kam } 2011e7bfa359SBing Zhao if (handle->vf_vlan.tag && handle->vf_vlan.created) 2012e7bfa359SBing Zhao mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); 201384c406e7SOri Kam } 201484c406e7SOri Kam } 201584c406e7SOri Kam 201684c406e7SOri Kam /** 201784c406e7SOri Kam * Remove the flow from the NIC and the memory. 201884c406e7SOri Kam * 201984c406e7SOri Kam * @param[in] dev 202084c406e7SOri Kam * Pointer to the Ethernet device structure. 202184c406e7SOri Kam * @param[in, out] flow 202284c406e7SOri Kam * Pointer to flow structure. 202384c406e7SOri Kam */ 202484c406e7SOri Kam static void 202584c406e7SOri Kam flow_verbs_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 202684c406e7SOri Kam { 2027b88341caSSuanming Mou struct mlx5_priv *priv = dev->data->dev_private; 2028e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 202984c406e7SOri Kam 203084c406e7SOri Kam if (!flow) 203184c406e7SOri Kam return; 203284c406e7SOri Kam flow_verbs_remove(dev, flow); 2033b88341caSSuanming Mou while (flow->dev_handles) { 2034b88341caSSuanming Mou uint32_t tmp_idx = flow->dev_handles; 2035b88341caSSuanming Mou 2036b88341caSSuanming Mou handle = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 2037b88341caSSuanming Mou tmp_idx); 2038b88341caSSuanming Mou if (!handle) 2039b88341caSSuanming Mou return; 2040b88341caSSuanming Mou flow->dev_handles = handle->next.next; 2041b88341caSSuanming Mou mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 2042b88341caSSuanming Mou tmp_idx); 204384c406e7SOri Kam } 204484be903cSViacheslav Ovsiienko if (flow->counter) { 20455382d28cSMatan Azrad flow_verbs_counter_release(dev, flow->counter); 2046956d5c74SSuanming Mou flow->counter = 0; 204784be903cSViacheslav Ovsiienko } 204884c406e7SOri Kam } 204984c406e7SOri Kam 205084c406e7SOri Kam /** 205184c406e7SOri Kam * Apply the flow to the NIC. 205284c406e7SOri Kam * 205384c406e7SOri Kam * @param[in] dev 205484c406e7SOri Kam * Pointer to the Ethernet device structure. 205584c406e7SOri Kam * @param[in, out] flow 205684c406e7SOri Kam * Pointer to flow structure. 205784c406e7SOri Kam * @param[out] error 205884c406e7SOri Kam * Pointer to error structure. 205984c406e7SOri Kam * 206084c406e7SOri Kam * @return 206184c406e7SOri Kam * 0 on success, a negative errno value otherwise and rte_errno is set. 206284c406e7SOri Kam */ 206384c406e7SOri Kam static int 206484c406e7SOri Kam flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow, 206584c406e7SOri Kam struct rte_flow_error *error) 206684c406e7SOri Kam { 2067dfedf3e3SViacheslav Ovsiienko struct mlx5_priv *priv = dev->data->dev_private; 2068e7bfa359SBing Zhao struct mlx5_flow_handle *handle; 206984c406e7SOri Kam struct mlx5_flow *dev_flow; 2070772dc0ebSSuanming Mou struct mlx5_hrxq *hrxq; 2071b88341caSSuanming Mou uint32_t dev_handles; 207284c406e7SOri Kam int err; 2073e7bfa359SBing Zhao int idx; 20748bb81f26SXueming Li struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 207584c406e7SOri Kam 20768bb81f26SXueming Li MLX5_ASSERT(wks); 20770064bf43SXueming Li for (idx = wks->flow_idx - 1; idx >= 0; idx--) { 20788bb81f26SXueming Li dev_flow = &wks->flows[idx]; 2079e7bfa359SBing Zhao handle = dev_flow->handle; 2080488d13abSSuanming Mou if (handle->fate_action == MLX5_FLOW_FATE_DROP) { 208165b3cd0dSSuanming Mou MLX5_ASSERT(priv->drop_queue.hrxq); 208265b3cd0dSSuanming Mou hrxq = priv->drop_queue.hrxq; 208384c406e7SOri Kam } else { 20840064bf43SXueming Li struct mlx5_flow_rss_desc *rss_desc = &wks->rss_desc; 208584c406e7SOri Kam 2086e745f900SSuanming Mou MLX5_ASSERT(rss_desc->queue_num); 2087e1592b6cSSuanming Mou rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN; 2088e1592b6cSSuanming Mou rss_desc->hash_fields = dev_flow->hash_fields; 2089e1592b6cSSuanming Mou rss_desc->tunnel = !!(handle->layers & 2090e1592b6cSSuanming Mou MLX5_FLOW_LAYER_TUNNEL); 2091fabf8a37SSuanming Mou rss_desc->shared_rss = 0; 20923a2f674bSSuanming Mou hrxq = mlx5_hrxq_get(dev, rss_desc); 209384c406e7SOri Kam if (!hrxq) { 209484c406e7SOri Kam rte_flow_error_set 209584c406e7SOri Kam (error, rte_errno, 209684c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 209784c406e7SOri Kam "cannot get hash queue"); 209884c406e7SOri Kam goto error; 209984c406e7SOri Kam } 21003a2f674bSSuanming Mou handle->rix_hrxq = hrxq->idx; 210184c406e7SOri Kam } 2102772dc0ebSSuanming Mou MLX5_ASSERT(hrxq); 2103341c8941SDekel Peled handle->drv_flow = mlx5_glue->create_flow 2104341c8941SDekel Peled (hrxq->qp, &dev_flow->verbs.attr); 2105341c8941SDekel Peled if (!handle->drv_flow) { 210684c406e7SOri Kam rte_flow_error_set(error, errno, 210784c406e7SOri Kam RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 210884c406e7SOri Kam NULL, 210984c406e7SOri Kam "hardware refuses to create flow"); 211084c406e7SOri Kam goto error; 211184c406e7SOri Kam } 2112dfedf3e3SViacheslav Ovsiienko if (priv->vmwa_context && 2113e7bfa359SBing Zhao handle->vf_vlan.tag && !handle->vf_vlan.created) { 2114dfedf3e3SViacheslav Ovsiienko /* 2115dfedf3e3SViacheslav Ovsiienko * The rule contains the VLAN pattern. 2116dfedf3e3SViacheslav Ovsiienko * For VF we are going to create VLAN 2117dfedf3e3SViacheslav Ovsiienko * interface to make hypervisor set correct 2118dfedf3e3SViacheslav Ovsiienko * e-Switch vport context. 2119dfedf3e3SViacheslav Ovsiienko */ 2120e7bfa359SBing Zhao mlx5_vlan_vmwa_acquire(dev, &handle->vf_vlan); 2121dfedf3e3SViacheslav Ovsiienko } 212284c406e7SOri Kam } 212384c406e7SOri Kam return 0; 212484c406e7SOri Kam error: 212584c406e7SOri Kam err = rte_errno; /* Save rte_errno before cleanup. */ 2126b88341caSSuanming Mou SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 2127b88341caSSuanming Mou dev_handles, handle, next) { 21286fc18392SSuanming Mou /* hrxq is union, don't touch it only the flag is set. */ 212965b3cd0dSSuanming Mou if (handle->rix_hrxq && 213065b3cd0dSSuanming Mou handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 213177749adaSSuanming Mou mlx5_hrxq_release(dev, handle->rix_hrxq); 213277749adaSSuanming Mou handle->rix_hrxq = 0; 213384c406e7SOri Kam } 2134e7bfa359SBing Zhao if (handle->vf_vlan.tag && handle->vf_vlan.created) 2135e7bfa359SBing Zhao mlx5_vlan_vmwa_release(dev, &handle->vf_vlan); 213684c406e7SOri Kam } 213784c406e7SOri Kam rte_errno = err; /* Restore rte_errno. */ 213884c406e7SOri Kam return -rte_errno; 213984c406e7SOri Kam } 214084c406e7SOri Kam 2141684dafe7SMoti Haimovsky /** 2142684dafe7SMoti Haimovsky * Query a flow. 2143684dafe7SMoti Haimovsky * 2144684dafe7SMoti Haimovsky * @see rte_flow_query() 2145684dafe7SMoti Haimovsky * @see rte_flow_ops 2146684dafe7SMoti Haimovsky */ 2147684dafe7SMoti Haimovsky static int 2148684dafe7SMoti Haimovsky flow_verbs_query(struct rte_eth_dev *dev, 2149684dafe7SMoti Haimovsky struct rte_flow *flow, 2150684dafe7SMoti Haimovsky const struct rte_flow_action *actions, 2151684dafe7SMoti Haimovsky void *data, 2152684dafe7SMoti Haimovsky struct rte_flow_error *error) 2153684dafe7SMoti Haimovsky { 2154684dafe7SMoti Haimovsky int ret = -EINVAL; 2155684dafe7SMoti Haimovsky 2156684dafe7SMoti Haimovsky for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2157684dafe7SMoti Haimovsky switch (actions->type) { 2158684dafe7SMoti Haimovsky case RTE_FLOW_ACTION_TYPE_VOID: 2159684dafe7SMoti Haimovsky break; 2160684dafe7SMoti Haimovsky case RTE_FLOW_ACTION_TYPE_COUNT: 216106629d86SViacheslav Ovsiienko ret = flow_verbs_counter_query(dev, flow, data, error); 2162684dafe7SMoti Haimovsky break; 2163684dafe7SMoti Haimovsky default: 2164684dafe7SMoti Haimovsky return rte_flow_error_set(error, ENOTSUP, 2165684dafe7SMoti Haimovsky RTE_FLOW_ERROR_TYPE_ACTION, 2166684dafe7SMoti Haimovsky actions, 2167684dafe7SMoti Haimovsky "action not supported"); 2168684dafe7SMoti Haimovsky } 2169684dafe7SMoti Haimovsky } 2170684dafe7SMoti Haimovsky return ret; 2171684dafe7SMoti Haimovsky } 2172684dafe7SMoti Haimovsky 217323f627e0SBing Zhao static int 217423f627e0SBing Zhao flow_verbs_sync_domain(struct rte_eth_dev *dev, uint32_t domains, 217523f627e0SBing Zhao uint32_t flags) 217623f627e0SBing Zhao { 217723f627e0SBing Zhao RTE_SET_USED(dev); 217823f627e0SBing Zhao RTE_SET_USED(domains); 217923f627e0SBing Zhao RTE_SET_USED(flags); 218023f627e0SBing Zhao 218123f627e0SBing Zhao return 0; 218223f627e0SBing Zhao } 218323f627e0SBing Zhao 21840c76d1c9SYongseok Koh const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = { 218584c406e7SOri Kam .validate = flow_verbs_validate, 218684c406e7SOri Kam .prepare = flow_verbs_prepare, 218784c406e7SOri Kam .translate = flow_verbs_translate, 218884c406e7SOri Kam .apply = flow_verbs_apply, 218984c406e7SOri Kam .remove = flow_verbs_remove, 219084c406e7SOri Kam .destroy = flow_verbs_destroy, 2191684dafe7SMoti Haimovsky .query = flow_verbs_query, 219223f627e0SBing Zhao .sync_domain = flow_verbs_sync_domain, 2193c5042f93SDmitry Kozlyuk .discover_priorities = flow_verbs_discover_priorities, 2194c68bb7a6SAsaf Penso .get_aged_flows = flow_null_get_aged_flows, 2195c68bb7a6SAsaf Penso .counter_alloc = flow_null_counter_allocate, 2196c68bb7a6SAsaf Penso .counter_free = flow_null_counter_free, 2197c68bb7a6SAsaf Penso .counter_query = flow_null_counter_query, 219884c406e7SOri Kam }; 2199